]> www.fi.muni.cz Git - evince.git/blob - shell/ev-window.c
a1521fcac1f749ecd80f3b13b94e98fb575fdea4
[evince.git] / shell / ev-window.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */
2 /* this file is part of evince, a gnome document viewer
3  *
4  *  Copyright (C) 2004 Martin Kretzschmar
5  *  Copyright (C) 2004 Red Hat, Inc.
6  *
7  *  Author:
8  *    Martin Kretzschmar <martink@gnome.org>
9  *
10  * Evince is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * Evince is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include "ev-window.h"
30 #include "ev-sidebar.h"
31 #include "ev-sidebar-bookmarks.h"
32 #include "ev-sidebar-thumbnails.h"
33 #include "ev-view.h"
34 #include "eggfindbar.h"
35
36 #include "pdf-document.h"
37
38 #include <glib/gi18n.h>
39 #include <gtk/gtk.h>
40 #include <libgnomevfs/gnome-vfs-mime-utils.h>
41
42 #include <string.h>
43
44 #include "ev-application.h"
45
46 enum {
47         PROP_0,
48         PROP_ATTRIBUTE
49 };
50
51 enum {
52         SIGNAL,
53         N_SIGNALS
54 };
55
56 struct _EvWindowPrivate {
57         GtkWidget *main_box;
58         GtkWidget *hpaned;
59         GtkWidget *sidebar;
60         GtkWidget *find_bar;
61         GtkWidget *view;
62         GtkActionGroup *action_group;
63         GtkUIManager *ui_manager;
64         GtkWidget *statusbar;
65         guint help_message_cid;
66         
67         EvDocument *document;
68 };
69
70 #if 0
71 /* enable these to add support for signals */
72 static guint ev_window_signals [N_SIGNALS] = { 0 };
73 #endif
74
75 static GObjectClass *parent_class = NULL;
76
77 G_DEFINE_TYPE (EvWindow, ev_window, GTK_TYPE_WINDOW)
78
79 #define EV_WINDOW_GET_PRIVATE(object) \
80         (G_TYPE_INSTANCE_GET_PRIVATE ((object), EV_TYPE_WINDOW, EvWindowPrivate))
81
82 #if 0
83 const char *
84 ev_window_get_attribute (EvWindow *self)
85 {
86         g_return_val_if_fail (self != NULL && EV_IS_WINDOW (self), NULL);
87         
88         return self->priv->attribute;
89 }
90
91 void
92 ev_window_set_attribute (EvWindow* self, const char *attribute)
93 {
94         g_assert (self != NULL && EV_IS_WINDOW (self));
95         g_assert (attribute != NULL);
96
97         if (self->priv->attribute != NULL) {
98                 g_free (self->priv->attribute);
99         }
100
101         self->priv->attribute = g_strdup (attribute);
102
103         g_object_notify (G_OBJECT (self), "attribute");
104 }
105
106 static void
107 ev_window_get_property (GObject *object, guint prop_id, GValue *value,
108                         GParamSpec *param_spec)
109 {
110         EvWindow *self;
111
112         self = EV_WINDOW (object);
113
114         switch (prop_id) {
115         case PROP_ATTRIBUTE:
116                 g_value_set_string (value, self->priv->attribute);
117                 break;
118         default:
119                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object,
120                                                    prop_id,
121                                                    param_spec);
122                 break;
123         }
124 }
125
126 static void
127 ev_window_set_property (GObject *object, guint prop_id, const GValue *value,
128                         GParamSpec *param_spec)
129 {
130         EvWindow *self;
131         
132         self = EV_WINDOW (object);
133         
134         switch (prop_id) {
135         case PROP_ATTRIBUTE:
136                 ev_window_set_attribute (self, g_value_get_string (value));
137                 break;
138         default:
139                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object,
140                                                    prop_id,
141                                                    param_spec);
142                 break;
143         }
144 }
145 #endif
146
147 static void
148 set_action_sensitive (EvWindow   *ev_window,
149                       const char *name,
150                       gboolean    sensitive)
151 {
152         GtkAction *action = gtk_action_group_get_action (ev_window->priv->action_group,
153                                                          name);
154         gtk_action_set_sensitive (action, sensitive);
155 }
156
157 static void
158 update_action_sensitivity (EvWindow *ev_window)
159 {
160         int n_pages;
161         int page;
162
163         if (ev_window->priv->document)
164                 n_pages = ev_document_get_n_pages (ev_window->priv->document);
165         else
166                 n_pages = 1;
167
168         page = ev_view_get_page (EV_VIEW (ev_window->priv->view));
169
170         set_action_sensitive (ev_window, "GoFirstPage", page > 1);
171         set_action_sensitive (ev_window, "GoPreviousPage", page > 1);
172         set_action_sensitive (ev_window, "GoNextPage", page < n_pages);
173         set_action_sensitive (ev_window, "GoLastPage", page < n_pages);
174 }
175
176 gboolean
177 ev_window_is_empty (const EvWindow *ev_window)
178 {
179         g_return_val_if_fail (EV_IS_WINDOW (ev_window), FALSE);
180         
181         return ev_window->priv->document == NULL;
182 }
183
184 static void
185 unable_to_load (EvWindow   *ev_window,
186                 const char *error_message)
187 {
188         GtkWidget *dialog;
189
190         dialog = gtk_message_dialog_new (GTK_WINDOW (ev_window),
191                                          GTK_DIALOG_DESTROY_WITH_PARENT,
192                                          GTK_MESSAGE_ERROR,
193                                          GTK_BUTTONS_CLOSE,
194                                          _("Unable to open document"));
195         gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
196                                                   "%s", error_message);
197         gtk_dialog_run (GTK_DIALOG (dialog));
198         gtk_widget_destroy (dialog);
199 }
200
201 void
202 ev_window_open (EvWindow *ev_window, const char *uri)
203 {
204         EvDocument *document = NULL;
205         char *mime_type;
206
207         mime_type = gnome_vfs_get_mime_type (uri);
208
209         if (!strcmp (mime_type, "application/pdf"))
210                 document = g_object_new (PDF_TYPE_DOCUMENT, NULL);
211
212         if (document) {
213                 GError *error = NULL;
214
215                 if (ev_document_load (document, uri, &error)) {
216                         if (ev_window->priv->document)
217                                 g_object_unref (ev_window->priv->document);
218                         ev_window->priv->document = document;
219
220                         ev_view_set_document (EV_VIEW (ev_window->priv->view),
221                                               document);
222
223                         update_action_sensitivity (ev_window);
224                 
225                 } else {
226                         g_assert (error != NULL);
227                         g_object_unref (document);
228                         unable_to_load (ev_window, error->message);
229                         g_error_free (error);
230                 }
231         } else {
232                 char *error_message;
233
234                 error_message = g_strdup_printf (_("Unhandled MIME type: '%s'"),
235                                                  mime_type);
236                 unable_to_load (ev_window, error_message);
237                 g_free (error_message);
238         }
239
240         g_free (mime_type);
241 }
242
243 static void
244 ev_window_cmd_file_open (GtkAction *action, EvWindow *ev_window)
245 {
246         ev_application_open (EV_APP, NULL);
247 }
248
249 static void
250 ev_window_cmd_file_print (GtkAction *action, EvWindow *ev_window)
251 {
252         g_return_if_fail (EV_IS_WINDOW (ev_window));
253         /* FIXME */
254 }
255
256 static void
257 ev_window_cmd_file_close_window (GtkAction *action, EvWindow *ev_window)
258 {
259         g_return_if_fail (EV_IS_WINDOW (ev_window));
260
261         gtk_widget_destroy (GTK_WIDGET (ev_window));
262 }
263
264 static void
265 ev_window_cmd_edit_find (GtkAction *action, EvWindow *ev_window)
266 {
267         g_return_if_fail (EV_IS_WINDOW (ev_window));
268
269         gtk_widget_show (ev_window->priv->find_bar);
270         egg_find_bar_grab_focus (EGG_FIND_BAR (ev_window->priv->find_bar));
271 }
272
273 static void
274 ev_window_cmd_edit_copy (GtkAction *action, EvWindow *ev_window)
275 {
276         g_return_if_fail (EV_IS_WINDOW (ev_window));
277
278         /* FIXME */
279 }
280
281 static void
282 ev_window_cmd_view_fullscreen (GtkAction *action, EvWindow *ev_window)
283 {
284         g_return_if_fail (EV_IS_WINDOW (ev_window));
285
286         /* FIXME */
287 }
288
289 static void
290 ev_window_cmd_view_zoom_in (GtkAction *action, EvWindow *ev_window)
291 {
292         g_return_if_fail (EV_IS_WINDOW (ev_window));
293
294         ev_view_zoom_in (EV_VIEW (ev_window->priv->view));
295 }
296
297 static void
298 ev_window_cmd_view_zoom_out (GtkAction *action, EvWindow *ev_window)
299 {
300         g_return_if_fail (EV_IS_WINDOW (ev_window));
301
302         ev_view_zoom_out (EV_VIEW (ev_window->priv->view));
303 }
304
305 static void
306 ev_window_cmd_view_normal_size (GtkAction *action, EvWindow *ev_window)
307 {
308         g_return_if_fail (EV_IS_WINDOW (ev_window));
309
310         ev_view_normal_size (EV_VIEW (ev_window->priv->view));
311 }
312
313 static void
314 ev_window_cmd_view_best_fit (GtkAction *action, EvWindow *ev_window)
315 {
316         g_return_if_fail (EV_IS_WINDOW (ev_window));
317
318         ev_view_best_fit (EV_VIEW (ev_window->priv->view));
319 }
320
321 static void
322 ev_window_cmd_view_page_width (GtkAction *action, EvWindow *ev_window)
323 {
324         g_return_if_fail (EV_IS_WINDOW (ev_window));
325
326         ev_view_fit_width (EV_VIEW (ev_window->priv->view));
327 }
328
329 static void
330 ev_window_cmd_go_back (GtkAction *action, EvWindow *ev_window)
331 {
332         g_return_if_fail (EV_IS_WINDOW (ev_window));
333
334         /* FIXME */
335 }
336
337 static void
338 ev_window_cmd_go_forward (GtkAction *action, EvWindow *ev_window)
339 {
340         g_return_if_fail (EV_IS_WINDOW (ev_window));
341
342         /* FIXME */
343 }
344
345 static void
346 ev_window_cmd_go_previous_page (GtkAction *action, EvWindow *ev_window)
347 {
348         g_return_if_fail (EV_IS_WINDOW (ev_window));
349
350         ev_view_set_page (EV_VIEW (ev_window->priv->view),
351                           ev_view_get_page (EV_VIEW (ev_window->priv->view)) - 1);
352 }
353
354 static void
355 ev_window_cmd_go_next_page (GtkAction *action, EvWindow *ev_window)
356 {
357         g_return_if_fail (EV_IS_WINDOW (ev_window));
358
359         ev_view_set_page (EV_VIEW (ev_window->priv->view),
360                           ev_view_get_page (EV_VIEW (ev_window->priv->view)) + 1);
361 }
362
363 static void
364 ev_window_cmd_go_first_page (GtkAction *action, EvWindow *ev_window)
365 {
366         g_return_if_fail (EV_IS_WINDOW (ev_window));
367
368         ev_view_set_page (EV_VIEW (ev_window->priv->view), 1);
369 }
370
371 static void
372 ev_window_cmd_go_last_page (GtkAction *action, EvWindow *ev_window)
373 {
374         g_return_if_fail (EV_IS_WINDOW (ev_window));
375
376         ev_view_set_page (EV_VIEW (ev_window->priv->view), G_MAXINT);
377 }
378
379 static void
380 ev_window_cmd_help_contents (GtkAction *action, EvWindow *ev_window)
381 {
382         g_return_if_fail (EV_IS_WINDOW (ev_window));
383
384         /* FIXME */
385 }
386
387 static void
388 ev_window_cmd_help_about (GtkAction *action, EvWindow *ev_window)
389 {
390         const char *authors[] = {
391                 N_("Many..."),
392                 NULL
393         };
394
395         const char *documenters[] = {
396                 N_("Not so many..."),
397                 NULL
398         };
399
400         const char *license[] = {
401                 N_("Evince is free software; you can redistribute it and/or modify\n"
402                    "it under the terms of the GNU General Public License as published by\n"
403                    "the Free Software Foundation; either version 2 of the License, or\n"
404                    "(at your option) any later version.\n"),            
405                 N_("Evince is distributed in the hope that it will be useful,\n"
406                    "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
407                    "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
408                    "GNU General Public License for more details.\n"),
409                 N_("You should have received a copy of the GNU General Public License\n"
410                    "along with Evince; if not, write to the Free Software Foundation, Inc.,\n"
411                    "59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n")
412         };
413
414         char *license_trans;
415
416 #ifdef ENABLE_NLS
417         const char **p;
418
419         for (p = authors; *p; ++p)
420                 *p = _(*p);
421
422         for (p = documenters; *p; ++p)
423                 *p = _(*p);
424 #endif
425
426         license_trans = g_strconcat (_(license[0]), "\n", _(license[1]), "\n",
427                                      _(license[2]), "\n", NULL);
428
429         gtk_show_about_dialog (
430                 GTK_WINDOW (ev_window),
431                 "name", _("Evince"),
432                 "version", VERSION,
433                 "copyright",
434                 _("\xc2\xa9 1996-2004 The Evince authors"),
435                 "license", license_trans,
436                 "website", "http://www.gnome.org/projects/evince",
437                 "comments", _("PostScript and PDF File Viewer."),
438                 "authors", authors,
439                 "documenters", documenters,
440                 "translator-credits", _("translator-credits"),
441                 NULL);
442
443         g_free (license_trans);
444 }
445
446 static void
447 ev_window_view_toolbar_cb (GtkAction *action, EvWindow *ev_window)
448 {
449         g_object_set (
450                 G_OBJECT (gtk_ui_manager_get_widget (
451                                   ev_window->priv->ui_manager,
452                                   "/ToolBar")),
453                 "visible",
454                 gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)),
455                 NULL);
456 }
457
458 static void
459 ev_window_view_statusbar_cb (GtkAction *action, EvWindow *ev_window)
460 {
461         g_object_set (
462                 ev_window->priv->statusbar,
463                 "visible",
464                 gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)),
465                 NULL);
466 }
467
468 static void
469 ev_window_view_sidebar_cb (GtkAction *action, EvWindow *ev_window)
470 {
471         /* FIXME */
472 }
473
474 static void
475 menu_item_select_cb (GtkMenuItem *proxy, EvWindow *ev_window)
476 {
477         GtkAction *action;
478         char *message;
479
480         action = g_object_get_data (G_OBJECT (proxy), "gtk-action");
481         g_return_if_fail (action != NULL);
482         
483         g_object_get (G_OBJECT (action), "tooltip", &message, NULL);
484         if (message) {
485                 gtk_statusbar_push (GTK_STATUSBAR (ev_window->priv->statusbar),
486                                     ev_window->priv->help_message_cid, message);
487                 g_free (message);
488         }
489 }
490
491 static void
492 menu_item_deselect_cb (GtkMenuItem *proxy, EvWindow *ev_window)
493 {
494         gtk_statusbar_pop (GTK_STATUSBAR (ev_window->priv->statusbar),
495                            ev_window->priv->help_message_cid);
496 }
497
498 static void
499 connect_proxy_cb (GtkUIManager *ui_manager, GtkAction *action,
500                   GtkWidget *proxy, EvWindow *ev_window)
501 {
502         if (GTK_IS_MENU_ITEM (proxy)) {
503                 g_signal_connect (proxy, "select",
504                                   G_CALLBACK (menu_item_select_cb), ev_window);
505                 g_signal_connect (proxy, "deselect",
506                                   G_CALLBACK (menu_item_deselect_cb),
507                                   ev_window);
508         }
509 }
510
511 static void
512 disconnect_proxy_cb (GtkUIManager *ui_manager, GtkAction *action,
513                      GtkWidget *proxy, EvWindow *ev_window)
514 {
515         if (GTK_IS_MENU_ITEM (proxy)) {
516                 g_signal_handlers_disconnect_by_func
517                         (proxy, G_CALLBACK (menu_item_select_cb), ev_window);
518                 g_signal_handlers_disconnect_by_func
519                         (proxy, G_CALLBACK (menu_item_deselect_cb), ev_window);
520         }
521 }
522
523 static void
524 view_page_changed_cb (EvView   *view,
525                       EvWindow *ev_window)
526 {
527         update_action_sensitivity (ev_window);
528 }
529
530 static void
531 find_bar_previous_cb (EggFindBar *find_bar,
532                       EvWindow   *ev_window)
533 {
534         /* FIXME - highlight previous result */
535         g_printerr ("Find Previous\n");
536
537 }
538
539 static void
540 find_bar_next_cb (EggFindBar *find_bar,
541                   EvWindow   *ev_window)
542 {
543         /* FIXME - highlight next result */
544         g_printerr ("Find Next\n");
545 }
546
547 static void
548 find_bar_close_cb (EggFindBar *find_bar,
549                    EvWindow   *ev_window)
550 {
551         gtk_widget_hide (ev_window->priv->find_bar);
552 }
553
554 static void
555 find_bar_search_changed_cb (EggFindBar *find_bar,
556                             GParamSpec *param,
557                             EvWindow   *ev_window)
558 {
559         gboolean case_sensitive;
560         gboolean visible;
561         const char *search_string;
562
563         g_return_if_fail (EV_IS_WINDOW (ev_window));
564         
565         /* Either the string or case sensitivity could have changed,
566          * we connect this callback to both. We also connect it
567          * to ::visible so when the find bar is hidden, we should
568          * pretend the search string is NULL/""
569          */
570
571         case_sensitive = egg_find_bar_get_case_sensitive (find_bar);
572         visible = GTK_WIDGET_VISIBLE (find_bar);
573         search_string = egg_find_bar_get_search_string (find_bar);
574         
575 #if 0
576         g_printerr ("search for '%s'\n", search_string ? search_string : "(nil)");
577 #endif
578
579         /* We don't require begin/end find calls to be matched up, it's really
580          * start_find and cancel_any_find_that_may_not_be_finished
581          */
582         if (visible && search_string) {
583                 ev_document_begin_find (ev_window->priv->document, search_string, case_sensitive);
584         } else {
585                 ev_document_end_find (ev_window->priv->document);
586         }
587 }
588
589 static void
590 ev_window_dispose (GObject *object)
591 {
592         EvWindowPrivate *priv;
593
594         g_return_if_fail (object != NULL && EV_IS_WINDOW (object));
595
596         priv = EV_WINDOW (object)->priv;
597
598         if (priv->ui_manager) {
599                 g_object_unref (priv->ui_manager);
600                 priv->ui_manager = NULL;
601         }
602
603         if (priv->action_group) {
604                 g_object_unref (priv->action_group);
605                 priv->action_group = NULL;
606         }
607         
608         G_OBJECT_CLASS (parent_class)->dispose (object);
609 }
610
611 static void
612 ev_window_class_init (EvWindowClass *ev_window_class)
613 {
614         GObjectClass *g_object_class;
615
616         parent_class = g_type_class_peek_parent (ev_window_class);
617
618         g_object_class = G_OBJECT_CLASS (ev_window_class);
619         g_object_class->dispose = ev_window_dispose;
620
621         g_type_class_add_private (g_object_class, sizeof (EvWindowPrivate));
622
623 #if 0
624         /* setting up signal system */
625         ev_window_class->signal = ev_window_signal;
626
627         ev_window_signals [SIGNAL] = g_signal_new (
628                 "signal",
629                 EV_TYPE_WINDOW,
630                 G_SIGNAL_RUN_LAST,
631                 G_STRUCT_OFFSET (EvWindowClass,
632                                  signal),
633                 NULL,
634                 NULL,
635                 g_cclosure_marshal_VOID__STRING,
636                 G_TYPE_NONE,
637                 0);
638         /* setting up property system */
639         g_object_class->set_property = ev_window_set_property;
640         g_object_class->get_property = ev_window_get_property;
641
642         g_object_class_install_property (
643                 g_object_class,
644                 PROP_ATTRIBUTE,
645                 g_param_spec_string ("attribute",
646                                      "Attribute",
647                                      "A simple unneccessary attribute that "
648                                      "does nothing special except being a "
649                                      "demonstration for the correct implem"
650                                      "entation of a GObject property",
651                                      "default_value",
652                                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
653 #endif
654 }
655
656 /* Normal items */
657 static GtkActionEntry entries[] = {
658         { "File", NULL, N_("_File") },
659         { "Edit", NULL, N_("_Edit") },
660         { "View", NULL, N_("_View") },
661         { "Go", NULL, N_("_Go") },
662         { "Help", NULL, N_("_Help") },
663
664         /* File menu */
665         { "FileOpen", GTK_STOCK_OPEN, N_("_Open"), "<control>O",
666           N_("Open a file"),
667           G_CALLBACK (ev_window_cmd_file_open) },
668         { "FilePrint", GTK_STOCK_PRINT, N_("_Print"), "<control>P",
669           N_("Print this document"),
670           G_CALLBACK (ev_window_cmd_file_print) },
671         { "FileCloseWindow", GTK_STOCK_CLOSE, N_("_Close"), "<control>W",
672           N_("Close this window"),
673           G_CALLBACK (ev_window_cmd_file_close_window) },
674
675         /* Edit menu */
676         { "EditCopy", GTK_STOCK_COPY, N_("_Copy"), "<control>C",
677           N_("Copy text from the document"),
678           G_CALLBACK (ev_window_cmd_edit_copy) },
679         
680         { "EditFind", GTK_STOCK_FIND, N_("_Find"), "<control>F",
681           N_("Find a word or phrase in the document"),
682           G_CALLBACK (ev_window_cmd_edit_find) },
683
684         /* View menu */
685         { "ViewFullscreen", NULL, N_("_Fullscreen"), "F11",
686           N_("Expand the window to fill the screen"),
687           G_CALLBACK (ev_window_cmd_view_fullscreen) },
688         { "ViewZoomIn", GTK_STOCK_ZOOM_IN, N_("Zoom _In"), "<control>plus",
689           N_("Enlarge the document"),
690           G_CALLBACK (ev_window_cmd_view_zoom_in) },
691         { "ViewZoomOut", GTK_STOCK_ZOOM_OUT, N_("Zoom _Out"), "<control>minus",
692           N_("Shrink the document"),
693           G_CALLBACK (ev_window_cmd_view_zoom_out) },
694         { "ViewNormalSize", GTK_STOCK_ZOOM_100, N_("_Normal Size"), "<control>0",
695           N_("Zoom to the normal size"),
696           G_CALLBACK (ev_window_cmd_view_normal_size) },
697         { "ViewBestFit", GTK_STOCK_ZOOM_FIT, N_("_Best Fit"), NULL,
698           N_("Zoom to fit the document to the current window"),
699           G_CALLBACK (ev_window_cmd_view_best_fit) },
700         { "ViewPageWidth", NULL, N_("Fit Page _Width"), NULL,
701           N_("Zoom to fit the width of the current window "),
702           G_CALLBACK (ev_window_cmd_view_page_width) },
703
704         /* Go menu */
705         { "GoBack", GTK_STOCK_GO_BACK, N_("_Back"), "<mod1>Left",
706           N_("Go to the page viewed before this one"),
707           G_CALLBACK (ev_window_cmd_go_back) },
708         { "GoForward", GTK_STOCK_GO_FORWARD, N_("Fo_rward"), "<mod1>Right",
709           N_("Go to the page viewed before this one"),
710           G_CALLBACK (ev_window_cmd_go_forward) },
711         { "GoPreviousPage", GTK_STOCK_GO_BACK, N_("_Previous Page"), "<control>Page_Up",
712           N_("Go to the previous page"),
713           G_CALLBACK (ev_window_cmd_go_previous_page) },
714         { "GoNextPage", GTK_STOCK_GO_FORWARD, N_("_Next Page"), "<control>Page_Down",
715           N_("Go to the next page"),
716           G_CALLBACK (ev_window_cmd_go_next_page) },
717         { "GoFirstPage", GTK_STOCK_GOTO_FIRST, N_("_First Page"), "<control>Home",
718           N_("Go to the first page"),
719           G_CALLBACK (ev_window_cmd_go_first_page) },        
720         { "GoLastPage", GTK_STOCK_GOTO_LAST, N_("_Last Page"), "<control>End",
721           N_("Go to the last page"),
722           G_CALLBACK (ev_window_cmd_go_last_page) },
723         
724         /* Help menu */
725         { "HelpContents", GTK_STOCK_HELP, N_("_Contents"), NULL,
726           N_("Display help for the viewer application"),
727           G_CALLBACK (ev_window_cmd_help_contents) },
728         
729         { "HelpAbout", GTK_STOCK_ABOUT, N_("_About"), NULL,
730           N_("Display credits for the document viewer creators"),
731           G_CALLBACK (ev_window_cmd_help_about) },
732 };
733
734 /* Toggle items */
735 static GtkToggleActionEntry toggle_entries[] = {
736         /* View Menu */
737         { "ViewToolbar", NULL, N_("_Toolbar"), "<shift><control>T",
738           N_("Show or hide toolbar"),
739           G_CALLBACK (ev_window_view_toolbar_cb), TRUE },
740         { "ViewStatusbar", NULL, N_("_Statusbar"), NULL,
741           N_("Show or hide statusbar"),
742           G_CALLBACK (ev_window_view_statusbar_cb), TRUE },
743         { "ViewSidebar", NULL, N_("Side_bar"), "F9",
744           N_("Show or hide sidebar"),
745           G_CALLBACK (ev_window_view_sidebar_cb), FALSE },
746 };
747
748 static void
749 ev_window_init (EvWindow *ev_window)
750 {
751         GtkActionGroup *action_group;
752         GtkAccelGroup *accel_group;
753         GError *error = NULL;
754         GtkWidget *scrolled_window;
755         GtkWidget *menubar;
756         GtkWidget *toolbar;
757         GtkWidget *sidebar_widget;
758
759         ev_window->priv = EV_WINDOW_GET_PRIVATE (ev_window);
760
761         gtk_window_set_title (GTK_WINDOW (ev_window), _("Document Viewer"));
762
763         ev_window->priv->main_box = gtk_vbox_new (FALSE, 0);
764         gtk_container_add (GTK_CONTAINER (ev_window), ev_window->priv->main_box);
765         gtk_widget_show (ev_window->priv->main_box);
766         
767         action_group = gtk_action_group_new ("MenuActions");
768         ev_window->priv->action_group = action_group;
769         gtk_action_group_set_translation_domain (action_group, NULL);
770         gtk_action_group_add_actions (action_group, entries,
771                                       G_N_ELEMENTS (entries), ev_window);
772         gtk_action_group_add_toggle_actions (action_group, toggle_entries,
773                                              G_N_ELEMENTS (toggle_entries),
774                                              ev_window);
775
776         ev_window->priv->ui_manager = gtk_ui_manager_new ();
777         gtk_ui_manager_insert_action_group (ev_window->priv->ui_manager,
778                                             action_group, 0);
779
780         accel_group =
781                 gtk_ui_manager_get_accel_group (ev_window->priv->ui_manager);
782         gtk_window_add_accel_group (GTK_WINDOW (ev_window), accel_group);
783
784         g_signal_connect (ev_window->priv->ui_manager, "connect_proxy",
785                           G_CALLBACK (connect_proxy_cb), ev_window);
786         g_signal_connect (ev_window->priv->ui_manager, "disconnect_proxy",
787                           G_CALLBACK (disconnect_proxy_cb), ev_window);
788
789         if (!gtk_ui_manager_add_ui_from_file (ev_window->priv->ui_manager,
790                                               DATADIR"/evince-ui.xml",
791                                               &error)) {
792                 g_message ("building menus failed: %s", error->message);
793                 g_error_free (error);
794         }
795
796         menubar = gtk_ui_manager_get_widget (ev_window->priv->ui_manager,
797                                              "/MainMenu");
798         gtk_box_pack_start (GTK_BOX (ev_window->priv->main_box), menubar,
799                             FALSE, FALSE, 0);
800
801         toolbar = gtk_ui_manager_get_widget (ev_window->priv->ui_manager,
802                                              "/ToolBar");
803         gtk_box_pack_start (GTK_BOX (ev_window->priv->main_box), toolbar,
804                             FALSE, FALSE, 0);
805
806         /* Add the main area */
807         ev_window->priv->hpaned = gtk_hpaned_new ();
808         gtk_widget_show (ev_window->priv->hpaned);
809         gtk_box_pack_start (GTK_BOX (ev_window->priv->main_box), ev_window->priv->hpaned,
810                             TRUE, TRUE, 0);
811
812         ev_window->priv->sidebar = ev_sidebar_new ();
813         gtk_widget_show (ev_window->priv->sidebar);
814         gtk_paned_add1 (GTK_PANED (ev_window->priv->hpaned),
815                         ev_window->priv->sidebar);
816
817         /* Stub sidebar, for now */
818         sidebar_widget = ev_sidebar_bookmarks_new ();
819         gtk_widget_show (sidebar_widget);
820         ev_sidebar_add_page (EV_SIDEBAR (ev_window->priv->sidebar),
821                              "bookmarks",
822                              _("Bookmarks"),
823                              sidebar_widget);
824
825         sidebar_widget = ev_sidebar_thumbnails_new ();
826         gtk_widget_show (sidebar_widget);
827         ev_sidebar_add_page (EV_SIDEBAR (ev_window->priv->sidebar),
828                              "thumbnails",
829                              _("Thumbnails"),
830                              sidebar_widget);
831         
832         scrolled_window = gtk_scrolled_window_new (NULL, NULL);
833         gtk_widget_show (scrolled_window);
834         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
835                                         GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
836
837         gtk_paned_add2 (GTK_PANED (ev_window->priv->hpaned),
838                         scrolled_window);
839
840         ev_window->priv->view = ev_view_new ();
841         gtk_widget_show (ev_window->priv->view);
842         gtk_container_add (GTK_CONTAINER (scrolled_window),
843                            ev_window->priv->view);
844         g_signal_connect (ev_window->priv->view,
845                           "page-changed",
846                           G_CALLBACK (view_page_changed_cb),
847                           ev_window);
848
849         ev_window->priv->statusbar = gtk_statusbar_new ();
850         gtk_widget_show (ev_window->priv->statusbar);
851         gtk_box_pack_end (GTK_BOX (ev_window->priv->main_box),
852                           ev_window->priv->statusbar,
853                           FALSE, TRUE, 0);
854         ev_window->priv->help_message_cid = gtk_statusbar_get_context_id
855                 (GTK_STATUSBAR (ev_window->priv->statusbar), "help_message");
856
857         ev_window->priv->find_bar = egg_find_bar_new ();
858         gtk_box_pack_end (GTK_BOX (ev_window->priv->main_box),
859                           ev_window->priv->find_bar,
860                           FALSE, TRUE, 0);
861         
862         /* Connect to find bar signals */
863         g_signal_connect (ev_window->priv->find_bar,
864                           "previous",
865                           G_CALLBACK (find_bar_previous_cb),
866                           ev_window);
867         g_signal_connect (ev_window->priv->find_bar,
868                           "next",
869                           G_CALLBACK (find_bar_next_cb),
870                           ev_window);
871         g_signal_connect (ev_window->priv->find_bar,
872                           "close",
873                           G_CALLBACK (find_bar_close_cb),
874                           ev_window);
875         g_signal_connect (ev_window->priv->find_bar,
876                           "notify::search-string",
877                           G_CALLBACK (find_bar_search_changed_cb),
878                           ev_window);
879         g_signal_connect (ev_window->priv->find_bar,
880                           "notify::case-sensitive",
881                           G_CALLBACK (find_bar_search_changed_cb),
882                           ev_window);
883         g_signal_connect (ev_window->priv->find_bar,
884                           "notify::visible",
885                           G_CALLBACK (find_bar_search_changed_cb),
886                           ev_window);
887         
888         update_action_sensitivity (ev_window);
889 }