]> www.fi.muni.cz Git - evince.git/blob - shell/ev-window.c
49b5a9911d90c5ae2c2b8dda8c2f93de45b6998f
[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  *  Copyright (C) 2000, 2001, 2002, 2003, 2004 Marco Pesenti Gritti
7  *  Copyright (C) 2003, 2004, 2005 Christian Persch
8  *
9  *  Author:
10  *    Martin Kretzschmar <martink@gnome.org>
11  *
12  * Evince is free software; you can redistribute it and/or modify it
13  * under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * Evince is distributed in the hope that it will be useful, but
18  * WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include "ev-window.h"
32 #include "ev-page-action.h"
33 #include "ev-sidebar.h"
34 #include "ev-sidebar-links.h"
35 #include "ev-sidebar-thumbnails.h"
36 #include "ev-view.h"
37 #include "ev-page-view.h"
38 #include "ev-password.h"
39 #include "ev-password-view.h"
40 #include "ev-print-job.h"
41 #include "ev-document-find.h"
42 #include "ev-document-security.h"
43 #include "eggfindbar.h"
44
45 #include "pdf-document.h"
46 #include "pixbuf-document.h"
47 #include "ps-document.h"
48
49 #include <glib/gi18n.h>
50 #include <gtk/gtk.h>
51
52 #include <libgnomevfs/gnome-vfs-mime-utils.h>
53 #include <libgnomevfs/gnome-vfs-uri.h>
54 #include <libgnomeprintui/gnome-print-dialog.h>
55
56 #include <gconf/gconf-client.h>
57
58 #include <string.h>
59
60 #include "ev-application.h"
61 #include "ev-stock-icons.h"
62
63 typedef enum {
64         PAGE_MODE_SINGLE_PAGE,
65         PAGE_MODE_CONTINUOUS_PAGE,
66         PAGE_MODE_PASSWORD,
67 } EvWindowPageMode;
68
69 typedef enum {
70         EV_CHROME_MENUBAR       = 1 << 0,
71         EV_CHROME_TOOLBAR       = 1 << 1,
72         EV_CHROME_SIDEBAR       = 1 << 2,
73         EV_CHROME_FINDBAR       = 1 << 3,
74         EV_CHROME_STATUSBAR     = 1 << 4,
75         EV_CHROME_NORMAL        = EV_CHROME_MENUBAR | EV_CHROME_TOOLBAR | EV_CHROME_SIDEBAR | EV_CHROME_STATUSBAR
76 } EvChrome;
77
78 struct _EvWindowPrivate {
79         GtkWidget *main_box;
80         GtkWidget *menubar;
81         GtkWidget *toolbar_dock;
82         GtkWidget *toolbar;
83         GtkWidget *hpaned;
84         GtkWidget *sidebar;
85         GtkWidget *thumbs_sidebar;
86         GtkWidget *find_bar;
87         GtkWidget *scrolled_window;
88         GtkWidget *view;
89         GtkWidget *page_view;
90         GtkWidget *password_view;
91         GtkActionGroup *action_group;
92         GtkUIManager *ui_manager;
93         GtkWidget *statusbar;
94         guint help_message_cid;
95         guint view_message_cid;
96         GtkWidget *exit_fullscreen_popup;
97         GtkWidget *exit_fullscreen_toolbar;
98         char *uri;
99
100         EvDocument *document;
101
102         EvWindowPageMode page_mode;
103         /* These members are used temporarily when in PAGE_MODE_PASSWORD */
104         EvDocument *password_document;
105         GtkWidget *password_dialog;
106         char *password_uri;
107
108         EvChrome chrome;
109         gboolean fullscreen_mode;
110 };
111
112 static GtkTargetEntry ev_drop_types[] = {
113         { "text/uri-list", 0, 0 }
114 };
115
116
117 #define EV_WINDOW_GET_PRIVATE(object) \
118         (G_TYPE_INSTANCE_GET_PRIVATE ((object), EV_TYPE_WINDOW, EvWindowPrivate))
119
120 #define PAGE_SELECTOR_ACTION    "PageSelector"
121
122 #define GCONF_CHROME_TOOLBAR    "/apps/evince/show_toolbar"
123 #define GCONF_CHROME_SIDEBAR    "/apps/evince/show_sidebar"
124 #define GCONF_CHROME_STATUSBAR  "/apps/evince/show_statusbar"
125
126 static void     ev_window_update_fullscreen_popup (EvWindow         *window);
127 static void     ev_window_set_page_mode           (EvWindow         *window,
128                                                    EvWindowPageMode  page_mode);
129 static gboolean start_loading_document            (EvWindow         *ev_window,
130                                                    EvDocument       *document,
131                                                    const char       *uri);
132
133
134 G_DEFINE_TYPE (EvWindow, ev_window, GTK_TYPE_WINDOW)
135
136 static void
137 set_action_sensitive (EvWindow   *ev_window,
138                       const char *name,
139                       gboolean    sensitive)
140 {
141         GtkAction *action = gtk_action_group_get_action (ev_window->priv->action_group,
142                                                          name);
143         gtk_action_set_sensitive (action, sensitive);
144 }
145
146 static void
147 update_action_sensitivity (EvWindow *ev_window)
148 {
149         EvDocument *document;
150         EvWindowPageMode page_mode;
151         EvView *view;
152
153         document = ev_window->priv->document;
154         page_mode = ev_window->priv->page_mode;
155
156         view = EV_VIEW (ev_window->priv->view);
157
158         /* File menu */
159         /* "FileOpen": always sensitive */
160         set_action_sensitive (ev_window, "FileSaveAs", document!=NULL);
161         set_action_sensitive (ev_window, "FilePrint", document!=NULL);
162         /* "FileCloseWindow": always sensitive */
163
164         /* Edit menu */
165         set_action_sensitive (ev_window, "EditCopy", document!=NULL);
166         set_action_sensitive (ev_window, "EditSelectAll", document!=NULL);
167
168         if (document)
169                 set_action_sensitive (ev_window, "EditFind", EV_IS_DOCUMENT_FIND (document));
170         else
171                 set_action_sensitive (ev_window, "EditFind", FALSE);
172
173         /* View menu */
174         set_action_sensitive (ev_window, "ViewZoomIn", document!=NULL);
175         set_action_sensitive (ev_window, "ViewZoomOut", document!=NULL);
176         set_action_sensitive (ev_window, "ViewNormalSize", document!=NULL);
177         set_action_sensitive (ev_window, "ViewBestFit", document!=NULL);
178         set_action_sensitive (ev_window, "ViewPageWidth", document!=NULL);
179
180         /* Go menu */
181         if (document) {
182                 int n_pages;
183                 int page;
184
185                 page = ev_view_get_page (EV_VIEW (ev_window->priv->view));
186                 n_pages = ev_document_get_n_pages (document);
187
188                 set_action_sensitive (ev_window, "GoPreviousPage", page > 1);
189                 set_action_sensitive (ev_window, "GoNextPage", page < n_pages);
190                 set_action_sensitive (ev_window, "GoFirstPage", page > 1);
191                 set_action_sensitive (ev_window, "GoLastPage", page < n_pages);
192         } else {
193                 set_action_sensitive (ev_window, "GoFirstPage", FALSE);
194                 set_action_sensitive (ev_window, "GoPreviousPage", FALSE);
195                 set_action_sensitive (ev_window, "GoNextPage", FALSE);
196                 set_action_sensitive (ev_window, "GoLastPage", FALSE);
197         }
198
199         /* Page View radio group */
200         if (document) {
201                 set_action_sensitive (ev_window, "SinglePage", page_mode != PAGE_MODE_PASSWORD);
202                 set_action_sensitive (ev_window, "ContinuousPage", page_mode != PAGE_MODE_PASSWORD);
203         } else {
204                 set_action_sensitive (ev_window, "SinglePage", FALSE);
205                 set_action_sensitive (ev_window, "ContinuousPage", FALSE);
206         }
207         /* Help menu */
208         /* "HelpContents": always sensitive */
209         /* "HelpAbout": always sensitive */
210
211         /* Toolbar-specific actions: */
212         set_action_sensitive (ev_window, PAGE_SELECTOR_ACTION, document!=NULL);
213 }
214
215 static void
216 update_chrome_visibility (EvWindow *window)
217 {
218         EvWindowPrivate *priv = window->priv;
219         gboolean menubar, toolbar, sidebar, findbar, statusbar;
220
221         menubar = (priv->chrome & EV_CHROME_MENUBAR) != 0 && !priv->fullscreen_mode;
222         toolbar = (priv->chrome & EV_CHROME_TOOLBAR) != 0;
223         sidebar = (priv->chrome & EV_CHROME_SIDEBAR) != 0;
224         findbar = (priv->chrome & EV_CHROME_FINDBAR) != 0;
225         statusbar = (priv->chrome & EV_CHROME_STATUSBAR) != 0 && !priv->fullscreen_mode;
226
227         g_object_set (priv->menubar, "visible", menubar, NULL);
228         g_object_set (priv->toolbar_dock, "visible", toolbar, NULL);
229         g_object_set (priv->sidebar, "visible", sidebar, NULL);
230         g_object_set (priv->find_bar, "visible", findbar, NULL);
231         g_object_set (priv->statusbar, "visible", statusbar, NULL);
232
233         g_object_set (priv->exit_fullscreen_toolbar, "visible", priv->fullscreen_mode, NULL);
234         if (priv->exit_fullscreen_popup != NULL) {
235                 g_object_set (priv->exit_fullscreen_popup, "visible", !toolbar, NULL);
236         }
237 }
238
239 static void
240 update_chrome_flag (EvWindow *window, EvChrome flag, const char *pref, gboolean active)
241 {
242         EvWindowPrivate *priv = window->priv;
243         GConfClient *client;
244         
245         if (active) {
246                 priv->chrome |= flag;
247         }
248         else {
249                 priv->chrome &= ~flag;
250         }
251
252         if (pref != NULL) {
253                 client = gconf_client_get_default ();
254                 gconf_client_set_bool (client, pref, active, NULL);
255                 g_object_unref (client);
256         }
257
258         update_chrome_visibility (window);
259 }
260
261 void
262 ev_window_open_page (EvWindow *ev_window, int page)
263 {
264         ev_view_set_page (EV_VIEW (ev_window->priv->view), page);
265 }
266
267 void
268 ev_window_open_link (EvWindow *ev_window, EvLink *link)
269 {
270         ev_view_go_to_link (EV_VIEW (ev_window->priv->view), link);
271 }
272
273 gboolean
274 ev_window_is_empty (const EvWindow *ev_window)
275 {
276         g_return_val_if_fail (EV_IS_WINDOW (ev_window), FALSE);
277
278         return ev_window->priv->document == NULL;
279 }
280
281 static void
282 unable_to_load (EvWindow   *ev_window,
283                 const char *error_message)
284 {
285         GtkWidget *dialog;
286
287         dialog = gtk_message_dialog_new (GTK_WINDOW (ev_window),
288                                          GTK_DIALOG_DESTROY_WITH_PARENT,
289                                          GTK_MESSAGE_ERROR,
290                                          GTK_BUTTONS_CLOSE,
291                                          _("Unable to open document"));
292         gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
293                                                   "%s", error_message);
294         gtk_dialog_run (GTK_DIALOG (dialog));
295         gtk_widget_destroy (dialog);
296 }
297
298 /* Would be nice to have this in gdk-pixbuf */
299 static gboolean
300 mime_type_supported_by_gdk_pixbuf (const gchar *mime_type)
301 {
302         GSList *formats, *list;
303         gboolean retval = FALSE;
304
305         formats = gdk_pixbuf_get_formats ();
306
307         list = formats;
308         while (list) {
309                 GdkPixbufFormat *format = list->data;
310                 int i;
311                 gchar **mime_types;
312
313                 if (gdk_pixbuf_format_is_disabled (format))
314                         continue;
315
316                 mime_types = gdk_pixbuf_format_get_mime_types (format);
317
318                 for (i = 0; mime_types[i] != NULL; i++) {
319                         if (strcmp (mime_types[i], mime_type) == 0) {
320                                 retval = TRUE;
321                                 break;
322                         }
323                 }
324
325                 if (retval)
326                         break;
327
328                 list = list->next;
329         }
330
331         g_slist_free (formats);
332
333         return retval;
334 }
335
336 static void
337 update_window_title (EvDocument *document, GParamSpec *pspec, EvWindow *ev_window)
338 {
339         char *title = NULL;
340         char *doc_title = NULL;
341         gboolean password_needed;
342
343         password_needed = (ev_window->priv->password_document != NULL);
344
345         if (document) {
346                 doc_title = ev_document_get_title (document);
347
348                 /* Make sure we get a valid title back */
349                 if (doc_title) {
350                         if (doc_title[0] == '\000' ||
351                             !g_utf8_validate (doc_title, -1, NULL)) {
352                                 g_free (doc_title);
353                                 doc_title = NULL;
354                         }
355                 }
356         }
357
358         if (doc_title) {
359                 char *p;
360
361                 for (p = doc_title; *p; ++p) {
362                         /* an '\n' byte is always ASCII, no need for UTF-8 special casing */
363                         if (*p == '\n')
364                                 *p = ' ';
365                 }
366         }
367
368         if (doc_title == NULL && ev_window->priv->uri) {
369                 doc_title = g_path_get_basename (ev_window->priv->uri);
370         }
371
372         if (password_needed) {
373                 if (doc_title == NULL) {
374                         title = g_strdup (_("Document Viewer - Password Required"));
375                 } else {
376                         title = g_strdup_printf (_("%s - Password Required"), doc_title);
377                 }
378         } else {
379                 if (doc_title == NULL) {
380                         title = g_strdup (_("Document Viewer"));
381                 } else {
382                         title = g_strdup (doc_title);
383                 }
384         }
385
386         gtk_window_set_title (GTK_WINDOW (ev_window), title);
387
388         g_free (doc_title);
389         g_free (title);
390 }
391
392 static void
393 update_total_pages (EvWindow *ev_window)
394 {
395         GtkAction *action;
396         int pages;
397
398         pages = ev_document_get_n_pages (ev_window->priv->document);
399         action = gtk_action_group_get_action
400                 (ev_window->priv->action_group, PAGE_SELECTOR_ACTION);
401         ev_page_action_set_total_pages (EV_PAGE_ACTION (action), pages);
402 }
403
404 /* This function assumes that ev_window just had ev_window->document set.
405  */
406 static void
407 ev_window_setup_document (EvWindow *ev_window)
408 {
409         EvDocument *document;
410         EvView *view = EV_VIEW (ev_window->priv->view);
411         //EvPageView *page_view = EV_PAGE_VIEW (ev_window->priv->page_view);
412         EvSidebar *sidebar = EV_SIDEBAR (ev_window->priv->sidebar);
413
414         document = ev_window->priv->document;
415
416         g_signal_connect_object (G_OBJECT (document),
417                                  "notify::title",
418                                  G_CALLBACK (update_window_title),
419                                  ev_window, 0);
420
421         ev_window_set_page_mode (ev_window, PAGE_MODE_SINGLE_PAGE);
422
423         ev_sidebar_set_document (sidebar, document);
424         ev_view_set_document (view, document);
425         //ev_page_view_set_document (page_view, document);
426
427         update_window_title (document, NULL, ev_window);
428         update_total_pages (ev_window);
429         update_action_sensitivity (ev_window);
430 }
431
432 static void
433 password_dialog_response (GtkWidget *password_dialog,
434                           gint       response_id,
435                           EvWindow  *ev_window)
436 {
437         char *password;
438         
439         if (response_id == GTK_RESPONSE_OK) {
440                 EvDocument *document;
441                 gchar *uri;
442
443                 password = ev_password_dialog_get_password (password_dialog);
444                 if (password)
445                         ev_document_security_set_password (EV_DOCUMENT_SECURITY (ev_window->priv->password_document),
446                                                            password);
447                 g_free (password);
448
449                 document = ev_window->priv->password_document;
450                 uri = ev_window->priv->password_uri;
451
452                 ev_window->priv->password_document = NULL;
453                 ev_window->priv->password_uri = NULL;
454
455                 if (start_loading_document (ev_window, document, uri)) {
456                         gtk_widget_destroy (password_dialog);
457                 }
458
459                 g_object_unref (document);
460                 g_free (uri);
461
462                 return;
463         }
464
465         gtk_widget_set_sensitive (ev_window->priv->password_view, TRUE);
466         gtk_widget_destroy (password_dialog);
467 }
468
469 /* Called either by start_loading_document or by the "unlock" callback on the
470  * password_view page.  It assumes that ev_window->priv->password_* has been set
471  * correctly.  These are cleared by password_dialog_response() */
472
473 static void
474 ev_window_popup_password_dialog (EvWindow *ev_window)
475 {
476         g_assert (ev_window->priv->password_document);
477         g_assert (ev_window->priv->password_uri);
478
479         gtk_widget_set_sensitive (ev_window->priv->password_view, FALSE);
480
481         update_window_title (ev_window->priv->password_document, NULL, ev_window);
482         if (ev_window->priv->password_dialog == NULL) {
483                 gchar *file_name;
484
485                 file_name = g_path_get_basename (ev_window->priv->password_uri);
486                 ev_window->priv->password_dialog =
487                         ev_password_dialog_new (GTK_WIDGET (ev_window), file_name);
488                 g_object_add_weak_pointer (G_OBJECT (ev_window->priv->password_dialog),
489                                            (gpointer *) &(ev_window->priv->password_dialog));
490                 g_signal_connect (ev_window->priv->password_dialog,
491                                   "response",
492                                   G_CALLBACK (password_dialog_response),
493                                   ev_window);
494                 g_free (file_name);
495                 gtk_widget_show (ev_window->priv->password_dialog);
496         } else {
497                 ev_password_dialog_set_bad_pass (ev_window->priv->password_dialog);
498         }
499 }
500
501 /* This wil try to load the document.  It might be called multiple times on the
502  * same document by the password dialog.
503  *
504  * Since the flow of the error dialog is very confusing, we assume that both
505  * document and uri will go away after this function is called, and thus we need
506  * to ref/dup them.  Additionally, it needs to clear
507  * ev_window->priv->password_{uri,document}, and thus people who call this
508  * function should _not_ necessarily expect those to exist after being
509  * called. */
510 static gboolean
511 start_loading_document (EvWindow   *ev_window,
512                         EvDocument *document,
513                         const char *uri)
514 {
515         gboolean result;
516         GError *error = NULL;
517
518         g_assert (document);
519         g_assert (document != ev_window->priv->document);
520         g_assert (uri);
521         if (ev_window->priv->password_document) {
522                 g_object_unref (ev_window->priv->password_document);
523                 ev_window->priv->password_document = NULL;
524         }
525         if (ev_window->priv->password_uri) {
526                 g_free (ev_window->priv->password_uri);
527                 ev_window->priv->password_uri = NULL;
528         }
529
530         result = ev_document_load (document, uri, &error);
531
532         /* Success! */
533         if (result) {
534                 if (ev_window->priv->document)
535                         g_object_unref (ev_window->priv->document);
536                 ev_window->priv->document = g_object_ref (document);
537                 ev_window_setup_document (ev_window);
538
539                 return TRUE;
540         }
541
542         /* unable to load the document */
543         g_assert (error != NULL);
544
545         if (error->domain == EV_DOCUMENT_ERROR &&
546             error->code == EV_DOCUMENT_ERROR_ENCRYPTED) {
547                 char *file_name;
548
549                 ev_window->priv->password_document = g_object_ref (document);
550                 ev_window->priv->password_uri = g_strdup (uri);
551
552                 file_name = g_path_get_basename (uri);
553                 ev_password_view_set_file_name (EV_PASSWORD_VIEW (ev_window->priv->password_view),
554                                                 file_name);
555                 g_free (file_name);
556                 ev_window_set_page_mode (ev_window, PAGE_MODE_PASSWORD);
557
558                 ev_window_popup_password_dialog (ev_window);
559         } else {
560                 unable_to_load (ev_window, error->message);
561         }
562         g_error_free (error);
563
564         return FALSE;
565 }
566
567 static gboolean
568 is_file_supported (const gchar *mime_type)
569 {
570         static char *supported_types [] = {
571                 "application/pdf",
572                 "application/postscript",
573                 "application/x-gzpostscript",
574                 "image/x-eps",
575                 NULL
576         };
577         gint   i;
578         
579         g_return_val_if_fail (mime_type != NULL, FALSE);
580
581         if (mime_type_supported_by_gdk_pixbuf (mime_type))
582                 return TRUE;
583         
584         for (i = 0; supported_types[i] != NULL; i++) {
585                 if (g_ascii_strcasecmp (mime_type, supported_types[i]) == 0)
586                         return TRUE;
587         }
588         
589         return FALSE;
590 }
591
592 void
593 ev_window_open (EvWindow *ev_window, const char *uri)
594 {
595         EvDocument *document = NULL;
596         char *mime_type;
597
598         g_free (ev_window->priv->uri);
599         ev_window->priv->uri = g_strdup (uri);
600
601         mime_type = gnome_vfs_get_mime_type (uri);
602
603         if (mime_type == NULL)
604                 document = NULL;
605         else if (!strcmp (mime_type, "application/pdf"))
606                 document = g_object_new (PDF_TYPE_DOCUMENT, NULL);
607         else if (!strcmp (mime_type, "application/postscript") ||
608                  !strcmp (mime_type, "application/x-gzpostscript") ||
609                  !strcmp (mime_type, "image/x-eps"))
610                 document = g_object_new (PS_TYPE_DOCUMENT, NULL);
611         else if (mime_type_supported_by_gdk_pixbuf (mime_type))
612                 document = g_object_new (PIXBUF_TYPE_DOCUMENT, NULL);
613
614         if (document) {
615                 start_loading_document (ev_window, document, uri);
616                 /* See the comment on start_loading_document on ref counting.
617                  * As the password dialog flow is confusing, we're very explicit
618                  * on ref counting. */
619                 g_object_unref (document);
620         } else {
621                 char *error_message;
622
623                 error_message = g_strdup_printf (_("Unhandled MIME type: '%s'"),
624                                                  mime_type?mime_type:"<Unknown MIME Type>");
625                 unable_to_load (ev_window, error_message);
626                 g_free (error_message);
627         }
628
629         g_free (mime_type);
630 }
631
632 static void
633 ev_window_open_uri_list (EvWindow *ev_window, GList *uri_list)
634 {
635         GList *list;
636         gchar *uri, *mime_type;
637         
638         g_return_if_fail (uri_list != NULL);
639         
640         list = uri_list;
641         while (list) {
642                 uri = gnome_vfs_uri_to_string (list->data, GNOME_VFS_URI_HIDE_NONE);
643                 mime_type = gnome_vfs_get_mime_type (uri);
644                 
645                 if (is_file_supported (mime_type)) {
646                         if (ev_window_is_empty (EV_WINDOW (ev_window))) {
647                                 ev_window_open (ev_window, uri);
648                                 
649                                 gtk_widget_show (GTK_WIDGET (ev_window));
650                         } else {
651                                 EvWindow *new_window;
652                                 
653                                 new_window = ev_application_new_window (EV_APP);
654                                 ev_window_open (new_window, uri);
655                                 
656                                 gtk_widget_show (GTK_WIDGET (new_window));
657                         }
658                 }
659
660                 g_free (mime_type);
661                 g_free (uri);
662
663                 list = g_list_next (list);
664         }
665 }
666
667 static void
668 ev_window_cmd_file_open (GtkAction *action, EvWindow *ev_window)
669 {
670         ev_application_open (EV_APP, NULL);
671 }
672
673 /* FIXME
674 static gboolean
675 overwrite_existing_file (GtkWindow *window, const gchar *file_name)
676 {
677         GtkWidget *msgbox;
678         gchar *utf8_file_name;
679         AtkObject *obj;
680         gint ret;
681
682         utf8_file_name = g_filename_to_utf8 (file_name, -1, NULL, NULL, NULL);
683         msgbox = gtk_message_dialog_new (
684                 window,
685                 (GtkDialogFlags)GTK_DIALOG_DESTROY_WITH_PARENT,
686                 GTK_MESSAGE_QUESTION,
687                 GTK_BUTTONS_NONE,
688                 _("A file named \"%s\" already exists."),
689                 utf8_file_name);
690         g_free (utf8_file_name);
691
692         gtk_message_dialog_format_secondary_text (
693                 GTK_MESSAGE_DIALOG (msgbox),
694                 _("Do you want to replace it with the one you are saving?"));
695
696         gtk_dialog_add_button (GTK_DIALOG (msgbox),
697                                GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
698
699         gtk_dialog_add_button (GTK_DIALOG (msgbox),
700                                _("_Replace"), GTK_RESPONSE_YES);
701
702         gtk_dialog_set_default_response (GTK_DIALOG (msgbox),
703                                          GTK_RESPONSE_CANCEL);
704
705         obj = gtk_widget_get_accessible (msgbox);
706
707         if (GTK_IS_ACCESSIBLE (obj))
708                 atk_object_set_name (obj, _("Question"));
709
710         ret = gtk_dialog_run (GTK_DIALOG (msgbox));
711         gtk_widget_destroy (msgbox);
712
713         return (ret == GTK_RESPONSE_YES);
714 }
715 */
716
717 static void
718 save_error_dialog (GtkWindow *window, const gchar *file_name)
719 {
720         GtkWidget *error_dialog;
721
722         error_dialog = gtk_message_dialog_new (
723                 window,
724                 (GtkDialogFlags)GTK_DIALOG_DESTROY_WITH_PARENT,
725                 GTK_MESSAGE_ERROR,
726                 GTK_BUTTONS_CLOSE,
727                 _("The file could not be saved as \"%s\"."),
728                 file_name);
729
730         /* Easy way to make the text bold while keeping the string
731          * above free from pango markup (FIXME ?) */
732         gtk_message_dialog_format_secondary_text (
733                 GTK_MESSAGE_DIALOG (error_dialog), " ");
734
735         gtk_dialog_run (GTK_DIALOG (error_dialog));
736         gtk_widget_destroy (error_dialog);
737 }
738
739 static void
740 ev_window_cmd_save_as (GtkAction *action, EvWindow *ev_window)
741 {
742         GtkWidget *fc;
743         GtkFileFilter *pdf_filter, *all_filter;
744         gchar *uri = NULL;
745
746         fc = gtk_file_chooser_dialog_new (
747                 _("Save a Copy"),
748                 NULL, GTK_FILE_CHOOSER_ACTION_SAVE,
749                 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
750                 GTK_STOCK_SAVE, GTK_RESPONSE_OK,
751                 NULL);
752         gtk_window_set_modal (GTK_WINDOW (fc), TRUE);
753
754         pdf_filter = gtk_file_filter_new ();
755         gtk_file_filter_set_name (pdf_filter, _("PDF Documents"));
756         gtk_file_filter_add_mime_type (pdf_filter, "application/pdf");
757         gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fc), pdf_filter);
758
759         all_filter = gtk_file_filter_new ();
760         gtk_file_filter_set_name (all_filter, _("All Files"));
761         gtk_file_filter_add_pattern (all_filter, "*");
762         gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fc), all_filter);
763         gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (fc), pdf_filter);
764
765         gtk_dialog_set_default_response (GTK_DIALOG (fc), GTK_RESPONSE_OK);
766
767         gtk_widget_show (fc);
768
769         while (gtk_dialog_run (GTK_DIALOG (fc)) == GTK_RESPONSE_OK) {
770                 uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (fc));
771
772 /* FIXME
773                 if (g_file_test (uri, G_FILE_TEST_EXISTS) &&
774                     !overwrite_existing_file (GTK_WINDOW (fc), uri))
775                                 continue;
776 */
777
778                 if (ev_document_save (ev_window->priv->document, uri, NULL))
779                         break;
780                 else
781                         save_error_dialog (GTK_WINDOW (fc), uri);
782         }
783         gtk_widget_destroy (fc);
784 }
785
786 static gboolean
787 using_postscript_printer (GnomePrintConfig *config)
788 {
789         const guchar *driver;
790         const guchar *transport;
791
792         driver = gnome_print_config_get (
793                 config, (const guchar *)"Settings.Engine.Backend.Driver");
794
795         transport = gnome_print_config_get (
796                 config, (const guchar *)"Settings.Transport.Backend");
797
798         if (driver) {
799                 if (!strcmp ((const gchar *)driver, "gnome-print-ps"))
800                         return TRUE;
801                 else
802                         return FALSE;
803         } else  if (transport) {
804                 if (!strcmp ((const gchar *)transport, "CUPS"))
805                         return TRUE;
806         }
807
808         return FALSE;
809 }
810
811 static void
812 ev_window_print (EvWindow *ev_window)
813 {
814         GnomePrintConfig *config;
815         GnomePrintJob *job;
816         GtkWidget *print_dialog;
817         EvPrintJob *print_job = NULL;
818
819         g_return_if_fail (EV_IS_WINDOW (ev_window));
820         g_return_if_fail (ev_window->priv->document != NULL);
821
822         config = gnome_print_config_default ();
823         job = gnome_print_job_new (config);
824
825         print_dialog = gnome_print_dialog_new (job, _("Print"),
826                                                (GNOME_PRINT_DIALOG_RANGE |
827                                                 GNOME_PRINT_DIALOG_COPIES));
828         gtk_dialog_set_response_sensitive (GTK_DIALOG (print_dialog),
829                                            GNOME_PRINT_DIALOG_RESPONSE_PREVIEW,
830                                            FALSE);
831
832         while (TRUE) {
833                 int response;
834                 response = gtk_dialog_run (GTK_DIALOG (print_dialog));
835
836                 if (response != GNOME_PRINT_DIALOG_RESPONSE_PRINT)
837                         break;
838
839                 /* FIXME: Change this when we have the first backend
840                  * that can print more than postscript
841                  */
842                 if (!using_postscript_printer (config)) {
843                         GtkWidget *dialog;
844
845                         dialog = gtk_message_dialog_new (
846                                 GTK_WINDOW (print_dialog), GTK_DIALOG_MODAL,
847                                 GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
848                                 _("Printing is not supported on this printer."));
849                         gtk_message_dialog_format_secondary_text (
850                                 GTK_MESSAGE_DIALOG (dialog),
851                                 _("You were trying to print to a printer using the \"%s\" driver. This program requires a PostScript printer driver."),
852                                 gnome_print_config_get (
853                                         config, "Settings.Engine.Backend.Driver"));
854                         gtk_dialog_run (GTK_DIALOG (dialog));
855                         gtk_widget_destroy (dialog);
856
857                         continue;
858                 }
859
860                 print_job = g_object_new (EV_TYPE_PRINT_JOB,
861                                           "gnome_print_job", job,
862                                           "document", ev_window->priv->document,
863                                           "print_dialog", print_dialog,
864                                           NULL);
865                 break;
866         }
867
868         gtk_widget_destroy (print_dialog);
869
870         if (print_job != NULL) {
871                 ev_print_job_print (print_job, GTK_WINDOW (ev_window));
872                 g_object_unref (print_job);
873         }
874 }
875
876 static void
877 ev_window_cmd_file_print (GtkAction *action, EvWindow *ev_window)
878 {
879         ev_window_print (ev_window);
880 }
881
882 static void
883 ev_window_cmd_file_close_window (GtkAction *action, EvWindow *ev_window)
884 {
885         g_return_if_fail (EV_IS_WINDOW (ev_window));
886
887         gtk_widget_destroy (GTK_WIDGET (ev_window));
888 }
889
890 static void
891 find_not_supported_dialog (EvWindow   *ev_window)
892 {
893         GtkWidget *dialog;
894
895         /* If you change this so it isn't modal, be sure you don't
896          * allow multiple copies of the dialog...
897          */
898
899         dialog = gtk_message_dialog_new (GTK_WINDOW (ev_window),
900                                          GTK_DIALOG_DESTROY_WITH_PARENT,
901                                          GTK_MESSAGE_ERROR,
902                                          GTK_BUTTONS_CLOSE,
903                                          _("The \"Find\" feature will not work with this document"));
904         gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
905                                                   _("Searching for text is only supported for PDF documents."));
906         gtk_dialog_run (GTK_DIALOG (dialog));
907         gtk_widget_destroy (dialog);
908 }
909
910 static void
911 ev_window_cmd_edit_select_all (GtkAction *action, EvWindow *ev_window)
912 {
913         g_return_if_fail (EV_IS_WINDOW (ev_window));
914
915         ev_view_select_all (EV_VIEW (ev_window->priv->view));
916 }
917
918 static void
919 ev_window_cmd_edit_find (GtkAction *action, EvWindow *ev_window)
920 {
921         g_return_if_fail (EV_IS_WINDOW (ev_window));
922
923         if (ev_window->priv->document == NULL) {
924                 g_printerr ("We should have set the Find menu item insensitive since there's no document\n");
925         } else if (!EV_IS_DOCUMENT_FIND (ev_window->priv->document)) {
926                 find_not_supported_dialog (ev_window);
927         } else {
928                 update_chrome_flag (ev_window, EV_CHROME_FINDBAR, NULL, TRUE);
929
930                 egg_find_bar_grab_focus (EGG_FIND_BAR (ev_window->priv->find_bar));
931         }
932 }
933
934 static void
935 ev_window_cmd_edit_copy (GtkAction *action, EvWindow *ev_window)
936 {
937         g_return_if_fail (EV_IS_WINDOW (ev_window));
938
939         ev_view_copy (EV_VIEW (ev_window->priv->view));
940 }
941
942 static void
943 ev_window_update_fullscreen_popup (EvWindow *window)
944 {
945         GtkWidget *popup = window->priv->exit_fullscreen_popup;
946         int popup_width, popup_height;
947         GdkRectangle screen_rect;
948
949         g_return_if_fail (popup != NULL);
950
951         popup_width = popup->requisition.width;
952         popup_height = popup->requisition.height;
953
954         /* FIXME multihead */
955         gdk_screen_get_monitor_geometry (gdk_screen_get_default (),
956                         gdk_screen_get_monitor_at_window
957                         (gdk_screen_get_default (),
958                          GTK_WIDGET (window)->window),
959                          &screen_rect);
960
961         if (gtk_widget_get_direction (popup) == GTK_TEXT_DIR_RTL)
962         {
963                 gtk_window_move (GTK_WINDOW (popup),
964                                  screen_rect.x,
965                                  screen_rect.y);
966         }
967         else
968         {
969                 gtk_window_move (GTK_WINDOW (popup),
970                                  screen_rect.x + screen_rect.width - popup_width,
971                                  screen_rect.y);
972         }
973 }
974
975 static void
976 screen_size_changed_cb (GdkScreen *screen,
977                         EvWindow *window)
978 {
979         ev_window_update_fullscreen_popup (window);
980 }
981
982 static void
983 destroy_exit_fullscreen_popup (EvWindow *window)
984 {
985         if (window->priv->exit_fullscreen_popup != NULL)
986         {
987                 /* FIXME multihead */
988                 g_signal_handlers_disconnect_by_func
989                         (gdk_screen_get_default (),
990                          G_CALLBACK (screen_size_changed_cb), window);
991
992                 gtk_widget_destroy (window->priv->exit_fullscreen_popup);
993                 window->priv->exit_fullscreen_popup = NULL;
994         }
995 }
996
997 static void
998 exit_fullscreen_button_clicked_cb (GtkWidget *button, EvWindow *window)
999 {
1000         GtkAction *action;
1001
1002         action = gtk_action_group_get_action (window->priv->action_group, "ViewFullscreen");
1003         g_return_if_fail (action != NULL);
1004
1005         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), FALSE);
1006 }
1007
1008 static void
1009 fullscreen_popup_size_request_cb (GtkWidget *popup, GtkRequisition *req, EvWindow *window)
1010 {
1011         ev_window_update_fullscreen_popup (window);
1012 }
1013
1014 static void
1015 ev_window_fullscreen (EvWindow *window)
1016 {
1017         GtkWidget *popup, *button, *icon, *label, *hbox;
1018
1019         window->priv->fullscreen_mode = TRUE;
1020
1021         g_return_if_fail (window->priv->exit_fullscreen_popup == NULL);
1022
1023         popup = gtk_window_new (GTK_WINDOW_POPUP);
1024         window->priv->exit_fullscreen_popup = popup;
1025
1026         button = gtk_button_new ();
1027         g_signal_connect (button, "clicked",
1028                           G_CALLBACK (exit_fullscreen_button_clicked_cb),
1029                           window);
1030         gtk_widget_show (button);
1031         gtk_container_add (GTK_CONTAINER (popup), button);
1032
1033         hbox = gtk_hbox_new (FALSE, 2);
1034         gtk_widget_show (hbox);
1035         gtk_container_add (GTK_CONTAINER (button), hbox);
1036
1037         icon = gtk_image_new_from_stock (EV_STOCK_LEAVE_FULLSCREEN, GTK_ICON_SIZE_BUTTON);
1038         gtk_widget_show (icon);
1039         gtk_box_pack_start (GTK_BOX (hbox), icon, FALSE, FALSE, 0);
1040
1041         label = gtk_label_new (_("Leave Fullscreen"));
1042         gtk_widget_show (label);
1043         gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
1044
1045         gtk_window_set_resizable (GTK_WINDOW (popup), FALSE);
1046
1047         /* FIXME multihead */
1048         g_signal_connect (gdk_screen_get_default (), "size-changed",
1049                           G_CALLBACK (screen_size_changed_cb), window);
1050         g_signal_connect (popup, "size_request",
1051                           G_CALLBACK (fullscreen_popup_size_request_cb), window);
1052
1053         update_chrome_visibility (window);
1054
1055         ev_window_update_fullscreen_popup (window);
1056 }
1057
1058 static void
1059 ev_window_unfullscreen (EvWindow *window)
1060 {
1061         window->priv->fullscreen_mode = FALSE;
1062
1063         destroy_exit_fullscreen_popup (window);
1064
1065         update_chrome_visibility (window);
1066 }
1067
1068 static void
1069 ev_window_cmd_view_fullscreen (GtkAction *action, EvWindow *ev_window)
1070 {
1071         gboolean fullscreen;
1072
1073         g_return_if_fail (EV_IS_WINDOW (ev_window));
1074
1075         fullscreen = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1076
1077         if (fullscreen) {
1078                 gtk_window_fullscreen (GTK_WINDOW (ev_window));
1079         } else {
1080                 gtk_window_unfullscreen (GTK_WINDOW (ev_window));
1081         }
1082 }
1083
1084 static gboolean
1085 ev_window_state_event_cb (GtkWidget *widget, GdkEventWindowState *event, EvWindow *window)
1086 {
1087         if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN)
1088         {
1089                 GtkActionGroup *action_group;
1090                 GtkAction *action;
1091                 gboolean fullscreen;
1092
1093                 fullscreen = event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN;
1094
1095                 if (fullscreen)
1096                 {
1097                         ev_window_fullscreen (window);
1098                 }
1099                 else
1100                 {
1101                         ev_window_unfullscreen (window);
1102                 }
1103
1104                 action_group = window->priv->action_group;
1105
1106                 action = gtk_action_group_get_action (action_group, "ViewFullscreen");
1107                 g_signal_handlers_block_by_func
1108                         (action, G_CALLBACK (ev_window_cmd_view_fullscreen), window);
1109                 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), fullscreen);
1110                 g_signal_handlers_unblock_by_func
1111                         (action, G_CALLBACK (ev_window_cmd_view_fullscreen), window);
1112
1113         }
1114
1115         return FALSE;
1116 }
1117
1118 static gboolean
1119 ev_window_focus_in_event (GtkWidget *widget, GdkEventFocus *event)
1120 {
1121         EvWindow *window = EV_WINDOW (widget);
1122         EvWindowPrivate *priv = window->priv;
1123
1124         if (priv->exit_fullscreen_popup != NULL &&
1125             (priv->chrome & EV_CHROME_TOOLBAR) == 0)
1126         {
1127                 gtk_widget_show (priv->exit_fullscreen_popup);
1128         }
1129
1130         return GTK_WIDGET_CLASS (ev_window_parent_class)->focus_in_event (widget, event);
1131 }
1132
1133 static gboolean
1134 ev_window_focus_out_event (GtkWidget *widget, GdkEventFocus *event)
1135 {
1136         EvWindow *window = EV_WINDOW (widget);
1137         EvWindowPrivate *priv = window->priv;
1138
1139         if (priv->exit_fullscreen_popup != NULL &&
1140             (priv->chrome & EV_CHROME_TOOLBAR) == 0)
1141         {
1142                 gtk_widget_hide (priv->exit_fullscreen_popup);
1143         }
1144
1145         return GTK_WIDGET_CLASS (ev_window_parent_class)->focus_out_event (widget, event);
1146 }
1147
1148 static void
1149 ev_window_set_page_mode (EvWindow         *window,
1150                          EvWindowPageMode  page_mode)
1151 {
1152         GtkWidget *child = NULL;
1153         GtkWidget *real_child;
1154
1155         if (window->priv->page_mode == page_mode)
1156                 return;
1157
1158         window->priv->page_mode = page_mode;
1159
1160         switch (page_mode) {
1161         case PAGE_MODE_SINGLE_PAGE:
1162                 child = window->priv->view;
1163                 break;
1164         case PAGE_MODE_PASSWORD:
1165                 child = window->priv->password_view;
1166                 break;
1167         case PAGE_MODE_CONTINUOUS_PAGE:
1168                 child = window->priv->page_view;
1169                 break;
1170         default:
1171                 g_assert_not_reached ();
1172         }
1173
1174         real_child = gtk_bin_get_child (GTK_BIN (window->priv->scrolled_window));
1175         if (child != real_child) {
1176                 gtk_container_remove (GTK_CONTAINER (window->priv->scrolled_window),
1177                                       real_child);
1178                 gtk_container_add (GTK_CONTAINER (window->priv->scrolled_window),
1179                                    child);
1180         }
1181         update_action_sensitivity (window);
1182 }
1183
1184 static void
1185 ev_window_cmd_view_zoom_in (GtkAction *action, EvWindow *ev_window)
1186 {
1187         g_return_if_fail (EV_IS_WINDOW (ev_window));
1188
1189         ev_view_zoom_in (EV_VIEW (ev_window->priv->view));
1190 }
1191
1192 static void
1193 ev_window_cmd_view_zoom_out (GtkAction *action, EvWindow *ev_window)
1194 {
1195         g_return_if_fail (EV_IS_WINDOW (ev_window));
1196
1197         ev_view_zoom_out (EV_VIEW (ev_window->priv->view));
1198 }
1199
1200 static void
1201 ev_window_cmd_view_normal_size (GtkAction *action, EvWindow *ev_window)
1202 {
1203         g_return_if_fail (EV_IS_WINDOW (ev_window));
1204
1205         ev_view_normal_size (EV_VIEW (ev_window->priv->view));
1206 }
1207
1208 static void
1209 ev_window_cmd_view_best_fit (GtkAction *action, EvWindow *ev_window)
1210 {
1211         EvWindowPrivate *priv = ev_window->priv;
1212         int width, height;
1213
1214         g_return_if_fail (EV_IS_WINDOW (ev_window));
1215
1216         width = priv->scrolled_window->allocation.width;
1217         height = priv->scrolled_window->allocation.height;
1218
1219         /* the scrolled window has a GTK_SHADOW_IN */
1220         width -= 2 * priv->view->style->xthickness;
1221         height -= 2 * priv->view->style->ythickness;
1222
1223         ev_view_best_fit (EV_VIEW (priv->view),
1224                           MAX (1, width), MAX (1, height));
1225 }
1226
1227 static void
1228 ev_window_cmd_view_page_width (GtkAction *action, EvWindow *ev_window)
1229 {
1230         EvWindowPrivate *priv = ev_window->priv;
1231         int width, height;
1232         GtkRequisition vsb_requisition;
1233         int scrollbar_spacing;
1234
1235         g_return_if_fail (EV_IS_WINDOW (ev_window));
1236
1237         width = priv->scrolled_window->allocation.width;
1238         height = priv->scrolled_window->allocation.height;
1239
1240         /* the scrolled window has a GTK_SHADOW_IN */
1241         width -= 2 * priv->view->style->xthickness;
1242         height -= 2 * priv->view->style->ythickness;
1243
1244         gtk_widget_size_request (
1245                 GTK_SCROLLED_WINDOW (priv->scrolled_window)->vscrollbar,
1246                 &vsb_requisition);
1247         gtk_widget_style_get (priv->scrolled_window,
1248                               "scrollbar_spacing", &scrollbar_spacing,
1249                               NULL);
1250
1251         ev_view_fit_width (EV_VIEW (ev_window->priv->view),
1252                            width, height,
1253                            vsb_requisition.width + scrollbar_spacing);
1254 }
1255
1256 static void
1257 ev_window_cmd_go_previous_page (GtkAction *action, EvWindow *ev_window)
1258 {
1259         g_return_if_fail (EV_IS_WINDOW (ev_window));
1260
1261         ev_view_set_page (EV_VIEW (ev_window->priv->view),
1262                           ev_view_get_page (EV_VIEW (ev_window->priv->view)) - 1);
1263 }
1264
1265 static void
1266 ev_window_cmd_go_next_page (GtkAction *action, EvWindow *ev_window)
1267 {
1268         g_return_if_fail (EV_IS_WINDOW (ev_window));
1269
1270         ev_view_set_page (EV_VIEW (ev_window->priv->view),
1271                           ev_view_get_page (EV_VIEW (ev_window->priv->view)) + 1);
1272 }
1273
1274 static void
1275 ev_window_cmd_go_first_page (GtkAction *action, EvWindow *ev_window)
1276 {
1277         g_return_if_fail (EV_IS_WINDOW (ev_window));
1278
1279         ev_view_set_page (EV_VIEW (ev_window->priv->view), 1);
1280 }
1281
1282 static void
1283 ev_window_cmd_go_last_page (GtkAction *action, EvWindow *ev_window)
1284 {
1285         g_return_if_fail (EV_IS_WINDOW (ev_window));
1286
1287         ev_view_set_page (EV_VIEW (ev_window->priv->view), G_MAXINT);
1288 }
1289
1290 static void
1291 ev_window_cmd_help_contents (GtkAction *action, EvWindow *ev_window)
1292 {
1293         g_return_if_fail (EV_IS_WINDOW (ev_window));
1294
1295         /* FIXME */
1296 }
1297
1298 static void
1299 ev_window_cmd_leave_fullscreen (GtkAction *action, EvWindow *window)
1300 {
1301         gtk_window_unfullscreen (GTK_WINDOW (window));
1302 }
1303
1304 static void
1305 ev_window_cmd_help_about (GtkAction *action, EvWindow *ev_window)
1306 {
1307         const char *authors[] = {
1308                 N_("Many..."),
1309                 NULL
1310         };
1311
1312         const char *documenters[] = {
1313                 N_("Not so many..."),
1314                 NULL
1315         };
1316
1317         const char *license[] = {
1318                 N_("Evince is free software; you can redistribute it and/or modify\n"
1319                    "it under the terms of the GNU General Public License as published by\n"
1320                    "the Free Software Foundation; either version 2 of the License, or\n"
1321                    "(at your option) any later version.\n"),
1322                 N_("Evince is distributed in the hope that it will be useful,\n"
1323                    "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
1324                    "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
1325                    "GNU General Public License for more details.\n"),
1326                 N_("You should have received a copy of the GNU General Public License\n"
1327                    "along with Evince; if not, write to the Free Software Foundation, Inc.,\n"
1328                    "59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n")
1329         };
1330
1331         char *license_trans;
1332
1333 #ifdef ENABLE_NLS
1334         const char **p;
1335
1336         for (p = authors; *p; ++p)
1337                 *p = _(*p);
1338
1339         for (p = documenters; *p; ++p)
1340                 *p = _(*p);
1341 #endif
1342
1343         license_trans = g_strconcat (_(license[0]), "\n", _(license[1]), "\n",
1344                                      _(license[2]), "\n", NULL);
1345
1346         gtk_show_about_dialog (
1347                 GTK_WINDOW (ev_window),
1348                 "name", _("Evince"),
1349                 "version", VERSION,
1350                 "copyright",
1351                 _("\xc2\xa9 1996-2004 The Evince authors"),
1352                 "license", license_trans,
1353                 "website", "http://www.gnome.org/projects/evince",
1354                 "comments", _("PostScript and PDF File Viewer."),
1355                 "authors", authors,
1356                 "documenters", documenters,
1357                 "translator-credits", _("translator-credits"),
1358                 NULL);
1359
1360         g_free (license_trans);
1361 }
1362
1363 static void
1364 ev_window_view_toolbar_cb (GtkAction *action, EvWindow *ev_window)
1365 {
1366         update_chrome_flag (ev_window, EV_CHROME_TOOLBAR,
1367                             GCONF_CHROME_TOOLBAR,
1368                             gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
1369 }
1370
1371 static void
1372 ev_window_view_statusbar_cb (GtkAction *action, EvWindow *ev_window)
1373 {
1374         update_chrome_flag (ev_window, EV_CHROME_STATUSBAR,
1375                             GCONF_CHROME_STATUSBAR,
1376                             gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
1377 }
1378
1379 static void
1380 ev_window_view_sidebar_cb (GtkAction *action, EvWindow *ev_window)
1381 {
1382         update_chrome_flag (ev_window, EV_CHROME_SIDEBAR,
1383                             GCONF_CHROME_SIDEBAR,
1384                             gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
1385 }
1386
1387 static void
1388 menu_item_select_cb (GtkMenuItem *proxy, EvWindow *ev_window)
1389 {
1390         GtkAction *action;
1391         char *message;
1392
1393         action = g_object_get_data (G_OBJECT (proxy), "gtk-action");
1394         g_return_if_fail (action != NULL);
1395
1396         g_object_get (G_OBJECT (action), "tooltip", &message, NULL);
1397         if (message) {
1398                 gtk_statusbar_push (GTK_STATUSBAR (ev_window->priv->statusbar),
1399                                     ev_window->priv->help_message_cid, message);
1400                 g_free (message);
1401         }
1402 }
1403
1404 static void
1405 menu_item_deselect_cb (GtkMenuItem *proxy, EvWindow *ev_window)
1406 {
1407         gtk_statusbar_pop (GTK_STATUSBAR (ev_window->priv->statusbar),
1408                            ev_window->priv->help_message_cid);
1409 }
1410
1411 static void
1412 connect_proxy_cb (GtkUIManager *ui_manager, GtkAction *action,
1413                   GtkWidget *proxy, EvWindow *ev_window)
1414 {
1415         if (GTK_IS_MENU_ITEM (proxy)) {
1416                 g_signal_connect (proxy, "select",
1417                                   G_CALLBACK (menu_item_select_cb), ev_window);
1418                 g_signal_connect (proxy, "deselect",
1419                                   G_CALLBACK (menu_item_deselect_cb),
1420                                   ev_window);
1421         }
1422 }
1423
1424 static void
1425 disconnect_proxy_cb (GtkUIManager *ui_manager, GtkAction *action,
1426                      GtkWidget *proxy, EvWindow *ev_window)
1427 {
1428         if (GTK_IS_MENU_ITEM (proxy)) {
1429                 g_signal_handlers_disconnect_by_func
1430                         (proxy, G_CALLBACK (menu_item_select_cb), ev_window);
1431                 g_signal_handlers_disconnect_by_func
1432                         (proxy, G_CALLBACK (menu_item_deselect_cb), ev_window);
1433         }
1434 }
1435
1436 static void
1437 update_current_page (EvWindow *ev_window,
1438                      EvView   *view)
1439 {
1440         int page;
1441         GtkAction *action;
1442         EvSidebarThumbnails *thumbs;
1443
1444         thumbs = EV_SIDEBAR_THUMBNAILS (ev_window->priv->thumbs_sidebar);
1445         ev_sidebar_thumbnails_select_page (thumbs, ev_view_get_page (view));
1446
1447         action = gtk_action_group_get_action
1448                 (ev_window->priv->action_group, PAGE_SELECTOR_ACTION);
1449
1450         page = ev_view_get_page (EV_VIEW (ev_window->priv->view));
1451         ev_page_action_set_current_page (EV_PAGE_ACTION (action), page);
1452 }
1453
1454 static void
1455 view_page_changed_cb (EvView   *view,
1456                       EvWindow *ev_window)
1457 {
1458         update_current_page (ev_window, view);
1459         update_action_sensitivity (ev_window);
1460 }
1461
1462 static void
1463 view_status_changed_cb (EvView     *view,
1464                         GParamSpec *pspec,
1465                         EvWindow   *ev_window)
1466 {
1467         const char *message;
1468
1469         gtk_statusbar_pop (GTK_STATUSBAR (ev_window->priv->statusbar),
1470                            ev_window->priv->view_message_cid);
1471
1472         message = ev_view_get_status (view);
1473         if (message) {
1474                 gtk_statusbar_push (GTK_STATUSBAR (ev_window->priv->statusbar),
1475                                     ev_window->priv->view_message_cid, message);
1476         }
1477 }
1478
1479 static void
1480 view_find_status_changed_cb (EvView     *view,
1481                              GParamSpec *pspec,
1482                              EvWindow   *ev_window)
1483 {
1484         const char *text;
1485
1486         text = ev_view_get_find_status (view);
1487         egg_find_bar_set_status_text (EGG_FIND_BAR (ev_window->priv->find_bar),
1488                                       text);
1489 }
1490
1491 static void
1492 find_bar_previous_cb (EggFindBar *find_bar,
1493                       EvWindow   *ev_window)
1494 {
1495         ev_view_find_previous (EV_VIEW (ev_window->priv->view));
1496 }
1497
1498 static void
1499 find_bar_next_cb (EggFindBar *find_bar,
1500                   EvWindow   *ev_window)
1501 {
1502         ev_view_find_next (EV_VIEW (ev_window->priv->view));
1503 }
1504
1505 static void
1506 find_bar_close_cb (EggFindBar *find_bar,
1507                    EvWindow   *ev_window)
1508 {
1509         update_chrome_flag (ev_window, EV_CHROME_FINDBAR, NULL, FALSE);
1510 }
1511
1512 static void
1513 ev_window_page_mode_cb (GtkRadioAction *action,
1514                         GtkRadioAction *activated_action,
1515                         EvWindow       *window)
1516 {
1517         int mode;
1518
1519         mode = gtk_radio_action_get_current_value (action);
1520
1521         g_assert (mode == PAGE_MODE_CONTINUOUS_PAGE ||
1522                   mode == PAGE_MODE_SINGLE_PAGE);
1523
1524         ev_window_set_page_mode (window, (EvWindowPageMode) mode);
1525 }
1526
1527 static void
1528 find_bar_search_changed_cb (EggFindBar *find_bar,
1529                             GParamSpec *param,
1530                             EvWindow   *ev_window)
1531 {
1532         gboolean case_sensitive;
1533         gboolean visible;
1534         const char *search_string;
1535
1536         g_return_if_fail (EV_IS_WINDOW (ev_window));
1537
1538         /* Either the string or case sensitivity could have changed,
1539          * we connect this callback to both. We also connect it
1540          * to ::visible so when the find bar is hidden, we should
1541          * pretend the search string is NULL/""
1542          */
1543
1544         case_sensitive = egg_find_bar_get_case_sensitive (find_bar);
1545         visible = GTK_WIDGET_VISIBLE (find_bar);
1546         search_string = egg_find_bar_get_search_string (find_bar);
1547
1548 #if 0
1549         g_printerr ("search for '%s'\n", search_string ? search_string : "(nil)");
1550 #endif
1551
1552         if (ev_window->priv->document &&
1553             EV_IS_DOCUMENT_FIND (ev_window->priv->document)) {
1554                 if (visible && search_string) {
1555                         ev_document_find_begin (EV_DOCUMENT_FIND (ev_window->priv->document), search_string, case_sensitive);
1556                 } else {
1557                         ev_document_find_cancel (EV_DOCUMENT_FIND (ev_window->priv->document));
1558                         egg_find_bar_set_status_text (EGG_FIND_BAR (ev_window->priv->find_bar),
1559                                                       NULL);
1560                         gtk_widget_queue_draw (GTK_WIDGET (ev_window->priv->view));
1561                 }
1562         }
1563 }
1564
1565 static void
1566 ev_window_dispose (GObject *object)
1567 {
1568         EvWindow *window = EV_WINDOW (object);
1569         EvWindowPrivate *priv = window->priv;
1570
1571         if (priv->ui_manager) {
1572                 g_object_unref (priv->ui_manager);
1573                 priv->ui_manager = NULL;
1574         }
1575
1576         if (priv->action_group) {
1577                 g_object_unref (priv->action_group);
1578                 priv->action_group = NULL;
1579         }
1580
1581         if (priv->document) {
1582                 g_object_unref (priv->document);
1583                 priv->document = NULL;
1584         }
1585
1586         if (priv->view) {
1587                 g_object_unref (priv->view);
1588                 priv->view = NULL;
1589         }
1590
1591         if (priv->page_view) {
1592                 g_object_unref (priv->page_view);
1593                 priv->page_view = NULL;
1594         }
1595
1596         if (priv->password_document) {
1597                 g_object_unref (priv->password_document);
1598                 priv->password_document = NULL;
1599         }
1600         
1601         if (priv->password_uri) {
1602                 g_free (priv->password_uri);
1603                 priv->password_uri = NULL;
1604         }
1605
1606         destroy_exit_fullscreen_popup (window);
1607
1608         G_OBJECT_CLASS (ev_window_parent_class)->dispose (object);
1609 }
1610
1611 static void
1612 ev_window_class_init (EvWindowClass *ev_window_class)
1613 {
1614         GObjectClass *g_object_class = G_OBJECT_CLASS (ev_window_class);
1615         GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (ev_window_class);
1616
1617         g_object_class->dispose = ev_window_dispose;
1618
1619         widget_class->focus_in_event = ev_window_focus_in_event;
1620         widget_class->focus_out_event = ev_window_focus_out_event;
1621
1622         g_type_class_add_private (g_object_class, sizeof (EvWindowPrivate));
1623 }
1624
1625 /* Normal items */
1626 static GtkActionEntry entries[] = {
1627         { "File", NULL, N_("_File") },
1628         { "Edit", NULL, N_("_Edit") },
1629         { "View", NULL, N_("_View") },
1630         { "Go", NULL, N_("_Go") },
1631         { "Help", NULL, N_("_Help") },
1632
1633         /* File menu */
1634         { "FileOpen", GTK_STOCK_OPEN, NULL, "<control>O",
1635           N_("Open an existing document"),
1636           G_CALLBACK (ev_window_cmd_file_open) },
1637         { "FileSaveAs", GTK_STOCK_SAVE_AS, N_("_Save a Copy..."), NULL,
1638           N_("Save the current document with a new filename"),
1639           G_CALLBACK (ev_window_cmd_save_as) },
1640         { "FilePrint", GTK_STOCK_PRINT, NULL, "<control>P",
1641           N_("Print this document"),
1642           G_CALLBACK (ev_window_cmd_file_print) },
1643         { "FileCloseWindow", GTK_STOCK_CLOSE, NULL, "<control>W",
1644           N_("Close this window"),
1645           G_CALLBACK (ev_window_cmd_file_close_window) },
1646
1647         /* Edit menu */
1648         { "EditCopy", GTK_STOCK_COPY, NULL, "<control>C",
1649           N_("Copy text from the document"),
1650           G_CALLBACK (ev_window_cmd_edit_copy) },
1651         { "EditSelectAll", NULL, N_("Select _All"), "<control>A",
1652           N_("Select the entire page"),
1653           G_CALLBACK (ev_window_cmd_edit_select_all) },
1654         { "EditFind", GTK_STOCK_FIND, NULL, "<control>F",
1655           N_("Find a word or phrase in the document"),
1656           G_CALLBACK (ev_window_cmd_edit_find) },
1657
1658         /* View menu */
1659         { "ViewZoomIn", GTK_STOCK_ZOOM_IN, NULL, "<control>plus",
1660           N_("Enlarge the document"),
1661           G_CALLBACK (ev_window_cmd_view_zoom_in) },
1662         { "ViewZoomOut", GTK_STOCK_ZOOM_OUT, NULL, "<control>minus",
1663           N_("Shrink the document"),
1664           G_CALLBACK (ev_window_cmd_view_zoom_out) },
1665         { "ViewNormalSize", GTK_STOCK_ZOOM_100, NULL, "<control>0",
1666           N_("Reset the zoom level to the default value"),
1667           G_CALLBACK (ev_window_cmd_view_normal_size) },
1668         { "ViewBestFit", EV_STOCK_ZOOM_PAGE, N_("_Best Fit"), NULL,
1669           N_("Make the current document fill the window"),
1670           G_CALLBACK (ev_window_cmd_view_best_fit) },
1671         { "ViewPageWidth", EV_STOCK_ZOOM_WIDTH, N_("Fit Page _Width"), NULL,
1672           N_("Make the current document fill the window width"),
1673           G_CALLBACK (ev_window_cmd_view_page_width) },
1674
1675         /* Go menu */
1676         { "GoPreviousPage", GTK_STOCK_GO_BACK, N_("_Previous Page"), "Page_Up",
1677           N_("Go to the previous page"),
1678           G_CALLBACK (ev_window_cmd_go_previous_page) },
1679         { "GoNextPage", GTK_STOCK_GO_FORWARD, N_("_Next Page"), "Page_Down",
1680           N_("Go to the next page"),
1681           G_CALLBACK (ev_window_cmd_go_next_page) },
1682         { "GoFirstPage", GTK_STOCK_GOTO_FIRST, N_("_First Page"), "<control>Home",
1683           N_("Go to the first page"),
1684           G_CALLBACK (ev_window_cmd_go_first_page) },
1685         { "GoLastPage", GTK_STOCK_GOTO_LAST, N_("_Last Page"), "<control>End",
1686           N_("Go to the last page"),
1687           G_CALLBACK (ev_window_cmd_go_last_page) },
1688
1689         /* Help menu */
1690         { "HelpContents", GTK_STOCK_HELP, N_("_Contents"), NULL,
1691           N_("Display help for the viewer application"),
1692           G_CALLBACK (ev_window_cmd_help_contents) },
1693
1694         { "HelpAbout", GTK_STOCK_ABOUT, N_("_About"), NULL,
1695           N_("Display credits for the document viewer creators"),
1696           G_CALLBACK (ev_window_cmd_help_about) },
1697
1698         /* Toolbar-only */
1699         { "LeaveFullscreen", EV_STOCK_LEAVE_FULLSCREEN, N_("Leave Fullscreen"), "Escape",
1700           N_("Leave fullscreen mode"),
1701           G_CALLBACK (ev_window_cmd_leave_fullscreen) }
1702 };
1703
1704 /* Toggle items */
1705 static GtkToggleActionEntry toggle_entries[] = {
1706         /* View Menu */
1707         { "ViewToolbar", NULL, N_("_Toolbar"), "<shift><control>T",
1708           N_("Show or hide the toolbar"),
1709           G_CALLBACK (ev_window_view_toolbar_cb), TRUE },
1710         { "ViewStatusbar", NULL, N_("_Statusbar"), NULL,
1711           N_("Show or hide the statusbar"),
1712           G_CALLBACK (ev_window_view_statusbar_cb), TRUE },
1713         { "ViewSidebar", NULL, N_("Side _pane"), "F9",
1714           N_("Show or hide the side pane"),
1715           G_CALLBACK (ev_window_view_sidebar_cb), TRUE },
1716         { "ViewFullscreen", NULL, N_("_Fullscreen"), "F11",
1717           N_("Expand the window to fill the screen"),
1718           G_CALLBACK (ev_window_cmd_view_fullscreen) },
1719 };
1720
1721 static GtkRadioActionEntry page_view_entries[] = {
1722         { "SinglePage", GTK_STOCK_DND, N_("Single"), NULL,
1723           N_("Show the document one page at a time"),
1724           PAGE_MODE_SINGLE_PAGE },
1725         { "ContinuousPage", GTK_STOCK_DND_MULTIPLE, N_("Multi"), NULL,
1726           N_("Show the full document at once"),
1727           PAGE_MODE_CONTINUOUS_PAGE }
1728 };
1729
1730 static void
1731 goto_page_cb (GtkAction *action, int page_number, EvWindow *ev_window)
1732 {
1733         EvView *view = EV_VIEW (ev_window->priv->view);
1734
1735         if (ev_view_get_page (view) != page_number) {
1736                 ev_view_set_page (view, page_number);
1737         }
1738 }
1739
1740 static void
1741 drag_data_received_cb (GtkWidget *widget, GdkDragContext *context,
1742                        gint x, gint y, GtkSelectionData *selection_data,
1743                        guint info, guint time, gpointer gdata)
1744 {
1745         GList    *uri_list = NULL;
1746
1747         uri_list = gnome_vfs_uri_list_parse ((gchar *) selection_data->data);
1748
1749         if (uri_list) {
1750                 ev_window_open_uri_list (EV_WINDOW (widget), uri_list);
1751                 
1752                 gnome_vfs_uri_list_free (uri_list);
1753
1754                 gtk_drag_finish (context, TRUE, FALSE, time);
1755         }
1756 }
1757
1758 static void
1759 register_custom_actions (EvWindow *window, GtkActionGroup *group)
1760 {
1761         GtkAction *action;
1762
1763         action = g_object_new (EV_TYPE_PAGE_ACTION,
1764                                "name", PAGE_SELECTOR_ACTION,
1765                                "label", _("Page"),
1766                                "tooltip", _("Select Page"),
1767                                NULL);
1768         g_signal_connect (action, "goto_page",
1769                           G_CALLBACK (goto_page_cb), window);
1770         gtk_action_group_add_action (group, action);
1771         g_object_unref (action);
1772 }
1773
1774 static void
1775 set_action_properties (GtkActionGroup *action_group)
1776 {
1777         GtkAction *action;
1778
1779         action = gtk_action_group_get_action (action_group, "GoPreviousPage");
1780         /*translators: this is the label for toolbar button*/
1781         g_object_set (action, "short_label", _("Previous"), NULL);
1782         g_object_set (action, "is-important", TRUE, NULL);
1783         action = gtk_action_group_get_action (action_group, "GoNextPage");
1784         /*translators: this is the label for toolbar button*/
1785         g_object_set (action, "is-important", TRUE, NULL);
1786         g_object_set (action, "short_label", _("Next"), NULL);
1787         action = gtk_action_group_get_action (action_group, "ViewPageWidth");
1788         /*translators: this is the label for toolbar button*/
1789         g_object_set (action, "short_label", _("Fit Width"), NULL);
1790         action = gtk_action_group_get_action (action_group, "ViewZoomIn");
1791
1792         action = gtk_action_group_get_action (action_group, "LeaveFullscreen");
1793         g_object_set (action, "is-important", TRUE, NULL);
1794 }
1795
1796 static void
1797 set_chrome_actions (EvWindow *window)
1798 {
1799         EvWindowPrivate *priv = window->priv;
1800         GtkActionGroup *action_group = priv->action_group;
1801         GtkAction *action;
1802
1803         action= gtk_action_group_get_action (action_group, "ViewToolbar");
1804         g_signal_handlers_block_by_func
1805                 (action, G_CALLBACK (ev_window_view_toolbar_cb), window);
1806         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1807                                       (priv->chrome & EV_CHROME_TOOLBAR) != 0);
1808         g_signal_handlers_unblock_by_func
1809                 (action, G_CALLBACK (ev_window_view_toolbar_cb), window);
1810
1811         action= gtk_action_group_get_action (action_group, "ViewSidebar");
1812         g_signal_handlers_block_by_func
1813                 (action, G_CALLBACK (ev_window_view_sidebar_cb), window);
1814         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1815                                       (priv->chrome & EV_CHROME_SIDEBAR) != 0);
1816         g_signal_handlers_unblock_by_func
1817                 (action, G_CALLBACK (ev_window_view_sidebar_cb), window);
1818
1819         action= gtk_action_group_get_action (action_group, "ViewStatusbar");
1820         g_signal_handlers_block_by_func
1821                 (action, G_CALLBACK (ev_window_view_statusbar_cb), window);
1822         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1823                                       (priv->chrome & EV_CHROME_STATUSBAR) != 0);
1824         g_signal_handlers_unblock_by_func
1825                 (action, G_CALLBACK (ev_window_view_statusbar_cb), window);
1826 }
1827
1828 static EvChrome
1829 load_chrome (void)
1830 {
1831         GConfClient *client;
1832         GConfValue *value;      
1833         EvChrome chrome = EV_CHROME_NORMAL;
1834
1835         client = gconf_client_get_default ();
1836
1837         value = gconf_client_get (client, GCONF_CHROME_TOOLBAR, NULL);
1838         if (value != NULL) {
1839                 if (value->type == GCONF_VALUE_BOOL && !gconf_value_get_bool (value)) {
1840                         chrome &= ~EV_CHROME_TOOLBAR;
1841                 }
1842                 gconf_value_free (value);
1843         }
1844
1845         value = gconf_client_get (client, GCONF_CHROME_SIDEBAR, NULL);
1846         if (value != NULL) {
1847                 if (value->type == GCONF_VALUE_BOOL && !gconf_value_get_bool (value)) {
1848                         chrome &= ~EV_CHROME_SIDEBAR;
1849                 }
1850                 gconf_value_free (value);
1851         }
1852
1853         value = gconf_client_get (client, GCONF_CHROME_STATUSBAR, NULL);
1854         if (value != NULL) {
1855                 if (value->type == GCONF_VALUE_BOOL && !gconf_value_get_bool (value)) {
1856                         chrome &= ~EV_CHROME_STATUSBAR;
1857                 }
1858                 gconf_value_free (value);
1859         }
1860
1861         g_object_unref (client);
1862
1863         return chrome;
1864 }
1865
1866 static void
1867 ev_window_init (EvWindow *ev_window)
1868 {
1869         GtkActionGroup *action_group;
1870         GtkAccelGroup *accel_group;
1871         GError *error = NULL;
1872         GtkWidget *sidebar_widget, *toolbar_dock;
1873
1874         ev_window->priv = EV_WINDOW_GET_PRIVATE (ev_window);
1875
1876         ev_window->priv->page_mode = PAGE_MODE_SINGLE_PAGE;
1877         update_window_title (NULL, NULL, ev_window);
1878
1879         ev_window->priv->main_box = gtk_vbox_new (FALSE, 0);
1880         gtk_container_add (GTK_CONTAINER (ev_window), ev_window->priv->main_box);
1881         gtk_widget_show (ev_window->priv->main_box);
1882
1883         action_group = gtk_action_group_new ("MenuActions");
1884         ev_window->priv->action_group = action_group;
1885         gtk_action_group_set_translation_domain (action_group, NULL);
1886         gtk_action_group_add_actions (action_group, entries,
1887                                       G_N_ELEMENTS (entries), ev_window);
1888         gtk_action_group_add_toggle_actions (action_group, toggle_entries,
1889                                              G_N_ELEMENTS (toggle_entries),
1890                                              ev_window);
1891         gtk_action_group_add_radio_actions (action_group, page_view_entries,
1892                                             G_N_ELEMENTS (page_view_entries),
1893                                             ev_window->priv->page_mode,
1894                                             G_CALLBACK (ev_window_page_mode_cb),
1895                                             ev_window);
1896         set_action_properties (action_group);
1897         register_custom_actions (ev_window, action_group);
1898
1899         ev_window->priv->ui_manager = gtk_ui_manager_new ();
1900         gtk_ui_manager_insert_action_group (ev_window->priv->ui_manager,
1901                                             action_group, 0);
1902
1903         accel_group =
1904                 gtk_ui_manager_get_accel_group (ev_window->priv->ui_manager);
1905         gtk_window_add_accel_group (GTK_WINDOW (ev_window), accel_group);
1906
1907         g_signal_connect (ev_window->priv->ui_manager, "connect_proxy",
1908                           G_CALLBACK (connect_proxy_cb), ev_window);
1909         g_signal_connect (ev_window->priv->ui_manager, "disconnect_proxy",
1910                           G_CALLBACK (disconnect_proxy_cb), ev_window);
1911
1912         if (!gtk_ui_manager_add_ui_from_file (ev_window->priv->ui_manager,
1913                                               DATADIR"/evince-ui.xml",
1914                                               &error)) {
1915                 g_message ("building menus failed: %s", error->message);
1916                 g_error_free (error);
1917         }
1918
1919         ev_window->priv->menubar =
1920                  gtk_ui_manager_get_widget (ev_window->priv->ui_manager,
1921                                             "/MainMenu");
1922         gtk_box_pack_start (GTK_BOX (ev_window->priv->main_box),
1923                             ev_window->priv->menubar,
1924                             FALSE, FALSE, 0);
1925
1926         /* This sucks, but there is no way to have a draw=no, expand=true separator
1927          * in a GtkUIManager-built toolbar. So, just add another toolbar.
1928          * See gtk+ bug 166489.
1929          */
1930         toolbar_dock = ev_window->priv->toolbar_dock = gtk_hbox_new (FALSE, 0);
1931         gtk_box_pack_start (GTK_BOX (ev_window->priv->main_box), toolbar_dock,
1932                             FALSE, FALSE, 0);
1933         gtk_widget_show (toolbar_dock);
1934
1935         ev_window->priv->toolbar =
1936                 gtk_ui_manager_get_widget (ev_window->priv->ui_manager,
1937                                            "/ToolBar");
1938         gtk_box_pack_start (GTK_BOX (toolbar_dock), ev_window->priv->toolbar,
1939                             TRUE, TRUE, 0);
1940         gtk_widget_show (ev_window->priv->toolbar);
1941
1942         ev_window->priv->exit_fullscreen_toolbar =
1943                 gtk_ui_manager_get_widget (ev_window->priv->ui_manager,
1944                                            "/LeaveFullscreenToolbar");
1945         gtk_box_pack_start (GTK_BOX (toolbar_dock),
1946                             ev_window->priv->exit_fullscreen_toolbar,
1947                             FALSE, FALSE, 0);
1948         gtk_toolbar_set_show_arrow (GTK_TOOLBAR (ev_window->priv->exit_fullscreen_toolbar),
1949                                     FALSE);
1950         gtk_toolbar_set_style (GTK_TOOLBAR (ev_window->priv->exit_fullscreen_toolbar),
1951                                GTK_TOOLBAR_BOTH_HORIZ);
1952
1953         /* Add the main area */
1954         ev_window->priv->hpaned = gtk_hpaned_new ();
1955         gtk_widget_show (ev_window->priv->hpaned);
1956         gtk_box_pack_start (GTK_BOX (ev_window->priv->main_box), ev_window->priv->hpaned,
1957                             TRUE, TRUE, 0);
1958
1959         ev_window->priv->sidebar = ev_sidebar_new ();
1960         gtk_paned_add1 (GTK_PANED (ev_window->priv->hpaned),
1961                         ev_window->priv->sidebar);
1962
1963         /* Stub sidebar, for now */
1964         sidebar_widget = ev_sidebar_links_new ();
1965         gtk_widget_show (sidebar_widget);
1966         ev_sidebar_add_page (EV_SIDEBAR (ev_window->priv->sidebar),
1967                              "index",
1968                              _("Index"),
1969                              sidebar_widget);
1970
1971         ev_window->priv->thumbs_sidebar = ev_sidebar_thumbnails_new ();
1972         gtk_widget_show (ev_window->priv->thumbs_sidebar);
1973         ev_sidebar_add_page (EV_SIDEBAR (ev_window->priv->sidebar),
1974                              "thumbnails",
1975                              _("Thumbnails"),
1976                              ev_window->priv->thumbs_sidebar);
1977
1978         ev_window->priv->scrolled_window =
1979                 GTK_WIDGET (g_object_new (GTK_TYPE_SCROLLED_WINDOW,
1980                                           "hscrollbar-policy", GTK_POLICY_AUTOMATIC,
1981                                           "vscrollbar-policy", GTK_POLICY_AUTOMATIC,
1982                                           "shadow-type", GTK_SHADOW_IN,
1983                                           NULL));
1984         gtk_widget_show (ev_window->priv->scrolled_window);
1985
1986         gtk_paned_add2 (GTK_PANED (ev_window->priv->hpaned),
1987                         ev_window->priv->scrolled_window);
1988
1989         ev_window->priv->view = ev_view_new ();
1990         //ev_window->priv->page_view = ev_page_view_new ();
1991         ev_window->priv->password_view = ev_password_view_new ();
1992         g_signal_connect_swapped (ev_window->priv->password_view,
1993                                   "unlock",
1994                                   G_CALLBACK (ev_window_popup_password_dialog),
1995                                   ev_window);
1996         gtk_widget_show (ev_window->priv->view);
1997         //gtk_widget_show (ev_window->priv->page_view);
1998         gtk_widget_show (ev_window->priv->password_view);
1999
2000         /* We own a ref on these widgets, as we can swap them in and out */
2001         g_object_ref (ev_window->priv->view);
2002         //g_object_ref (ev_window->priv->page_view);
2003         g_object_ref (ev_window->priv->password_view);
2004
2005         gtk_container_add (GTK_CONTAINER (ev_window->priv->scrolled_window),
2006                            ev_window->priv->view);
2007         g_signal_connect (ev_window->priv->view,
2008                           "page-changed",
2009                           G_CALLBACK (view_page_changed_cb),
2010                           ev_window);
2011         g_signal_connect (ev_window->priv->view,
2012                           "notify::find-status",
2013                           G_CALLBACK (view_find_status_changed_cb),
2014                           ev_window);
2015         g_signal_connect (ev_window->priv->view,
2016                           "notify::status",
2017                           G_CALLBACK (view_status_changed_cb),
2018                           ev_window);
2019
2020         ev_window->priv->statusbar = gtk_statusbar_new ();
2021         gtk_box_pack_end (GTK_BOX (ev_window->priv->main_box),
2022                           ev_window->priv->statusbar,
2023                           FALSE, TRUE, 0);
2024         ev_window->priv->help_message_cid = gtk_statusbar_get_context_id
2025                 (GTK_STATUSBAR (ev_window->priv->statusbar), "help_message");
2026         ev_window->priv->view_message_cid = gtk_statusbar_get_context_id
2027                 (GTK_STATUSBAR (ev_window->priv->statusbar), "view_message");
2028
2029         ev_window->priv->find_bar = egg_find_bar_new ();
2030         gtk_box_pack_end (GTK_BOX (ev_window->priv->main_box),
2031                           ev_window->priv->find_bar,
2032                           FALSE, TRUE, 0);
2033
2034         ev_window->priv->chrome = load_chrome ();
2035         set_chrome_actions (ev_window);
2036         update_chrome_visibility (ev_window);
2037
2038         /* Connect to find bar signals */
2039         g_signal_connect (ev_window->priv->find_bar,
2040                           "previous",
2041                           G_CALLBACK (find_bar_previous_cb),
2042                           ev_window);
2043         g_signal_connect (ev_window->priv->find_bar,
2044                           "next",
2045                           G_CALLBACK (find_bar_next_cb),
2046                           ev_window);
2047         g_signal_connect (ev_window->priv->find_bar,
2048                           "close",
2049                           G_CALLBACK (find_bar_close_cb),
2050                           ev_window);
2051         g_signal_connect (ev_window->priv->find_bar,
2052                           "notify::search-string",
2053                           G_CALLBACK (find_bar_search_changed_cb),
2054                           ev_window);
2055         g_signal_connect (ev_window->priv->find_bar,
2056                           "notify::case-sensitive",
2057                           G_CALLBACK (find_bar_search_changed_cb),
2058                           ev_window);
2059         g_signal_connect (ev_window->priv->find_bar,
2060                           "notify::visible",
2061                           G_CALLBACK (find_bar_search_changed_cb),
2062                           ev_window);
2063
2064         g_signal_connect (ev_window, "window-state-event",
2065                           G_CALLBACK (ev_window_state_event_cb),
2066                           ev_window);
2067
2068         /* Give focus to the scrolled window */
2069         gtk_widget_grab_focus (ev_window->priv->scrolled_window);
2070
2071         /* Drag and Drop */
2072         gtk_drag_dest_unset (GTK_WIDGET (ev_window));
2073         gtk_drag_dest_set (GTK_WIDGET (ev_window), GTK_DEST_DEFAULT_ALL, ev_drop_types,
2074                            sizeof (ev_drop_types) / sizeof (ev_drop_types[0]),
2075                            GDK_ACTION_COPY);
2076         g_signal_connect (G_OBJECT (ev_window), "drag_data_received",
2077                           G_CALLBACK (drag_data_received_cb), NULL);
2078
2079         update_action_sensitivity (ev_window);
2080 }