]> www.fi.muni.cz Git - evince.git/blob - shell/ev-window.c
Add Continuous and Dual page modes.
[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-password.h"
38 #include "ev-password-view.h"
39 #include "ev-print-job.h"
40 #include "ev-document-thumbnails.h"
41 #include "ev-document-links.h"
42 #include "ev-document-types.h"
43 #include "ev-document-find.h"
44 #include "ev-document-security.h"
45 #include "ev-job-queue.h"
46 #include "eggfindbar.h"
47 #include "egg-recent-view-gtk.h"
48 #include "egg-recent-view.h"
49 #include "egg-recent-model.h"
50
51 #include <glib/gi18n.h>
52 #include <gtk/gtk.h>
53 #include <gnome.h>
54
55 #include <libgnomevfs/gnome-vfs-mime-utils.h>
56 #include <libgnomevfs/gnome-vfs-uri.h>
57 #include <libgnomevfs/gnome-vfs-utils.h>
58 #include <libgnomeprintui/gnome-print-dialog.h>
59
60 #include <gconf/gconf-client.h>
61
62 #include <string.h>
63
64 #include "ev-application.h"
65 #include "ev-stock-icons.h"
66
67 typedef enum {
68         PAGE_MODE_SINGLE_PAGE,
69         PAGE_MODE_CONTINUOUS_PAGE,
70         PAGE_MODE_PASSWORD,
71 } EvWindowPageMode;
72
73 typedef enum {
74         EV_CHROME_MENUBAR       = 1 << 0,
75         EV_CHROME_TOOLBAR       = 1 << 1,
76         EV_CHROME_SIDEBAR       = 1 << 2,
77         EV_CHROME_FINDBAR       = 1 << 3,
78         EV_CHROME_STATUSBAR     = 1 << 4,
79         EV_CHROME_NORMAL        = EV_CHROME_MENUBAR | EV_CHROME_TOOLBAR | EV_CHROME_SIDEBAR | EV_CHROME_STATUSBAR
80 } EvChrome;
81
82 struct _EvWindowPrivate {
83         GtkWidget *main_box;
84         GtkWidget *menubar;
85         GtkWidget *toolbar_dock;
86         GtkWidget *toolbar;
87         GtkWidget *hpaned;
88         GtkWidget *sidebar;
89         GtkWidget *find_bar;
90         GtkWidget *scrolled_window;
91         GtkWidget *view;
92         GtkWidget *page_view;
93         GtkWidget *password_view;
94         GtkActionGroup *action_group;
95         GtkUIManager *ui_manager;
96         GtkWidget *statusbar;
97         guint help_message_cid;
98         guint view_message_cid;
99         GtkWidget *fullscreen_toolbar;
100         GtkWidget *fullscreen_popup;
101         char *uri;
102
103         EvDocument *document;
104         EvPageCache *page_cache;
105
106         EvWindowPageMode page_mode;
107         /* These members are used temporarily when in PAGE_MODE_PASSWORD */
108         EvDocument *password_document;
109         GtkWidget *password_dialog;
110         char *password_uri;
111
112         EvChrome chrome;
113         gboolean fullscreen_mode;
114         GSource *fullscreen_timeout_source;
115
116         /* recent file stuff */
117         EggRecentModel *recent_model;
118         EggRecentViewGtk *recent_view;
119 };
120
121 static const GtkTargetEntry ev_drop_types[] = {
122         { "text/uri-list", 0, 0 }
123 };
124
125
126 #define EV_WINDOW_GET_PRIVATE(object) \
127         (G_TYPE_INSTANCE_GET_PRIVATE ((object), EV_TYPE_WINDOW, EvWindowPrivate))
128
129 #define PAGE_SELECTOR_ACTION    "PageSelector"
130
131 #define GCONF_CHROME_TOOLBAR    "/apps/evince/show_toolbar"
132 #define GCONF_CHROME_SIDEBAR    "/apps/evince/show_sidebar"
133 #define GCONF_CHROME_STATUSBAR  "/apps/evince/show_statusbar"
134
135 #define GCONF_SIDEBAR_SIZE      "/apps/evince/sidebar_size"
136
137 #define SIDEBAR_DEFAULT_SIZE    132
138 #define VIEW_SPACING            10
139
140 static void     ev_window_update_fullscreen_popup (EvWindow         *window);
141 static void     ev_window_sidebar_visibility_changed_cb (EvSidebar *ev_sidebar, GParamSpec *pspec,
142                                                          EvWindow   *ev_window);
143 static void     ev_window_set_page_mode           (EvWindow         *window,
144                                                    EvWindowPageMode  page_mode);
145 static gboolean start_loading_document            (EvWindow         *ev_window,
146                                                    EvDocument       *document,
147                                                    const char       *uri);
148 static void     ev_window_set_sizing_mode         (EvWindow         *ev_window,
149                                                    EvSizingMode      sizing_mode,
150                                                    gboolean          first_time);
151
152 static void     ev_window_add_recent (EvWindow *window, const char *filename);
153 static void     ev_window_fullscreen (EvWindow *window);
154
155 G_DEFINE_TYPE (EvWindow, ev_window, GTK_TYPE_WINDOW)
156
157 static void
158 set_action_sensitive (EvWindow   *ev_window,
159                       const char *name,
160                       gboolean    sensitive)
161 {
162         GtkAction *action = gtk_action_group_get_action (ev_window->priv->action_group,
163                                                          name);
164         gtk_action_set_sensitive (action, sensitive);
165 }
166
167 static void
168 update_action_sensitivity (EvWindow *ev_window)
169 {
170         EvView *view;
171         EvDocument *document;
172         EvWindowPageMode page_mode;
173         gboolean sensitive, has_pages = FALSE, has_document;
174         int n_pages = 0, page = -1;
175
176         view = EV_VIEW (ev_window->priv->view);
177         document = ev_window->priv->document;
178         page_mode = ev_window->priv->page_mode;
179         has_document = document != NULL;
180         if (has_document && ev_window->priv->page_cache) {
181                 page = ev_page_cache_get_current_page (ev_window->priv->page_cache);
182                 n_pages = ev_page_cache_get_n_pages (ev_window->priv->page_cache);
183                 has_pages = has_document && n_pages > 0;
184         }
185
186         /* File menu */
187         /* "FileOpen": always sensitive */
188         set_action_sensitive (ev_window, "FileSaveAs", has_document);
189         set_action_sensitive (ev_window, "FilePrint", has_pages);
190         /* "FileCloseWindow": always sensitive */
191
192         /* Edit menu */
193
194         sensitive = has_pages && ev_document_can_get_text (document);
195         set_action_sensitive (ev_window, "EditCopy", sensitive);
196         set_action_sensitive (ev_window, "EditSelectAll", sensitive);
197         set_action_sensitive (ev_window, "EditFind",
198                               has_pages && EV_IS_DOCUMENT_FIND (document));
199         set_action_sensitive (ev_window, "EditFindNext",
200                               ev_view_can_find_next (view));
201
202         /* View menu */
203         set_action_sensitive (ev_window, "ViewContinuous", has_pages);
204         set_action_sensitive (ev_window, "ViewDual", has_pages);
205         set_action_sensitive (ev_window, "ViewZoomIn",
206                               has_pages && ev_view_can_zoom_in (view));
207         set_action_sensitive (ev_window, "ViewZoomOut",
208                               has_pages && ev_view_can_zoom_out (view));
209         set_action_sensitive (ev_window, "ViewNormalSize", has_pages);
210         set_action_sensitive (ev_window, "ViewBestFit", has_pages);
211         set_action_sensitive (ev_window, "ViewPageWidth", has_pages);
212         set_action_sensitive (ev_window, "ViewReload", has_pages);
213
214         /* Go menu */
215         if (document) {
216                 set_action_sensitive (ev_window, "GoPreviousPage", page > 0);
217                 set_action_sensitive (ev_window, "GoNextPage", page < n_pages - 1);
218                 set_action_sensitive (ev_window, "GoFirstPage", page > 0);
219                 set_action_sensitive (ev_window, "GoLastPage", page < n_pages - 1);
220         } else {
221                 set_action_sensitive (ev_window, "GoFirstPage", FALSE);
222                 set_action_sensitive (ev_window, "GoPreviousPage", FALSE);
223                 set_action_sensitive (ev_window, "GoNextPage", FALSE);
224                 set_action_sensitive (ev_window, "GoLastPage", FALSE);
225         }
226
227         /* Page View radio group */
228         if (document) {
229                 set_action_sensitive (ev_window, "SinglePage", page_mode != PAGE_MODE_PASSWORD);
230                 set_action_sensitive (ev_window, "ContinuousPage", page_mode != PAGE_MODE_PASSWORD);
231         } else {
232                 set_action_sensitive (ev_window, "SinglePage", FALSE);
233                 set_action_sensitive (ev_window, "ContinuousPage", FALSE);
234         }
235         /* Help menu */
236         /* "HelpContents": always sensitive */
237         /* "HelpAbout": always sensitive */
238
239         /* Toolbar-specific actions: */
240         set_action_sensitive (ev_window, PAGE_SELECTOR_ACTION, has_pages);
241 }
242
243 static void
244 set_widget_visibility (GtkWidget *widget, gboolean visible)
245 {
246         g_return_if_fail (GTK_IS_WIDGET (widget));
247         
248         if (visible)
249                 gtk_widget_show (widget);
250         else
251                 gtk_widget_hide (widget);
252 }
253
254 static void
255 update_chrome_visibility (EvWindow *window)
256 {
257         EvWindowPrivate *priv = window->priv;
258         gboolean menubar, toolbar, sidebar, findbar, statusbar, fullscreen_toolbar;
259
260         menubar = (priv->chrome & EV_CHROME_MENUBAR) != 0 && !priv->fullscreen_mode;
261         toolbar = (priv->chrome & EV_CHROME_TOOLBAR) != 0 && !priv->fullscreen_mode;
262         sidebar = (priv->chrome & EV_CHROME_SIDEBAR) != 0 && !priv->fullscreen_mode;
263         fullscreen_toolbar = (priv->chrome & EV_CHROME_TOOLBAR) != 0;
264         statusbar = (priv->chrome & EV_CHROME_STATUSBAR) != 0 && !priv->fullscreen_mode;
265         findbar = (priv->chrome & EV_CHROME_FINDBAR) != 0;
266
267         set_widget_visibility (priv->menubar, menubar);
268         set_widget_visibility (priv->toolbar_dock, toolbar);
269         set_widget_visibility (priv->sidebar, sidebar);
270         set_widget_visibility (priv->find_bar, findbar);
271         set_widget_visibility (priv->statusbar, statusbar);
272         set_widget_visibility (priv->fullscreen_toolbar, fullscreen_toolbar);
273
274         if (priv->fullscreen_popup != NULL) {
275                 set_widget_visibility (priv->fullscreen_popup, priv->fullscreen_mode);
276         }
277 }
278
279 static void
280 update_chrome_flag (EvWindow *window, EvChrome flag, const char *pref, gboolean active)
281 {
282         EvWindowPrivate *priv = window->priv;
283         GConfClient *client;
284         
285         if (active) {
286                 priv->chrome |= flag;
287         }
288         else {
289                 priv->chrome &= ~flag;
290         }
291
292         if (pref != NULL) {
293                 client = gconf_client_get_default ();
294                 gconf_client_set_bool (client, pref, active, NULL);
295                 g_object_unref (client);
296         }
297
298         update_chrome_visibility (window);
299 }
300
301 static void
302 ev_window_cmd_continuous (GtkAction *action, EvWindow *ev_window)
303 {
304         gboolean continuous;
305
306         continuous = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
307         g_object_set (G_OBJECT (ev_window->priv->view),
308                       "continuous", continuous,
309                       NULL);
310         update_action_sensitivity (ev_window);
311 }
312
313 static void
314 ev_window_cmd_dual (GtkAction *action, EvWindow *ev_window)
315 {
316         gboolean dual_page;
317
318         dual_page = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
319         g_object_set (G_OBJECT (ev_window->priv->view),
320                       "dual-page", dual_page,
321                       NULL);
322         update_action_sensitivity (ev_window);
323 }
324
325 static void
326 ev_window_cmd_view_best_fit (GtkAction *action, EvWindow *ev_window)
327 {
328         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
329                 ev_window_set_sizing_mode (ev_window, EV_SIZING_BEST_FIT, FALSE);
330         } else {
331                 ev_window_set_sizing_mode (ev_window, EV_SIZING_FREE, FALSE);
332         }
333         update_action_sensitivity (ev_window);
334 }
335
336 static void
337 ev_window_cmd_view_page_width (GtkAction *action, EvWindow *ev_window)
338 {
339         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
340                 ev_window_set_sizing_mode (ev_window, EV_SIZING_FIT_WIDTH, FALSE);
341         } else {
342                 ev_window_set_sizing_mode (ev_window, EV_SIZING_FREE, FALSE);
343         }
344         update_action_sensitivity (ev_window);
345 }
346
347 static void
348 update_sizing_buttons (EvWindow *window)
349 {
350         GtkActionGroup *action_group = window->priv->action_group;
351         GtkAction *action;
352         gboolean best_fit, page_width;
353         EvSizingMode sizing_mode;
354
355         if (window->priv->view == NULL)
356                 return;
357
358         g_object_get (window->priv->view,
359                       "sizing_mode", &sizing_mode,
360                       NULL);
361
362         switch (sizing_mode) {
363         case EV_SIZING_BEST_FIT:
364                 best_fit = TRUE;
365                 page_width = FALSE;
366                 break;
367         case EV_SIZING_FIT_WIDTH:
368                 best_fit = FALSE;
369                 page_width = TRUE;
370                 break;
371
372         default:
373                 best_fit = page_width = FALSE;
374                 break;
375         }
376
377         action = gtk_action_group_get_action (action_group, "ViewBestFit");
378         g_signal_handlers_block_by_func
379                 (action, G_CALLBACK (ev_window_cmd_view_best_fit), window);
380         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), best_fit);
381         g_signal_handlers_unblock_by_func
382                 (action, G_CALLBACK (ev_window_cmd_view_best_fit), window);
383
384         action = gtk_action_group_get_action (action_group, "ViewPageWidth");   
385         g_signal_handlers_block_by_func
386                 (action, G_CALLBACK (ev_window_cmd_view_page_width), window);
387         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), page_width);
388         g_signal_handlers_unblock_by_func
389                 (action, G_CALLBACK (ev_window_cmd_view_page_width), window);
390 }
391
392 void
393 ev_window_open_page (EvWindow *ev_window, int page)
394 {
395         if (ev_window->priv->page_cache) {
396             page = CLAMP (page, 0, ev_page_cache_get_n_pages (ev_window->priv->page_cache));
397             ev_page_cache_set_current_page (ev_window->priv->page_cache, page);
398         }
399 }
400
401 gboolean
402 ev_window_is_empty (const EvWindow *ev_window)
403 {
404         g_return_val_if_fail (EV_IS_WINDOW (ev_window), FALSE);
405
406         return ev_window->priv->document == NULL;
407 }
408
409 static void
410 unable_to_load (EvWindow   *ev_window,
411                 const char *error_message)
412 {
413         GtkWidget *dialog;
414
415         dialog = gtk_message_dialog_new (GTK_WINDOW (ev_window),
416                                          GTK_DIALOG_DESTROY_WITH_PARENT,
417                                          GTK_MESSAGE_ERROR,
418                                          GTK_BUTTONS_CLOSE,
419                                          _("Unable to open document"));
420         gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
421                                                   "%s", error_message);
422         gtk_dialog_run (GTK_DIALOG (dialog));
423         gtk_widget_destroy (dialog);
424 }
425
426 static void
427 update_window_title (EvDocument *document, GParamSpec *pspec, EvWindow *ev_window)
428 {
429         char *title = NULL;
430         char *doc_title = NULL;
431         gboolean password_needed;
432
433         password_needed = (ev_window->priv->password_document != NULL);
434         if (document && ev_window->priv->page_cache) {
435                 doc_title = ev_page_cache_get_title (ev_window->priv->page_cache);
436
437                 /* Make sure we get a valid title back */
438                 if (doc_title) {
439                         if (doc_title[0] == '\000' ||
440                             !g_utf8_validate (doc_title, -1, NULL)) {
441                                 g_free (doc_title);
442                                 doc_title = NULL;
443                         }
444                 }
445         }
446
447         if (doc_title) {
448                 char *p;
449
450                 for (p = doc_title; *p; ++p) {
451                         /* an '\n' byte is always ASCII, no need for UTF-8 special casing */
452                         if (*p == '\n')
453                                 *p = ' ';
454                 }
455         }
456
457         if (doc_title == NULL && ev_window->priv->uri) {
458                 char *basename;
459
460                 basename = g_path_get_basename (ev_window->priv->uri);
461                 doc_title = gnome_vfs_unescape_string_for_display (basename);
462                 g_free (basename);
463         }
464
465         if (password_needed) {
466                 if (doc_title == NULL) {
467                         title = g_strdup (_("Document Viewer - Password Required"));
468                 } else {
469                         title = g_strdup_printf (_("%s - Password Required"), doc_title);
470                 }
471         } else {
472                 if (doc_title == NULL) {
473                         title = g_strdup (_("Document Viewer"));
474                 } else {
475                         title = g_strdup (doc_title);
476                 }
477         }
478
479         gtk_window_set_title (GTK_WINDOW (ev_window), title);
480
481         g_free (doc_title);
482         g_free (title);
483 }
484
485 static void
486 find_changed_cb (EvDocument *document, int page, EvWindow *ev_window)
487 {
488         update_action_sensitivity (ev_window);
489 }
490
491 static void
492 page_changed_cb (EvPageCache *page_cache,
493                  gint         page,
494                  EvWindow    *ev_window)
495 {
496         update_action_sensitivity (ev_window);
497 }
498
499 static void
500 update_document_mode (EvWindow *window, EvDocumentMode mode)
501 {
502         if (mode == EV_DOCUMENT_MODE_FULL_SCREEN) {
503                 gtk_window_fullscreen (GTK_WINDOW (window));
504         }
505 }
506
507 static void
508 ev_window_setup_document (EvWindow *ev_window)
509 {
510         EvDocumentInfo *info;
511         EvDocument *document;
512         EvView *view = EV_VIEW (ev_window->priv->view);
513         EvSidebar *sidebar = EV_SIDEBAR (ev_window->priv->sidebar);
514         GtkAction *action;
515
516         document = ev_window->priv->document;
517         ev_window->priv->page_cache = ev_document_get_page_cache (ev_window->priv->document);
518         g_signal_connect (ev_window->priv->page_cache, "page-changed", G_CALLBACK (page_changed_cb), ev_window);
519
520         g_signal_connect_object (G_OBJECT (document),
521                                  "notify::title",
522                                  G_CALLBACK (update_window_title),
523                                  ev_window, 0);
524         if (EV_IS_DOCUMENT_FIND (document)) {
525                 g_signal_connect_object (G_OBJECT (document),
526                                          "find_changed",
527                                          G_CALLBACK (find_changed_cb),  
528                                          ev_window, 0);
529         }
530
531         ev_window_set_page_mode (ev_window, PAGE_MODE_SINGLE_PAGE);
532
533         ev_sidebar_set_document (sidebar, document);
534
535         if (ev_page_cache_get_n_pages (ev_window->priv->page_cache) > 0) {
536                 ev_view_set_document (view, document);
537         }
538
539         update_window_title (document, NULL, ev_window);
540         action = gtk_action_group_get_action (ev_window->priv->action_group, PAGE_SELECTOR_ACTION);
541         ev_page_action_set_document (EV_PAGE_ACTION (action), document);
542         update_action_sensitivity (ev_window);
543
544         info = ev_document_get_info (document);
545         update_document_mode (ev_window, info->mode);
546         g_free (info);
547 }
548
549 static void
550 password_dialog_response (GtkWidget *password_dialog,
551                           gint       response_id,
552                           EvWindow  *ev_window)
553 {
554         char *password;
555         
556         if (response_id == GTK_RESPONSE_OK) {
557                 EvDocument *document;
558                 gchar *uri;
559
560                 password = ev_password_dialog_get_password (password_dialog);
561                 if (password) {
562                         ev_document_doc_mutex_lock ();
563                         ev_document_security_set_password (EV_DOCUMENT_SECURITY (ev_window->priv->password_document),
564                                                            password);
565                         ev_document_doc_mutex_unlock ();
566                 }
567                 g_free (password);
568
569                 document = ev_window->priv->password_document;
570                 uri = ev_window->priv->password_uri;
571
572                 ev_window->priv->password_document = NULL;
573                 ev_window->priv->password_uri = NULL;
574
575                 if (start_loading_document (ev_window, document, uri)) {
576                         gtk_widget_destroy (password_dialog);
577                 }
578
579                 g_object_unref (document);
580                 g_free (uri);
581
582                 return;
583         }
584
585         gtk_widget_set_sensitive (ev_window->priv->password_view, TRUE);
586         gtk_widget_destroy (password_dialog);
587 }
588
589 /* Called either by start_loading_document or by the "unlock" callback on the
590  * password_view page.  It assumes that ev_window->priv->password_* has been set
591  * correctly.  These are cleared by password_dialog_response() */
592
593 static void
594 ev_window_popup_password_dialog (EvWindow *ev_window)
595 {
596         g_assert (ev_window->priv->password_document);
597         g_assert (ev_window->priv->password_uri);
598
599         gtk_widget_set_sensitive (ev_window->priv->password_view, FALSE);
600
601         update_window_title (ev_window->priv->password_document, NULL, ev_window);
602         if (ev_window->priv->password_dialog == NULL) {
603                 gchar *basename, *file_name;
604
605                 basename = g_path_get_basename (ev_window->priv->password_uri);
606                 file_name = gnome_vfs_unescape_string_for_display (basename);
607                 ev_window->priv->password_dialog =
608                         ev_password_dialog_new (GTK_WIDGET (ev_window), file_name);
609                 g_object_add_weak_pointer (G_OBJECT (ev_window->priv->password_dialog),
610                                            (gpointer *) &(ev_window->priv->password_dialog));
611                 g_signal_connect (ev_window->priv->password_dialog,
612                                   "response",
613                                   G_CALLBACK (password_dialog_response),
614                                   ev_window);
615                 g_free (basename);
616                 g_free (file_name);
617                 gtk_widget_show (ev_window->priv->password_dialog);
618         } else {
619                 ev_password_dialog_set_bad_pass (ev_window->priv->password_dialog);
620         }
621 }
622
623 /* This wil try to load the document.  It might be called multiple times on the
624  * same document by the password dialog.
625  *
626  * Since the flow of the error dialog is very confusing, we assume that both
627  * document and uri will go away after this function is called, and thus we need
628  * to ref/dup them.  Additionally, it needs to clear
629  * ev_window->priv->password_{uri,document}, and thus people who call this
630  * function should _not_ necessarily expect those to exist after being
631  * called. */
632 static gboolean
633 start_loading_document (EvWindow   *ev_window,
634                         EvDocument *document,
635                         const char *uri)
636 {
637         gboolean result;
638         GError *error = NULL;
639
640         g_assert (document);
641         g_assert (document != ev_window->priv->document);
642         g_assert (uri);
643         if (ev_window->priv->password_document) {
644                 g_object_unref (ev_window->priv->password_document);
645                 ev_window->priv->password_document = NULL;
646         }
647         if (ev_window->priv->password_uri) {
648                 g_free (ev_window->priv->password_uri);
649                 ev_window->priv->password_uri = NULL;
650         }
651
652         result = ev_document_load (document, uri, &error);
653
654         /* Success! */
655         if (result) {
656                 if (ev_window->priv->document)
657                         g_object_unref (ev_window->priv->document);
658                 ev_window->priv->document = g_object_ref (document);
659                 ev_window_setup_document (ev_window);
660                 
661                 ev_window_add_recent (ev_window, uri);
662
663                 return TRUE;
664         }
665
666         /* unable to load the document */
667         g_assert (error != NULL);
668
669         if (error->domain == EV_DOCUMENT_ERROR &&
670             error->code == EV_DOCUMENT_ERROR_ENCRYPTED) {
671                 gchar *base_name, *file_name;
672
673                 ev_window->priv->password_document = g_object_ref (document);
674                 ev_window->priv->password_uri = g_strdup (uri);
675
676                 base_name = g_path_get_basename (uri);
677                 file_name = gnome_vfs_unescape_string_for_display (base_name);
678
679                 ev_password_view_set_file_name (EV_PASSWORD_VIEW (ev_window->priv->password_view),
680                                                 file_name);
681                 g_free (file_name);
682                 g_free (base_name);
683                 ev_window_set_page_mode (ev_window, PAGE_MODE_PASSWORD);
684
685                 ev_window_popup_password_dialog (ev_window);
686         } else {
687                 unable_to_load (ev_window, error->message);
688         }
689         g_error_free (error);
690
691         return FALSE;
692 }
693
694 void
695 ev_window_open (EvWindow *ev_window, const char *uri)
696 {
697         EvDocument *document = NULL;
698         char *mime_type;
699
700         g_free (ev_window->priv->uri);
701         ev_window->priv->uri = g_strdup (uri);
702
703         mime_type = gnome_vfs_get_mime_type (uri);
704
705         if (mime_type == NULL)
706                 document = NULL;
707         else {
708                 GType document_type = ev_document_type_lookup (mime_type);
709
710                 if (document_type!=G_TYPE_INVALID) {
711                         document = g_object_new (document_type, NULL);
712                 }
713         }
714
715         if (document) {
716                 start_loading_document (ev_window, document, uri);
717                 /* See the comment on start_loading_document on ref counting.
718                  * As the password dialog flow is confusing, we're very explicit
719                  * on ref counting. */
720                 g_object_unref (document);
721         } else {
722                 char *error_message;
723
724                 error_message = g_strdup_printf (_("Unhandled MIME type: '%s'"),
725                                                  mime_type?mime_type:"<Unknown MIME Type>");
726                 unable_to_load (ev_window, error_message);
727                 g_free (error_message);
728         }
729
730         g_free (mime_type);
731 }
732
733 static void
734 ev_window_open_uri_list (EvWindow *ev_window, GList *uri_list)
735 {
736         GList *list;
737         gchar *uri, *mime_type;
738         
739         g_return_if_fail (uri_list != NULL);
740         
741         list = uri_list;
742         while (list) {
743                 uri = gnome_vfs_uri_to_string (list->data, GNOME_VFS_URI_HIDE_NONE);
744                 mime_type = gnome_vfs_get_mime_type (uri);
745                 
746                 if (ev_document_type_lookup (mime_type)!=G_TYPE_INVALID) {
747                         if (ev_window_is_empty (EV_WINDOW (ev_window))) {
748                                 ev_window_open (ev_window, uri);
749                                 
750                                 gtk_widget_show (GTK_WIDGET (ev_window));
751                         } else {
752                                 EvWindow *new_window;
753                                 
754                                 new_window = ev_application_new_window (EV_APP);
755                                 ev_window_open (new_window, uri);
756                                 
757                                 gtk_widget_show (GTK_WIDGET (new_window));
758                         }
759                 }
760
761                 g_free (mime_type);
762                 g_free (uri);
763
764                 list = g_list_next (list);
765         }
766 }
767
768 static void
769 ev_window_cmd_file_open (GtkAction *action, EvWindow *ev_window)
770 {
771         ev_application_open (EV_APP, NULL);
772 }
773
774 static void
775 ev_window_cmd_recent_file_activate (EggRecentViewGtk *view, EggRecentItem *item,
776                                     EvWindow *ev_window)
777 {
778         char *uri;
779         GtkWidget *window;
780
781         uri = egg_recent_item_get_uri (item);
782
783         window = GTK_WIDGET (ev_application_get_empty_window (EV_APP));
784         gtk_widget_show (window);
785         ev_window_open (EV_WINDOW (window), uri);
786         
787         g_free (uri);
788 }
789
790 static void
791 ev_window_add_recent (EvWindow *window, const char *filename)
792 {
793         EggRecentItem *item;
794
795         if (strstr (filename, "file:///") == NULL)
796                 return;
797
798         item = egg_recent_item_new_from_uri (filename);
799         egg_recent_item_add_group (item, "Evince");
800         egg_recent_model_add_full (window->priv->recent_model, item);
801 }
802
803 static void
804 ev_window_setup_recent (EvWindow *ev_window)
805 {
806         GtkWidget *menu_item;
807         GtkWidget *menu;
808
809         menu_item = gtk_ui_manager_get_widget (ev_window->priv->ui_manager, "/MainMenu/FileMenu");
810         menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (menu_item));
811         menu_item = gtk_ui_manager_get_widget (ev_window->priv->ui_manager, "/MainMenu/FileMenu/RecentFilesMenu");
812
813         g_return_if_fail (menu != NULL);
814         g_return_if_fail (menu_item != NULL);
815
816         /* it would be better if we just filtered by mime-type, but there
817          * doesn't seem to be an easy way to figure out which mime-types we
818          * can handle */
819         ev_window->priv->recent_model = egg_recent_model_new (EGG_RECENT_MODEL_SORT_MRU);
820
821         ev_window->priv->recent_view = egg_recent_view_gtk_new (menu, menu_item);
822         egg_recent_view_gtk_show_icons (EGG_RECENT_VIEW_GTK (ev_window->priv->recent_view), FALSE);
823         egg_recent_model_set_limit (ev_window->priv->recent_model, 5);
824
825         egg_recent_view_set_model (EGG_RECENT_VIEW (ev_window->priv->recent_view),
826                                    ev_window->priv->recent_model);
827
828         egg_recent_model_set_filter_groups (ev_window->priv->recent_model,
829                                             "Evince", NULL);
830
831         egg_recent_view_gtk_set_trailing_sep (ev_window->priv->recent_view, TRUE);
832         
833         g_signal_connect (ev_window->priv->recent_view, "activate",
834                         G_CALLBACK (ev_window_cmd_recent_file_activate), ev_window);
835 }
836
837 /* FIXME
838 static gboolean
839 overwrite_existing_file (GtkWindow *window, const gchar *file_name)
840 {
841         GtkWidget *msgbox;
842         gchar *utf8_file_name;
843         AtkObject *obj;
844         gint ret;
845
846         utf8_file_name = g_filename_to_utf8 (file_name, -1, NULL, NULL, NULL);
847         msgbox = gtk_message_dialog_new (
848                 window,
849                 (GtkDialogFlags)GTK_DIALOG_DESTROY_WITH_PARENT,
850                 GTK_MESSAGE_QUESTION,
851                 GTK_BUTTONS_NONE,
852                 _("A file named \"%s\" already exists."),
853                 utf8_file_name);
854         g_free (utf8_file_name);
855
856         gtk_message_dialog_format_secondary_text (
857                 GTK_MESSAGE_DIALOG (msgbox),
858                 _("Do you want to replace it with the one you are saving?"));
859
860         gtk_dialog_add_button (GTK_DIALOG (msgbox),
861                                GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
862
863         gtk_dialog_add_button (GTK_DIALOG (msgbox),
864                                _("_Replace"), GTK_RESPONSE_YES);
865
866         gtk_dialog_set_default_response (GTK_DIALOG (msgbox),
867                                          GTK_RESPONSE_CANCEL);
868
869         obj = gtk_widget_get_accessible (msgbox);
870
871         if (GTK_IS_ACCESSIBLE (obj))
872                 atk_object_set_name (obj, _("Question"));
873
874         ret = gtk_dialog_run (GTK_DIALOG (msgbox));
875         gtk_widget_destroy (msgbox);
876
877         return (ret == GTK_RESPONSE_YES);
878 }
879 */
880
881 static void
882 save_error_dialog (GtkWindow *window, const gchar *file_name)
883 {
884         GtkWidget *error_dialog;
885
886         error_dialog = gtk_message_dialog_new (
887                 window,
888                 (GtkDialogFlags)GTK_DIALOG_DESTROY_WITH_PARENT,
889                 GTK_MESSAGE_ERROR,
890                 GTK_BUTTONS_CLOSE,
891                 _("The file could not be saved as \"%s\"."),
892                 file_name);
893
894         /* Easy way to make the text bold while keeping the string
895          * above free from pango markup (FIXME ?) */
896         gtk_message_dialog_format_secondary_text (
897                 GTK_MESSAGE_DIALOG (error_dialog), " ");
898
899         gtk_dialog_run (GTK_DIALOG (error_dialog));
900         gtk_widget_destroy (error_dialog);
901 }
902
903 static void
904 ev_window_cmd_save_as (GtkAction *action, EvWindow *ev_window)
905 {
906         GtkWidget *fc;
907         GtkFileFilter *pdf_filter, *all_filter;
908         gchar *uri = NULL;
909         gboolean success;
910
911         fc = gtk_file_chooser_dialog_new (
912                 _("Save a Copy"),
913                 NULL, GTK_FILE_CHOOSER_ACTION_SAVE,
914                 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
915                 GTK_STOCK_SAVE, GTK_RESPONSE_OK,
916                 NULL);
917         gtk_window_set_modal (GTK_WINDOW (fc), TRUE);
918
919         pdf_filter = gtk_file_filter_new ();
920         gtk_file_filter_set_name (pdf_filter, _("PDF Documents"));
921         gtk_file_filter_add_mime_type (pdf_filter, "application/pdf");
922         gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fc), pdf_filter);
923
924         all_filter = gtk_file_filter_new ();
925         gtk_file_filter_set_name (all_filter, _("All Files"));
926         gtk_file_filter_add_pattern (all_filter, "*");
927         gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fc), all_filter);
928         gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (fc), pdf_filter);
929
930         gtk_dialog_set_default_response (GTK_DIALOG (fc), GTK_RESPONSE_OK);
931
932         gtk_widget_show (fc);
933
934         while (gtk_dialog_run (GTK_DIALOG (fc)) == GTK_RESPONSE_OK) {
935                 uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (fc));
936
937 /* FIXME
938                 if (g_file_test (uri, G_FILE_TEST_EXISTS) &&
939                     !overwrite_existing_file (GTK_WINDOW (fc), uri))
940                                 continue;
941 */
942                 
943                 ev_document_doc_mutex_lock ();
944                 success = ev_document_save (ev_window->priv->document, uri, NULL);
945                 ev_document_doc_mutex_unlock ();
946
947                 if (success)
948                         break;
949                 else
950                         save_error_dialog (GTK_WINDOW (fc), uri);
951         }
952         gtk_widget_destroy (fc);
953 }
954
955 static gboolean
956 using_postscript_printer (GnomePrintConfig *config)
957 {
958         const guchar *driver;
959         const guchar *transport;
960
961         driver = gnome_print_config_get (
962                 config, (const guchar *)"Settings.Engine.Backend.Driver");
963
964         transport = gnome_print_config_get (
965                 config, (const guchar *)"Settings.Transport.Backend");
966
967         if (driver) {
968                 if (!strcmp ((const gchar *)driver, "gnome-print-ps"))
969                         return TRUE;
970                 else
971                         return FALSE;
972         } else  if (transport) {
973                 if (!strcmp ((const gchar *)transport, "CUPS"))
974                         return TRUE;
975         }
976
977         return FALSE;
978 }
979
980 static void
981 ev_window_print (EvWindow *ev_window)
982 {
983         GnomePrintConfig *config;
984         GnomePrintJob *job;
985         GtkWidget *print_dialog;
986         EvPrintJob *print_job = NULL;
987
988         g_return_if_fail (EV_IS_WINDOW (ev_window));
989         g_return_if_fail (ev_window->priv->document != NULL);
990
991         config = gnome_print_config_default ();
992         job = gnome_print_job_new (config);
993
994         print_dialog = gnome_print_dialog_new (job, (guchar *) _("Print"),
995                                                (GNOME_PRINT_DIALOG_RANGE |
996                                                 GNOME_PRINT_DIALOG_COPIES));
997         gtk_dialog_set_response_sensitive (GTK_DIALOG (print_dialog),
998                                            GNOME_PRINT_DIALOG_RESPONSE_PREVIEW,
999                                            FALSE);
1000
1001         while (TRUE) {
1002                 int response;
1003                 response = gtk_dialog_run (GTK_DIALOG (print_dialog));
1004
1005                 if (response != GNOME_PRINT_DIALOG_RESPONSE_PRINT)
1006                         break;
1007
1008                 /* FIXME: Change this when we have the first backend
1009                  * that can print more than postscript
1010                  */
1011                 if (!using_postscript_printer (config)) {
1012                         GtkWidget *dialog;
1013
1014                         dialog = gtk_message_dialog_new (
1015                                 GTK_WINDOW (print_dialog), GTK_DIALOG_MODAL,
1016                                 GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
1017                                 _("Printing is not supported on this printer."));
1018                         gtk_message_dialog_format_secondary_text (
1019                                 GTK_MESSAGE_DIALOG (dialog),
1020                                 _("You were trying to print to a printer using the \"%s\" driver. This program requires a PostScript printer driver."),
1021                                 gnome_print_config_get (
1022                                         config, (guchar *)"Settings.Engine.Backend.Driver"));
1023                         gtk_dialog_run (GTK_DIALOG (dialog));
1024                         gtk_widget_destroy (dialog);
1025
1026                         continue;
1027                 }
1028
1029                 print_job = g_object_new (EV_TYPE_PRINT_JOB,
1030                                           "gnome_print_job", job,
1031                                           "document", ev_window->priv->document,
1032                                           "print_dialog", print_dialog,
1033                                           NULL);
1034                 break;
1035         }
1036
1037         gtk_widget_destroy (print_dialog);
1038
1039         if (print_job != NULL) {
1040                 ev_print_job_print (print_job, GTK_WINDOW (ev_window));
1041                 g_object_unref (print_job);
1042         }
1043 }
1044
1045 static void
1046 ev_window_cmd_file_print (GtkAction *action, EvWindow *ev_window)
1047 {
1048         ev_window_print (ev_window);
1049 }
1050
1051 static void
1052 ev_window_cmd_file_close_window (GtkAction *action, EvWindow *ev_window)
1053 {
1054         g_return_if_fail (EV_IS_WINDOW (ev_window));
1055
1056         gtk_widget_destroy (GTK_WIDGET (ev_window));
1057 }
1058
1059 static void
1060 find_not_supported_dialog (EvWindow   *ev_window)
1061 {
1062         GtkWidget *dialog;
1063
1064         /* If you change this so it isn't modal, be sure you don't
1065          * allow multiple copies of the dialog...
1066          */
1067
1068         dialog = gtk_message_dialog_new (GTK_WINDOW (ev_window),
1069                                          GTK_DIALOG_DESTROY_WITH_PARENT,
1070                                          GTK_MESSAGE_ERROR,
1071                                          GTK_BUTTONS_CLOSE,
1072                                          _("The \"Find\" feature will not work with this document"));
1073         gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
1074                                                   _("Searching for text is only supported for PDF documents."));
1075         gtk_dialog_run (GTK_DIALOG (dialog));
1076         gtk_widget_destroy (dialog);
1077 }
1078
1079 static void
1080 ev_window_cmd_edit_select_all (GtkAction *action, EvWindow *ev_window)
1081 {
1082         g_return_if_fail (EV_IS_WINDOW (ev_window));
1083
1084         ev_view_select_all (EV_VIEW (ev_window->priv->view));
1085 }
1086
1087 static void
1088 ev_window_cmd_edit_find (GtkAction *action, EvWindow *ev_window)
1089 {
1090         g_return_if_fail (EV_IS_WINDOW (ev_window));
1091
1092         if (ev_window->priv->document == NULL) {
1093                 g_printerr ("We should have set the Find menu item insensitive since there's no document\n");
1094         } else if (!EV_IS_DOCUMENT_FIND (ev_window->priv->document)) {
1095                 find_not_supported_dialog (ev_window);
1096         } else {
1097                 update_chrome_flag (ev_window, EV_CHROME_FINDBAR, NULL, TRUE);
1098
1099                 gtk_widget_grab_focus (ev_window->priv->find_bar);
1100         }
1101 }
1102
1103 static void
1104 ev_window_cmd_edit_find_next (GtkAction *action, EvWindow *ev_window)
1105 {
1106         g_return_if_fail (EV_IS_WINDOW (ev_window));
1107
1108         ev_view_find_next (EV_VIEW (ev_window->priv->view));
1109 }
1110
1111 static void
1112 ev_window_cmd_edit_copy (GtkAction *action, EvWindow *ev_window)
1113 {
1114         g_return_if_fail (EV_IS_WINDOW (ev_window));
1115
1116         ev_view_copy (EV_VIEW (ev_window->priv->view));
1117 }
1118
1119 static void
1120 ev_window_update_fullscreen_popup (EvWindow *window)
1121 {
1122         GtkWidget *popup = window->priv->fullscreen_popup;
1123         int popup_width, popup_height;
1124         GdkRectangle screen_rect;
1125         gboolean toolbar;
1126
1127         g_return_if_fail (popup != NULL);
1128
1129         toolbar = (window->priv->chrome & EV_CHROME_TOOLBAR) != 0;
1130         popup_width = popup->requisition.width;
1131         popup_height = popup->requisition.height;
1132
1133         /* FIXME multihead */
1134         gdk_screen_get_monitor_geometry (gdk_screen_get_default (),
1135                         gdk_screen_get_monitor_at_window
1136                         (gdk_screen_get_default (),
1137                          GTK_WIDGET (window)->window),
1138                          &screen_rect);
1139         if (toolbar) {
1140                 gtk_widget_set_size_request (popup,
1141                                              screen_rect.width,
1142                                              -1);
1143                 gtk_window_move (GTK_WINDOW (popup),
1144                                  screen_rect.x,
1145                                  screen_rect.y);
1146
1147         } else {
1148                 if (gtk_widget_get_direction (popup) == GTK_TEXT_DIR_RTL)
1149                 {
1150                         gtk_window_move (GTK_WINDOW (popup),
1151                                          screen_rect.x,
1152                                          screen_rect.y);
1153                 } else {
1154                         gtk_window_move (GTK_WINDOW (popup),
1155                                          screen_rect.x + screen_rect.width - popup_width,
1156                                          screen_rect.y);
1157                 }
1158         }
1159 }
1160
1161 static void
1162 screen_size_changed_cb (GdkScreen *screen,
1163                         EvWindow *window)
1164 {
1165         ev_window_update_fullscreen_popup (window);
1166 }
1167
1168 static void
1169 ev_window_sidebar_position_change_cb (GObject *object, GParamSpec *pspec,
1170                                       EvWindow *ev_window)
1171 {
1172         GConfClient *client;
1173         int sidebar_size;
1174
1175         sidebar_size = gtk_paned_get_position (GTK_PANED (object));
1176
1177         client = gconf_client_get_default ();
1178         gconf_client_set_int (client, GCONF_SIDEBAR_SIZE, sidebar_size, NULL);
1179         g_object_unref (client);
1180 }
1181
1182 static void
1183 destroy_fullscreen_popup (EvWindow *window)
1184 {
1185         if (window->priv->fullscreen_popup != NULL)
1186         {
1187                 /* FIXME multihead */
1188                 g_signal_handlers_disconnect_by_func
1189                         (gdk_screen_get_default (),
1190                          G_CALLBACK (screen_size_changed_cb), window);
1191
1192                 gtk_widget_destroy (window->priv->fullscreen_popup);
1193                 window->priv->fullscreen_popup = NULL;
1194         }
1195 }
1196
1197 static void
1198 exit_fullscreen_button_clicked_cb (GtkWidget *button, EvWindow *window)
1199 {
1200         GtkAction *action;
1201
1202         action = gtk_action_group_get_action (window->priv->action_group, "ViewFullscreen");
1203         g_return_if_fail (action != NULL);
1204
1205         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), FALSE);
1206 }
1207
1208 static void
1209 fullscreen_popup_size_request_cb (GtkWidget *popup, GtkRequisition *req, EvWindow *window)
1210 {
1211         ev_window_update_fullscreen_popup (window);
1212 }
1213
1214 static gboolean
1215 fullscreen_timeout_cb (gpointer data)
1216 {
1217         EvWindow *window = EV_WINDOW (data);
1218
1219         g_object_set (window->priv->fullscreen_popup, "visible", FALSE, NULL);
1220         ev_view_hide_cursor (EV_VIEW (window->priv->view));
1221         window->priv->fullscreen_timeout_source = NULL;
1222
1223         return FALSE;
1224 }
1225
1226 static void
1227 fullscreen_set_timeout (EvWindow *window)
1228 {
1229         GSource *source;
1230
1231         if (window->priv->fullscreen_timeout_source != NULL)
1232                 g_source_destroy (window->priv->fullscreen_timeout_source);
1233
1234         source = g_timeout_source_new (1000);
1235         g_source_set_callback (source, fullscreen_timeout_cb, window, NULL);
1236         g_source_attach (source, NULL);
1237         window->priv->fullscreen_timeout_source = source;
1238 }
1239
1240 static void
1241 fullscreen_clear_timeout (EvWindow *window)
1242 {
1243         if (window->priv->fullscreen_timeout_source != NULL)
1244                 g_source_destroy (window->priv->fullscreen_timeout_source);
1245
1246         window->priv->fullscreen_timeout_source = NULL;
1247         ev_view_show_cursor (EV_VIEW (window->priv->view));
1248 }
1249
1250 static gboolean
1251 fullscreen_motion_notify_cb (GtkWidget *widget,
1252                              GdkEventMotion *event,
1253                              gpointer user_data)
1254 {
1255         EvWindow *window = EV_WINDOW (user_data);
1256
1257         if (!GTK_WIDGET_VISIBLE (window->priv->fullscreen_popup)) {
1258                 g_object_set (window->priv->fullscreen_popup, "visible", TRUE, NULL);
1259                 ev_view_show_cursor (EV_VIEW (window->priv->view));
1260         }
1261
1262         fullscreen_set_timeout (window);
1263
1264         return FALSE;
1265 }
1266
1267 static gboolean
1268 fullscreen_leave_notify_cb (GtkWidget *widget,
1269                             GdkEventCrossing *event,
1270                             gpointer user_data)
1271 {
1272         EvWindow *window = EV_WINDOW (user_data);
1273
1274         fullscreen_clear_timeout (window);
1275
1276         return FALSE;
1277 }
1278
1279 static GtkWidget *
1280 ev_window_get_exit_fullscreen_button (EvWindow *window)
1281 {
1282         GtkWidget *button, *icon, *label, *hbox;
1283
1284         button = gtk_button_new ();
1285         g_signal_connect (button, "clicked",
1286                           G_CALLBACK (exit_fullscreen_button_clicked_cb),
1287                           window);
1288         gtk_widget_show (button);
1289
1290         hbox = gtk_hbox_new (FALSE, 2);
1291         gtk_widget_show (hbox);
1292         gtk_container_add (GTK_CONTAINER (button), hbox);
1293
1294         icon = gtk_image_new_from_stock (EV_STOCK_LEAVE_FULLSCREEN, GTK_ICON_SIZE_BUTTON);
1295         gtk_widget_show (icon);
1296         gtk_box_pack_start (GTK_BOX (hbox), icon, FALSE, FALSE, 0);
1297
1298         label = gtk_label_new (_("Leave Fullscreen"));
1299         gtk_widget_show (label);
1300         gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
1301
1302         return button;
1303 }
1304
1305 static GtkWidget *
1306 ev_window_create_fullscreen_popup (EvWindow *window)
1307 {
1308         GtkWidget *popup;
1309         GtkWidget *hbox;
1310         GtkWidget *button;
1311
1312         popup = gtk_window_new (GTK_WINDOW_POPUP);
1313         hbox = gtk_hbox_new (FALSE, 0);
1314         button = ev_window_get_exit_fullscreen_button (window);
1315
1316         gtk_container_add (GTK_CONTAINER (popup), hbox);
1317         gtk_box_pack_start (GTK_BOX (hbox), window->priv->fullscreen_toolbar,
1318                             TRUE, TRUE, 0);
1319         gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
1320
1321         gtk_widget_show (button);
1322         gtk_widget_show (hbox);
1323
1324         gtk_window_set_resizable (GTK_WINDOW (popup), FALSE);
1325
1326         /* FIXME multihead */
1327         g_signal_connect (gdk_screen_get_default (), "size-changed",
1328                           G_CALLBACK (screen_size_changed_cb), window);
1329         g_signal_connect (popup, "size_request",
1330                           G_CALLBACK (fullscreen_popup_size_request_cb), window);
1331
1332         return popup;
1333 }
1334
1335 static void
1336 ev_window_fullscreen (EvWindow *window)
1337 {
1338         window->priv->fullscreen_mode = TRUE;
1339
1340         if (window->priv->fullscreen_popup == NULL)
1341                 window->priv->fullscreen_popup
1342                         = ev_window_create_fullscreen_popup (window);
1343         update_chrome_visibility (window);
1344
1345         g_object_set (G_OBJECT (window->priv->scrolled_window),
1346                       "shadow-type", GTK_SHADOW_NONE,
1347                       NULL);
1348
1349         g_signal_connect (window->priv->view,
1350                           "motion-notify-event",
1351                           G_CALLBACK (fullscreen_motion_notify_cb),
1352                           window);
1353         g_signal_connect (window->priv->view,
1354                           "leave-notify-event",
1355                           G_CALLBACK (fullscreen_leave_notify_cb),
1356                           window);
1357         fullscreen_set_timeout (window);
1358
1359         gtk_widget_grab_focus (window->priv->view);
1360
1361         ev_window_update_fullscreen_popup (window);
1362 }
1363
1364 static void
1365 ev_window_unfullscreen (EvWindow *window)
1366 {
1367         EvView *view = EV_VIEW (window->priv->view);
1368
1369         window->priv->fullscreen_mode = FALSE;
1370
1371         g_object_set (G_OBJECT (window->priv->scrolled_window),
1372                       "shadow-type", GTK_SHADOW_IN,
1373                       NULL);
1374
1375         fullscreen_clear_timeout (window);
1376
1377         g_signal_handlers_disconnect_by_func (view,
1378                                               (gpointer) fullscreen_motion_notify_cb,
1379                                               window);
1380
1381         ev_view_set_show_border (view, TRUE);
1382         ev_view_set_spacing (view, VIEW_SPACING);       
1383         update_chrome_visibility (window);
1384 }
1385
1386 static void
1387 ev_window_cmd_view_fullscreen (GtkAction *action, EvWindow *window)
1388 {
1389         EvView *view;
1390         gboolean fullscreen;
1391
1392         g_return_if_fail (EV_IS_WINDOW (window));
1393
1394         view = EV_VIEW (window->priv->view);
1395         fullscreen = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1396
1397         if (fullscreen) {
1398                 gtk_window_fullscreen (GTK_WINDOW (window));
1399         } else {
1400                 gtk_window_unfullscreen (GTK_WINDOW (window));
1401         }
1402
1403         ev_view_set_show_border (view, FALSE);
1404         ev_view_set_spacing (view, 0);  
1405 }
1406
1407 static gboolean
1408 ev_window_state_event (GtkWidget *widget, GdkEventWindowState *event)
1409 {
1410         EvWindow *window = EV_WINDOW (widget);
1411
1412         if (event->changed_mask & GDK_WINDOW_STATE_MAXIMIZED) {
1413                 gboolean show;
1414
1415                 show = (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) == 0;
1416
1417                 gtk_statusbar_set_has_resize_grip (GTK_STATUSBAR (window->priv->statusbar),
1418                                                    show);
1419         }
1420
1421         if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1422                 GtkActionGroup *action_group;
1423                 GtkAction *action;
1424                 gboolean fullscreen;
1425
1426                 fullscreen = event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN;
1427
1428                 if (fullscreen) {
1429                         ev_window_fullscreen (window);
1430                 } else {
1431                         ev_window_unfullscreen (window);
1432                 }
1433
1434                 action_group = window->priv->action_group;
1435
1436                 action = gtk_action_group_get_action (action_group, "ViewFullscreen");
1437                 g_signal_handlers_block_by_func
1438                         (action, G_CALLBACK (ev_window_cmd_view_fullscreen), window);
1439                 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), fullscreen);
1440                 g_signal_handlers_unblock_by_func
1441                         (action, G_CALLBACK (ev_window_cmd_view_fullscreen), window);
1442         }
1443
1444         return FALSE;
1445 }
1446
1447 static gboolean
1448 ev_window_focus_in_event (GtkWidget *widget, GdkEventFocus *event)
1449 {
1450         EvWindow *window = EV_WINDOW (widget);
1451         EvWindowPrivate *priv = window->priv;
1452
1453         if (priv->fullscreen_mode)
1454         {
1455                 gtk_widget_show (priv->fullscreen_popup);
1456         }
1457
1458         return GTK_WIDGET_CLASS (ev_window_parent_class)->focus_in_event (widget, event);
1459 }
1460
1461 static gboolean
1462 ev_window_focus_out_event (GtkWidget *widget, GdkEventFocus *event)
1463 {
1464         EvWindow *window = EV_WINDOW (widget);
1465         EvWindowPrivate *priv = window->priv;
1466
1467         if (priv->fullscreen_mode)
1468         {
1469                 gtk_widget_hide (priv->fullscreen_popup);
1470         }
1471
1472         return GTK_WIDGET_CLASS (ev_window_parent_class)->focus_out_event (widget, event);
1473 }
1474
1475 static void
1476 ev_window_set_page_mode (EvWindow         *window,
1477                          EvWindowPageMode  page_mode)
1478 {
1479         GtkWidget *child = NULL;
1480         GtkWidget *real_child;
1481
1482         if (window->priv->page_mode == page_mode)
1483                 return;
1484
1485         window->priv->page_mode = page_mode;
1486
1487         switch (page_mode) {
1488         case PAGE_MODE_SINGLE_PAGE:
1489                 child = window->priv->view;
1490                 break;
1491         case PAGE_MODE_PASSWORD:
1492                 child = window->priv->password_view;
1493                 break;
1494         case PAGE_MODE_CONTINUOUS_PAGE:
1495                 child = window->priv->page_view;
1496                 break;
1497         default:
1498                 g_assert_not_reached ();
1499         }
1500
1501         real_child = gtk_bin_get_child (GTK_BIN (window->priv->scrolled_window));
1502         if (child != real_child) {
1503                 gtk_container_remove (GTK_CONTAINER (window->priv->scrolled_window),
1504                                       real_child);
1505                 gtk_container_add (GTK_CONTAINER (window->priv->scrolled_window),
1506                                    child);
1507         }
1508         update_action_sensitivity (window);
1509 }
1510
1511 static void
1512 ev_window_cmd_view_zoom_in (GtkAction *action, EvWindow *ev_window)
1513 {
1514         g_return_if_fail (EV_IS_WINDOW (ev_window));
1515
1516         ev_window_set_sizing_mode (ev_window, EV_SIZING_FREE, FALSE);
1517         ev_view_zoom_in (EV_VIEW (ev_window->priv->view));
1518         update_action_sensitivity (ev_window);
1519 }
1520
1521 static void
1522 ev_window_cmd_view_zoom_out (GtkAction *action, EvWindow *ev_window)
1523 {
1524         g_return_if_fail (EV_IS_WINDOW (ev_window));
1525
1526         ev_window_set_sizing_mode (ev_window, EV_SIZING_FREE, FALSE);
1527         ev_view_zoom_out (EV_VIEW (ev_window->priv->view));
1528         update_action_sensitivity (ev_window);
1529 }
1530
1531 static void
1532 ev_window_cmd_view_normal_size (GtkAction *action, EvWindow *ev_window)
1533 {
1534         g_return_if_fail (EV_IS_WINDOW (ev_window));
1535
1536         ev_view_zoom_normal (EV_VIEW (ev_window->priv->view));
1537         update_action_sensitivity (ev_window);
1538 }
1539
1540 static void
1541 ev_window_cmd_go_previous_page (GtkAction *action, EvWindow *ev_window)
1542 {
1543         g_return_if_fail (EV_IS_WINDOW (ev_window));
1544
1545         ev_page_cache_prev_page (ev_window->priv->page_cache);
1546 }
1547
1548 static void
1549 ev_window_cmd_go_next_page (GtkAction *action, EvWindow *ev_window)
1550 {
1551         g_return_if_fail (EV_IS_WINDOW (ev_window));
1552
1553         ev_page_cache_next_page (ev_window->priv->page_cache);
1554 }
1555
1556 static void
1557 ev_window_cmd_go_first_page (GtkAction *action, EvWindow *ev_window)
1558 {
1559         g_return_if_fail (EV_IS_WINDOW (ev_window));
1560
1561         ev_page_cache_set_current_page (ev_window->priv->page_cache, 0);
1562 }
1563
1564 static void
1565 ev_window_cmd_go_last_page (GtkAction *action, EvWindow *ev_window)
1566 {
1567         int n_pages;
1568
1569         g_return_if_fail (EV_IS_WINDOW (ev_window));
1570
1571         n_pages = ev_page_cache_get_n_pages (ev_window->priv->page_cache);
1572         ev_page_cache_set_current_page (ev_window->priv->page_cache, n_pages - 1);
1573 }
1574
1575 static void
1576 ev_window_cmd_view_reload (GtkAction *action, EvWindow *ev_window)
1577 {
1578         char *uri;
1579         int page;
1580
1581         g_return_if_fail (EV_IS_WINDOW (ev_window));
1582
1583         page = ev_page_cache_get_current_page (ev_window->priv->page_cache);
1584         uri = g_strdup (ev_window->priv->uri);
1585
1586         ev_window_open (ev_window, uri);
1587         ev_window_open_page (ev_window, page);
1588
1589         g_free (uri);
1590 }
1591
1592 static void
1593 ev_window_cmd_help_contents (GtkAction *action, EvWindow *ev_window)
1594 {
1595         GError *error = NULL;
1596
1597         g_return_if_fail (EV_IS_WINDOW (ev_window));
1598
1599         gnome_help_display ("evince.xml", NULL, &error);
1600
1601         if(error != NULL) {
1602                 g_warning (error->message);
1603                 g_error_free (error);
1604         }
1605 }
1606
1607 static void
1608 ev_window_cmd_leave_fullscreen (GtkAction *action, EvWindow *window)
1609 {
1610         gtk_window_unfullscreen (GTK_WINDOW (window));
1611 }
1612
1613 static void
1614 ev_window_cmd_escape (GtkAction *action, EvWindow *window)
1615 {
1616         GtkWidget *widget;
1617
1618         widget = gtk_window_get_focus (GTK_WINDOW (window));
1619         if (widget && gtk_widget_get_ancestor (widget, EGG_TYPE_FIND_BAR)) {
1620                 update_chrome_flag (window, EV_CHROME_FINDBAR, NULL, FALSE);
1621         } else {
1622                 gtk_window_unfullscreen (GTK_WINDOW (window));
1623         }
1624 }
1625
1626 static void
1627 update_view_size (EvWindow *window)
1628 {
1629         int width, height;
1630         GtkRequisition vsb_requisition;
1631         GtkRequisition hsb_requisition;
1632         int scrollbar_spacing;
1633
1634         /* Calculate the width available for the */
1635         width = window->priv->scrolled_window->allocation.width;
1636         height = window->priv->scrolled_window->allocation.height;
1637
1638         if (gtk_scrolled_window_get_shadow_type (GTK_SCROLLED_WINDOW (window->priv->scrolled_window)) == GTK_SHADOW_IN) {
1639                 width -= 2 * window->priv->view->style->xthickness;
1640                 height -= 2 * window->priv->view->style->ythickness;
1641         }
1642
1643         gtk_widget_size_request (GTK_SCROLLED_WINDOW (window->priv->scrolled_window)->vscrollbar,
1644                                  &vsb_requisition);
1645         gtk_widget_size_request (GTK_SCROLLED_WINDOW (window->priv->scrolled_window)->hscrollbar,
1646                                  &hsb_requisition);
1647         gtk_widget_style_get (window->priv->scrolled_window,
1648                               "scrollbar_spacing", &scrollbar_spacing,
1649                               NULL);
1650
1651         ev_view_set_zoom_for_size (EV_VIEW (window->priv->view),
1652                                    MAX (1, width),
1653                                    MAX (1, height),
1654                                    vsb_requisition.width + scrollbar_spacing,
1655                                    hsb_requisition.height + scrollbar_spacing);
1656 }
1657
1658 static void
1659 size_allocate_cb (GtkWidget     *scrolled_window,
1660                   GtkAllocation *allocation,
1661                   EvWindow      *window)
1662 {
1663         update_view_size (window);
1664 }
1665
1666 static void
1667 ev_window_set_sizing_mode (EvWindow     *ev_window,
1668                            EvSizingMode  sizing_mode,
1669                            gboolean      first_time)
1670 {
1671         GtkWidget *scrolled_window;
1672
1673         /* Short circuit the call if it's not the first time we call this */
1674         if (!first_time) {
1675                 EvSizingMode old_sizing_mode;
1676
1677                 g_object_get (ev_window->priv->view,
1678                               "sizing-mode", &old_sizing_mode,
1679                               NULL);
1680                 if (old_sizing_mode == sizing_mode)
1681                         return;
1682         }
1683
1684         scrolled_window = ev_window->priv->scrolled_window;
1685         g_object_set (ev_window->priv->view,
1686                       "sizing-mode", sizing_mode,
1687                       NULL);
1688         g_signal_handlers_disconnect_by_func (scrolled_window, size_allocate_cb, ev_window);
1689
1690         update_view_size (ev_window);
1691
1692         switch (sizing_mode) {
1693         case EV_SIZING_BEST_FIT:
1694                 g_object_set (G_OBJECT (scrolled_window),
1695                               "hscrollbar-policy", GTK_POLICY_NEVER,
1696                               "vscrollbar-policy", GTK_POLICY_NEVER,
1697                               NULL);
1698                 g_signal_connect (scrolled_window, "size-allocate",
1699                                   G_CALLBACK (size_allocate_cb),
1700                                   ev_window);
1701                 break;
1702         case EV_SIZING_FIT_WIDTH:
1703                 g_object_set (G_OBJECT (scrolled_window),
1704                               "hscrollbar-policy", GTK_POLICY_NEVER,
1705                               "vscrollbar-policy", GTK_POLICY_AUTOMATIC,
1706                               NULL);
1707                 g_signal_connect (scrolled_window, "size-allocate",
1708                                   G_CALLBACK (size_allocate_cb),
1709                                   ev_window);
1710                 break;
1711         case EV_SIZING_FREE:
1712                 g_object_set (G_OBJECT (scrolled_window),
1713                               "hscrollbar-policy", GTK_POLICY_AUTOMATIC,
1714                               "vscrollbar-policy", GTK_POLICY_AUTOMATIC,
1715                               NULL);
1716                 break;
1717         }
1718
1719         update_sizing_buttons (ev_window);
1720 }
1721
1722 static void
1723 ev_window_cmd_help_about (GtkAction *action, EvWindow *ev_window)
1724 {
1725         const char *authors[] = {
1726                 N_("Many..."),
1727                 NULL
1728         };
1729
1730         const char *documenters[] = {
1731                 N_("Not so many..."),
1732                 NULL
1733         };
1734
1735         const char *license[] = {
1736                 N_("Evince is free software; you can redistribute it and/or modify\n"
1737                    "it under the terms of the GNU General Public License as published by\n"
1738                    "the Free Software Foundation; either version 2 of the License, or\n"
1739                    "(at your option) any later version.\n"),
1740                 N_("Evince is distributed in the hope that it will be useful,\n"
1741                    "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
1742                    "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
1743                    "GNU General Public License for more details.\n"),
1744                 N_("You should have received a copy of the GNU General Public License\n"
1745                    "along with Evince; if not, write to the Free Software Foundation, Inc.,\n"
1746                    "59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n")
1747         };
1748
1749         char *license_trans;
1750
1751 #ifdef ENABLE_NLS
1752         const char **p;
1753
1754         for (p = authors; *p; ++p)
1755                 *p = _(*p);
1756
1757         for (p = documenters; *p; ++p)
1758                 *p = _(*p);
1759 #endif
1760
1761         license_trans = g_strconcat (_(license[0]), "\n", _(license[1]), "\n",
1762                                      _(license[2]), "\n", NULL);
1763
1764         gtk_show_about_dialog (
1765                 GTK_WINDOW (ev_window),
1766                 "name", _("Evince"),
1767                 "version", VERSION,
1768                 "copyright",
1769                 _("\xc2\xa9 1996-2004 The Evince authors"),
1770                 "license", license_trans,
1771                 "website", "http://www.gnome.org/projects/evince",
1772                 "comments", _("PostScript and PDF File Viewer."),
1773                 "authors", authors,
1774                 "documenters", documenters,
1775                 "translator-credits", _("translator-credits"),
1776                 NULL);
1777
1778         g_free (license_trans);
1779 }
1780
1781 static void
1782 ev_window_view_toolbar_cb (GtkAction *action, EvWindow *ev_window)
1783 {
1784         update_chrome_flag (ev_window, EV_CHROME_TOOLBAR,
1785                             GCONF_CHROME_TOOLBAR,
1786                             gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
1787 }
1788
1789 static void
1790 ev_window_view_statusbar_cb (GtkAction *action, EvWindow *ev_window)
1791 {
1792         update_chrome_flag (ev_window, EV_CHROME_STATUSBAR,
1793                             GCONF_CHROME_STATUSBAR,
1794                             gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
1795 }
1796
1797 static void
1798 ev_window_view_sidebar_cb (GtkAction *action, EvWindow *ev_window)
1799 {
1800         update_chrome_flag (ev_window, EV_CHROME_SIDEBAR,
1801                             GCONF_CHROME_SIDEBAR,
1802                             gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
1803 }
1804
1805 static void
1806 ev_window_sidebar_visibility_changed_cb (EvSidebar *ev_sidebar, GParamSpec *pspec,
1807                                          EvWindow   *ev_window)
1808 {
1809         GtkAction *action;
1810         gboolean visible;
1811
1812         visible = GTK_WIDGET_VISIBLE (ev_sidebar);
1813
1814         /* In fullscreen mode the sidebar is not visible,
1815          * but we don't want to update the chrome
1816          */
1817         if (ev_window->priv->fullscreen_mode)
1818                 return;
1819         
1820         action = gtk_action_group_get_action (ev_window->priv->action_group, "ViewSidebar");
1821         
1822         g_signal_handlers_block_by_func
1823                 (action, G_CALLBACK (ev_window_view_sidebar_cb), ev_window);
1824         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), visible);
1825         g_signal_handlers_unblock_by_func
1826                 (action, G_CALLBACK (ev_window_view_sidebar_cb), ev_window);
1827
1828         update_chrome_flag (ev_window, EV_CHROME_SIDEBAR,
1829                             GCONF_CHROME_SIDEBAR, visible);
1830 }
1831
1832 static void
1833 menu_item_select_cb (GtkMenuItem *proxy, EvWindow *ev_window)
1834 {
1835         GtkAction *action;
1836         char *message;
1837
1838         action = g_object_get_data (G_OBJECT (proxy), "gtk-action");
1839         g_return_if_fail (action != NULL);
1840
1841         g_object_get (G_OBJECT (action), "tooltip", &message, NULL);
1842         if (message) {
1843                 gtk_statusbar_push (GTK_STATUSBAR (ev_window->priv->statusbar),
1844                                     ev_window->priv->help_message_cid, message);
1845                 g_free (message);
1846         }
1847 }
1848
1849 static void
1850 menu_item_deselect_cb (GtkMenuItem *proxy, EvWindow *ev_window)
1851 {
1852         gtk_statusbar_pop (GTK_STATUSBAR (ev_window->priv->statusbar),
1853                            ev_window->priv->help_message_cid);
1854 }
1855
1856 static void
1857 connect_proxy_cb (GtkUIManager *ui_manager, GtkAction *action,
1858                   GtkWidget *proxy, EvWindow *ev_window)
1859 {
1860         if (GTK_IS_MENU_ITEM (proxy)) {
1861                 g_signal_connect (proxy, "select",
1862                                   G_CALLBACK (menu_item_select_cb), ev_window);
1863                 g_signal_connect (proxy, "deselect",
1864                                   G_CALLBACK (menu_item_deselect_cb),
1865                                   ev_window);
1866         }
1867 }
1868
1869 static void
1870 disconnect_proxy_cb (GtkUIManager *ui_manager, GtkAction *action,
1871                      GtkWidget *proxy, EvWindow *ev_window)
1872 {
1873         if (GTK_IS_MENU_ITEM (proxy)) {
1874                 g_signal_handlers_disconnect_by_func
1875                         (proxy, G_CALLBACK (menu_item_select_cb), ev_window);
1876                 g_signal_handlers_disconnect_by_func
1877                         (proxy, G_CALLBACK (menu_item_deselect_cb), ev_window);
1878         }
1879 }
1880
1881 static void
1882 view_status_changed_cb (EvView     *view,
1883                         GParamSpec *pspec,
1884                         EvWindow   *ev_window)
1885 {
1886         const char *message;
1887
1888         gtk_statusbar_pop (GTK_STATUSBAR (ev_window->priv->statusbar),
1889                            ev_window->priv->view_message_cid);
1890
1891         message = ev_view_get_status (view);
1892         if (message) {
1893                 gtk_statusbar_push (GTK_STATUSBAR (ev_window->priv->statusbar),
1894                                     ev_window->priv->view_message_cid, message);
1895         }
1896 }
1897
1898 static void
1899 view_find_status_changed_cb (EvView     *view,
1900                              GParamSpec *pspec,
1901                              EvWindow   *ev_window)
1902 {
1903         const char *text;
1904
1905         text = ev_view_get_find_status (view);
1906         egg_find_bar_set_status_text (EGG_FIND_BAR (ev_window->priv->find_bar),
1907                                       text);
1908 }
1909
1910 static void
1911 find_bar_previous_cb (EggFindBar *find_bar,
1912                       EvWindow   *ev_window)
1913 {
1914         ev_view_find_previous (EV_VIEW (ev_window->priv->view));
1915 }
1916
1917 static void
1918 find_bar_next_cb (EggFindBar *find_bar,
1919                   EvWindow   *ev_window)
1920 {
1921         ev_view_find_next (EV_VIEW (ev_window->priv->view));
1922 }
1923
1924 static void
1925 find_bar_close_cb (EggFindBar *find_bar,
1926                    EvWindow   *ev_window)
1927 {
1928         update_chrome_flag (ev_window, EV_CHROME_FINDBAR, NULL, FALSE);
1929 }
1930
1931 static void
1932 ev_window_page_mode_cb (GtkRadioAction *action,
1933                         GtkRadioAction *activated_action,
1934                         EvWindow       *window)
1935 {
1936         int mode;
1937
1938         mode = gtk_radio_action_get_current_value (action);
1939
1940         g_assert (mode == PAGE_MODE_CONTINUOUS_PAGE ||
1941                   mode == PAGE_MODE_SINGLE_PAGE);
1942
1943         ev_window_set_page_mode (window, (EvWindowPageMode) mode);
1944 }
1945
1946 static void
1947 find_bar_search_changed_cb (EggFindBar *find_bar,
1948                             GParamSpec *param,
1949                             EvWindow   *ev_window)
1950 {
1951         gboolean case_sensitive;
1952         gboolean visible;
1953         const char *search_string;
1954
1955         g_return_if_fail (EV_IS_WINDOW (ev_window));
1956
1957         /* Either the string or case sensitivity could have changed,
1958          * we connect this callback to both. We also connect it
1959          * to ::visible so when the find bar is hidden, we should
1960          * pretend the search string is NULL/""
1961          */
1962
1963         case_sensitive = egg_find_bar_get_case_sensitive (find_bar);
1964         visible = GTK_WIDGET_VISIBLE (find_bar);
1965         search_string = egg_find_bar_get_search_string (find_bar);
1966
1967 #if 0
1968         g_printerr ("search for '%s'\n", search_string ? search_string : "(nil)");
1969 #endif
1970
1971         if (ev_window->priv->document &&
1972             EV_IS_DOCUMENT_FIND (ev_window->priv->document)) {
1973                 if (visible && search_string && search_string[0]) {
1974                         ev_document_doc_mutex_lock ();
1975                         ev_document_find_begin (EV_DOCUMENT_FIND (ev_window->priv->document), 
1976                                                 ev_page_cache_get_current_page (ev_window->priv->page_cache),
1977                                                 search_string,
1978                                                 case_sensitive);
1979                         ev_document_doc_mutex_unlock ();
1980                 } else {
1981                         ev_document_doc_mutex_lock ();
1982                         ev_document_find_cancel (EV_DOCUMENT_FIND (ev_window->priv->document));
1983                         ev_document_doc_mutex_unlock ();
1984
1985                         egg_find_bar_set_status_text (EGG_FIND_BAR (ev_window->priv->find_bar),
1986                                                       NULL);
1987                         gtk_widget_queue_draw (GTK_WIDGET (ev_window->priv->view));
1988                 }
1989         }
1990 }
1991
1992 static void
1993 ev_window_dispose (GObject *object)
1994 {
1995         EvWindow *window = EV_WINDOW (object);
1996         EvWindowPrivate *priv = window->priv;
1997
1998         if (priv->ui_manager) {
1999                 g_object_unref (priv->ui_manager);
2000                 priv->ui_manager = NULL;
2001         }
2002
2003         if (priv->action_group) {
2004                 g_object_unref (priv->action_group);
2005                 priv->action_group = NULL;
2006         }
2007
2008         if (priv->document) {
2009                 g_object_unref (priv->document);
2010                 priv->document = NULL;
2011         }
2012
2013         if (priv->view) {
2014                 g_object_unref (priv->view);
2015                 priv->view = NULL;
2016         }
2017
2018         if (priv->page_view) {
2019                 g_object_unref (priv->page_view);
2020                 priv->page_view = NULL;
2021         }
2022
2023         if (priv->password_document) {
2024                 g_object_unref (priv->password_document);
2025                 priv->password_document = NULL;
2026         }
2027         
2028         if (priv->password_uri) {
2029                 g_free (priv->password_uri);
2030                 priv->password_uri = NULL;
2031         }
2032
2033         if (priv->find_bar) {
2034                 g_signal_handlers_disconnect_by_func
2035                         (window->priv->find_bar,
2036                          G_CALLBACK (find_bar_close_cb),
2037                          window);
2038                 priv->find_bar = NULL;
2039         }
2040
2041         destroy_fullscreen_popup (window);
2042
2043         G_OBJECT_CLASS (ev_window_parent_class)->dispose (object);
2044 }
2045
2046 static void
2047 ev_window_class_init (EvWindowClass *ev_window_class)
2048 {
2049         GObjectClass *g_object_class = G_OBJECT_CLASS (ev_window_class);
2050         GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (ev_window_class);
2051
2052         g_object_class->dispose = ev_window_dispose;
2053
2054         widget_class->window_state_event = ev_window_state_event;
2055         widget_class->focus_in_event = ev_window_focus_in_event;
2056         widget_class->focus_out_event = ev_window_focus_out_event;
2057
2058         g_type_class_add_private (g_object_class, sizeof (EvWindowPrivate));
2059 }
2060
2061 /* Normal items */
2062 static const GtkActionEntry entries[] = {
2063         { "File", NULL, N_("_File") },
2064         { "Edit", NULL, N_("_Edit") },
2065         { "View", NULL, N_("_View") },
2066         { "Go", NULL, N_("_Go") },
2067         { "Help", NULL, N_("_Help") },
2068
2069         /* File menu */
2070         { "FileOpen", GTK_STOCK_OPEN, NULL, "<control>O",
2071           N_("Open an existing document"),
2072           G_CALLBACK (ev_window_cmd_file_open) },
2073         { "FileSaveAs", GTK_STOCK_SAVE_AS, N_("_Save a Copy..."), NULL,
2074           N_("Save the current document with a new filename"),
2075           G_CALLBACK (ev_window_cmd_save_as) },
2076         { "FilePrint", GTK_STOCK_PRINT, N_("Print..."), "<control>P",
2077           N_("Print this document"),
2078           G_CALLBACK (ev_window_cmd_file_print) },
2079         { "FileCloseWindow", GTK_STOCK_CLOSE, NULL, "<control>W",
2080           N_("Close this window"),
2081           G_CALLBACK (ev_window_cmd_file_close_window) },
2082
2083         /* Edit menu */
2084         { "EditCopy", GTK_STOCK_COPY, NULL, "<control>C",
2085           N_("Copy text from the document"),
2086           G_CALLBACK (ev_window_cmd_edit_copy) },
2087         { "EditSelectAll", NULL, N_("Select _All"), "<control>A",
2088           N_("Select the entire page"),
2089           G_CALLBACK (ev_window_cmd_edit_select_all) },
2090         { "EditFind", GTK_STOCK_FIND, NULL, "<control>F",
2091           N_("Find a word or phrase in the document"),
2092           G_CALLBACK (ev_window_cmd_edit_find) },
2093         { "EditFindNext", NULL, N_("Find Ne_xt"), "<control>G",
2094           N_("Find next occurrence of the word or phrase"),
2095           G_CALLBACK (ev_window_cmd_edit_find_next) },
2096
2097         /* View menu */
2098         { "ViewZoomIn", GTK_STOCK_ZOOM_IN, NULL, "<control>plus",
2099           N_("Enlarge the document"),
2100           G_CALLBACK (ev_window_cmd_view_zoom_in) },
2101         { "ViewZoomOut", GTK_STOCK_ZOOM_OUT, NULL, "<control>minus",
2102           N_("Shrink the document"),
2103           G_CALLBACK (ev_window_cmd_view_zoom_out) },
2104         { "ViewNormalSize", GTK_STOCK_ZOOM_100, NULL, "<control>0",
2105           N_("Reset the zoom level to the default value"),
2106           G_CALLBACK (ev_window_cmd_view_normal_size) },
2107         { "ViewReload", GTK_STOCK_REFRESH, N_("_Reload"), "<control>R",
2108           N_("Reload the document"),
2109           G_CALLBACK (ev_window_cmd_view_reload) },
2110
2111         /* Go menu */
2112         { "GoPreviousPage", GTK_STOCK_GO_BACK, N_("_Previous Page"), "Page_Up",
2113           N_("Go to the previous page"),
2114           G_CALLBACK (ev_window_cmd_go_previous_page) },
2115         { "GoNextPage", GTK_STOCK_GO_FORWARD, N_("_Next Page"), "Page_Down",
2116           N_("Go to the next page"),
2117           G_CALLBACK (ev_window_cmd_go_next_page) },
2118         { "GoFirstPage", GTK_STOCK_GOTO_FIRST, N_("_First Page"), "<control>Home",
2119           N_("Go to the first page"),
2120           G_CALLBACK (ev_window_cmd_go_first_page) },
2121         { "GoLastPage", GTK_STOCK_GOTO_LAST, N_("_Last Page"), "<control>End",
2122           N_("Go to the last page"),
2123           G_CALLBACK (ev_window_cmd_go_last_page) },
2124
2125         /* Help menu */
2126         { "HelpContents", GTK_STOCK_HELP, N_("_Contents"), "F1",
2127           N_("Display help for the viewer application"),
2128           G_CALLBACK (ev_window_cmd_help_contents) },
2129
2130         { "HelpAbout", GTK_STOCK_ABOUT, N_("_About"), NULL,
2131           N_("Display credits for the document viewer creators"),
2132           G_CALLBACK (ev_window_cmd_help_about) },
2133
2134         /* Toolbar-only */
2135         { "LeaveFullscreen", EV_STOCK_LEAVE_FULLSCREEN, N_("Leave Fullscreen"), NULL,
2136           N_("Leave fullscreen mode"),
2137           G_CALLBACK (ev_window_cmd_leave_fullscreen) },
2138
2139         { "Escape", NULL, N_("Selection Caret"), "Escape", "",
2140           G_CALLBACK (ev_window_cmd_escape) }
2141 };
2142
2143 /* Toggle items */
2144 static const GtkToggleActionEntry toggle_entries[] = {
2145         /* View Menu */
2146         { "ViewToolbar", NULL, N_("_Toolbar"), "<shift><control>T",
2147           N_("Show or hide the toolbar"),
2148           G_CALLBACK (ev_window_view_toolbar_cb), TRUE },
2149         { "ViewStatusbar", NULL, N_("_Statusbar"), NULL,
2150           N_("Show or hide the statusbar"),
2151           G_CALLBACK (ev_window_view_statusbar_cb), TRUE },
2152         { "ViewSidebar", NULL, N_("Side _pane"), "F9",
2153           N_("Show or hide the side pane"),
2154           G_CALLBACK (ev_window_view_sidebar_cb), TRUE },
2155         { "ViewContinuous", NULL, N_("_Continuous"), NULL,
2156           N_("Show the entire document"),
2157           G_CALLBACK (ev_window_cmd_continuous), TRUE },
2158         { "ViewDual", NULL, N_("_Dual"), NULL,
2159           N_("Show two pages at once"),
2160           G_CALLBACK (ev_window_cmd_dual), FALSE },
2161         { "ViewFullscreen", NULL, N_("_Fullscreen"), "F11",
2162           N_("Expand the window to fill the screen"),
2163           G_CALLBACK (ev_window_cmd_view_fullscreen) },
2164         { "ViewBestFit", EV_STOCK_ZOOM_PAGE, N_("_Best Fit"), NULL,
2165           N_("Make the current document fill the window"),
2166           G_CALLBACK (ev_window_cmd_view_best_fit) },
2167         { "ViewPageWidth", EV_STOCK_ZOOM_WIDTH, N_("Fit Page _Width"), NULL,
2168           N_("Make the current document fill the window width"),
2169           G_CALLBACK (ev_window_cmd_view_page_width) },
2170 };
2171
2172 static const GtkRadioActionEntry page_view_entries[] = {
2173         { "SinglePage", GTK_STOCK_DND, N_("Single"), NULL,
2174           N_("Show the document one page at a time"),
2175           PAGE_MODE_SINGLE_PAGE },
2176         { "ContinuousPage", GTK_STOCK_DND_MULTIPLE, N_("Multi"), NULL,
2177           N_("Show the full document at once"),
2178           PAGE_MODE_CONTINUOUS_PAGE }
2179 };
2180
2181 static void
2182 drag_data_received_cb (GtkWidget *widget, GdkDragContext *context,
2183                        gint x, gint y, GtkSelectionData *selection_data,
2184                        guint info, guint time, gpointer gdata)
2185 {
2186         GList    *uri_list = NULL;
2187
2188         uri_list = gnome_vfs_uri_list_parse ((gchar *) selection_data->data);
2189
2190         if (uri_list) {
2191                 ev_window_open_uri_list (EV_WINDOW (widget), uri_list);
2192                 
2193                 gnome_vfs_uri_list_free (uri_list);
2194
2195                 gtk_drag_finish (context, TRUE, FALSE, time);
2196         }
2197 }
2198
2199 static void
2200 register_custom_actions (EvWindow *window, GtkActionGroup *group)
2201 {
2202         GtkAction *action;
2203
2204         action = g_object_new (EV_TYPE_PAGE_ACTION,
2205                                "name", PAGE_SELECTOR_ACTION,
2206                                "label", _("Page"),
2207                                "tooltip", _("Select Page"),
2208                                NULL);
2209         gtk_action_group_add_action (group, action);
2210         g_object_unref (action);
2211 }
2212
2213 static void
2214 set_action_properties (GtkActionGroup *action_group)
2215 {
2216         GtkAction *action;
2217
2218         action = gtk_action_group_get_action (action_group, "GoPreviousPage");
2219         /*translators: this is the label for toolbar button*/
2220         g_object_set (action, "short_label", _("Previous"), NULL);
2221         g_object_set (action, "is-important", TRUE, NULL);
2222
2223         action = gtk_action_group_get_action (action_group, "GoNextPage");
2224         g_object_set (action, "is-important", TRUE, NULL);
2225         /*translators: this is the label for toolbar button*/
2226         g_object_set (action, "short_label", _("Next"), NULL);
2227
2228         action = gtk_action_group_get_action (action_group, "ViewZoomIn");
2229         /*translators: this is the label for toolbar button*/
2230         g_object_set (action, "short_label", _("Zoom In"), NULL);
2231         action = gtk_action_group_get_action (action_group, "ViewZoomIn");
2232
2233         action = gtk_action_group_get_action (action_group, "ViewZoomOut");
2234         /*translators: this is the label for toolbar button*/
2235         g_object_set (action, "short_label", _("Zoom Out"), NULL);
2236         action = gtk_action_group_get_action (action_group, "ViewZoomIn");
2237
2238         action = gtk_action_group_get_action (action_group, "ViewBestFit");
2239         /*translators: this is the label for toolbar button*/
2240         g_object_set (action, "short_label", _("Best Fit"), NULL);
2241         action = gtk_action_group_get_action (action_group, "ViewZoomIn");
2242
2243         action = gtk_action_group_get_action (action_group, "ViewPageWidth");
2244         /*translators: this is the label for toolbar button*/
2245         g_object_set (action, "short_label", _("Fit Width"), NULL);
2246         action = gtk_action_group_get_action (action_group, "ViewZoomIn");
2247
2248         action = gtk_action_group_get_action (action_group, "LeaveFullscreen");
2249         g_object_set (action, "is-important", TRUE, NULL);
2250 }
2251
2252 static void
2253 set_chrome_actions (EvWindow *window)
2254 {
2255         EvWindowPrivate *priv = window->priv;
2256         GtkActionGroup *action_group = priv->action_group;
2257         GtkAction *action;
2258
2259         action= gtk_action_group_get_action (action_group, "ViewToolbar");
2260         g_signal_handlers_block_by_func
2261                 (action, G_CALLBACK (ev_window_view_toolbar_cb), window);
2262         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
2263                                       (priv->chrome & EV_CHROME_TOOLBAR) != 0);
2264         g_signal_handlers_unblock_by_func
2265                 (action, G_CALLBACK (ev_window_view_toolbar_cb), window);
2266
2267         action= gtk_action_group_get_action (action_group, "ViewSidebar");
2268         g_signal_handlers_block_by_func
2269                 (action, G_CALLBACK (ev_window_view_sidebar_cb), window);
2270         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
2271                                       (priv->chrome & EV_CHROME_SIDEBAR) != 0);
2272         g_signal_handlers_unblock_by_func
2273                 (action, G_CALLBACK (ev_window_view_sidebar_cb), window);
2274
2275         action= gtk_action_group_get_action (action_group, "ViewStatusbar");
2276         g_signal_handlers_block_by_func
2277                 (action, G_CALLBACK (ev_window_view_statusbar_cb), window);
2278         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
2279                                       (priv->chrome & EV_CHROME_STATUSBAR) != 0);
2280         g_signal_handlers_unblock_by_func
2281                 (action, G_CALLBACK (ev_window_view_statusbar_cb), window);
2282 }
2283
2284 static EvChrome
2285 load_chrome (void)
2286 {
2287         EvChrome chrome = EV_CHROME_NORMAL;
2288         GConfClient *client;
2289         GConfValue *value;
2290
2291         client = gconf_client_get_default ();
2292
2293         value = gconf_client_get (client, GCONF_CHROME_TOOLBAR, NULL);
2294         if (value != NULL) {
2295                 if (value->type == GCONF_VALUE_BOOL && !gconf_value_get_bool (value)) {
2296                         chrome &= ~EV_CHROME_TOOLBAR;
2297                 }
2298                 gconf_value_free (value);
2299         }
2300
2301         value = gconf_client_get (client, GCONF_CHROME_SIDEBAR, NULL);
2302         if (value != NULL) {
2303                 if (value->type == GCONF_VALUE_BOOL && !gconf_value_get_bool (value)) {
2304                         chrome &= ~EV_CHROME_SIDEBAR;
2305                 }
2306                 gconf_value_free (value);
2307         }
2308
2309         value = gconf_client_get (client, GCONF_CHROME_STATUSBAR, NULL);
2310         if (value != NULL) {
2311                 if (value->type == GCONF_VALUE_BOOL && !gconf_value_get_bool (value)) {
2312                         chrome &= ~EV_CHROME_STATUSBAR;
2313                 }
2314                 gconf_value_free (value);
2315         }
2316
2317         g_object_unref (client);
2318
2319         return chrome;
2320 }
2321
2322 static void
2323 sidebar_widget_model_set (EvSidebarLinks *ev_sidebar_links,
2324                           GParamSpec     *pspec,
2325                           EvWindow       *ev_window)
2326 {
2327         GtkTreeModel *model;
2328         GtkAction *action;
2329
2330         g_object_get (G_OBJECT (ev_sidebar_links),
2331                       "model", &model,
2332                       NULL);
2333
2334         action = gtk_action_group_get_action (ev_window->priv->action_group, PAGE_SELECTOR_ACTION);
2335         ev_page_action_set_model (EV_PAGE_ACTION (action), model);
2336 }
2337
2338 static void
2339 ev_window_init (EvWindow *ev_window)
2340 {
2341         GtkActionGroup *action_group;
2342         GtkAccelGroup *accel_group;
2343         GError *error = NULL;
2344         GtkWidget *sidebar_widget, *toolbar_dock;
2345         GConfValue *value;
2346         GConfClient *client;
2347         int sidebar_size;
2348
2349         ev_window->priv = EV_WINDOW_GET_PRIVATE (ev_window);
2350
2351         ev_window->priv->page_mode = PAGE_MODE_SINGLE_PAGE;
2352         update_window_title (NULL, NULL, ev_window);
2353
2354         ev_window->priv->main_box = gtk_vbox_new (FALSE, 0);
2355         gtk_container_add (GTK_CONTAINER (ev_window), ev_window->priv->main_box);
2356         gtk_widget_show (ev_window->priv->main_box);
2357
2358         action_group = gtk_action_group_new ("MenuActions");
2359         ev_window->priv->action_group = action_group;
2360         gtk_action_group_set_translation_domain (action_group, NULL);
2361         gtk_action_group_add_actions (action_group, entries,
2362                                       G_N_ELEMENTS (entries), ev_window);
2363         gtk_action_group_add_toggle_actions (action_group, toggle_entries,
2364                                              G_N_ELEMENTS (toggle_entries),
2365                                              ev_window);
2366         gtk_action_group_add_radio_actions (action_group, page_view_entries,
2367                                             G_N_ELEMENTS (page_view_entries),
2368                                             ev_window->priv->page_mode,
2369                                             G_CALLBACK (ev_window_page_mode_cb),
2370                                             ev_window);
2371         set_action_properties (action_group);
2372         register_custom_actions (ev_window, action_group);
2373
2374         ev_window->priv->ui_manager = gtk_ui_manager_new ();
2375         gtk_ui_manager_insert_action_group (ev_window->priv->ui_manager,
2376                                             action_group, 0);
2377
2378         accel_group =
2379                 gtk_ui_manager_get_accel_group (ev_window->priv->ui_manager);
2380         gtk_window_add_accel_group (GTK_WINDOW (ev_window), accel_group);
2381
2382         g_signal_connect (ev_window->priv->ui_manager, "connect_proxy",
2383                           G_CALLBACK (connect_proxy_cb), ev_window);
2384         g_signal_connect (ev_window->priv->ui_manager, "disconnect_proxy",
2385                           G_CALLBACK (disconnect_proxy_cb), ev_window);
2386
2387         if (!gtk_ui_manager_add_ui_from_file (ev_window->priv->ui_manager,
2388                                               DATADIR"/evince-ui.xml",
2389                                               &error)) {
2390                 g_message ("building menus failed: %s", error->message);
2391                 g_error_free (error);
2392         }
2393
2394         ev_window->priv->menubar =
2395                  gtk_ui_manager_get_widget (ev_window->priv->ui_manager,
2396                                             "/MainMenu");
2397         gtk_box_pack_start (GTK_BOX (ev_window->priv->main_box),
2398                             ev_window->priv->menubar,
2399                             FALSE, FALSE, 0);
2400
2401         /* This sucks, but there is no way to have a draw=no, expand=true separator
2402          * in a GtkUIManager-built toolbar. So, just add another toolbar.
2403          * See gtk+ bug 166489.
2404          */
2405         toolbar_dock = ev_window->priv->toolbar_dock = gtk_hbox_new (FALSE, 0);
2406         gtk_box_pack_start (GTK_BOX (ev_window->priv->main_box), toolbar_dock,
2407                             FALSE, FALSE, 0);
2408         gtk_widget_show (toolbar_dock);
2409
2410         ev_window->priv->toolbar =
2411                 gtk_ui_manager_get_widget (ev_window->priv->ui_manager,
2412                                            "/ToolBar");
2413         gtk_box_pack_start (GTK_BOX (toolbar_dock), ev_window->priv->toolbar,
2414                             TRUE, TRUE, 0);
2415         gtk_widget_show (ev_window->priv->toolbar);
2416
2417         ev_window->priv->fullscreen_toolbar =
2418                 gtk_ui_manager_get_widget (ev_window->priv->ui_manager, "/LeaveFullscreenToolbar");
2419         gtk_toolbar_set_show_arrow (GTK_TOOLBAR (ev_window->priv->fullscreen_toolbar), TRUE);
2420
2421         /* Add the main area */
2422         ev_window->priv->hpaned = gtk_hpaned_new ();
2423         g_signal_connect (ev_window->priv->hpaned,
2424                           "notify::position",
2425                           G_CALLBACK (ev_window_sidebar_position_change_cb),
2426                           ev_window);
2427         
2428         sidebar_size = SIDEBAR_DEFAULT_SIZE;
2429         client = gconf_client_get_default ();
2430         value = gconf_client_get (client, GCONF_SIDEBAR_SIZE, NULL);
2431         if (value != NULL) {
2432                 if (value->type == GCONF_VALUE_INT) {
2433                         sidebar_size = gconf_value_get_int (value);
2434                 }
2435                 gconf_value_free (value);
2436         }
2437         g_object_unref (client);
2438         gtk_paned_set_position (GTK_PANED (ev_window->priv->hpaned), sidebar_size);
2439         gtk_box_pack_start (GTK_BOX (ev_window->priv->main_box), ev_window->priv->hpaned,
2440                             TRUE, TRUE, 0);
2441         gtk_widget_show (ev_window->priv->hpaned);
2442         
2443         ev_window->priv->sidebar = ev_sidebar_new ();
2444         gtk_paned_pack1 (GTK_PANED (ev_window->priv->hpaned),
2445                          ev_window->priv->sidebar, FALSE, FALSE);
2446         gtk_widget_show (ev_window->priv->sidebar);
2447
2448         /* Stub sidebar, for now */
2449         sidebar_widget = ev_sidebar_links_new ();
2450         g_signal_connect (sidebar_widget,
2451                           "notify::model",
2452                           G_CALLBACK (sidebar_widget_model_set),
2453                           ev_window);
2454         gtk_widget_show (sidebar_widget);
2455         ev_sidebar_add_page (EV_SIDEBAR (ev_window->priv->sidebar),
2456                              sidebar_widget);
2457
2458         sidebar_widget = ev_sidebar_thumbnails_new ();
2459         gtk_widget_show (sidebar_widget);
2460         ev_sidebar_add_page (EV_SIDEBAR (ev_window->priv->sidebar),
2461                              sidebar_widget);
2462
2463         ev_window->priv->scrolled_window =
2464                 GTK_WIDGET (g_object_new (GTK_TYPE_SCROLLED_WINDOW,
2465                                           "shadow-type", GTK_SHADOW_IN,
2466                                           NULL));
2467         gtk_widget_show (ev_window->priv->scrolled_window);
2468
2469         gtk_paned_add2 (GTK_PANED (ev_window->priv->hpaned),
2470                         ev_window->priv->scrolled_window);
2471
2472         ev_window->priv->view = ev_view_new ();
2473         ev_view_set_spacing (EV_VIEW (ev_window->priv->view), VIEW_SPACING);    
2474         ev_window->priv->password_view = ev_password_view_new ();
2475         g_signal_connect_swapped (ev_window->priv->password_view,
2476                                   "unlock",
2477                                   G_CALLBACK (ev_window_popup_password_dialog),
2478                                   ev_window);
2479         gtk_widget_show (ev_window->priv->view);
2480         //gtk_widget_show (ev_window->priv->page_view);
2481         gtk_widget_show (ev_window->priv->password_view);
2482
2483         /* We own a ref on these widgets, as we can swap them in and out */
2484         g_object_ref (ev_window->priv->view);
2485         //g_object_ref (ev_window->priv->page_view);
2486         g_object_ref (ev_window->priv->password_view);
2487
2488         gtk_container_add (GTK_CONTAINER (ev_window->priv->scrolled_window),
2489                            ev_window->priv->view);
2490         g_signal_connect (ev_window->priv->view,
2491                           "notify::find-status",
2492                           G_CALLBACK (view_find_status_changed_cb),
2493                           ev_window);
2494         g_signal_connect (ev_window->priv->view,
2495                           "notify::status",
2496                           G_CALLBACK (view_status_changed_cb),
2497                           ev_window);
2498
2499         ev_window->priv->statusbar = gtk_statusbar_new ();
2500         gtk_box_pack_end (GTK_BOX (ev_window->priv->main_box),
2501                           ev_window->priv->statusbar,
2502                           FALSE, TRUE, 0);
2503         ev_window->priv->help_message_cid = gtk_statusbar_get_context_id
2504                 (GTK_STATUSBAR (ev_window->priv->statusbar), "help_message");
2505         ev_window->priv->view_message_cid = gtk_statusbar_get_context_id
2506                 (GTK_STATUSBAR (ev_window->priv->statusbar), "view_message");
2507
2508         ev_window->priv->find_bar = egg_find_bar_new ();
2509         gtk_box_pack_end (GTK_BOX (ev_window->priv->main_box),
2510                           ev_window->priv->find_bar,
2511                           FALSE, TRUE, 0);
2512
2513         ev_window_setup_recent (ev_window);
2514         ev_window->priv->chrome = load_chrome ();
2515         set_chrome_actions (ev_window);
2516         update_chrome_visibility (ev_window);
2517
2518         /* Connect sidebar signals */
2519         g_signal_connect (ev_window->priv->sidebar,
2520                           "notify::visible",
2521                           G_CALLBACK (ev_window_sidebar_visibility_changed_cb),
2522                           ev_window);
2523         
2524         /* Connect to find bar signals */
2525         g_signal_connect (ev_window->priv->find_bar,
2526                           "previous",
2527                           G_CALLBACK (find_bar_previous_cb),
2528                           ev_window);
2529         g_signal_connect (ev_window->priv->find_bar,
2530                           "next",
2531                           G_CALLBACK (find_bar_next_cb),
2532                           ev_window);
2533         g_signal_connect (ev_window->priv->find_bar,
2534                           "close",
2535                           G_CALLBACK (find_bar_close_cb),
2536                           ev_window);
2537         g_signal_connect (ev_window->priv->find_bar,
2538                           "notify::search-string",
2539                           G_CALLBACK (find_bar_search_changed_cb),
2540                           ev_window);
2541         g_signal_connect (ev_window->priv->find_bar,
2542                           "notify::case-sensitive",
2543                           G_CALLBACK (find_bar_search_changed_cb),
2544                           ev_window);
2545         g_signal_connect (ev_window->priv->find_bar,
2546                           "notify::visible",
2547                           G_CALLBACK (find_bar_search_changed_cb),
2548                           ev_window);
2549
2550         /* Give focus to the scrolled window */
2551         gtk_widget_grab_focus (ev_window->priv->scrolled_window);
2552
2553         /* Drag and Drop */
2554         gtk_drag_dest_unset (GTK_WIDGET (ev_window));
2555         gtk_drag_dest_set (GTK_WIDGET (ev_window), GTK_DEST_DEFAULT_ALL, ev_drop_types,
2556                            sizeof (ev_drop_types) / sizeof (ev_drop_types[0]),
2557                            GDK_ACTION_COPY);
2558         g_signal_connect (G_OBJECT (ev_window), "drag_data_received",
2559                           G_CALLBACK (drag_data_received_cb), NULL);
2560
2561         /* Set it to something random to force a change */
2562         ev_window_set_sizing_mode (ev_window,  EV_SIZING_FIT_WIDTH, TRUE);
2563         update_action_sensitivity (ev_window);
2564 }