]> www.fi.muni.cz Git - evince.git/blob - shell/ev-window.c
Use GtkRecent instead of EggRecent when it's available. Fixes bug #349273
[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-window-title.h"
33 #include "ev-page-action.h"
34 #include "ev-sidebar.h"
35 #include "ev-sidebar-links.h"
36 #include "ev-sidebar-attachments.h"
37 #include "ev-sidebar-thumbnails.h"
38 #include "ev-view.h"
39 #include "ev-password.h"
40 #include "ev-password-view.h"
41 #include "ev-properties-dialog.h"
42 #include "ev-ps-exporter.h"
43 #include "ev-document-thumbnails.h"
44 #include "ev-document-links.h"
45 #include "ev-document-fonts.h"
46 #include "ev-document-find.h"
47 #include "ev-document-security.h"
48 #include "ev-document-factory.h"
49 #include "ev-job-queue.h"
50 #include "ev-jobs.h"
51 #include "ev-sidebar-page.h"
52 #include "eggfindbar.h"
53
54 #ifndef HAVE_GTK_RECENT
55 #include "egg-recent-view-uimanager.h"
56 #include "egg-recent-view.h"
57 #include "egg-recent-model.h"
58 #endif
59
60 #include "egg-toolbar-editor.h"
61 #include "egg-editable-toolbar.h"
62 #include "egg-toolbars-model.h"
63 #include "ephy-zoom.h"
64 #include "ephy-zoom-action.h"
65 #include "ev-application.h"
66 #include "ev-stock-icons.h"
67 #include "ev-metadata-manager.h"
68 #include "ev-file-helpers.h"
69 #include "ev-utils.h"
70 #include "ev-debug.h"
71
72 #ifdef WITH_GNOME_PRINT
73 #include "ev-print-job.h"
74 #include <libgnomeprintui/gnome-print-dialog.h>
75 #endif
76
77 #ifdef WITH_GTK_PRINT
78 #include <gtk/gtkprintunixdialog.h>
79 #endif
80
81 #include <poppler.h>
82
83 #include <glib/gi18n.h>
84 #include <gtk/gtk.h>
85 #include <gnome.h>
86 #include <libgnomevfs/gnome-vfs-utils.h>
87 #include <gconf/gconf-client.h>
88
89 #include <string.h>
90
91 typedef enum {
92         PAGE_MODE_DOCUMENT,
93         PAGE_MODE_PASSWORD
94 } EvWindowPageMode;
95
96 typedef enum {
97         EV_CHROME_MENUBAR       = 1 << 0,
98         EV_CHROME_TOOLBAR       = 1 << 1,
99         EV_CHROME_FINDBAR       = 1 << 2,
100         EV_CHROME_RAISE_TOOLBAR = 1 << 3,
101         EV_CHROME_FULLSCREEN_TOOLBAR    = 1 << 4,
102         EV_CHROME_SIDEBAR       = 1 << 5,
103         EV_CHROME_NORMAL        = EV_CHROME_MENUBAR | EV_CHROME_TOOLBAR | EV_CHROME_SIDEBAR
104 } EvChrome;
105
106 struct _EvWindowPrivate {
107         /* UI */
108         EvChrome chrome;
109
110         GtkWidget *main_box;
111         GtkWidget *menubar;
112         GtkWidget *toolbar_dock;
113         GtkWidget *toolbar;
114         GtkWidget *hpaned;
115         GtkWidget *sidebar;
116         GtkWidget *find_bar;
117         GtkWidget *scrolled_window;
118         GtkWidget *view;
119         GtkWidget *password_view;
120         GtkWidget *sidebar_thumbs;
121         GtkWidget *sidebar_links;
122         GtkWidget *sidebar_attachments;
123
124         /* Dialogs */
125         GtkWidget *properties;
126 #ifdef WITH_PRINT
127         GtkWidget *print_dialog;
128 #endif
129         GtkWidget *password_dialog;
130
131         /* UI Builders */
132         GtkActionGroup   *action_group;
133         GtkActionGroup   *view_popup_action_group;
134         GtkActionGroup   *attachment_popup_action_group;
135 #ifdef HAVE_GTK_RECENT
136         GtkRecentManager *recent_manager;
137         GtkActionGroup   *recent_action_group;
138         guint             recent_ui_id;
139 #endif
140         GtkUIManager     *ui_manager;
141
142         /* Fullscreen mode */
143         GtkWidget *fullscreen_toolbar;
144         GtkWidget *fullscreen_popup;
145         guint      fullscreen_timeout_id;
146         
147         /* Popup link */
148         GtkWidget *view_popup;
149         EvLink    *link;
150
151         /* Popup attachment */
152         GtkWidget    *attachment_popup;
153         GList        *attach_list;
154
155         /* Document */
156         char *uri;
157         char *local_uri;
158         EvLinkDest *dest;
159         
160         EvDocument *document;
161
162         EvPageCache *page_cache;
163         EvWindowPageMode page_mode;
164         EvWindowTitle *title;
165 #ifndef HAVE_GTK_RECENT
166         EggRecentViewUIManager *recent_view;
167 #endif
168
169         EvJob *xfer_job;
170 #ifdef WITH_GNOME_PRINT
171         GnomePrintJob *print_job;
172 #endif
173
174 #ifdef WITH_GTK_PRINT
175         EvJob            *print_job;
176         GtkPrintJob      *gtk_print_job;
177         GtkPrinter       *printer;
178         GtkPrintSettings *print_settings;
179         GtkPageSetup     *print_page_setup;
180 #endif
181 };
182
183 static const GtkTargetEntry ev_drop_types[] = {
184         { "text/uri-list", 0, 0 }
185 };
186
187
188 #define EV_WINDOW_GET_PRIVATE(object) \
189         (G_TYPE_INSTANCE_GET_PRIVATE ((object), EV_TYPE_WINDOW, EvWindowPrivate))
190
191 #define PAGE_SELECTOR_ACTION    "PageSelector"
192 #define ZOOM_CONTROL_ACTION     "ViewZoom"
193
194 #define GCONF_OVERRIDE_RESTRICTIONS "/apps/evince/override_restrictions"
195 #define GCONF_LOCKDOWN_SAVE         "/desktop/gnome/lockdown/disable_save_to_disk"
196 #define GCONF_LOCKDOWN_PRINT        "/desktop/gnome/lockdown/disable_printing"
197
198 #define FULLSCREEN_TIMEOUT 5 * 1000
199
200 #define SIDEBAR_DEFAULT_SIZE    132
201 #define LINKS_SIDEBAR_ID "links"
202 #define THUMBNAILS_SIDEBAR_ID "thumbnails"
203 #define ATTACHMENTS_SIDEBAR_ID "attachments"
204
205 static void     ev_window_update_actions                (EvWindow *ev_window);
206 static void     ev_window_update_fullscreen_popup       (EvWindow         *window);
207 static void     ev_window_sidebar_visibility_changed_cb (EvSidebar        *ev_sidebar,
208                                                          GParamSpec       *pspec,
209                                                          EvWindow         *ev_window);
210 static void     ev_window_set_page_mode                 (EvWindow         *window,
211                                                          EvWindowPageMode  page_mode);
212 static void     ev_window_xfer_job_cb                   (EvJobXfer        *job,
213                                                          gpointer          data);
214 static void     ev_window_print_job_cb                  (EvJobPrint       *job,
215                                                          EvWindow         *window);
216 static void     ev_window_sizing_mode_changed_cb        (EvView           *view,
217                                                          GParamSpec       *pspec,
218                                                          EvWindow         *ev_window);
219 static void     ev_window_zoom_changed_cb               (EvView           *view,
220                                                          GParamSpec       *pspec,
221                                                          EvWindow         *ev_window);
222 static void     ev_window_add_recent                    (EvWindow         *window,
223                                                          const char       *filename);
224 static void     ev_window_run_fullscreen                (EvWindow         *window);
225 static void     ev_window_stop_fullscreen               (EvWindow         *window);
226 static void     ev_window_cmd_view_fullscreen           (GtkAction        *action,
227                                                          EvWindow         *window);
228 static void     ev_window_run_presentation              (EvWindow         *window);
229 static void     ev_window_stop_presentation             (EvWindow         *window);
230 static void     ev_window_cmd_view_presentation         (GtkAction        *action,
231                                                          EvWindow         *window);
232 static void     ev_window_run_preview                   (EvWindow         *window);
233 static void     ev_view_popup_cmd_open_link             (GtkAction        *action,
234                                                          EvWindow         *window);
235 static void     ev_view_popup_cmd_copy_link_address     (GtkAction        *action,
236                                                          EvWindow         *window);
237 static void     ev_attachment_popup_cmd_open_attachment (GtkAction        *action,
238                                                          EvWindow *window);
239 static void     ev_attachment_popup_cmd_save_attachment_as (GtkAction *action, 
240                                                          EvWindow *window);
241 static void     ev_window_cmd_view_best_fit             (GtkAction        *action, 
242                                                          EvWindow         *ev_window);
243 static void     ev_window_cmd_view_page_width           (GtkAction        *action, 
244                                                          EvWindow         *ev_window);
245 static void     fullscreen_set_timeout                  (EvWindow *window);
246 static gboolean fullscreen_motion_notify_cb             (GtkWidget *widget,
247                                                          GdkEventMotion *event,
248                                                          gpointer user_data);
249 static gboolean fullscreen_leave_notify_cb              (GtkWidget *widget,
250                                                          GdkEventCrossing *event,
251                                                          gpointer user_data);
252
253 G_DEFINE_TYPE (EvWindow, ev_window, GTK_TYPE_WINDOW)
254
255 static void
256 ev_window_set_action_sensitive (EvWindow   *ev_window,
257                                 const char *name,
258                                 gboolean    sensitive)
259 {
260         GtkAction *action = gtk_action_group_get_action (ev_window->priv->action_group,
261                                                          name);
262         gtk_action_set_sensitive (action, sensitive);
263 }
264
265
266 static void
267 ev_window_setup_action_sensitivity (EvWindow *ev_window)
268 {
269         EvDocument *document = ev_window->priv->document;
270         const EvDocumentInfo *info = NULL;
271
272         gboolean has_document = FALSE;
273         gboolean ok_to_print = TRUE;
274         gboolean ok_to_copy = TRUE;
275         gboolean has_properties = TRUE;
276         gboolean override_restrictions = FALSE;
277         gboolean can_get_text = FALSE;
278         gboolean has_pages = FALSE;
279         gboolean can_find = FALSE;
280
281         GConfClient *client;
282
283         if (document) {
284                 has_document = TRUE;
285                 info = ev_page_cache_get_info (ev_window->priv->page_cache);
286         }
287
288         if (has_document && ev_window->priv->page_cache) {
289                 has_pages = ev_page_cache_get_n_pages (ev_window->priv->page_cache) > 0;
290         }
291
292         if (!info || info->fields_mask == 0) {
293                 has_properties = FALSE;
294         }
295
296         if (has_document && ev_document_can_get_text (document)) {
297                 can_get_text = TRUE;
298         }
299         
300         if (has_document && EV_IS_DOCUMENT_FIND (document)) {
301                 can_find = TRUE;
302         }
303
304         client = gconf_client_get_default ();
305         override_restrictions = gconf_client_get_bool (client, 
306                                                        GCONF_OVERRIDE_RESTRICTIONS, 
307                                                        NULL);
308         if (!override_restrictions && info && info->fields_mask & EV_DOCUMENT_INFO_PERMISSIONS) {
309                 ok_to_print = (info->permissions & EV_DOCUMENT_PERMISSIONS_OK_TO_PRINT);
310                 ok_to_copy = (info->permissions & EV_DOCUMENT_PERMISSIONS_OK_TO_COPY);
311         }
312
313         if (has_document && !EV_IS_PS_EXPORTER(document))
314                 ok_to_print = FALSE;
315
316         
317         if (gconf_client_get_bool (client, GCONF_LOCKDOWN_SAVE, NULL)) {
318                 ok_to_copy = FALSE;
319         }
320
321         if (gconf_client_get_bool (client, GCONF_LOCKDOWN_PRINT, NULL)) {
322                 ok_to_print = FALSE;
323         }
324 #ifndef WITH_PRINT
325         ok_to_print = FALSE;
326 #endif
327         g_object_unref (client);
328
329
330         /* File menu */
331         ev_window_set_action_sensitive (ev_window, "FileSaveAs", has_document && ok_to_copy);
332         ev_window_set_action_sensitive (ev_window, "FilePrint", has_pages && ok_to_print);
333         ev_window_set_action_sensitive (ev_window, "FileProperties", has_document && has_properties);
334
335         /* Edit menu */
336         ev_window_set_action_sensitive (ev_window, "EditSelectAll", has_pages && can_get_text);
337         ev_window_set_action_sensitive (ev_window, "EditFind",
338                               has_pages && EV_IS_DOCUMENT_FIND (document));
339         ev_window_set_action_sensitive (ev_window, "Slash",
340                               has_pages && EV_IS_DOCUMENT_FIND (document));
341         ev_window_set_action_sensitive (ev_window, "EditRotateLeft", has_pages);
342         ev_window_set_action_sensitive (ev_window, "EditRotateRight", has_pages);
343
344         /* View menu */
345         ev_window_set_action_sensitive (ev_window, "ViewContinuous", has_pages);
346         ev_window_set_action_sensitive (ev_window, "ViewDual", has_pages);
347         ev_window_set_action_sensitive (ev_window, "ViewBestFit", has_pages);
348         ev_window_set_action_sensitive (ev_window, "ViewPageWidth", has_pages);
349         ev_window_set_action_sensitive (ev_window, "ViewReload", has_pages);
350
351         /* Toolbar-specific actions: */
352         ev_window_set_action_sensitive (ev_window, PAGE_SELECTOR_ACTION, has_pages);
353         ev_window_set_action_sensitive (ev_window, ZOOM_CONTROL_ACTION,  has_pages);
354
355         ev_window_update_actions (ev_window);
356 }
357
358 static void
359 ev_window_update_actions (EvWindow *ev_window)
360 {
361         EvView *view = EV_VIEW (ev_window->priv->view);
362         int n_pages = 0, page = -1;
363         gboolean has_pages = FALSE;
364
365         if (ev_window->priv->document && ev_window->priv->page_cache) {
366                 page = ev_page_cache_get_current_page (ev_window->priv->page_cache);
367                 n_pages = ev_page_cache_get_n_pages (ev_window->priv->page_cache);
368                 has_pages = n_pages > 0;
369         }
370
371         ev_window_set_action_sensitive (ev_window, "EditCopy", has_pages && ev_view_get_has_selection (view));
372         ev_window_set_action_sensitive (ev_window, "EditFindNext",
373                               ev_view_can_find_next (view));
374         ev_window_set_action_sensitive (ev_window, "EditFindPrevious",
375                               ev_view_can_find_previous (view));
376
377         ev_window_set_action_sensitive (ev_window, "ViewZoomIn",
378                               has_pages && ev_view_can_zoom_in (view));
379         ev_window_set_action_sensitive (ev_window, "ViewZoomOut",
380                               has_pages && ev_view_can_zoom_out (view));
381
382         /* Go menu */
383         if (has_pages) {
384                 ev_window_set_action_sensitive (ev_window, "GoPreviousPage", page > 0);
385                 ev_window_set_action_sensitive (ev_window, "GoNextPage", page < n_pages - 1);
386                 ev_window_set_action_sensitive (ev_window, "GoFirstPage", page > 0);
387                 ev_window_set_action_sensitive (ev_window, "GoLastPage", page < n_pages - 1);
388         } else {
389                 ev_window_set_action_sensitive (ev_window, "GoFirstPage", FALSE);
390                 ev_window_set_action_sensitive (ev_window, "GoPreviousPage", FALSE);
391                 ev_window_set_action_sensitive (ev_window, "GoNextPage", FALSE);
392                 ev_window_set_action_sensitive (ev_window, "GoLastPage", FALSE);
393         }
394
395         if (has_pages &&
396             ev_view_get_sizing_mode (view) != EV_SIZING_FIT_WIDTH &&
397             ev_view_get_sizing_mode (view) != EV_SIZING_BEST_FIT) {
398                 GtkAction *action;
399                 float      zoom;
400                 float      real_zoom;
401
402                 action = gtk_action_group_get_action (ev_window->priv->action_group, 
403                                                       ZOOM_CONTROL_ACTION);
404
405                 real_zoom = ev_view_get_zoom (EV_VIEW (ev_window->priv->view));
406                 zoom = ephy_zoom_get_nearest_zoom_level (real_zoom);
407
408                 ephy_zoom_action_set_zoom_level (EPHY_ZOOM_ACTION (action), zoom);
409         }
410 }
411
412 static void
413 ev_window_set_view_accels_sensitivity (EvWindow *window, gboolean sensitive)
414 {
415         if (window->priv->action_group) {
416                 ev_window_set_action_sensitive (window, "PageDown", sensitive);
417                 ev_window_set_action_sensitive (window, "PageUp", sensitive);
418                 ev_window_set_action_sensitive (window, "Space", sensitive);
419                 ev_window_set_action_sensitive (window, "ShiftSpace", sensitive);
420                 ev_window_set_action_sensitive (window, "BackSpace", sensitive);
421                 ev_window_set_action_sensitive (window, "ShiftBackSpace", sensitive);
422                 ev_window_set_action_sensitive (window, "Return", sensitive);
423                 ev_window_set_action_sensitive (window, "ShiftReturn", sensitive);
424                 ev_window_set_action_sensitive (window, "Slash", sensitive);
425                 ev_window_set_action_sensitive (window, "Plus", sensitive);
426                 ev_window_set_action_sensitive (window, "Minus", sensitive);
427                 ev_window_set_action_sensitive (window, "KpPlus", sensitive);
428                 ev_window_set_action_sensitive (window, "KpMinus", sensitive);
429                 ev_window_set_action_sensitive (window, "Equal", sensitive);
430         }
431 }
432
433 static void
434 set_widget_visibility (GtkWidget *widget, gboolean visible)
435 {
436         g_assert (GTK_IS_WIDGET (widget));
437         
438         if (visible)
439                 gtk_widget_show (widget);
440         else
441                 gtk_widget_hide (widget);
442 }
443
444 static void
445 update_chrome_visibility (EvWindow *window)
446 {
447         EvWindowPrivate *priv = window->priv;
448         gboolean menubar, toolbar, findbar, fullscreen_toolbar, sidebar;
449         gboolean fullscreen_mode, presentation, fullscreen;
450
451         presentation = ev_view_get_presentation (EV_VIEW (priv->view));
452         fullscreen = ev_view_get_fullscreen (EV_VIEW (priv->view));
453         fullscreen_mode = fullscreen || presentation;
454
455         menubar = (priv->chrome & EV_CHROME_MENUBAR) != 0 && !fullscreen_mode;
456         toolbar = ((priv->chrome & EV_CHROME_TOOLBAR) != 0  || 
457                    (priv->chrome & EV_CHROME_RAISE_TOOLBAR) != 0) && !fullscreen_mode;
458         fullscreen_toolbar = ((priv->chrome & EV_CHROME_FULLSCREEN_TOOLBAR) != 0 || 
459                               (priv->chrome & EV_CHROME_RAISE_TOOLBAR) != 0) && fullscreen;
460         findbar = (priv->chrome & EV_CHROME_FINDBAR) != 0;
461         sidebar = (priv->chrome & EV_CHROME_SIDEBAR) != 0 && !fullscreen_mode;
462
463         set_widget_visibility (priv->menubar, menubar); 
464         set_widget_visibility (priv->toolbar_dock, toolbar);
465         set_widget_visibility (priv->find_bar, findbar);
466         set_widget_visibility (priv->sidebar, sidebar);
467
468         ev_window_set_action_sensitive (window, "EditToolbar", toolbar);
469         gtk_widget_set_sensitive (priv->menubar, menubar);
470
471         if (priv->fullscreen_popup != NULL) {
472                 set_widget_visibility (priv->fullscreen_toolbar, fullscreen_toolbar);
473                 set_widget_visibility (priv->fullscreen_popup, fullscreen_toolbar);
474         }
475 }
476
477 static void
478 update_chrome_flag (EvWindow *window, EvChrome flag, gboolean active)
479 {
480         EvWindowPrivate *priv = window->priv;
481         
482         if (active) {
483                 priv->chrome |= flag;
484         } else {
485                 priv->chrome &= ~flag;
486         }
487
488         update_chrome_visibility (window);
489 }
490
491 static void
492 update_sizing_buttons (EvWindow *window)
493 {
494         GtkActionGroup *action_group = window->priv->action_group;
495         GtkAction *action;
496         gboolean best_fit, page_width;
497         EvSizingMode sizing_mode;
498
499         if (window->priv->view == NULL)
500                 return;
501
502         g_object_get (window->priv->view,
503                       "sizing_mode", &sizing_mode,
504                       NULL);
505
506         switch (sizing_mode) {
507                 case EV_SIZING_BEST_FIT:
508                         best_fit = TRUE;
509                         page_width = FALSE;
510                         break;
511                 case EV_SIZING_FIT_WIDTH:
512                         best_fit = FALSE;
513                         page_width = TRUE;
514                         break;
515                 default:
516                         best_fit = page_width = FALSE;
517                         break;
518         }
519
520         action = gtk_action_group_get_action (action_group, "ViewBestFit");
521         g_signal_handlers_block_by_func
522                 (action, G_CALLBACK (ev_window_cmd_view_best_fit), window);
523         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), best_fit);
524         g_signal_handlers_unblock_by_func
525                 (action, G_CALLBACK (ev_window_cmd_view_best_fit), window);
526
527         action = gtk_action_group_get_action (action_group, "ViewPageWidth");   
528         g_signal_handlers_block_by_func
529                 (action, G_CALLBACK (ev_window_cmd_view_page_width), window);
530         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), page_width);
531         g_signal_handlers_unblock_by_func
532                 (action, G_CALLBACK (ev_window_cmd_view_page_width), window);
533
534         action = gtk_action_group_get_action (window->priv->action_group, 
535                                               ZOOM_CONTROL_ACTION);     
536         if (best_fit) {
537                 ephy_zoom_action_set_zoom_level (EPHY_ZOOM_ACTION (action), 
538                                                  EPHY_ZOOM_BEST_FIT);
539         } else if (page_width) {
540                 ephy_zoom_action_set_zoom_level (EPHY_ZOOM_ACTION (action), 
541                                                  EPHY_ZOOM_FIT_WIDTH);
542         }
543 }
544
545 gboolean
546 ev_window_is_empty (const EvWindow *ev_window)
547 {
548         g_return_val_if_fail (EV_IS_WINDOW (ev_window), FALSE);
549
550         return (ev_window->priv->document == NULL) && 
551                 (ev_window->priv->xfer_job == NULL);
552 }
553
554 static void
555 ev_window_error_dialog_response_cb (GtkWidget *dialog,
556                                    gint       response_id,
557                                    EvWindow  *ev_window)
558 {
559         gtk_widget_destroy (dialog);
560 }
561
562 static void
563 ev_window_error_dialog (GtkWindow *window, const gchar *msg, GError *error)
564 {
565         GtkWidget *dialog;
566
567         dialog = gtk_message_dialog_new (GTK_WINDOW (window),
568                                          GTK_DIALOG_DESTROY_WITH_PARENT,
569                                          GTK_MESSAGE_ERROR,
570                                          GTK_BUTTONS_CLOSE,
571                                          msg);
572         gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
573                                                   "%s", error->message);
574         g_signal_connect (dialog, "response",
575                           G_CALLBACK (ev_window_error_dialog_response_cb),
576                            window);
577         gtk_widget_show (dialog);
578 }
579
580 static void
581 find_changed_cb (EvDocument *document, int page, EvWindow *ev_window)
582 {
583         ev_window_update_actions (ev_window);
584 }
585
586 static void
587 page_changed_cb (EvPageCache *page_cache,
588                  gint         page,
589                  EvWindow    *ev_window)
590 {
591         ev_window_update_actions (ev_window);
592
593         if (!ev_window_is_empty (ev_window))
594                 ev_metadata_manager_set_int (ev_window->priv->uri, "page", page);
595 }
596
597 static void
598 update_document_mode (EvWindow *window, EvDocumentMode mode)
599 {
600         if (mode == EV_DOCUMENT_MODE_PRESENTATION) {
601                 ev_window_run_presentation (window);
602         }
603         else if (mode == EV_DOCUMENT_MODE_FULL_SCREEN) {
604                 ev_window_run_fullscreen (window);
605         }
606 }
607
608 static void
609 setup_document_from_metadata (EvWindow *window)
610 {
611         char *uri = window->priv->uri;
612         GValue page = { 0, };
613         gint new_page;
614
615         if (uri && ev_metadata_manager_get (uri, "page", &page, TRUE)) {
616                 new_page = CLAMP (g_value_get_int (&page), 0, ev_page_cache_get_n_pages (window->priv->page_cache) - 1);
617                 ev_page_cache_set_current_page (window->priv->page_cache,
618                                                 new_page);
619                 g_value_unset (&page);
620         }
621 }
622
623 static void
624 setup_chrome_from_metadata (EvWindow *window)
625 {
626         EvChrome chrome = EV_CHROME_NORMAL;
627         GValue show_toolbar = { 0, };
628
629         if (ev_metadata_manager_get (NULL, "show_toolbar", &show_toolbar, FALSE)) {
630                 if (!g_value_get_boolean (&show_toolbar))
631                         chrome &= ~EV_CHROME_TOOLBAR;
632                 g_value_unset (&show_toolbar);
633         }
634         window->priv->chrome = chrome;
635 }
636
637 static void
638 setup_sidebar_from_metadata (EvWindow *window, EvDocument *document)
639 {
640         char *uri = window->priv->uri;
641         GtkWidget *sidebar = window->priv->sidebar;
642         GtkWidget *links = window->priv->sidebar_links;
643         GtkWidget *thumbs = window->priv->sidebar_thumbs;
644         GtkWidget *attachments = window->priv->sidebar_attachments;
645         GValue sidebar_size = { 0, };
646         GValue sidebar_page = { 0, };
647         GValue sidebar_visibility = { 0, };
648
649         if (ev_metadata_manager_get (uri, "sidebar_size", &sidebar_size, FALSE)) {
650                 gtk_paned_set_position (GTK_PANED (window->priv->hpaned),
651                                         g_value_get_int (&sidebar_size));
652                 g_value_unset(&sidebar_size);
653         }
654         
655         if (document && ev_metadata_manager_get (uri, "sidebar_page", &sidebar_page, FALSE)) {
656                 const char *page_id = g_value_get_string (&sidebar_page);
657                 
658                 if (strcmp (page_id, LINKS_SIDEBAR_ID) == 0 && ev_sidebar_page_support_document (EV_SIDEBAR_PAGE (links), document)) {
659                         ev_sidebar_set_page (EV_SIDEBAR (sidebar), links);
660                 } else if (strcmp (page_id, THUMBNAILS_SIDEBAR_ID) && ev_sidebar_page_support_document (EV_SIDEBAR_PAGE (thumbs), document)) {
661                         ev_sidebar_set_page (EV_SIDEBAR (sidebar), thumbs);
662                 } else if (strcmp (page_id, ATTACHMENTS_SIDEBAR_ID) && ev_sidebar_page_support_document (EV_SIDEBAR_PAGE (attachments), document)) {
663                         ev_sidebar_set_page (EV_SIDEBAR (sidebar), thumbs);
664                 }
665                 g_value_unset (&sidebar_page);
666         } else if (document && ev_sidebar_page_support_document (EV_SIDEBAR_PAGE (links), document)) {
667                 ev_sidebar_set_page (EV_SIDEBAR (sidebar), links);
668         }
669
670         if (ev_metadata_manager_get (uri, "sidebar_visibility", &sidebar_visibility, FALSE)) {
671                 update_chrome_flag (window, EV_CHROME_SIDEBAR, g_value_get_boolean (&sidebar_visibility));
672                 g_value_unset (&sidebar_visibility);
673         }
674 }
675
676 static void
677 setup_view_from_metadata (EvWindow *window)
678 {
679         EvView *view = EV_VIEW (window->priv->view);
680         char *uri = window->priv->uri;
681         GEnumValue *enum_value;
682         GValue width = { 0, };
683         GValue height = { 0, };
684         GValue maximized = { 0, };
685         GValue x = { 0, };
686         GValue y = { 0, };
687         GValue sizing_mode = { 0, };
688         GValue zoom = { 0, };
689         GValue continuous = { 0, };
690         GValue dual_page = { 0, };
691         GValue presentation = { 0, };
692         GValue fullscreen = { 0, };
693         GValue rotation = { 0, };
694         gboolean restore_size = TRUE;
695
696         /* Window size */
697
698         if (ev_metadata_manager_get (uri, "window_maximized", &maximized, FALSE)) {
699                 if (g_value_get_boolean (&maximized)) {
700                         gtk_window_maximize (GTK_WINDOW (window));
701                         restore_size = FALSE;
702                 } else {
703                         gtk_window_unmaximize (GTK_WINDOW (window));
704                 }
705                 g_value_unset (&maximized);
706         }
707
708         if (restore_size &&
709             ev_metadata_manager_get (uri, "window_width", &width, TRUE) &&
710             ev_metadata_manager_get (uri, "window_height", &height, TRUE)) {
711                 gtk_window_resize (GTK_WINDOW (window),
712                                    g_value_get_int (&width),
713                                    g_value_get_int (&height));
714                 g_value_unset (&width);
715                 g_value_unset (&height);                
716         }
717         if (restore_size &&
718             ev_metadata_manager_get (uri, "window_x", &x, TRUE) &&
719             ev_metadata_manager_get (uri, "window_y", &y, TRUE)) {
720                 gtk_window_move (GTK_WINDOW (window), g_value_get_int (&x),
721                                  g_value_get_int (&y));
722                 g_value_unset (&x);
723                 g_value_unset (&y);
724         }
725
726         /* Sizing mode */
727         if (ev_metadata_manager_get (uri, "sizing_mode", &sizing_mode, FALSE)) {
728                 enum_value = g_enum_get_value_by_nick
729                         (EV_SIZING_MODE_CLASS, g_value_get_string (&sizing_mode));
730                 g_value_unset (&sizing_mode);
731                 ev_view_set_sizing_mode (view, enum_value->value);
732         }
733
734         /* Zoom */
735         if (ev_metadata_manager_get (uri, "zoom", &zoom, FALSE) &&
736             ev_view_get_sizing_mode (view) == EV_SIZING_FREE) {
737                 ev_view_set_zoom (view, g_value_get_double (&zoom), FALSE);
738                 g_value_unset (&zoom);
739         }
740
741         /* Continuous */
742         if (ev_metadata_manager_get (uri, "continuous", &continuous, FALSE)) {
743                 ev_view_set_continuous (view, g_value_get_boolean (&continuous));
744                 g_value_unset (&continuous);
745         }
746
747         /* Dual page */
748         if (ev_metadata_manager_get (uri, "dual-page", &dual_page, FALSE)) {
749                 ev_view_set_dual_page (view, g_value_get_boolean (&dual_page));
750                 g_value_unset (&dual_page);
751         }
752
753         /* Presentation */
754         if (ev_metadata_manager_get (uri, "presentation", &presentation, FALSE)) {
755                 if (g_value_get_boolean (&presentation) && uri) {
756                         ev_window_run_presentation (window);
757                 }
758                 g_value_unset (&presentation);
759         }
760
761         /* Fullscreen */
762         if (ev_metadata_manager_get (uri, "fullscreen", &fullscreen, FALSE)) {
763                 if (g_value_get_boolean (&fullscreen) && uri) {
764                         ev_window_run_fullscreen (window);
765                 }
766                 g_value_unset (&fullscreen);
767         }
768
769         /* Rotation */
770         if (ev_metadata_manager_get (uri, "rotation", &rotation, TRUE)) {
771                 if (g_value_get_int (&rotation)) {
772                         switch (g_value_get_int (&rotation)) {
773                                 case 90:
774                                         ev_view_set_rotation (view, 90);
775                                         break;
776                                 case 180:
777                                         ev_view_set_rotation (view, 180);
778                                         break;
779                                 case 270:
780                                         ev_view_set_rotation (view, 270);
781                                         break;
782                                 default:
783                                         break;
784                         }
785                 }
786                 g_value_unset (&rotation);
787         }
788 }
789
790 static void
791 ev_window_setup_document (EvWindow *ev_window)
792 {
793         const EvDocumentInfo *info;
794         EvDocument *document;
795         EvView *view = EV_VIEW (ev_window->priv->view);
796         EvSidebar *sidebar = EV_SIDEBAR (ev_window->priv->sidebar);
797         GtkAction *action;
798
799         document = ev_window->priv->document;
800         ev_window->priv->page_cache = ev_page_cache_get (ev_window->priv->document);
801         g_signal_connect (ev_window->priv->page_cache, "page-changed", G_CALLBACK (page_changed_cb), ev_window);
802
803         if (EV_IS_DOCUMENT_FIND (document)) {
804                 g_signal_connect_object (G_OBJECT (document),
805                                          "find_changed",
806                                          G_CALLBACK (find_changed_cb),  
807                                          ev_window, 0);
808         }
809
810         ev_sidebar_set_document (sidebar, document);
811
812         if (ev_page_cache_get_n_pages (ev_window->priv->page_cache) > 0) {
813                 ev_view_set_document (view, document);
814         }
815         ev_window_set_page_mode (ev_window, PAGE_MODE_DOCUMENT);
816
817         ev_window_title_set_document (ev_window->priv->title, document);
818         ev_window_title_set_uri (ev_window->priv->title, ev_window->priv->uri);
819
820         action = gtk_action_group_get_action (ev_window->priv->action_group, PAGE_SELECTOR_ACTION);
821         ev_page_action_set_document (EV_PAGE_ACTION (action), document);
822         ev_window_setup_action_sensitivity (ev_window);
823
824         if (ev_window->priv->properties) {
825                 ev_properties_dialog_set_document (EV_PROPERTIES_DIALOG (ev_window->priv->properties),
826                                                    ev_window->priv->document);
827         }
828         
829         setup_document_from_metadata (ev_window);
830         setup_sidebar_from_metadata (ev_window, document);
831
832         info = ev_page_cache_get_info (ev_window->priv->page_cache);
833         update_document_mode (ev_window, info->mode);
834 }
835
836 static void
837 password_dialog_response (GtkWidget *password_dialog,
838                           gint       response_id,
839                           EvWindow  *ev_window)
840 {
841         char *password;
842         
843         if (response_id == GTK_RESPONSE_OK) {
844
845                 password = ev_password_dialog_get_password (EV_PASSWORD_DIALOG (password_dialog));
846                 if (password) {
847                         ev_document_doc_mutex_lock ();
848                         ev_document_security_set_password (EV_DOCUMENT_SECURITY (ev_window->priv->xfer_job->document),
849                                                            password);
850                         ev_document_doc_mutex_unlock ();
851                 }
852                 g_free (password);
853
854                 ev_password_dialog_save_password (EV_PASSWORD_DIALOG (password_dialog));
855
856                 ev_window_title_set_type (ev_window->priv->title, EV_WINDOW_TITLE_DOCUMENT);
857                 ev_job_queue_add_job (ev_window->priv->xfer_job, EV_JOB_PRIORITY_HIGH);
858                 
859                 gtk_widget_destroy (password_dialog);
860                         
861                 return;
862         }
863
864         gtk_widget_set_sensitive (ev_window->priv->password_view, TRUE);
865         gtk_widget_destroy (password_dialog);
866 }
867
868 /* Called either by ev_window_xfer_job_cb or by the "unlock" callback on the
869  * password_view page.  It assumes that ev_window->priv->password_* has been set
870  * correctly.  These are cleared by password_dialog_response() */
871
872 static void
873 ev_window_popup_password_dialog (EvWindow *ev_window)
874 {
875         g_assert (ev_window->priv->xfer_job);
876
877         gtk_widget_set_sensitive (ev_window->priv->password_view, FALSE);
878
879         ev_window_title_set_uri (ev_window->priv->title, ev_window->priv->uri);
880         ev_window_title_set_type (ev_window->priv->title, EV_WINDOW_TITLE_PASSWORD);
881
882         if (ev_window->priv->password_dialog == NULL) {
883                 ev_window->priv->password_dialog =
884                         g_object_new (EV_TYPE_PASSWORD_DIALOG, "uri", ev_window->priv->uri, NULL);
885                 gtk_window_set_transient_for (GTK_WINDOW (ev_window->priv->password_dialog), GTK_WINDOW (ev_window));
886
887                 g_object_add_weak_pointer (G_OBJECT (ev_window->priv->password_dialog),
888                                            (gpointer *) &(ev_window->priv->password_dialog));
889                 g_signal_connect (ev_window->priv->password_dialog,
890                                   "response",
891                                   G_CALLBACK (password_dialog_response),
892                                   ev_window);
893                 gtk_widget_show (ev_window->priv->password_dialog);
894         } else {
895                 ev_password_dialog_set_bad_pass (EV_PASSWORD_DIALOG (ev_window->priv->password_dialog));
896         }
897 }
898
899 static void
900 ev_window_clear_xfer_job (EvWindow *ev_window)
901 {
902     if (ev_window->priv->xfer_job != NULL) {
903
904         if (!ev_window->priv->xfer_job->finished)
905                 ev_job_queue_remove_job (ev_window->priv->xfer_job);
906
907         g_signal_handlers_disconnect_by_func (ev_window->priv->xfer_job, ev_window_xfer_job_cb, ev_window);
908         g_object_unref (ev_window->priv->xfer_job);
909         ev_window->priv->xfer_job = NULL;
910     }
911 }
912
913 static void
914 ev_window_clear_local_uri (EvWindow *ev_window)
915 {
916     char *filename;
917     
918     if (ev_window->priv->local_uri) {
919             filename = g_filename_from_uri (ev_window->priv->local_uri, NULL, NULL);
920             if (filename != NULL) {
921                     unlink (filename);
922                     g_free (filename);
923             }
924             g_free (ev_window->priv->local_uri);
925             ev_window->priv->local_uri = NULL;
926     }
927 }
928
929 /* This callback will executed when load job will be finished.
930  *
931  * Since the flow of the error dialog is very confusing, we assume that both
932  * document and uri will go away after this function is called, and thus we need
933  * to ref/dup them.  Additionally, it needs to clear
934  * ev_window->priv->password_{uri,document}, and thus people who call this
935  * function should _not_ necessarily expect those to exist after being
936  * called. */
937 static void
938 ev_window_xfer_job_cb  (EvJobXfer *job,
939                         gpointer data)
940 {
941         EvWindow *ev_window = EV_WINDOW (data);
942         EvDocument *document = EV_JOB (job)->document;
943
944         g_assert (job->uri);
945         
946         ev_view_set_loading (EV_VIEW (ev_window->priv->view), FALSE);
947
948         /* Success! */
949         if (job->error == NULL) {
950
951                 g_free (ev_window->priv->uri);
952                 ev_window->priv->uri = g_strdup (job->uri);
953                 setup_view_from_metadata (ev_window);
954
955                 if (job->local_uri) {
956                         ev_window->priv->local_uri = g_strdup (job->local_uri);
957                 } else {
958                         ev_window->priv->local_uri = NULL;
959                 }
960                 
961                 if (ev_window->priv->document)
962                         g_object_unref (ev_window->priv->document);
963                 ev_window->priv->document = g_object_ref (document);
964                 
965                 ev_window_setup_document (ev_window);
966                 ev_window_add_recent (ev_window, ev_window->priv->uri);         
967
968                 if (job->dest)
969                         ev_window_goto_dest (ev_window, job->dest);
970
971                 switch (job->mode) {
972                         case EV_WINDOW_MODE_FULLSCREEN:
973                                 ev_window_run_fullscreen (ev_window);
974                                 break;
975                         case EV_WINDOW_MODE_PRESENTATION:
976                                 ev_window_run_presentation (ev_window);
977                                 break;
978                         case EV_WINDOW_MODE_PREVIEW:
979                                 ev_window_run_preview (ev_window);
980                                 break;
981                         default:
982                                 break;
983                 }
984
985                 ev_window_clear_xfer_job (ev_window);           
986                 return;
987         }
988
989         if (job->error->domain == EV_DOCUMENT_ERROR &&
990             job->error->code == EV_DOCUMENT_ERROR_ENCRYPTED) {
991                 gchar *base_name, *file_name;
992
993                 g_free (ev_window->priv->uri);
994                 ev_window->priv->uri = g_strdup (job->uri);
995                 setup_view_from_metadata (ev_window);
996
997
998                 file_name = gnome_vfs_format_uri_for_display (job->uri);
999                 base_name = g_path_get_basename (file_name);
1000                 ev_password_view_set_file_name (EV_PASSWORD_VIEW (ev_window->priv->password_view),
1001                                                 base_name);
1002                 g_free (file_name);
1003                 g_free (base_name);
1004                 ev_window_set_page_mode (ev_window, PAGE_MODE_PASSWORD);
1005
1006                 ev_window_popup_password_dialog (ev_window);
1007         } else {
1008                 ev_window_error_dialog (GTK_WINDOW (ev_window), 
1009                                         _("Unable to open document"),
1010                                         job->error);
1011                 ev_window_clear_xfer_job (ev_window);
1012         }       
1013
1014         return;
1015 }
1016
1017 const char *
1018 ev_window_get_uri (EvWindow *ev_window)
1019 {
1020         return ev_window->priv->uri;
1021 }
1022
1023 static void
1024 ev_window_close_dialogs (EvWindow *ev_window)
1025 {
1026         if (ev_window->priv->password_dialog)
1027                 gtk_widget_destroy (ev_window->priv->password_dialog);
1028         ev_window->priv->password_dialog = NULL;
1029         
1030 #ifdef WITH_PRINT
1031         if (ev_window->priv->print_dialog)
1032                 gtk_widget_destroy (ev_window->priv->print_dialog);
1033         ev_window->priv->print_dialog = NULL;
1034 #endif
1035
1036 #ifdef WITH_GNOME_PRINT
1037         if (ev_window->priv->print_job)
1038                 g_object_unref (ev_window->priv->print_job);
1039         ev_window->priv->print_job = NULL;
1040 #endif
1041         
1042         if (ev_window->priv->properties)
1043                 gtk_widget_destroy (ev_window->priv->properties);
1044         ev_window->priv->properties = NULL;
1045 }
1046
1047 void
1048 ev_window_open_uri (EvWindow       *ev_window,
1049                     const char     *uri,
1050                     EvLinkDest     *dest,
1051                     EvWindowRunMode mode)
1052 {
1053         ev_window_close_dialogs (ev_window);
1054         ev_window_clear_xfer_job (ev_window);
1055         ev_window_clear_local_uri (ev_window);
1056         ev_view_set_loading (EV_VIEW (ev_window->priv->view), TRUE);
1057
1058         ev_window->priv->xfer_job = ev_job_xfer_new (uri, dest, mode);
1059         g_signal_connect (ev_window->priv->xfer_job,
1060                           "finished",
1061                           G_CALLBACK (ev_window_xfer_job_cb),
1062                           ev_window);
1063         ev_job_queue_add_job (ev_window->priv->xfer_job, EV_JOB_PRIORITY_HIGH);
1064 }
1065
1066 void
1067 ev_window_goto_dest (EvWindow *ev_window, EvLinkDest *dest)
1068 {
1069         ev_view_goto_dest (EV_VIEW (ev_window->priv->view), dest);
1070 }
1071
1072 static void
1073 file_open_dialog_response_cb (GtkWidget *chooser,
1074                               gint       response_id,
1075                               EvWindow  *ev_window)
1076 {
1077         if (response_id == GTK_RESPONSE_OK) {
1078                 GSList *uris;
1079
1080                 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (chooser));
1081
1082                 ev_application_open_uri_list (EV_APP, uris, GDK_CURRENT_TIME);
1083         
1084                 g_slist_foreach (uris, (GFunc)g_free, NULL);    
1085                 g_slist_free (uris);
1086         }
1087         ev_application_set_chooser_uri (EV_APP, 
1088                                         gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (chooser)));
1089
1090         gtk_widget_destroy (chooser);
1091 }
1092
1093 static void
1094 ev_window_cmd_file_open (GtkAction *action, EvWindow *window)
1095 {
1096         GtkWidget *chooser;
1097
1098         chooser = gtk_file_chooser_dialog_new (_("Open Document"),
1099                                                GTK_WINDOW (window),
1100                                                GTK_FILE_CHOOSER_ACTION_OPEN,
1101                                                GTK_STOCK_CANCEL,
1102                                                GTK_RESPONSE_CANCEL,
1103                                                GTK_STOCK_OPEN, GTK_RESPONSE_OK,
1104                                                NULL);
1105
1106         ev_document_factory_add_filters (chooser, NULL);
1107         gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (chooser), TRUE);
1108         gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (chooser), FALSE);
1109         if (ev_application_get_chooser_uri (EV_APP) != NULL)
1110                 gtk_file_chooser_set_uri (GTK_FILE_CHOOSER (chooser),
1111                                           ev_application_get_chooser_uri (EV_APP));
1112         
1113         g_signal_connect (chooser, "response",
1114                           G_CALLBACK (file_open_dialog_response_cb),
1115                           window);
1116
1117         gtk_widget_show (chooser);
1118 }
1119
1120 #ifdef HAVE_GTK_RECENT
1121 static void
1122 ev_window_cmd_recent_file_activate (GtkAction     *action,
1123                                     GtkRecentInfo *info)
1124 {
1125         const gchar *uri;
1126
1127         uri = gtk_recent_info_get_uri (info);
1128         
1129         ev_application_open_uri (EV_APP, uri, NULL, GDK_CURRENT_TIME, NULL);
1130 }
1131 #else
1132 static void
1133 ev_window_cmd_recent_file_activate (GtkAction *action,
1134                                     EvWindow *ev_window)
1135 {
1136         char *uri;
1137         EggRecentItem *item;
1138
1139         item = egg_recent_view_uimanager_get_item (ev_window->priv->recent_view,
1140                                                    action);
1141
1142         uri = egg_recent_item_get_uri (item);
1143
1144         ev_application_open_uri (EV_APP, uri, NULL, GDK_CURRENT_TIME, NULL);
1145         
1146         g_free (uri);
1147 }
1148 #endif /* HAVE_GTK_RECENT */
1149
1150 static void
1151 ev_window_add_recent (EvWindow *window, const char *filename)
1152 {
1153 #ifdef HAVE_GTK_RECENT
1154         gtk_recent_manager_add_item (window->priv->recent_manager, filename);
1155 #else
1156         EggRecentItem *item;
1157
1158         item = egg_recent_item_new_from_uri (filename);
1159         egg_recent_item_add_group (item, "Evince");
1160         egg_recent_model_add_full (ev_application_get_recent_model (EV_APP), item);
1161 #endif /* HAVE_GTK_RECENT */
1162 }
1163
1164 #ifdef HAVE_GTK_RECENT
1165 static gint
1166 compare_recent_items (GtkRecentInfo *a, GtkRecentInfo *b)
1167 {
1168         gboolean     has_ev_a, has_ev_b;
1169         const gchar *evince = g_get_application_name ();
1170
1171         has_ev_a = gtk_recent_info_has_application (a, evince);
1172         has_ev_b = gtk_recent_info_has_application (b, evince);
1173         
1174         if (has_ev_a && has_ev_b) {
1175                 time_t time_a, time_b;
1176
1177                 time_a = gtk_recent_info_get_modified (a);
1178                 time_b = gtk_recent_info_get_modified (b);
1179
1180                 return (time_b - time_a);
1181         } else if (has_ev_a) {
1182                 return -1;
1183         } else if (has_ev_b) {
1184                 return 1;
1185         }
1186
1187         return 0;
1188 }
1189 #endif /* HAVE_GTK_RECENT */
1190
1191 static void
1192 ev_window_setup_recent (EvWindow *ev_window)
1193 {
1194 #ifdef HAVE_GTK_RECENT
1195         GList        *items, *l;
1196         guint         n_items = 0;
1197         const gchar  *evince = g_get_application_name ();
1198         static guint  i = 0;
1199
1200         if (ev_window->priv->recent_ui_id > 0) {
1201                 gtk_ui_manager_remove_ui (ev_window->priv->ui_manager,
1202                                           ev_window->priv->recent_ui_id);
1203                 gtk_ui_manager_ensure_update (ev_window->priv->ui_manager);
1204         }
1205         ev_window->priv->recent_ui_id = gtk_ui_manager_new_merge_id (ev_window->priv->ui_manager);
1206
1207         if (ev_window->priv->recent_action_group) {
1208                 gtk_ui_manager_remove_action_group (ev_window->priv->ui_manager,
1209                                                     ev_window->priv->recent_action_group);
1210                 g_object_unref (ev_window->priv->recent_action_group);
1211         }
1212         ev_window->priv->recent_action_group = gtk_action_group_new ("RecentFilesActions");
1213         gtk_ui_manager_insert_action_group (ev_window->priv->ui_manager,
1214                                             ev_window->priv->recent_action_group, 0);
1215
1216         items = gtk_recent_manager_get_items (ev_window->priv->recent_manager);
1217         items = g_list_sort (items, (GCompareFunc) compare_recent_items);
1218
1219         for (l = items; l && l->data; l = g_list_next (l)) {
1220                 GtkRecentInfo *info;
1221                 GtkAction     *action;
1222                 gchar         *action_name;
1223                 gchar         *label;
1224
1225                 info = (GtkRecentInfo *) l->data;
1226
1227                 if (!gtk_recent_info_has_application (info, evince))
1228                         continue;
1229
1230                 action_name = g_strdup_printf ("RecentFile%u", i++);
1231                 label = g_strdup_printf ("_%d.  %s",
1232                                          n_items + 1,
1233                                          gtk_recent_info_get_display_name (info));
1234                 
1235                 action = g_object_new (GTK_TYPE_ACTION,
1236                                        "name", action_name,
1237                                        "label", label,
1238                                        NULL);
1239
1240                 g_object_weak_ref (G_OBJECT (action),
1241                                    (GWeakNotify) gtk_recent_info_unref,
1242                                    gtk_recent_info_ref (info));
1243                 g_signal_connect (G_OBJECT (action), "activate",
1244                                   G_CALLBACK (ev_window_cmd_recent_file_activate),
1245                                   (gpointer) info);
1246
1247                 gtk_action_group_add_action (ev_window->priv->recent_action_group,
1248                                              action);
1249                 g_object_unref (action);
1250
1251                 gtk_ui_manager_add_ui (ev_window->priv->ui_manager,
1252                                        ev_window->priv->recent_ui_id,
1253                                        "/MainMenu/FileMenu/RecentFilesMenu",
1254                                        label,
1255                                        action_name,
1256                                        GTK_UI_MANAGER_MENUITEM,
1257                                        FALSE);
1258                 g_free (action_name);
1259                 g_free (label);
1260
1261                 if (++n_items == 5)
1262                         break;
1263         }
1264         
1265         g_list_foreach (items, (GFunc) gtk_recent_info_unref, NULL);
1266         g_list_free (items);
1267 #else /* HAVE_GTK_RECENT */
1268         ev_window->priv->recent_view = egg_recent_view_uimanager_new (ev_window->priv->ui_manager,
1269                                                                       "/MainMenu/FileMenu/RecentFilesMenu",
1270                                                                       G_CALLBACK (ev_window_cmd_recent_file_activate), 
1271                                                                       ev_window);       
1272
1273         egg_recent_view_uimanager_show_icons (EGG_RECENT_VIEW_UIMANAGER (ev_window->priv->recent_view), FALSE);
1274
1275         egg_recent_view_set_model (EGG_RECENT_VIEW (ev_window->priv->recent_view),
1276                                    ev_application_get_recent_model (EV_APP));
1277
1278         egg_recent_view_uimanager_set_trailing_sep (ev_window->priv->recent_view, TRUE);
1279         
1280         g_signal_connect (ev_window->priv->recent_view, "activate",
1281                         G_CALLBACK (ev_window_cmd_recent_file_activate), ev_window);
1282 #endif /* HAVE_GTK_RECENT */
1283 }
1284
1285 static void
1286 file_save_dialog_response_cb (GtkWidget *fc,
1287                               gint       response_id,
1288                               EvWindow  *ev_window)
1289 {
1290         gboolean success;
1291
1292         if (response_id == GTK_RESPONSE_OK) {
1293                 gchar *uri;
1294                 GError *err = NULL;
1295
1296                 uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (fc));
1297
1298                 ev_document_doc_mutex_lock ();
1299                 success = ev_document_save (ev_window->priv->document, uri, &err);
1300                 ev_document_doc_mutex_unlock ();
1301
1302                 if (err) {
1303                         gchar *msg;
1304                         msg = g_strdup_printf (_("The file could not be saved as “%s”."), uri);
1305                         ev_window_error_dialog (GTK_WINDOW (fc), msg, err);
1306                         g_free (msg);
1307                 }
1308
1309                 g_free (uri);
1310         }
1311
1312         gtk_widget_destroy (fc);
1313 }
1314
1315 static void
1316 ev_window_cmd_save_as (GtkAction *action, EvWindow *ev_window)
1317 {
1318         GtkWidget *fc;
1319         gchar *base_name;
1320         gchar *file_name;
1321
1322         fc = gtk_file_chooser_dialog_new (
1323                 _("Save a Copy"),
1324                 GTK_WINDOW (ev_window), GTK_FILE_CHOOSER_ACTION_SAVE,
1325                 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1326                 GTK_STOCK_SAVE, GTK_RESPONSE_OK,
1327                 NULL);
1328
1329         ev_document_factory_add_filters (fc, ev_window->priv->document);
1330         gtk_dialog_set_default_response (GTK_DIALOG (fc), GTK_RESPONSE_OK);
1331
1332         gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER (fc), TRUE);    
1333         file_name = gnome_vfs_format_uri_for_display (ev_window->priv->uri);
1334         base_name = g_path_get_basename (file_name);
1335         gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (fc), base_name);
1336         g_free (file_name);
1337         g_free (base_name);
1338
1339         g_signal_connect (fc, "response",
1340                           G_CALLBACK (file_save_dialog_response_cb),
1341                           ev_window);
1342
1343         gtk_widget_show (fc);
1344 }
1345
1346 #ifdef WITH_GTK_PRINT
1347 static void
1348 ev_window_clear_print_job (EvWindow *window)
1349 {
1350         if (window->priv->print_job) {
1351                 if (!window->priv->print_job->finished)
1352                         ev_job_queue_remove_job (window->priv->print_job);
1353
1354                 g_signal_handlers_disconnect_by_func (window->priv->print_job,
1355                                                       ev_window_print_job_cb,
1356                                                       window);
1357                 g_object_unref (window->priv->print_job);
1358                 window->priv->print_job = NULL;
1359         }
1360 }
1361
1362 static void
1363 ev_window_print_finished (GtkPrintJob *print_job,
1364                           EvWindow    *window,
1365                           GError      *error)
1366 {
1367         ev_window_clear_print_job (window);
1368         
1369         if (error) {
1370                 GtkWidget *dialog;
1371                 
1372                 dialog = gtk_message_dialog_new (GTK_WINDOW (window),
1373                                                  GTK_DIALOG_MODAL,
1374                                                  GTK_MESSAGE_ERROR,
1375                                                  GTK_BUTTONS_OK,
1376                                                  _("Failed to print document"));
1377                 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
1378                                                           error->message);
1379
1380                 gtk_dialog_run (GTK_DIALOG (dialog));
1381                 gtk_widget_destroy (dialog);
1382         }
1383 }
1384
1385 static void
1386 ev_window_print_send (EvWindow    *window,
1387                       const gchar *filename)
1388 {
1389         GtkPrintJob *job;
1390         GError      *error = NULL;
1391         
1392         if (window->priv->gtk_print_job)
1393                 g_object_unref (window->priv->gtk_print_job);
1394         
1395         job = gtk_print_job_new ("evince-print",
1396                                  window->priv->printer,
1397                                  window->priv->print_settings,
1398                                  window->priv->print_page_setup);
1399         
1400         window->priv->gtk_print_job = job;
1401
1402         if (gtk_print_job_set_source_file (job, filename, &error)) {
1403                 gtk_print_job_send (job,
1404                                     (GtkPrintJobCompleteFunc)ev_window_print_finished,
1405                                     window, NULL);
1406         } else {
1407                 ev_window_clear_print_job (window);
1408                 g_warning (error->message);
1409                 g_error_free (error);
1410         }
1411 }
1412
1413 static void
1414 ev_window_print_job_cb (EvJobPrint *job,
1415                         EvWindow   *window)
1416 {
1417         if (job->error) {
1418                 g_warning (job->error->message);
1419                 ev_window_clear_print_job (window);
1420                 return;
1421         }
1422
1423         g_assert (job->temp_file != NULL);
1424
1425         ev_window_print_send (window, job->temp_file);
1426 }
1427
1428 static gboolean
1429 ev_window_print_dialog_response_cb (GtkDialog *dialog,
1430                                     gint       response,
1431                                     EvWindow  *window)
1432 {
1433         EvBackend     document_type;
1434         gboolean      export_to_ps = TRUE;
1435         GtkPrintPages print_pages;
1436         
1437         if (response != GTK_RESPONSE_OK) {
1438                 gtk_widget_destroy (GTK_WIDGET (dialog));
1439                 window->priv->print_dialog = NULL;
1440
1441                 return FALSE;
1442         }
1443
1444         if (window->priv->printer)
1445                 g_object_unref (window->priv->printer);
1446         if (window->priv->print_settings)
1447                 g_object_unref (window->priv->print_settings);
1448         if (window->priv->print_page_setup)
1449                 g_object_unref (window->priv->print_page_setup);
1450         
1451         window->priv->printer = g_object_ref (
1452                 gtk_print_unix_dialog_get_selected_printer (GTK_PRINT_UNIX_DIALOG (dialog)));
1453         window->priv->print_settings = g_object_ref (
1454                 gtk_print_unix_dialog_get_settings (GTK_PRINT_UNIX_DIALOG (dialog)));
1455         window->priv->print_page_setup = g_object_ref (
1456                 gtk_print_unix_dialog_get_page_setup (GTK_PRINT_UNIX_DIALOG (dialog)));
1457
1458         document_type = ev_document_factory_get_backend (window->priv->document);
1459         print_pages = gtk_print_settings_get_print_pages (window->priv->print_settings);
1460         
1461         if (print_pages == GTK_PRINT_PAGES_ALL) {
1462                 switch (document_type) {
1463                         case EV_BACKEND_PDF:
1464                                 /* Export to ps when printing to file */
1465                                 if (gtk_print_settings_has_key (window->priv->print_settings,
1466                                                                 GTK_PRINT_SETTINGS_OUTPUT_URI)) {
1467                                         export_to_ps = TRUE;
1468                                 } else {
1469                                         export_to_ps = !gtk_printer_accepts_pdf (window->priv->printer);
1470                                 }
1471
1472                                 break;
1473                         case EV_BACKEND_PS:
1474                                 export_to_ps = FALSE;
1475                                 break;
1476                         default:
1477                                 export_to_ps = TRUE;
1478                                 break;
1479                 }
1480         }
1481
1482         if ((export_to_ps || document_type == EV_BACKEND_PS) &&
1483             !gtk_printer_accepts_ps (window->priv->printer)) {
1484                 GtkWidget *msgdialog;
1485
1486                 msgdialog = gtk_message_dialog_new (GTK_WINDOW (dialog),
1487                                                     GTK_DIALOG_MODAL,
1488                                                     GTK_MESSAGE_ERROR,
1489                                                     GTK_BUTTONS_OK,
1490                                                     _("Printing is not supported on this printer."));
1491                 
1492                 gtk_dialog_run (GTK_DIALOG (msgdialog));
1493                 gtk_widget_destroy (msgdialog);
1494
1495                 return FALSE;
1496         }
1497
1498         if (export_to_ps) {
1499                 EvPrintRange *ranges = NULL;
1500                 EvPageCache  *page_cache;
1501                 gint          n_ranges = 0;
1502                 gint          current_page;
1503                 gint          width;
1504                 gint          height;
1505
1506                 ev_window_clear_print_job (window);
1507
1508                 current_page =
1509                         gtk_print_unix_dialog_get_current_page (GTK_PRINT_UNIX_DIALOG (dialog));
1510
1511                 switch (print_pages) {
1512                         case GTK_PRINT_PAGES_CURRENT:
1513                                 ranges = g_new0 (EvPrintRange, 1);
1514
1515                                 ranges->start = current_page;
1516                                 ranges->end = current_page;
1517                                 n_ranges = 1;
1518                                 
1519                                 break;
1520                         case GTK_PRINT_PAGES_RANGES: {
1521                                 GtkPageRange *page_range;
1522
1523                                 page_range = gtk_print_settings_get_page_ranges (window->priv->print_settings,
1524                                                                                  &n_ranges);
1525                                 if (n_ranges > 0)
1526                                         ranges = g_memdup (page_range, n_ranges * sizeof (GtkPageRange));
1527                         }
1528                                 break;
1529                         default:
1530                                 break;
1531                 }
1532                                 
1533                 page_cache = ev_page_cache_get (window->priv->document);
1534                 ev_page_cache_get_size (page_cache,
1535                                         current_page,
1536                                         0, 1.0,
1537                                         &width, &height);
1538         
1539                 window->priv->print_job =
1540                         ev_job_print_new (window->priv->document,
1541                                           ranges, n_ranges,
1542                                           (gdouble)width,
1543                                           (gdouble)height);
1544                 
1545                 g_signal_connect (window->priv->print_job, "finished",
1546                                   G_CALLBACK (ev_window_print_job_cb),
1547                                   window);
1548                 /* The priority doesn't matter for this job */
1549                 ev_job_queue_add_job (window->priv->print_job, EV_JOB_PRIORITY_LOW);
1550         } else {
1551                 gchar *filename;
1552
1553                 filename = g_filename_from_uri (window->priv->uri, NULL, NULL);
1554                 ev_window_print_send (window, filename);
1555                 g_free (filename);
1556         }
1557         
1558         gtk_widget_destroy (GTK_WIDGET (dialog));
1559         window->priv->print_dialog = NULL;
1560
1561         return TRUE;
1562 }
1563
1564 void
1565 ev_window_print_range (EvWindow *ev_window, int first_page, int last_page)
1566 {
1567         GtkWidget   *dialog;
1568         EvPageCache *page_cache;
1569         gint         current_page;
1570         gint         document_last_page;
1571
1572         g_return_if_fail (EV_IS_WINDOW (ev_window));
1573         g_return_if_fail (ev_window->priv->document != NULL);
1574
1575         if (ev_window->priv->print_dialog) {
1576                 gtk_window_present (GTK_WINDOW (ev_window->priv->print_dialog));
1577                 return;
1578         }
1579         
1580         page_cache = ev_page_cache_get (ev_window->priv->document);
1581         current_page = ev_page_cache_get_current_page (page_cache);
1582         document_last_page = ev_page_cache_get_n_pages (page_cache);
1583
1584         if (!ev_window->priv->print_settings)
1585                 ev_window->priv->print_settings = gtk_print_settings_new ();
1586
1587         if (first_page != 1 || last_page != document_last_page) {
1588                 GtkPageRange range;
1589
1590                 /* Ranges in GtkPrint are 0 - N */
1591                 range.start = first_page - 1;
1592                 range.end = last_page - 1;
1593                 
1594                 gtk_print_settings_set_print_pages (ev_window->priv->print_settings,
1595                                                     GTK_PRINT_PAGES_RANGES);
1596                 gtk_print_settings_set_page_ranges (ev_window->priv->print_settings,
1597                                                     &range, 1);
1598         }
1599
1600         dialog = gtk_print_unix_dialog_new (_("Print"), GTK_WINDOW (ev_window));
1601         ev_window->priv->print_dialog = dialog;
1602         gtk_print_unix_dialog_set_manual_capabilities (GTK_PRINT_UNIX_DIALOG (dialog),
1603                                                        GTK_PRINT_CAPABILITY_PAGE_SET |
1604                                                        GTK_PRINT_CAPABILITY_COPIES |
1605                                                        GTK_PRINT_CAPABILITY_COLLATE |
1606                                                        GTK_PRINT_CAPABILITY_REVERSE |
1607                                                        GTK_PRINT_CAPABILITY_SCALE |
1608                                                        GTK_PRINT_CAPABILITY_GENERATE_PS);
1609         gtk_print_unix_dialog_set_current_page (GTK_PRINT_UNIX_DIALOG (dialog),
1610                                                 current_page);
1611         
1612         gtk_print_unix_dialog_set_settings (GTK_PRINT_UNIX_DIALOG (dialog),
1613                                             ev_window->priv->print_settings);
1614         
1615         if (ev_window->priv->print_page_setup)
1616                 gtk_print_unix_dialog_set_page_setup (GTK_PRINT_UNIX_DIALOG (dialog),
1617                                                       ev_window->priv->print_page_setup);
1618         
1619         g_signal_connect (G_OBJECT (dialog), "response",
1620                           G_CALLBACK (ev_window_print_dialog_response_cb),
1621                           ev_window);
1622
1623         gtk_widget_show (dialog);
1624 }
1625 #endif /* WITH_GTK_PRINT */
1626
1627 #ifdef WITH_GNOME_PRINT
1628 static gboolean
1629 ev_window_print_dialog_response_cb (GtkDialog *print_dialog,
1630                                     gint       response,
1631                                     EvWindow  *ev_window)
1632 {
1633         EvPrintJob *print_job;
1634         GnomePrintConfig *config;
1635     
1636         if (response != GNOME_PRINT_DIALOG_RESPONSE_PRINT) {
1637                 gtk_widget_destroy (GTK_WIDGET (print_dialog));
1638                 ev_window->priv->print_dialog = NULL;
1639                 g_object_unref (ev_window->priv->print_job);
1640                 ev_window->priv->print_job = NULL;
1641                 
1642                 return FALSE;
1643         }
1644
1645         config = gnome_print_dialog_get_config (GNOME_PRINT_DIALOG (print_dialog));
1646
1647         /* FIXME: Change this when we have the first backend
1648          * that can print more than postscript
1649          */
1650         if (using_pdf_printer (config)) {
1651                 GtkWidget *dialog;
1652                 
1653                 dialog = gtk_message_dialog_new (GTK_WINDOW (print_dialog), GTK_DIALOG_MODAL,
1654                                                  GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
1655                                                  _("Generating PDF is not supported"));
1656                 gtk_dialog_run (GTK_DIALOG (dialog));
1657                 gtk_widget_destroy (dialog);
1658                 
1659                 return FALSE;
1660         } else if (!using_postscript_printer (config)) {
1661                 GtkWidget *dialog;
1662
1663                 dialog = gtk_message_dialog_new (GTK_WINDOW (print_dialog), GTK_DIALOG_MODAL,
1664                                                  GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
1665                                                  _("Printing is not supported on this printer."));
1666                 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
1667                                                           _("You were trying to print to a printer using the “%s” driver. "
1668                                                             "This program requires a PostScript printer driver."),
1669                                                           gnome_print_config_get (config, (guchar *)"Settings.Engine.Backend.Driver"));
1670                 gtk_dialog_run (GTK_DIALOG (dialog));
1671                 gtk_widget_destroy (dialog);
1672                 
1673                 return FALSE;
1674         }
1675
1676         save_print_config_to_file (config);
1677     
1678         print_job = g_object_new (EV_TYPE_PRINT_JOB,
1679                                   "gnome_print_job", ev_window->priv->print_job,
1680                                   "document", ev_window->priv->document,
1681                                   "print_dialog", print_dialog,
1682                                   NULL);
1683
1684         if (print_job != NULL) {
1685                 ev_print_job_print (print_job, GTK_WINDOW (ev_window));
1686                 g_object_unref (print_job);
1687         }
1688
1689         g_object_unref (config);
1690
1691         gtk_widget_destroy (GTK_WIDGET (print_dialog));
1692         ev_window->priv->print_dialog = NULL;
1693         g_object_unref (ev_window->priv->print_job);
1694         ev_window->priv->print_job = NULL;
1695
1696         return FALSE;
1697 }
1698
1699 void
1700 ev_window_print_range (EvWindow *ev_window, int first_page, int last_page)
1701 {
1702         GnomePrintConfig *config;
1703         gchar *pages_label;
1704
1705         g_return_if_fail (EV_IS_WINDOW (ev_window));
1706         g_return_if_fail (ev_window->priv->document != NULL);
1707
1708         config = load_print_config_from_file ();
1709
1710         if (ev_window->priv->print_job == NULL)
1711                 ev_window->priv->print_job = gnome_print_job_new (config);
1712         
1713         if (ev_window->priv->print_dialog == NULL) {
1714                 ev_window->priv->print_dialog =
1715                         gnome_print_dialog_new (ev_window->priv->print_job,
1716                                                 (guchar *) _("Print"),
1717                                                 (GNOME_PRINT_DIALOG_RANGE |
1718                                                  GNOME_PRINT_DIALOG_COPIES));
1719         }
1720         
1721         gtk_window_set_transient_for (GTK_WINDOW (ev_window->priv->print_dialog),
1722                                       GTK_WINDOW (ev_window));                                                          
1723         g_object_unref (config);                                                                
1724
1725         pages_label = g_strconcat (_("Pages"), " ", NULL);
1726         gnome_print_dialog_construct_range_page (GNOME_PRINT_DIALOG (ev_window->priv->print_dialog),
1727                                                  GNOME_PRINT_RANGE_ALL |
1728                                                  GNOME_PRINT_RANGE_RANGE,
1729                                                  first_page, last_page,
1730                                                  NULL, (const guchar *)pages_label);
1731         g_free (pages_label);
1732                                                  
1733         gtk_dialog_set_response_sensitive (GTK_DIALOG (ev_window->priv->print_dialog),
1734                                            GNOME_PRINT_DIALOG_RESPONSE_PREVIEW,
1735                                            FALSE);
1736
1737         g_signal_connect (G_OBJECT (ev_window->priv->print_dialog), "response",
1738                           G_CALLBACK (ev_window_print_dialog_response_cb),
1739                           ev_window);
1740         gtk_widget_show (ev_window->priv->print_dialog);
1741 }
1742 #endif /* WITH_GNOME_PRINT */
1743
1744 static void
1745 ev_window_print (EvWindow *window)
1746 {
1747         EvPageCache *page_cache;
1748         gint         last_page;
1749
1750         page_cache = ev_page_cache_get (window->priv->document);
1751         last_page = ev_page_cache_get_n_pages (page_cache);
1752
1753 #ifdef WITH_PRINT
1754         ev_window_print_range (window, 1, last_page);
1755 #endif
1756 }
1757
1758 static void
1759 ev_window_cmd_file_print (GtkAction *action, EvWindow *ev_window)
1760 {
1761         ev_window_print (ev_window);
1762 }
1763
1764 static void
1765 ev_window_cmd_file_properties (GtkAction *action, EvWindow *ev_window)
1766 {
1767         if (ev_window->priv->properties == NULL) {
1768                 ev_window->priv->properties = ev_properties_dialog_new ();
1769                 ev_properties_dialog_set_document (EV_PROPERTIES_DIALOG (ev_window->priv->properties),
1770                                                    ev_window->priv->document);
1771                 g_object_add_weak_pointer (G_OBJECT (ev_window->priv->properties),
1772                                            (gpointer *) &(ev_window->priv->properties));
1773                 gtk_window_set_transient_for (GTK_WINDOW (ev_window->priv->properties),
1774                                               GTK_WINDOW (ev_window));
1775         }
1776
1777         gtk_widget_show (ev_window->priv->properties);
1778 }
1779                                         
1780 static void
1781 ev_window_cmd_file_close_window (GtkAction *action, EvWindow *ev_window)
1782 {
1783         g_return_if_fail (EV_IS_WINDOW (ev_window));
1784
1785         gtk_widget_destroy (GTK_WIDGET (ev_window));
1786 }
1787
1788 static void
1789 ev_window_cmd_focus_page_selector (GtkAction *act, EvWindow *window)
1790 {
1791         GtkAction *action;
1792         
1793         update_chrome_flag (window, EV_CHROME_RAISE_TOOLBAR, TRUE);
1794         ev_window_set_action_sensitive (window, "ViewToolbar", FALSE);
1795         
1796         action = gtk_action_group_get_action (window->priv->action_group,
1797                                               PAGE_SELECTOR_ACTION);
1798         ev_page_action_grab_focus (EV_PAGE_ACTION (action));
1799 }
1800
1801 static void
1802 ev_window_cmd_scroll_forward (GtkAction *action, EvWindow *window)
1803 {
1804         ev_view_scroll (EV_VIEW (window->priv->view), EV_SCROLL_PAGE_FORWARD, FALSE);
1805 }
1806
1807 static void
1808 ev_window_cmd_scroll_backward (GtkAction *action, EvWindow *window)
1809 {
1810         ev_view_scroll (EV_VIEW (window->priv->view), EV_SCROLL_PAGE_BACKWARD, FALSE);
1811 }
1812
1813 static void
1814 ev_window_cmd_continuous (GtkAction *action, EvWindow *ev_window)
1815 {
1816         gboolean continuous;
1817
1818         ev_window_stop_presentation (ev_window);
1819         continuous = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1820         g_object_set (G_OBJECT (ev_window->priv->view),
1821                       "continuous", continuous,
1822                       NULL);
1823         ev_window_update_actions (ev_window);
1824 }
1825
1826 static void
1827 ev_window_cmd_dual (GtkAction *action, EvWindow *ev_window)
1828 {
1829         gboolean dual_page;
1830
1831         ev_window_stop_presentation (ev_window);
1832         dual_page = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1833         g_object_set (G_OBJECT (ev_window->priv->view),
1834                       "dual-page", dual_page,
1835                       NULL);
1836         ev_window_update_actions (ev_window);
1837 }
1838
1839 static void
1840 ev_window_cmd_view_best_fit (GtkAction *action, EvWindow *ev_window)
1841 {
1842         ev_window_stop_presentation (ev_window);
1843
1844         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
1845                 ev_view_set_sizing_mode (EV_VIEW (ev_window->priv->view), EV_SIZING_BEST_FIT);
1846         } else {
1847                 ev_view_set_sizing_mode (EV_VIEW (ev_window->priv->view), EV_SIZING_FREE);
1848         }
1849         ev_window_update_actions (ev_window);
1850 }
1851
1852 static void
1853 ev_window_cmd_view_page_width (GtkAction *action, EvWindow *ev_window)
1854 {
1855         ev_window_stop_presentation (ev_window);
1856
1857         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
1858                 ev_view_set_sizing_mode (EV_VIEW (ev_window->priv->view), EV_SIZING_FIT_WIDTH);
1859         } else {
1860                 ev_view_set_sizing_mode (EV_VIEW (ev_window->priv->view), EV_SIZING_FREE);
1861         }
1862         ev_window_update_actions (ev_window);
1863 }
1864
1865
1866 static void
1867 ev_window_cmd_edit_select_all (GtkAction *action, EvWindow *ev_window)
1868 {
1869         g_return_if_fail (EV_IS_WINDOW (ev_window));
1870
1871         ev_view_select_all (EV_VIEW (ev_window->priv->view));
1872 }
1873
1874 static void
1875 ev_window_cmd_edit_find (GtkAction *action, EvWindow *ev_window)
1876 {
1877         g_return_if_fail (EV_IS_WINDOW (ev_window));
1878
1879         if (ev_window->priv->document == NULL || !EV_IS_DOCUMENT_FIND (ev_window->priv->document)) {
1880                 g_error ("Find action should be insensitive since document doesn't support find");
1881                 return;
1882         } 
1883
1884         update_chrome_flag (ev_window, EV_CHROME_FINDBAR, TRUE);
1885         gtk_widget_grab_focus (ev_window->priv->find_bar);
1886 }
1887
1888 static void
1889 ev_window_cmd_edit_find_next (GtkAction *action, EvWindow *ev_window)
1890 {
1891         g_return_if_fail (EV_IS_WINDOW (ev_window));
1892
1893         ev_view_find_next (EV_VIEW (ev_window->priv->view));
1894 }
1895
1896 static void
1897 ev_window_cmd_edit_find_previous (GtkAction *action, EvWindow *ev_window)
1898 {
1899         g_return_if_fail (EV_IS_WINDOW (ev_window));
1900
1901         ev_view_find_previous (EV_VIEW (ev_window->priv->view));
1902 }
1903
1904 static void
1905 ev_window_cmd_edit_copy (GtkAction *action, EvWindow *ev_window)
1906 {
1907         g_return_if_fail (EV_IS_WINDOW (ev_window));
1908
1909         ev_view_copy (EV_VIEW (ev_window->priv->view));
1910 }
1911
1912 static void
1913 ev_window_update_fullscreen_popup (EvWindow *window)
1914 {
1915         GtkWidget *popup = window->priv->fullscreen_popup;
1916         int popup_width, popup_height;
1917         GdkScreen *screen;
1918         GdkRectangle screen_rect;
1919         gboolean toolbar;
1920
1921         g_return_if_fail (popup != NULL);
1922
1923         if (GTK_WIDGET (window)->window == NULL)
1924                 return;
1925
1926         toolbar = (window->priv->chrome & EV_CHROME_FULLSCREEN_TOOLBAR) != 0 || 
1927                   (window->priv->chrome & EV_CHROME_RAISE_TOOLBAR) != 0;
1928         popup_width = popup->requisition.width;
1929         popup_height = popup->requisition.height;
1930
1931         screen = gtk_widget_get_screen (GTK_WIDGET (window));
1932         gdk_screen_get_monitor_geometry (screen,
1933                         gdk_screen_get_monitor_at_window
1934                         (screen,
1935                          GTK_WIDGET (window)->window),
1936                          &screen_rect);
1937         if (toolbar) {
1938                 gtk_widget_set_size_request (popup,
1939                                              screen_rect.width,
1940                                              -1);
1941                 gtk_window_move (GTK_WINDOW (popup),
1942                                  screen_rect.x,
1943                                  screen_rect.y);
1944
1945         } else {
1946                 if (gtk_widget_get_direction (popup) == GTK_TEXT_DIR_RTL)
1947                 {
1948                         gtk_window_move (GTK_WINDOW (popup),
1949                                          screen_rect.x,
1950                                          screen_rect.y);
1951                 } else {
1952                         gtk_window_move (GTK_WINDOW (popup),
1953                                          screen_rect.x + screen_rect.width - popup_width,
1954                                          screen_rect.y);
1955                 }
1956         }
1957 }
1958
1959 static void
1960 screen_size_changed_cb (GdkScreen *screen,
1961                         EvWindow *window)
1962 {
1963         ev_window_update_fullscreen_popup (window);
1964 }
1965
1966 static void
1967 ev_window_sidebar_position_change_cb (GObject *object, GParamSpec *pspec,
1968                                       EvWindow *ev_window)
1969 {
1970         if (!ev_window_is_empty (ev_window))
1971                 ev_metadata_manager_set_int (ev_window->priv->uri, "sidebar_size",
1972                                              gtk_paned_get_position (GTK_PANED (object)));
1973 }
1974
1975 static void
1976 destroy_fullscreen_popup (EvWindow *window)
1977 {
1978         if (window->priv->fullscreen_popup != NULL)
1979         {
1980                 gtk_widget_destroy (window->priv->fullscreen_popup);
1981                 window->priv->fullscreen_popup = NULL;
1982         }
1983 }
1984
1985 static void
1986 exit_fullscreen_button_clicked_cb (GtkWidget *button, EvWindow *window)
1987 {
1988         GtkAction *action;
1989
1990         action = gtk_action_group_get_action (window->priv->action_group, "ViewFullscreen");
1991         g_return_if_fail (action != NULL);
1992
1993         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), FALSE);
1994 }
1995
1996 static void
1997 fullscreen_popup_size_request_cb (GtkWidget *popup, GtkRequisition *req, EvWindow *window)
1998 {
1999         ev_window_update_fullscreen_popup (window);
2000 }
2001
2002 static gboolean
2003 fullscreen_timeout_cb (gpointer data)
2004 {
2005         EvWindow *window = EV_WINDOW (data);
2006         
2007         update_chrome_flag (window, EV_CHROME_FULLSCREEN_TOOLBAR, FALSE);
2008         ev_view_hide_cursor (EV_VIEW (window->priv->view));
2009         window->priv->fullscreen_timeout_id = 0;
2010
2011         return FALSE;
2012 }
2013
2014 static void
2015 fullscreen_set_timeout (EvWindow *window)
2016 {
2017         if (window->priv->fullscreen_timeout_id != 0) {
2018                 g_source_remove (window->priv->fullscreen_timeout_id);
2019         }
2020         
2021         window->priv->fullscreen_timeout_id = 
2022             g_timeout_add (FULLSCREEN_TIMEOUT, fullscreen_timeout_cb, window);
2023
2024         update_chrome_flag (window, EV_CHROME_FULLSCREEN_TOOLBAR, TRUE);
2025         update_chrome_visibility (window);
2026         ev_view_show_cursor (EV_VIEW (window->priv->view));
2027 }
2028
2029 static void
2030 fullscreen_clear_timeout (EvWindow *window)
2031 {
2032         if (window->priv->fullscreen_timeout_id != 0) {
2033                 g_source_remove (window->priv->fullscreen_timeout_id);
2034         }
2035         
2036         window->priv->fullscreen_timeout_id = 0;
2037         update_chrome_visibility (window);
2038         ev_view_show_cursor (EV_VIEW (window->priv->view));
2039 }
2040
2041
2042 static gboolean
2043 fullscreen_motion_notify_cb (GtkWidget *widget,
2044                              GdkEventMotion *event,
2045                              gpointer user_data)
2046 {
2047         EvWindow *window = EV_WINDOW (user_data);
2048
2049         fullscreen_set_timeout (window);
2050
2051         return FALSE;
2052 }
2053
2054 static gboolean
2055 fullscreen_leave_notify_cb (GtkWidget *widget,
2056                             GdkEventCrossing *event,
2057                             gpointer user_data)
2058 {
2059         EvWindow *window = EV_WINDOW (user_data);
2060
2061         fullscreen_clear_timeout (window);
2062
2063         return FALSE;
2064 }
2065
2066 static GtkWidget *
2067 ev_window_get_exit_fullscreen_button (EvWindow *window)
2068 {
2069         GtkWidget *button, *icon, *label, *hbox;
2070
2071         button = gtk_button_new ();
2072         g_signal_connect (button, "clicked",
2073                           G_CALLBACK (exit_fullscreen_button_clicked_cb),
2074                           window);
2075         gtk_widget_show (button);
2076
2077         hbox = gtk_hbox_new (FALSE, 2);
2078         gtk_widget_show (hbox);
2079         gtk_container_add (GTK_CONTAINER (button), hbox);
2080
2081         icon = gtk_image_new_from_stock (EV_STOCK_LEAVE_FULLSCREEN, GTK_ICON_SIZE_BUTTON);
2082         gtk_widget_show (icon);
2083         gtk_box_pack_start (GTK_BOX (hbox), icon, FALSE, FALSE, 0);
2084
2085         label = gtk_label_new (_("Leave Fullscreen"));
2086         gtk_widget_show (label);
2087         gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
2088
2089         return button;
2090 }
2091
2092 static GtkWidget *
2093 ev_window_create_fullscreen_popup (EvWindow *window)
2094 {
2095         GtkWidget *popup;
2096         GtkWidget *hbox;
2097         GtkWidget *button;
2098         GdkScreen *screen;
2099
2100         window->priv->fullscreen_toolbar = egg_editable_toolbar_new_with_model
2101                         (window->priv->ui_manager, ev_application_get_toolbars_model (EV_APP), NULL);
2102
2103         popup = gtk_window_new (GTK_WINDOW_POPUP);
2104         hbox = gtk_hbox_new (FALSE, 0);
2105         button = ev_window_get_exit_fullscreen_button (window);
2106
2107         gtk_container_add (GTK_CONTAINER (popup), hbox);
2108         gtk_box_pack_start (GTK_BOX (hbox), window->priv->fullscreen_toolbar,
2109                             TRUE, TRUE, 0);
2110         gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
2111
2112         gtk_widget_show (button);
2113         gtk_widget_show (hbox);
2114
2115         gtk_window_set_resizable (GTK_WINDOW (popup), FALSE);
2116
2117         screen = gtk_widget_get_screen (GTK_WIDGET (window));
2118         g_signal_connect_object (screen, "size-changed",
2119                                  G_CALLBACK (screen_size_changed_cb),
2120                                  window, 0);
2121         g_signal_connect_object (popup, "size_request",
2122                                  G_CALLBACK (fullscreen_popup_size_request_cb),
2123                                  window, 0);
2124
2125         gtk_window_set_screen (GTK_WINDOW (popup),
2126                                gtk_widget_get_screen (GTK_WIDGET (window)));
2127
2128         return popup;
2129 }
2130
2131
2132 static void
2133 ev_window_update_fullscreen_action (EvWindow *window)
2134 {
2135         GtkAction *action;
2136
2137         action = gtk_action_group_get_action (window->priv->action_group, "ViewFullscreen");
2138         g_signal_handlers_block_by_func
2139                 (action, G_CALLBACK (ev_window_cmd_view_fullscreen), window);
2140         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
2141                                       ev_view_get_fullscreen (EV_VIEW (window->priv->view)));
2142         g_signal_handlers_unblock_by_func
2143                 (action, G_CALLBACK (ev_window_cmd_view_fullscreen), window);
2144 }
2145
2146 static void
2147 ev_window_run_fullscreen (EvWindow *window)
2148 {
2149         if (window->priv->fullscreen_popup == NULL)
2150                 window->priv->fullscreen_popup
2151                         = ev_window_create_fullscreen_popup (window);
2152
2153         g_object_set (G_OBJECT (window->priv->scrolled_window),
2154                       "shadow-type", GTK_SHADOW_NONE,
2155                       NULL);
2156
2157         ev_view_set_fullscreen (EV_VIEW (window->priv->view), TRUE);
2158         ev_window_update_fullscreen_action (window);
2159         
2160         gtk_window_fullscreen (GTK_WINDOW (window));
2161         gtk_widget_grab_focus (window->priv->view);
2162         ev_window_update_fullscreen_popup (window);
2163
2164         g_signal_connect (window->priv->view,
2165                           "motion-notify-event",
2166                           G_CALLBACK (fullscreen_motion_notify_cb),
2167                           window);
2168         g_signal_connect (window->priv->view,
2169                           "leave-notify-event",
2170                           G_CALLBACK (fullscreen_leave_notify_cb),
2171                           window);
2172         fullscreen_set_timeout (window);
2173
2174         if (!ev_window_is_empty (window))
2175                 ev_metadata_manager_set_boolean (window->priv->uri, "fullscreen", TRUE);
2176 }
2177
2178 static void
2179 ev_window_stop_fullscreen (EvWindow *window)
2180 {
2181         EvView *view = EV_VIEW (window->priv->view);
2182
2183         if (!ev_view_get_fullscreen (EV_VIEW (view)))
2184                 return;
2185
2186         g_object_set (G_OBJECT (window->priv->scrolled_window),
2187                       "shadow-type", GTK_SHADOW_IN,
2188                       NULL);
2189
2190         ev_view_set_fullscreen (view, FALSE);
2191         ev_window_update_fullscreen_action (window);
2192         gtk_window_unfullscreen (GTK_WINDOW (window));
2193
2194         g_signal_handlers_disconnect_by_func (window->priv->view,
2195                                               (gpointer) fullscreen_motion_notify_cb,
2196                                               window);
2197         g_signal_handlers_disconnect_by_func (window->priv->view,
2198                                               (gpointer) fullscreen_leave_notify_cb,
2199                                               window);
2200         fullscreen_clear_timeout (window);
2201
2202         if (!ev_window_is_empty (window))
2203                 ev_metadata_manager_set_boolean (window->priv->uri, "fullscreen", FALSE);
2204 }
2205
2206 static void
2207 ev_window_cmd_view_fullscreen (GtkAction *action, EvWindow *window)
2208 {
2209         gboolean fullscreen;
2210
2211         g_return_if_fail (EV_IS_WINDOW (window));
2212         ev_window_stop_presentation (window);
2213
2214         fullscreen = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
2215         if (fullscreen) {
2216                 ev_window_run_fullscreen (window);
2217         } else {
2218                 ev_window_stop_fullscreen (window);
2219         }
2220 }
2221
2222 static void
2223 ev_window_update_presentation_action (EvWindow *window)
2224 {
2225         GtkAction *action;
2226
2227         action = gtk_action_group_get_action (window->priv->action_group, "ViewPresentation");
2228         g_signal_handlers_block_by_func
2229                 (action, G_CALLBACK (ev_window_cmd_view_presentation), window);
2230         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
2231                                       ev_view_get_presentation (EV_VIEW (window->priv->view)));
2232         g_signal_handlers_unblock_by_func
2233                 (action, G_CALLBACK (ev_window_cmd_view_presentation), window);
2234 }
2235
2236 static void
2237 ev_window_run_presentation (EvWindow *window)
2238 {
2239         g_object_set (G_OBJECT (window->priv->scrolled_window),
2240                       "shadow-type", GTK_SHADOW_NONE,
2241                       NULL);
2242
2243         ev_view_set_presentation (EV_VIEW (window->priv->view), TRUE);
2244         ev_window_update_presentation_action (window);
2245
2246         gtk_widget_grab_focus (window->priv->view);
2247         gtk_window_fullscreen (GTK_WINDOW (window));
2248
2249         g_signal_connect (window->priv->view,
2250                           "motion-notify-event",
2251                           G_CALLBACK (fullscreen_motion_notify_cb),
2252                           window);
2253         g_signal_connect (window->priv->view,
2254                           "leave-notify-event",
2255                           G_CALLBACK (fullscreen_leave_notify_cb),
2256                           window);
2257         fullscreen_set_timeout (window);
2258
2259         if (!ev_window_is_empty (window))
2260                 ev_metadata_manager_set_boolean (window->priv->uri, "presentation", TRUE);
2261 }
2262
2263 static void
2264 ev_window_stop_presentation (EvWindow *window)
2265 {
2266         if (!ev_view_get_presentation (EV_VIEW (window->priv->view)))
2267                 return;
2268
2269         g_object_set (G_OBJECT (window->priv->scrolled_window),
2270                       "shadow-type", GTK_SHADOW_IN,
2271                       NULL);
2272
2273         ev_view_set_presentation (EV_VIEW (window->priv->view), FALSE);
2274         ev_window_update_presentation_action (window);
2275         gtk_window_unfullscreen (GTK_WINDOW (window));
2276
2277         g_signal_handlers_disconnect_by_func (window->priv->view,
2278                                               (gpointer) fullscreen_motion_notify_cb,
2279                                               window);
2280         g_signal_handlers_disconnect_by_func (window->priv->view,
2281                                               (gpointer) fullscreen_leave_notify_cb,
2282                                               window);
2283         fullscreen_clear_timeout (window);
2284
2285         if (!ev_window_is_empty (window))
2286                 ev_metadata_manager_set_boolean (window->priv->uri, "presentation", FALSE);
2287 }
2288
2289 static void
2290 ev_window_cmd_view_presentation (GtkAction *action, EvWindow *window)
2291 {
2292         gboolean presentation;
2293
2294         g_return_if_fail (EV_IS_WINDOW (window));
2295         ev_window_stop_fullscreen (window);
2296
2297         presentation = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
2298         if (presentation) {
2299                 ev_window_run_presentation (window);
2300         } else {
2301                 ev_window_stop_presentation (window);
2302         }
2303 }
2304
2305 static void
2306 ev_window_run_preview (EvWindow *window)
2307 {
2308         EggToolbarsModel *model;
2309         EggTbModelFlags   flags;
2310
2311         model = egg_toolbars_model_new ();
2312
2313         egg_toolbars_model_load_toolbars (model,
2314                                           DATADIR"/evince-toolbar.xml");
2315         
2316         flags = egg_toolbars_model_get_flags (model, 1);
2317         egg_toolbars_model_set_flags (model, 1, flags &= ~(EGG_TB_MODEL_HIDDEN));
2318
2319         egg_editable_toolbar_set_model (EGG_EDITABLE_TOOLBAR (window->priv->toolbar),
2320                                         model);
2321         
2322         egg_editable_toolbar_hide (EGG_EDITABLE_TOOLBAR (window->priv->toolbar),
2323                                    "DefaultToolBar");
2324         egg_editable_toolbar_show (EGG_EDITABLE_TOOLBAR (window->priv->toolbar),
2325                                    "PreviewToolBar");
2326
2327         ev_view_set_continuous (EV_VIEW (window->priv->view), FALSE); 
2328         
2329         update_chrome_flag (window, EV_CHROME_MENUBAR, FALSE);
2330         update_chrome_flag (window, EV_CHROME_SIDEBAR, FALSE);
2331         update_chrome_visibility (window);
2332 }
2333
2334 static gboolean
2335 ev_window_focus_in_event (GtkWidget *widget, GdkEventFocus *event)
2336 {
2337         EvWindow *window = EV_WINDOW (widget);
2338         EvWindowPrivate *priv = window->priv;
2339
2340         if (ev_view_get_fullscreen (EV_VIEW (priv->view)))
2341                 fullscreen_set_timeout (window);
2342
2343         return GTK_WIDGET_CLASS (ev_window_parent_class)->focus_in_event (widget, event);
2344 }
2345
2346 static gboolean
2347 ev_window_focus_out_event (GtkWidget *widget, GdkEventFocus *event)
2348 {
2349         EvWindow *window = EV_WINDOW (widget);
2350         EvWindowPrivate *priv = window->priv;
2351
2352         if (ev_view_get_fullscreen (EV_VIEW (priv->view))) {
2353                 fullscreen_set_timeout (window);
2354                 gtk_widget_hide (priv->fullscreen_popup);
2355         }
2356
2357         return GTK_WIDGET_CLASS (ev_window_parent_class)->focus_out_event (widget, event);
2358 }
2359
2360 static void
2361 ev_window_screen_changed (GtkWidget *widget,
2362                           GdkScreen *old_screen)
2363 {
2364         EvWindow *window = EV_WINDOW (widget);
2365         EvWindowPrivate *priv = window->priv;
2366         GdkScreen *screen;
2367
2368         if (GTK_WIDGET_CLASS (ev_window_parent_class)->screen_changed) {
2369                 GTK_WIDGET_CLASS (ev_window_parent_class)->screen_changed (widget, old_screen);
2370         }
2371
2372         if (priv->fullscreen_popup != NULL) {
2373                 g_signal_handlers_disconnect_by_func
2374                         (old_screen, G_CALLBACK (screen_size_changed_cb), window);
2375
2376                 screen = gtk_widget_get_screen (widget);
2377                 g_signal_connect_object (screen, "size-changed",
2378                                          G_CALLBACK (screen_size_changed_cb),
2379                                          window, 0);
2380                 gtk_window_set_screen (GTK_WINDOW (priv->fullscreen_popup), screen);
2381
2382                 ev_window_update_fullscreen_popup (window);
2383         }
2384 }
2385
2386 static void
2387 ev_window_set_page_mode (EvWindow         *window,
2388                          EvWindowPageMode  page_mode)
2389 {
2390         GtkWidget *child = NULL;
2391         GtkWidget *real_child;
2392
2393         if (window->priv->page_mode == page_mode)
2394                 return;
2395
2396         window->priv->page_mode = page_mode;
2397
2398         switch (page_mode) {
2399                 case PAGE_MODE_DOCUMENT:
2400                         child = window->priv->view;
2401                         break;
2402                 case PAGE_MODE_PASSWORD:
2403                         child = window->priv->password_view;
2404                         break;
2405                 default:
2406                         g_assert_not_reached ();
2407         }
2408
2409         real_child = gtk_bin_get_child (GTK_BIN (window->priv->scrolled_window));
2410         if (child != real_child) {
2411                 gtk_container_remove (GTK_CONTAINER (window->priv->scrolled_window),
2412                                       real_child);
2413                 gtk_container_add (GTK_CONTAINER (window->priv->scrolled_window),
2414                                    child);
2415         }
2416         ev_window_update_actions (window);
2417 }
2418
2419
2420 static void
2421 ev_window_cmd_edit_rotate_left (GtkAction *action, EvWindow *ev_window)
2422 {
2423         ev_view_rotate_left (EV_VIEW (ev_window->priv->view));
2424 }
2425
2426 static void
2427 ev_window_cmd_edit_rotate_right (GtkAction *action, EvWindow *ev_window)
2428 {
2429         ev_view_rotate_right (EV_VIEW (ev_window->priv->view));
2430 }
2431
2432 static void
2433 ev_window_cmd_edit_toolbar_cb (GtkDialog *dialog, gint response, gpointer data)
2434 {
2435         EvWindow *ev_window = EV_WINDOW (data);
2436         egg_editable_toolbar_set_edit_mode
2437                         (EGG_EDITABLE_TOOLBAR (ev_window->priv->toolbar), FALSE);
2438         ev_application_save_toolbars_model (EV_APP);
2439         gtk_widget_destroy (GTK_WIDGET (dialog));
2440 }
2441
2442 static void
2443 ev_window_cmd_edit_toolbar (GtkAction *action, EvWindow *ev_window)
2444 {
2445         GtkWidget *dialog;
2446         GtkWidget *editor;
2447
2448         dialog = gtk_dialog_new_with_buttons (_("Toolbar Editor"),
2449                                               GTK_WINDOW (ev_window), 
2450                                               GTK_DIALOG_DESTROY_WITH_PARENT, 
2451                                               GTK_STOCK_CLOSE,
2452                                               GTK_RESPONSE_CLOSE, 
2453                                               NULL);
2454         gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE);
2455         gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)), 5);
2456         gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 2);
2457         gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
2458         gtk_window_set_default_size (GTK_WINDOW (dialog), 500, 400);
2459           
2460         editor = egg_toolbar_editor_new (ev_window->priv->ui_manager,
2461                                          ev_application_get_toolbars_model (EV_APP));
2462         gtk_container_set_border_width (GTK_CONTAINER (editor), 5);
2463         gtk_box_set_spacing (GTK_BOX (EGG_TOOLBAR_EDITOR (editor)), 5);
2464              
2465         gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), editor);
2466
2467         egg_editable_toolbar_set_edit_mode
2468                 (EGG_EDITABLE_TOOLBAR (ev_window->priv->toolbar), TRUE);
2469
2470         g_signal_connect (dialog, "response",
2471                           G_CALLBACK (ev_window_cmd_edit_toolbar_cb),
2472                           ev_window);
2473         gtk_widget_show_all (dialog);
2474 }
2475
2476 static void
2477 ev_window_cmd_view_zoom_in (GtkAction *action, EvWindow *ev_window)
2478 {
2479         g_return_if_fail (EV_IS_WINDOW (ev_window));
2480
2481         ev_view_set_sizing_mode (EV_VIEW (ev_window->priv->view), EV_SIZING_FREE);
2482         ev_view_zoom_in (EV_VIEW (ev_window->priv->view));
2483 }
2484
2485 static void
2486 ev_window_cmd_view_zoom_out (GtkAction *action, EvWindow *ev_window)
2487 {
2488         g_return_if_fail (EV_IS_WINDOW (ev_window));
2489
2490         ev_view_set_sizing_mode (EV_VIEW (ev_window->priv->view), EV_SIZING_FREE);
2491         ev_view_zoom_out (EV_VIEW (ev_window->priv->view));
2492 }
2493
2494 static void
2495 ev_window_cmd_go_previous_page (GtkAction *action, EvWindow *ev_window)
2496 {
2497         g_return_if_fail (EV_IS_WINDOW (ev_window));
2498
2499         ev_view_previous_page (EV_VIEW (ev_window->priv->view));
2500 }
2501
2502 static void
2503 ev_window_cmd_go_next_page (GtkAction *action, EvWindow *ev_window)
2504 {
2505         g_return_if_fail (EV_IS_WINDOW (ev_window));
2506
2507         ev_view_next_page (EV_VIEW (ev_window->priv->view));
2508 }
2509
2510 static void
2511 ev_window_cmd_go_first_page (GtkAction *action, EvWindow *ev_window)
2512 {
2513         g_return_if_fail (EV_IS_WINDOW (ev_window));
2514
2515         ev_page_cache_set_current_page (ev_window->priv->page_cache, 0);
2516 }
2517
2518 static void
2519 ev_window_cmd_go_last_page (GtkAction *action, EvWindow *ev_window)
2520 {
2521         int n_pages;
2522
2523         g_return_if_fail (EV_IS_WINDOW (ev_window));
2524
2525         n_pages = ev_page_cache_get_n_pages (ev_window->priv->page_cache);
2526         ev_page_cache_set_current_page (ev_window->priv->page_cache, n_pages - 1);
2527 }
2528
2529 static void
2530 ev_window_cmd_go_forward (GtkAction *action, EvWindow *ev_window)
2531 {
2532         int n_pages, current_page;
2533         
2534         g_return_if_fail (EV_IS_WINDOW (ev_window));
2535
2536         n_pages = ev_page_cache_get_n_pages (ev_window->priv->page_cache);
2537         current_page = ev_page_cache_get_current_page (ev_window->priv->page_cache);
2538         
2539         if (current_page + 10 < n_pages)
2540                 ev_page_cache_set_current_page (ev_window->priv->page_cache, current_page + 10);
2541 }
2542
2543 static void
2544 ev_window_cmd_go_backward (GtkAction *action, EvWindow *ev_window)
2545 {
2546         int current_page;
2547         
2548         g_return_if_fail (EV_IS_WINDOW (ev_window));
2549
2550         current_page = ev_page_cache_get_current_page (ev_window->priv->page_cache);
2551         
2552         if (current_page - 10 >= 0)
2553                 ev_page_cache_set_current_page (ev_window->priv->page_cache, current_page - 10);
2554 }
2555
2556 static void
2557 ev_window_cmd_view_reload (GtkAction *action, EvWindow *ev_window)
2558 {
2559         char *uri;
2560
2561         g_return_if_fail (EV_IS_WINDOW (ev_window));
2562
2563         uri = g_strdup (ev_window->priv->uri);
2564
2565         ev_window_open_uri (ev_window, uri, NULL, 0);
2566
2567         g_free (uri);
2568 }
2569
2570 static void
2571 ev_window_cmd_help_contents (GtkAction *action, EvWindow *ev_window)
2572 {
2573         GError *error = NULL;
2574
2575         g_return_if_fail (EV_IS_WINDOW (ev_window));
2576
2577         gnome_help_display ("evince.xml", NULL, &error);
2578
2579         if(error != NULL) {
2580                 g_warning (error->message);
2581                 g_error_free (error);
2582         }
2583 }
2584
2585 static void
2586 ev_window_cmd_leave_fullscreen (GtkAction *action, EvWindow *window)
2587 {
2588         gtk_window_unfullscreen (GTK_WINDOW (window));
2589 }
2590
2591 static void
2592 ev_window_cmd_escape (GtkAction *action, EvWindow *window)
2593 {
2594         GtkWidget *widget;
2595
2596         widget = gtk_window_get_focus (GTK_WINDOW (window));
2597         if (widget && gtk_widget_get_ancestor (widget, EGG_TYPE_FIND_BAR)) {
2598                 update_chrome_flag (window, EV_CHROME_FINDBAR, FALSE);
2599                 gtk_widget_grab_focus (window->priv->view);
2600         } else {
2601                 gboolean fullscreen;
2602                 gboolean presentation;
2603
2604                 g_object_get (window->priv->view,
2605                               "fullscreen", &fullscreen,
2606                               "presentation", &presentation,
2607                               NULL);
2608
2609                 if (fullscreen)
2610                         ev_window_stop_fullscreen (window);
2611                 if (presentation)
2612                         ev_window_stop_presentation (window);
2613
2614                 if (fullscreen && presentation)
2615                         g_warning ("Both fullscreen and presentation set somehow");
2616         }
2617 }
2618
2619 static void
2620 update_view_size (EvView *view, EvWindow *window)
2621 {
2622         int width, height;
2623         GtkRequisition vsb_requisition;
2624         GtkRequisition hsb_requisition;
2625         int scrollbar_spacing;
2626
2627         /* Calculate the width available for the */
2628         width = window->priv->scrolled_window->allocation.width;
2629         height = window->priv->scrolled_window->allocation.height;
2630
2631         if (gtk_scrolled_window_get_shadow_type (GTK_SCROLLED_WINDOW (window->priv->scrolled_window)) == GTK_SHADOW_IN) {
2632                 width -= 2 * window->priv->view->style->xthickness;
2633                 height -= 2 * window->priv->view->style->ythickness;
2634         }
2635
2636         gtk_widget_size_request (GTK_SCROLLED_WINDOW (window->priv->scrolled_window)->vscrollbar,
2637                                  &vsb_requisition);
2638         gtk_widget_size_request (GTK_SCROLLED_WINDOW (window->priv->scrolled_window)->hscrollbar,
2639                                  &hsb_requisition);
2640         gtk_widget_style_get (window->priv->scrolled_window,
2641                               "scrollbar_spacing", &scrollbar_spacing,
2642                               NULL);
2643
2644         ev_view_set_zoom_for_size (EV_VIEW (window->priv->view),
2645                                    MAX (1, width),
2646                                    MAX (1, height),
2647                                    vsb_requisition.width + scrollbar_spacing,
2648                                    hsb_requisition.height + scrollbar_spacing);
2649 }
2650
2651 static void
2652 save_sizing_mode (EvWindow *window)
2653 {
2654         EvSizingMode mode;
2655         GEnumValue *enum_value;
2656
2657         mode = ev_view_get_sizing_mode (EV_VIEW (window->priv->view));
2658         enum_value = g_enum_get_value (EV_SIZING_MODE_CLASS, mode);
2659
2660         if (!ev_window_is_empty (window))
2661                 ev_metadata_manager_set_string (window->priv->uri, "sizing_mode",
2662                                                 enum_value->value_nick);
2663 }
2664
2665 static void     
2666 ev_window_sizing_mode_changed_cb (EvView *view, GParamSpec *pspec,
2667                                   EvWindow   *ev_window)
2668 {
2669         GtkWidget *scrolled_window;
2670         EvSizingMode sizing_mode;
2671
2672         g_object_get (ev_window->priv->view,
2673                       "sizing-mode", &sizing_mode,
2674                       NULL);
2675
2676         scrolled_window = ev_window->priv->scrolled_window;
2677
2678         g_signal_handlers_disconnect_by_func (ev_window->priv->view, update_view_size, ev_window);
2679
2680         if (sizing_mode != EV_SIZING_FREE)
2681                 update_view_size (NULL, ev_window);
2682
2683         switch (sizing_mode) {
2684                 case EV_SIZING_BEST_FIT:
2685                         g_object_set (G_OBJECT (scrolled_window),
2686                                       "hscrollbar-policy", GTK_POLICY_NEVER,
2687                                       "vscrollbar-policy", GTK_POLICY_AUTOMATIC,
2688                                       NULL);
2689                         g_signal_connect (ev_window->priv->view, "zoom_invalid",
2690                                           G_CALLBACK (update_view_size),
2691                                           ev_window);
2692                         break;
2693                 case EV_SIZING_FIT_WIDTH:
2694                         g_object_set (G_OBJECT (scrolled_window),
2695                                       "hscrollbar-policy", GTK_POLICY_NEVER,
2696                                       "vscrollbar-policy", GTK_POLICY_AUTOMATIC,
2697                                       NULL);
2698                         g_signal_connect (ev_window->priv->view, "zoom_invalid",
2699                                           G_CALLBACK (update_view_size),
2700                                           ev_window);
2701                         break;
2702                 case EV_SIZING_FREE:
2703                         g_object_set (G_OBJECT (scrolled_window),
2704                                       "hscrollbar-policy", GTK_POLICY_AUTOMATIC,
2705                                       "vscrollbar-policy", GTK_POLICY_AUTOMATIC,
2706                                       NULL);
2707                         break;
2708         }
2709
2710         update_sizing_buttons (ev_window);
2711         save_sizing_mode (ev_window);
2712 }
2713
2714 static void     
2715 ev_window_zoom_changed_cb (EvView *view, GParamSpec *pspec, EvWindow *ev_window)
2716 {
2717         ev_window_update_actions (ev_window);
2718
2719         if (ev_view_get_sizing_mode (view) == EV_SIZING_FREE && !ev_window_is_empty (ev_window)) {
2720                 ev_metadata_manager_set_double (ev_window->priv->uri, "zoom",
2721                                                 ev_view_get_zoom (view));
2722         }
2723 }
2724
2725 static void
2726 ev_window_update_continuous_action (EvWindow *window)
2727 {
2728         GtkAction *action;
2729
2730         action = gtk_action_group_get_action (window->priv->action_group, "ViewContinuous");
2731         g_signal_handlers_block_by_func
2732                 (action, G_CALLBACK (ev_window_cmd_continuous), window);
2733         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
2734                                       ev_view_get_continuous (EV_VIEW (window->priv->view)));
2735         g_signal_handlers_unblock_by_func
2736                 (action, G_CALLBACK (ev_window_cmd_continuous), window);
2737 }
2738
2739 static void
2740 ev_window_update_dual_page_action (EvWindow *window)
2741 {
2742         GtkAction *action;
2743
2744         action = gtk_action_group_get_action (window->priv->action_group, "ViewDual");
2745         g_signal_handlers_block_by_func
2746                 (action, G_CALLBACK (ev_window_cmd_dual), window);
2747         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
2748                                       ev_view_get_dual_page (EV_VIEW (window->priv->view)));
2749         g_signal_handlers_unblock_by_func
2750                 (action, G_CALLBACK (ev_window_cmd_dual), window);
2751 }
2752
2753 static void     
2754 ev_window_continuous_changed_cb (EvView *view, GParamSpec *pspec, EvWindow *ev_window)
2755 {
2756         ev_window_update_continuous_action (ev_window);
2757
2758         if (!ev_window_is_empty (ev_window))
2759                 ev_metadata_manager_set_boolean (ev_window->priv->uri, "continuous",
2760                                                  ev_view_get_continuous (EV_VIEW (ev_window->priv->view)));
2761 }
2762
2763 static void     
2764 ev_window_rotation_changed_cb (EvView *view, GParamSpec *pspec, EvWindow *window)
2765 {
2766         int rotation;
2767
2768         rotation = ev_view_get_rotation (EV_VIEW (window->priv->view));
2769
2770         if (!ev_window_is_empty (window))
2771                 ev_metadata_manager_set_int (window->priv->uri, "rotation",
2772                                              rotation);
2773
2774         ev_sidebar_thumbnails_refresh (EV_SIDEBAR_THUMBNAILS (window->priv->sidebar_thumbs),
2775                                        rotation);
2776 }
2777
2778 static void
2779 ev_window_has_selection_changed_cb (EvView *view, GParamSpec *pspec, EvWindow *window)
2780 {
2781         ev_window_update_actions (window);
2782 }
2783
2784 static void     
2785 ev_window_dual_mode_changed_cb (EvView *view, GParamSpec *pspec, EvWindow *ev_window)
2786 {
2787         ev_window_update_dual_page_action (ev_window);
2788
2789         if (!ev_window_is_empty (ev_window))
2790                 ev_metadata_manager_set_boolean (ev_window->priv->uri, "dual-page",
2791                                                  ev_view_get_dual_page (EV_VIEW (ev_window->priv->view)));
2792 }
2793
2794 static char *
2795 build_comments_string (void)
2796 {
2797         PopplerBackend backend;
2798         const char *backend_name;
2799         const char *version;
2800
2801         backend = poppler_get_backend ();
2802         version = poppler_get_version ();
2803         switch (backend) {
2804                 case POPPLER_BACKEND_CAIRO:
2805                         backend_name = "cairo";
2806                         break;
2807                 case POPPLER_BACKEND_SPLASH:
2808                         backend_name = "splash";
2809                         break;
2810                 default:
2811                         backend_name = "unknown";
2812                         break;
2813         }
2814
2815         return g_strdup_printf (_("PostScript and PDF File Viewer.\n"
2816                                   "Using poppler %s (%s)"),
2817                                 version, backend_name);
2818 }
2819
2820 static void
2821 ev_window_cmd_help_about (GtkAction *action, EvWindow *ev_window)
2822 {
2823         const char *authors[] = {
2824                 "Martin Kretzschmar <m_kretzschmar@gmx.net>",
2825                 "Jonathan Blandford <jrb@gnome.org>",
2826                 "Marco Pesenti Gritti <marco@gnome.org>",
2827                 "Nickolay V. Shmyrev <nshmyrev@yandex.ru>",
2828                 "Bryan Clark <clarkbw@gnome.org>",
2829                 "Carlos Garcia Campos  <carlosgc@gnome.org>",
2830                 NULL
2831         };
2832
2833         const char *documenters[] = {
2834                 "Nickolay V. Shmyrev <nshmyrev@yandex.ru>",
2835                 NULL
2836         };
2837
2838         const char *license[] = {
2839                 N_("Evince is free software; you can redistribute it and/or modify "
2840                    "it under the terms of the GNU General Public License as published by "
2841                    "the Free Software Foundation; either version 2 of the License, or "
2842                    "(at your option) any later version.\n"),
2843                 N_("Evince is distributed in the hope that it will be useful, "
2844                    "but WITHOUT ANY WARRANTY; without even the implied warranty of "
2845                    "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the "
2846                    "GNU General Public License for more details.\n"),
2847                 N_("You should have received a copy of the GNU General Public License "
2848                    "along with Evince; if not, write to the Free Software Foundation, Inc., "
2849                    "59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n")
2850         };
2851
2852         char *license_trans;
2853         char *comments;
2854
2855 #ifdef ENABLE_NLS
2856         const char **p;
2857
2858         for (p = authors; *p; ++p)
2859                 *p = _(*p);
2860
2861         for (p = documenters; *p; ++p)
2862                 *p = _(*p);
2863 #endif
2864
2865         license_trans = g_strconcat (_(license[0]), "\n", _(license[1]), "\n",
2866                                      _(license[2]), "\n", NULL);
2867         comments = build_comments_string ();
2868
2869         gtk_show_about_dialog (
2870                 GTK_WINDOW (ev_window),
2871                 "name", _("Evince"),
2872                 "version", VERSION,
2873                 "copyright",
2874                 _("\xc2\xa9 1996-2005 The Evince authors"),
2875                 "license", license_trans,
2876                 "website", "http://www.gnome.org/projects/evince",
2877                 "comments", comments,
2878                 "authors", authors,
2879                 "documenters", documenters,
2880                 "translator-credits", _("translator-credits"),
2881                 "logo-icon-name", "evince",
2882                 "wrap-license", TRUE,
2883                 NULL);
2884
2885         g_free (comments);
2886         g_free (license_trans);
2887 }
2888
2889 static void
2890 ev_window_view_toolbar_cb (GtkAction *action, EvWindow *ev_window)
2891 {
2892         gboolean active;
2893         
2894         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
2895         update_chrome_flag (ev_window, EV_CHROME_TOOLBAR, active);
2896         ev_metadata_manager_set_boolean (NULL, "show_toolbar", active);
2897 }
2898
2899 static void
2900 ev_window_view_sidebar_cb (GtkAction *action, EvWindow *ev_window)
2901 {
2902         update_chrome_flag (ev_window, EV_CHROME_SIDEBAR,
2903                             gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
2904 }
2905
2906 static void
2907 ev_window_sidebar_current_page_changed_cb (EvSidebar  *ev_sidebar,
2908                                            GParamSpec *pspec,
2909                                            EvWindow   *ev_window)
2910 {
2911         GtkWidget *current_page;
2912         const char *id;
2913
2914         g_object_get (G_OBJECT (ev_sidebar), "current_page", &current_page, NULL);
2915
2916         if (current_page == ev_window->priv->sidebar_links) {
2917                 id = LINKS_SIDEBAR_ID;
2918         } else if (current_page == ev_window->priv->sidebar_thumbs) {
2919                 id = THUMBNAILS_SIDEBAR_ID;
2920         } else if (current_page == ev_window->priv->sidebar_attachments) {
2921                 id = ATTACHMENTS_SIDEBAR_ID;
2922         } else {
2923                 g_assert_not_reached();
2924         }
2925
2926         g_object_unref (current_page);
2927
2928         if (!ev_window_is_empty (ev_window))
2929                 ev_metadata_manager_set_string (ev_window->priv->uri, "sidebar_page", id);
2930 }
2931
2932 static void
2933 ev_window_sidebar_visibility_changed_cb (EvSidebar  *ev_sidebar,
2934                                          GParamSpec *pspec,
2935                                          EvWindow   *ev_window)
2936 {
2937         EvView *view = EV_VIEW (ev_window->priv->view);
2938         GtkAction *action;
2939
2940         action = gtk_action_group_get_action (ev_window->priv->action_group, "ViewSidebar");
2941         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
2942                                       GTK_WIDGET_VISIBLE (ev_sidebar));
2943
2944         if (!ev_view_get_presentation (view) && 
2945             !ev_view_get_fullscreen (view)) {
2946                 ev_metadata_manager_set_boolean (ev_window->priv->uri, "sidebar_visibility",
2947                                                  GTK_WIDGET_VISIBLE (ev_sidebar));
2948         }
2949 }
2950
2951 static gboolean
2952 view_menu_popup_cb (EvView   *view,
2953                     EvLink   *link,
2954                     EvWindow *ev_window)
2955 {
2956         GtkWidget *popup;
2957         gboolean   show_external = FALSE;
2958         gboolean   show_internal = FALSE;
2959         GtkAction *action;
2960
2961         if (ev_view_get_presentation (EV_VIEW (ev_window->priv->view)))
2962                 return FALSE;
2963         
2964         if (ev_window->priv->link)
2965                 g_object_unref (ev_window->priv->link);
2966         
2967         if (link)
2968                 ev_window->priv->link = g_object_ref (link);
2969         else    
2970                 ev_window->priv->link = NULL;
2971
2972         popup = ev_window->priv->view_popup;
2973
2974         if (ev_window->priv->link) {
2975                 EvLinkAction *ev_action;
2976
2977                 ev_action = ev_link_get_action (link);
2978                 if (!ev_action)
2979                         return FALSE;
2980                 
2981                 switch (ev_link_action_get_action_type (ev_action)) {
2982                         case EV_LINK_ACTION_TYPE_GOTO_DEST:
2983                         case EV_LINK_ACTION_TYPE_GOTO_REMOTE:
2984                                 show_internal = TRUE;
2985                                 break;
2986                         case EV_LINK_ACTION_TYPE_EXTERNAL_URI:
2987                         case EV_LINK_ACTION_TYPE_LAUNCH:
2988                                 show_external = TRUE;
2989                                 break;
2990                         default:
2991                                 break;
2992                 }
2993         }
2994         
2995         action = gtk_action_group_get_action (ev_window->priv->view_popup_action_group,
2996                                               "OpenLink");
2997         gtk_action_set_visible (action, show_external);
2998
2999         action = gtk_action_group_get_action (ev_window->priv->view_popup_action_group,
3000                                               "CopyLinkAddress");
3001         gtk_action_set_visible (action, show_external);
3002
3003         action = gtk_action_group_get_action (ev_window->priv->view_popup_action_group,
3004                                               "GoLink");
3005         gtk_action_set_visible (action, show_internal);
3006
3007         gtk_menu_popup (GTK_MENU (popup), NULL, NULL,
3008                         NULL, NULL,
3009                         3, gtk_get_current_event_time ());
3010         return TRUE;
3011 }
3012
3013 static gboolean
3014 attachment_bar_menu_popup_cb (EvSidebarAttachments *attachbar,
3015                               GList           *attach_list,
3016                               EvWindow        *ev_window)
3017 {
3018         GtkWidget *popup;
3019
3020         g_assert (attach_list != NULL);
3021
3022         if (ev_window->priv->attach_list) {
3023                 g_list_foreach (ev_window->priv->attach_list,
3024                                 (GFunc) g_object_unref, NULL);
3025                 g_list_free (ev_window->priv->attach_list);
3026         }
3027         
3028         ev_window->priv->attach_list = attach_list;
3029         
3030         popup = ev_window->priv->attachment_popup;
3031
3032         gtk_menu_popup (GTK_MENU (popup), NULL, NULL,
3033                         NULL, NULL,
3034                         3, gtk_get_current_event_time ());
3035
3036         return TRUE;
3037 }
3038
3039 static void
3040 view_find_status_changed_cb (EvView     *view,
3041                              GParamSpec *pspec,
3042                              EvWindow   *ev_window)
3043 {
3044         const char *text;
3045
3046         text = ev_view_get_find_status (view);
3047         egg_find_bar_set_status_text (EGG_FIND_BAR (ev_window->priv->find_bar),
3048                                       text);
3049 }
3050
3051 static void
3052 find_bar_previous_cb (EggFindBar *find_bar,
3053                       EvWindow   *ev_window)
3054 {
3055         ev_view_find_previous (EV_VIEW (ev_window->priv->view));
3056 }
3057
3058 static void
3059 find_bar_next_cb (EggFindBar *find_bar,
3060                   EvWindow   *ev_window)
3061 {
3062         ev_view_find_next (EV_VIEW (ev_window->priv->view));
3063 }
3064
3065 static void
3066 find_bar_close_cb (EggFindBar *find_bar,
3067                    EvWindow   *ev_window)
3068 {
3069         update_chrome_flag (ev_window, EV_CHROME_FINDBAR, FALSE);
3070 }
3071
3072 static void
3073 find_bar_search_changed_cb (EggFindBar *find_bar,
3074                             GParamSpec *param,
3075                             EvWindow   *ev_window)
3076 {
3077         gboolean case_sensitive;
3078         gboolean visible;
3079         const char *search_string;
3080
3081         g_return_if_fail (EV_IS_WINDOW (ev_window));
3082
3083         /* Either the string or case sensitivity could have changed,
3084          * we connect this callback to both. We also connect it
3085          * to ::visible so when the find bar is hidden, we should
3086          * pretend the search string is NULL/""
3087          */
3088
3089         case_sensitive = egg_find_bar_get_case_sensitive (find_bar);
3090         visible = GTK_WIDGET_VISIBLE (find_bar);
3091         search_string = egg_find_bar_get_search_string (find_bar);
3092
3093         ev_view_search_changed (EV_VIEW(ev_window->priv->view));
3094
3095         if (ev_window->priv->document &&
3096             EV_IS_DOCUMENT_FIND (ev_window->priv->document)) {
3097                 if (visible && search_string && search_string[0]) {
3098                         ev_document_doc_mutex_lock ();
3099                         ev_document_find_begin (EV_DOCUMENT_FIND (ev_window->priv->document), 
3100                                                 ev_page_cache_get_current_page (ev_window->priv->page_cache),
3101                                                 search_string,
3102                                                 case_sensitive);
3103                         ev_document_doc_mutex_unlock ();
3104                 } else {
3105                         ev_document_doc_mutex_lock ();
3106                         ev_document_find_cancel (EV_DOCUMENT_FIND (ev_window->priv->document));
3107                         ev_document_doc_mutex_unlock ();
3108
3109                         ev_window_update_actions (ev_window);
3110                         egg_find_bar_set_status_text (EGG_FIND_BAR (ev_window->priv->find_bar),
3111                                                       NULL);
3112                         gtk_widget_queue_draw (GTK_WIDGET (ev_window->priv->view));
3113                 }
3114         }
3115 }
3116
3117 static void
3118 find_bar_scroll(EggFindBar *find_bar, GtkScrollType scroll, EvWindow* ev_window)
3119 {
3120         ev_view_scroll(EV_VIEW(ev_window->priv->view), scroll, FALSE);
3121 }
3122
3123 static void
3124 zoom_control_changed_cb (EphyZoomAction *action,
3125                          float           zoom,
3126                          EvWindow       *ev_window)
3127 {
3128         EvSizingMode mode;
3129         
3130         g_return_if_fail (EV_IS_WINDOW (ev_window));
3131
3132         if (zoom == EPHY_ZOOM_BEST_FIT) {
3133                 mode = EV_SIZING_BEST_FIT;
3134         } else if (zoom == EPHY_ZOOM_FIT_WIDTH) {
3135                 mode = EV_SIZING_FIT_WIDTH;
3136         } else {
3137                 mode = EV_SIZING_FREE;
3138         }
3139         
3140         ev_view_set_sizing_mode (EV_VIEW (ev_window->priv->view), mode);
3141         
3142         if (mode == EV_SIZING_FREE) {
3143                 ev_view_set_zoom (EV_VIEW (ev_window->priv->view), zoom, FALSE);
3144         }
3145 }
3146
3147 static void
3148 ev_window_finalize (GObject *object)
3149 {
3150         GList *windows = ev_application_get_windows (EV_APP);
3151
3152         if (windows == NULL) {
3153                 ev_application_shutdown (EV_APP);
3154         } else {
3155                 g_list_free (windows);
3156         }
3157         
3158         G_OBJECT_CLASS (ev_window_parent_class)->finalize (object);
3159 }
3160
3161 static void
3162 ev_window_dispose (GObject *object)
3163 {
3164         EvWindow *window = EV_WINDOW (object);
3165         EvWindowPrivate *priv = window->priv;
3166
3167         if (priv->title) {
3168                 ev_window_title_free (priv->title);
3169                 priv->title = NULL;
3170         }
3171
3172         if (priv->ui_manager) {
3173                 g_object_unref (priv->ui_manager);
3174                 priv->ui_manager = NULL;
3175         }
3176
3177         if (priv->action_group) {
3178                 g_object_unref (priv->action_group);
3179                 priv->action_group = NULL;
3180         }
3181
3182         if (priv->view_popup_action_group) {
3183                 g_object_unref (priv->view_popup_action_group);
3184                 priv->view_popup_action_group = NULL;
3185         }
3186
3187         if (priv->attachment_popup_action_group) {
3188                 g_object_unref (priv->attachment_popup_action_group);
3189                 priv->attachment_popup_action_group = NULL;
3190         }
3191
3192 #ifdef HAVE_GTK_RECENT
3193         if (priv->recent_action_group) {
3194                 g_object_unref (priv->recent_action_group);
3195                 priv->recent_action_group = NULL;
3196         }
3197
3198         if (priv->recent_manager) {
3199                 g_signal_handlers_disconnect_by_func (priv->recent_manager,
3200                                                       ev_window_setup_recent,
3201                                                       window);
3202                 priv->recent_manager = NULL;
3203         }
3204
3205         priv->recent_ui_id = 0;
3206 #else
3207         if (priv->recent_view) {
3208                 g_object_unref (priv->recent_view);
3209                 priv->recent_view = NULL;
3210         }
3211 #endif /* HAVE_GTK_RECENT */
3212
3213         if (priv->page_cache) {
3214                 g_signal_handlers_disconnect_by_func (priv->page_cache, page_changed_cb, window);
3215                 priv->page_cache = NULL;
3216         }
3217
3218         if (priv->document) {
3219                 g_object_unref (priv->document);
3220                 priv->document = NULL;
3221         }
3222         
3223         if (priv->view) {
3224                 g_object_unref (priv->view);
3225                 priv->view = NULL;
3226         }
3227
3228         if (priv->xfer_job) {
3229                 ev_window_clear_xfer_job (window);
3230         }
3231         
3232         if (priv->local_uri) {
3233                 ev_window_clear_local_uri (window);
3234         }
3235         
3236         ev_window_close_dialogs (window);
3237
3238 #ifdef WITH_GTK_PRINT
3239         ev_window_clear_print_job (window);
3240
3241         if (window->priv->gtk_print_job) {
3242                 g_object_unref (window->priv->gtk_print_job);
3243                 window->priv->gtk_print_job = NULL;
3244         }
3245         
3246         if (window->priv->printer) {
3247                 g_object_unref (window->priv->printer);
3248                 window->priv->printer = NULL;
3249         }
3250
3251         if (window->priv->print_settings) {
3252                 g_object_unref (window->priv->print_settings);
3253                 window->priv->print_settings = NULL;
3254         }
3255
3256         if (window->priv->print_page_setup) {
3257                 g_object_unref (window->priv->print_page_setup);
3258                 window->priv->print_page_setup = NULL;
3259         }
3260 #endif
3261
3262         if (priv->link) {
3263                 g_object_unref (priv->link);
3264                 priv->link = NULL;
3265         }
3266
3267         if (priv->attach_list) {
3268                 g_list_foreach (priv->attach_list,
3269                                 (GFunc) g_object_unref,
3270                                 NULL);
3271                 g_list_free (priv->attach_list);
3272                 priv->attach_list = NULL;
3273         }
3274
3275         if (priv->find_bar) {
3276                 g_signal_handlers_disconnect_by_func
3277                         (window->priv->find_bar,
3278                          G_CALLBACK (find_bar_close_cb),
3279                          window);
3280                 priv->find_bar = NULL;
3281         }
3282
3283         if (priv->uri) {
3284                 g_free (priv->uri);
3285                 priv->uri = NULL;
3286         }
3287
3288         if (priv->dest) {
3289                 g_object_unref (priv->dest);
3290                 priv->dest = NULL;
3291         }
3292
3293         if (priv->fullscreen_timeout_id) {
3294                 g_source_remove (priv->fullscreen_timeout_id);
3295                 priv->fullscreen_timeout_id = 0;
3296         }
3297         destroy_fullscreen_popup (window);
3298
3299         G_OBJECT_CLASS (ev_window_parent_class)->dispose (object);
3300 }
3301
3302 static void
3303 ev_window_class_init (EvWindowClass *ev_window_class)
3304 {
3305         GObjectClass *g_object_class = G_OBJECT_CLASS (ev_window_class);
3306         GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (ev_window_class);
3307
3308         g_object_class->dispose = ev_window_dispose;
3309         g_object_class->finalize = ev_window_finalize;
3310
3311         widget_class->focus_in_event = ev_window_focus_in_event;
3312         widget_class->focus_out_event = ev_window_focus_out_event;
3313         widget_class->screen_changed = ev_window_screen_changed;
3314
3315         g_type_class_add_private (g_object_class, sizeof (EvWindowPrivate));
3316 }
3317
3318 /* Normal items */
3319 static const GtkActionEntry entries[] = {
3320         { "File", NULL, N_("_File") },
3321         { "Edit", NULL, N_("_Edit") },
3322         { "View", NULL, N_("_View") },
3323         { "Go", NULL, N_("_Go") },
3324         { "Help", NULL, N_("_Help") },
3325
3326         /* File menu */
3327         { "FileOpen", GTK_STOCK_OPEN, N_("_Open..."), "<control>O",
3328           N_("Open an existing document"),
3329           G_CALLBACK (ev_window_cmd_file_open) },
3330         { "FileSaveAs", GTK_STOCK_SAVE_AS, N_("_Save a Copy..."), "<control>S",
3331           N_("Save a copy of the current document"),
3332           G_CALLBACK (ev_window_cmd_save_as) },
3333         { "FilePrint", GTK_STOCK_PRINT, N_("_Print..."), "<control>P",
3334           N_("Print this document"),
3335           G_CALLBACK (ev_window_cmd_file_print) },
3336         { "FileProperties", GTK_STOCK_PROPERTIES, N_("P_roperties"), "<alt>Return", NULL,
3337           G_CALLBACK (ev_window_cmd_file_properties) },                       
3338         { "FileCloseWindow", GTK_STOCK_CLOSE, NULL, "<control>W", NULL,
3339           G_CALLBACK (ev_window_cmd_file_close_window) },
3340
3341         /* Edit menu */
3342         { "EditCopy", GTK_STOCK_COPY, NULL, "<control>C", NULL,
3343           G_CALLBACK (ev_window_cmd_edit_copy) },
3344         { "EditSelectAll", NULL, N_("Select _All"), "<control>A", NULL,
3345           G_CALLBACK (ev_window_cmd_edit_select_all) },
3346         { "EditFind", GTK_STOCK_FIND, N_("_Find..."), "<control>F",
3347           N_("Find a word or phrase in the document"),
3348           G_CALLBACK (ev_window_cmd_edit_find) },
3349         { "EditFindNext", NULL, N_("Find Ne_xt"), "<control>G", NULL,
3350           G_CALLBACK (ev_window_cmd_edit_find_next) },
3351         { "EditFindPrevious", NULL, N_("Find Pre_vious"), "<shift><control>G", NULL,
3352           G_CALLBACK (ev_window_cmd_edit_find_previous) },
3353         { "EditToolbar", NULL, N_("T_oolbar"), NULL, NULL,
3354           G_CALLBACK (ev_window_cmd_edit_toolbar) },
3355         { "EditRotateLeft", NULL, N_("Rotate _Left"), NULL, NULL,
3356           G_CALLBACK (ev_window_cmd_edit_rotate_left) },
3357         { "EditRotateRight", NULL, N_("Rotate _Right"), NULL, NULL,
3358           G_CALLBACK (ev_window_cmd_edit_rotate_right) },
3359
3360         /* View menu */
3361         { "ViewZoomIn", GTK_STOCK_ZOOM_IN, NULL, "<control>plus",
3362           N_("Enlarge the document"),
3363           G_CALLBACK (ev_window_cmd_view_zoom_in) },
3364         { "ViewZoomOut", GTK_STOCK_ZOOM_OUT, NULL, "<control>minus",
3365           N_("Shrink the document"),
3366           G_CALLBACK (ev_window_cmd_view_zoom_out) },
3367         { "ViewReload", GTK_STOCK_REFRESH, N_("_Reload"), "<control>R",
3368           N_("Reload the document"),
3369           G_CALLBACK (ev_window_cmd_view_reload) },
3370
3371         /* Go menu */
3372         { "GoPreviousPage", GTK_STOCK_GO_BACK, N_("_Previous Page"), "<control>Page_Up",
3373           N_("Go to the previous page"),
3374           G_CALLBACK (ev_window_cmd_go_previous_page) },
3375         { "GoNextPage", GTK_STOCK_GO_FORWARD, N_("_Next Page"), "<control>Page_Down",
3376           N_("Go to the next page"),
3377           G_CALLBACK (ev_window_cmd_go_next_page) },
3378         { "GoFirstPage", GTK_STOCK_GOTO_FIRST, N_("_First Page"), "<control>Home",
3379           N_("Go to the first page"),
3380           G_CALLBACK (ev_window_cmd_go_first_page) },
3381         { "GoLastPage", GTK_STOCK_GOTO_LAST, N_("_Last Page"), "<control>End",
3382           N_("Go to the last page"),
3383           G_CALLBACK (ev_window_cmd_go_last_page) },
3384
3385         /* Help menu */
3386         { "HelpContents", GTK_STOCK_HELP, N_("_Contents"), "F1", NULL,
3387           G_CALLBACK (ev_window_cmd_help_contents) },
3388
3389         { "HelpAbout", GTK_STOCK_ABOUT, N_("_About"), NULL, NULL,
3390           G_CALLBACK (ev_window_cmd_help_about) },
3391
3392         /* Toolbar-only */
3393         { "LeaveFullscreen", EV_STOCK_LEAVE_FULLSCREEN, N_("Leave Fullscreen"), NULL,
3394           N_("Leave fullscreen mode"),
3395           G_CALLBACK (ev_window_cmd_leave_fullscreen) },
3396
3397         /* Accellerators */
3398         { "Escape", NULL, "", "Escape", "",
3399           G_CALLBACK (ev_window_cmd_escape) },
3400         { "Slash", GTK_STOCK_FIND, NULL, "slash", NULL,
3401           G_CALLBACK (ev_window_cmd_edit_find) },
3402         { "PageDown", NULL, "", "Page_Down", NULL,
3403           G_CALLBACK (ev_window_cmd_scroll_forward) },
3404         { "PageUp", NULL, "", "Page_Up", NULL,
3405           G_CALLBACK (ev_window_cmd_scroll_backward) },
3406         { "Space", NULL, "", "space", NULL,
3407           G_CALLBACK (ev_window_cmd_scroll_forward) },
3408         { "ShiftSpace", NULL, "", "<shift>space", NULL,
3409           G_CALLBACK (ev_window_cmd_scroll_backward) },
3410         { "BackSpace", NULL, "", "BackSpace", NULL,
3411           G_CALLBACK (ev_window_cmd_scroll_backward) },
3412         { "ShiftBackSpace", NULL, "", "<shift>BackSpace", NULL,
3413           G_CALLBACK (ev_window_cmd_scroll_forward) },
3414         { "Return", NULL, "", "Return", NULL,
3415           G_CALLBACK (ev_window_cmd_scroll_forward) },
3416         { "ShiftReturn", NULL, "", "<shift>Return", NULL,
3417           G_CALLBACK (ev_window_cmd_scroll_backward) },
3418         { "Plus", GTK_STOCK_ZOOM_IN, NULL, "plus", NULL,
3419           G_CALLBACK (ev_window_cmd_view_zoom_in) },
3420         { "CtrlEqual", GTK_STOCK_ZOOM_IN, NULL, "<control>equal", NULL,
3421           G_CALLBACK (ev_window_cmd_view_zoom_in) },
3422         { "Equal", GTK_STOCK_ZOOM_IN, NULL, "equal", NULL,
3423           G_CALLBACK (ev_window_cmd_view_zoom_in) },
3424         { "Minus", GTK_STOCK_ZOOM_OUT, NULL, "minus", NULL,
3425           G_CALLBACK (ev_window_cmd_view_zoom_out) },
3426         { "FocusPageSelector", NULL, "", "<control>l", NULL,
3427           G_CALLBACK (ev_window_cmd_focus_page_selector) },
3428         { "GoBackwardFast", NULL, "", "<shift>Page_Up", NULL,
3429           G_CALLBACK (ev_window_cmd_go_backward) },
3430         { "GoForwardFast", NULL, "", "<shift>Page_Down", NULL,
3431           G_CALLBACK (ev_window_cmd_go_forward) },
3432         { "KpPlus", GTK_STOCK_ZOOM_IN, NULL, "KP_Add", NULL,
3433           G_CALLBACK (ev_window_cmd_view_zoom_in) },
3434         { "KpMinus", GTK_STOCK_ZOOM_OUT, NULL, "KP_Subtract", NULL,
3435           G_CALLBACK (ev_window_cmd_view_zoom_out) },
3436         { "CtrlKpPlus", GTK_STOCK_ZOOM_IN, NULL, "<control>KP_Add", NULL,
3437           G_CALLBACK (ev_window_cmd_view_zoom_in) },
3438         { "CtrlKpMinus", GTK_STOCK_ZOOM_OUT, NULL, "<control>KP_Subtract", NULL,
3439           G_CALLBACK (ev_window_cmd_view_zoom_out) },
3440 };
3441
3442 /* Toggle items */
3443 static const GtkToggleActionEntry toggle_entries[] = {
3444         /* View Menu */
3445         { "ViewToolbar", NULL, N_("_Toolbar"), "<shift><control>T",
3446           N_("Show or hide the toolbar"),
3447           G_CALLBACK (ev_window_view_toolbar_cb), TRUE },
3448         { "ViewSidebar", GTK_STOCK_INDEX, N_("Side _Pane"), "F9",
3449           N_("Show or hide the side pane"),
3450           G_CALLBACK (ev_window_view_sidebar_cb), TRUE },
3451         { "ViewContinuous", EV_STOCK_VIEW_CONTINUOUS, N_("_Continuous"), NULL,
3452           N_("Show the entire document"),
3453           G_CALLBACK (ev_window_cmd_continuous), TRUE },
3454         { "ViewDual", EV_STOCK_VIEW_DUAL, N_("_Dual"), NULL,
3455           N_("Show two pages at once"),
3456           G_CALLBACK (ev_window_cmd_dual), FALSE },
3457         { "ViewFullscreen", NULL, N_("_Fullscreen"), "F11",
3458           N_("Expand the window to fill the screen"),
3459           G_CALLBACK (ev_window_cmd_view_fullscreen) },
3460         { "ViewPresentation", NULL, N_("_Presentation"), "F5",
3461           N_("Run document as a presentation"),
3462           G_CALLBACK (ev_window_cmd_view_presentation) },
3463         { "ViewBestFit", EV_STOCK_ZOOM_PAGE, N_("_Best Fit"), NULL,
3464           N_("Make the current document fill the window"),
3465           G_CALLBACK (ev_window_cmd_view_best_fit) },
3466         { "ViewPageWidth", EV_STOCK_ZOOM_WIDTH, N_("Fit Page _Width"), NULL,
3467           N_("Make the current document fill the window width"),
3468           G_CALLBACK (ev_window_cmd_view_page_width) },
3469 };
3470
3471 /* Popups specific items */
3472 static const GtkActionEntry view_popup_entries [] = {
3473         /* Links */
3474         { "OpenLink", GTK_STOCK_OPEN, N_("_Open Link"), NULL,
3475           NULL, G_CALLBACK (ev_view_popup_cmd_open_link) },
3476         { "GoLink", GTK_STOCK_GO_FORWARD, N_("_Go To"), NULL,
3477           NULL, G_CALLBACK (ev_view_popup_cmd_open_link) },
3478         { "CopyLinkAddress", NULL, N_("_Copy Link Address"), NULL,
3479           NULL,
3480           G_CALLBACK (ev_view_popup_cmd_copy_link_address) },
3481 };
3482
3483 static const GtkActionEntry attachment_popup_entries [] = {
3484         { "OpenAttachment", GTK_STOCK_OPEN, N_("_Open..."), NULL,
3485           NULL, G_CALLBACK (ev_attachment_popup_cmd_open_attachment) },
3486         { "SaveAttachmentAs", GTK_STOCK_SAVE_AS, N_("_Save a Copy..."), NULL,
3487           NULL, G_CALLBACK (ev_attachment_popup_cmd_save_attachment_as) },
3488 };
3489
3490 static void
3491 drag_data_received_cb (GtkWidget *widget, GdkDragContext *context,
3492                        gint x, gint y, GtkSelectionData *selection_data,
3493                        guint info, guint time, gpointer gdata)
3494 {
3495         GList  *uri_list = NULL;
3496         GSList *uris = NULL;
3497         gchar  *uri;
3498
3499         uri_list = gnome_vfs_uri_list_parse ((gchar *) selection_data->data);
3500
3501         if (uri_list) {
3502                 while (uri_list) {
3503                         uri = gnome_vfs_uri_to_string (uri_list->data, GNOME_VFS_URI_HIDE_NONE);
3504                         uris = g_slist_append (uris, (gpointer) uri);
3505                         
3506                         uri_list = g_list_next (uri_list);
3507                 }
3508
3509                 gnome_vfs_uri_list_free (uri_list);
3510                 
3511                 ev_application_open_uri_list (EV_APP, uris, 0);
3512                 
3513                 g_slist_free (uris);
3514         }
3515 }
3516
3517 static void
3518 activate_link_cb (EvPageAction *page_action, EvLink *link, EvWindow *window)
3519 {
3520         ev_view_handle_link (EV_VIEW (window->priv->view), link);
3521         gtk_widget_grab_focus (window->priv->view);
3522 }
3523
3524 static gboolean
3525 activate_label_cb (EvPageAction *page_action, char *label, EvWindow *window)
3526 {
3527         g_return_val_if_fail (EV_IS_WINDOW (window), FALSE);
3528
3529         gtk_widget_grab_focus (window->priv->view);
3530
3531         return ev_page_cache_set_page_label (window->priv->page_cache, label);
3532 }
3533
3534 static void
3535 register_custom_actions (EvWindow *window, GtkActionGroup *group)
3536 {
3537         GtkAction *action;
3538
3539         action = g_object_new (EV_TYPE_PAGE_ACTION,
3540                                "name", PAGE_SELECTOR_ACTION,
3541                                "label", _("Page"),
3542                                "tooltip", _("Select Page"),
3543                                "visible_overflown", FALSE,
3544                                NULL);
3545         g_signal_connect (action, "activate_link",
3546                           G_CALLBACK (activate_link_cb), window);
3547         g_signal_connect (action, "activate_label",
3548                           G_CALLBACK (activate_label_cb), window);
3549         gtk_action_group_add_action (group, action);
3550         g_object_unref (action);
3551
3552         action = g_object_new (EPHY_TYPE_ZOOM_ACTION,
3553                                "name", ZOOM_CONTROL_ACTION,
3554                                "label", _("Zoom"),
3555                                "stock_id", GTK_STOCK_ZOOM_IN,
3556                                "tooltip", _("Adjust the zoom level"),
3557                                "zoom", 1.0,
3558                                NULL);
3559         g_signal_connect (action, "zoom_to_level",
3560                           G_CALLBACK (zoom_control_changed_cb), window);
3561         gtk_action_group_add_action (group, action);
3562         g_object_unref (action);
3563 }
3564
3565 static void
3566 set_action_properties (GtkActionGroup *action_group)
3567 {
3568         GtkAction *action;
3569
3570         action = gtk_action_group_get_action (action_group, "GoPreviousPage");
3571         /*translators: this is the label for toolbar button*/
3572         g_object_set (action, "short_label", _("Previous"), NULL);
3573         g_object_set (action, "is-important", TRUE, NULL);
3574
3575         action = gtk_action_group_get_action (action_group, "GoNextPage");
3576         g_object_set (action, "is-important", TRUE, NULL);
3577         /*translators: this is the label for toolbar button*/
3578         g_object_set (action, "short_label", _("Next"), NULL);
3579
3580         action = gtk_action_group_get_action (action_group, "ViewZoomIn");
3581         /*translators: this is the label for toolbar button*/
3582         g_object_set (action, "short_label", _("Zoom In"), NULL);
3583         action = gtk_action_group_get_action (action_group, "ViewZoomIn");
3584
3585         action = gtk_action_group_get_action (action_group, "ViewZoomOut");
3586         /*translators: this is the label for toolbar button*/
3587         g_object_set (action, "short_label", _("Zoom Out"), NULL);
3588         action = gtk_action_group_get_action (action_group, "ViewZoomIn");
3589
3590         action = gtk_action_group_get_action (action_group, "ViewBestFit");
3591         /*translators: this is the label for toolbar button*/
3592         g_object_set (action, "short_label", _("Best Fit"), NULL);
3593         action = gtk_action_group_get_action (action_group, "ViewZoomIn");
3594
3595         action = gtk_action_group_get_action (action_group, "ViewPageWidth");
3596         /*translators: this is the label for toolbar button*/
3597         g_object_set (action, "short_label", _("Fit Width"), NULL);
3598         action = gtk_action_group_get_action (action_group, "ViewZoomIn");
3599
3600         action = gtk_action_group_get_action (action_group, "LeaveFullscreen");
3601         g_object_set (action, "is-important", TRUE, NULL);
3602 }
3603
3604 static void
3605 set_chrome_actions (EvWindow *window)
3606 {
3607         EvWindowPrivate *priv = window->priv;
3608         GtkActionGroup *action_group = priv->action_group;
3609         GtkAction *action;
3610
3611         action= gtk_action_group_get_action (action_group, "ViewToolbar");
3612         g_signal_handlers_block_by_func
3613                 (action, G_CALLBACK (ev_window_view_toolbar_cb), window);
3614         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
3615                                       (priv->chrome & EV_CHROME_TOOLBAR) != 0);
3616         g_signal_handlers_unblock_by_func
3617                 (action, G_CALLBACK (ev_window_view_toolbar_cb), window);
3618 }
3619
3620 static void
3621 sidebar_widget_model_set (EvSidebarLinks *ev_sidebar_links,
3622                           GParamSpec     *pspec,
3623                           EvWindow       *ev_window)
3624 {
3625         GtkTreeModel *model;
3626         GtkAction *action;
3627
3628         g_object_get (G_OBJECT (ev_sidebar_links),
3629                       "model", &model,
3630                       NULL);
3631
3632         action = gtk_action_group_get_action (ev_window->priv->action_group, PAGE_SELECTOR_ACTION);
3633         ev_page_action_set_model (EV_PAGE_ACTION (action), model);
3634         g_object_unref (model);
3635 }
3636
3637 static gboolean
3638 view_actions_focus_in_cb (GtkWidget *widget, GdkEventFocus *event, EvWindow *window)
3639 {
3640         update_chrome_flag (window, EV_CHROME_RAISE_TOOLBAR, FALSE);
3641         ev_window_set_action_sensitive (window, "ViewToolbar", TRUE);
3642
3643         ev_window_set_view_accels_sensitivity (window, TRUE);
3644
3645         return FALSE;
3646 }
3647
3648 static gboolean
3649 view_actions_focus_out_cb (GtkWidget *widget, GdkEventFocus *event, EvWindow *window)
3650 {
3651         ev_window_set_view_accels_sensitivity (window, FALSE);
3652
3653         return FALSE;
3654 }
3655
3656 static void
3657 sidebar_page_main_widget_update_cb (GObject *ev_sidebar_page,
3658                                     GParamSpec         *pspec,
3659                                     EvWindow           *ev_window)
3660 {
3661         GtkWidget *widget;
3662         
3663         g_object_get (ev_sidebar_page, "main_widget", &widget, NULL);
3664
3665         if (widget != NULL) {           
3666                 g_signal_connect_object (widget, "focus_in_event",
3667                                          G_CALLBACK (view_actions_focus_in_cb),
3668                                          ev_window, 0);
3669                 g_signal_connect_object (widget, "focus_out_event",
3670                                          G_CALLBACK (view_actions_focus_out_cb),
3671                                          ev_window, 0);
3672                 g_object_unref (widget);
3673         }
3674 }
3675
3676 static gboolean
3677 window_state_event_cb (EvWindow *window, GdkEventWindowState *event, gpointer dummy)
3678 {
3679         if (!(event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) {
3680                 gboolean maximized;
3681
3682                 maximized = event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED;
3683                 if (!ev_window_is_empty (window))
3684                         ev_metadata_manager_set_boolean (window->priv->uri, "window_maximized", maximized);
3685         }
3686
3687         return FALSE;
3688 }
3689
3690 static gboolean
3691 window_configure_event_cb (EvWindow *window, GdkEventConfigure *event, gpointer dummy)
3692 {
3693         char *uri = window->priv->uri;
3694         GdkWindowState state;
3695         int x, y, width, height;
3696
3697         state = gdk_window_get_state (GTK_WIDGET (window)->window);
3698
3699         if (!(state & GDK_WINDOW_STATE_FULLSCREEN)) {
3700                 gtk_window_get_position (GTK_WINDOW (window), &x, &y);
3701                 gtk_window_get_size (GTK_WINDOW (window), &width, &height);
3702
3703                 if (!ev_window_is_empty (window)) {
3704                         ev_metadata_manager_set_int (uri, "window_x", x);
3705                         ev_metadata_manager_set_int (uri, "window_y", y);
3706                         ev_metadata_manager_set_int (uri, "window_width", width);
3707                         ev_metadata_manager_set_int (uri, "window_height", height);
3708                 }
3709         }
3710
3711         return FALSE;
3712 }
3713
3714 static void
3715 sidebar_links_link_activated_cb (EvSidebarLinks *sidebar_links, EvLink *link, EvWindow *window)
3716 {
3717         ev_view_handle_link (EV_VIEW (window->priv->view), link);
3718 }
3719
3720 static void
3721 launch_action (EvWindow *window, EvLinkAction *action)
3722 {
3723         const char *filename = ev_link_action_get_filename (action);
3724         char *uri = NULL;
3725
3726         if (filename  && g_path_is_absolute (filename)) {
3727                 uri = gnome_vfs_get_uri_from_local_path (filename);
3728         } else {
3729                 GnomeVFSURI *base_uri, *resolved_uri;
3730
3731                 base_uri = gnome_vfs_uri_new (window->priv->uri);
3732                 if (base_uri && filename) {
3733                         resolved_uri = gnome_vfs_uri_resolve_relative (base_uri, filename);     
3734                         if (resolved_uri) {
3735                                 uri = gnome_vfs_uri_to_string (resolved_uri, GNOME_VFS_URI_HIDE_NONE);
3736                                 gnome_vfs_uri_unref (resolved_uri);
3737                         }
3738                         gnome_vfs_uri_unref (base_uri);
3739                 }
3740         }
3741
3742         if (uri) {
3743                 gnome_vfs_url_show (uri);
3744         } else {
3745                 gnome_vfs_url_show (filename);
3746         }
3747
3748         g_free (uri);
3749
3750         /* According to the PDF spec filename can be an executable. I'm not sure
3751            allowing to launch executables is a good idea though. -- marco */
3752 }
3753
3754 static void
3755 launch_external_uri (EvWindow *window, EvLinkAction *action)
3756 {
3757         const char *uri;
3758         char *escaped;
3759
3760         uri = ev_link_action_get_uri (action);
3761         escaped = gnome_vfs_escape_host_and_path_string (uri);
3762
3763         gnome_vfs_url_show (escaped);
3764         g_free (escaped);
3765 }
3766
3767 static void
3768 open_remote_link (EvWindow *window, EvLinkAction *action)
3769 {
3770         gchar *uri;
3771         gchar *dir;
3772
3773         dir = g_path_get_dirname (window->priv->uri);
3774         
3775         uri = g_build_filename (dir, ev_link_action_get_filename (action),
3776                                 NULL);
3777         g_free (dir);
3778         
3779         ev_application_open_uri_at_dest (EV_APP, uri,
3780                                          ev_link_action_get_dest (action),
3781                                          0,
3782                                          GDK_CURRENT_TIME);
3783
3784         g_free (uri);
3785 }
3786
3787 static void
3788 do_action_named (EvWindow *window, EvLinkAction *action)
3789 {
3790         const gchar *name = ev_link_action_get_name (action);
3791
3792         if (g_ascii_strcasecmp (name, "FirstPage") == 0) {
3793                 ev_window_cmd_go_first_page (NULL, window);
3794         } else if (g_ascii_strcasecmp (name, "PrevPage") == 0) {
3795                 ev_window_cmd_go_previous_page (NULL, window);
3796         } else if (g_ascii_strcasecmp (name, "NextPage") == 0) {
3797                 ev_window_cmd_go_next_page (NULL, window);
3798         } else if (g_ascii_strcasecmp (name, "LastPage") == 0) {
3799                 ev_window_cmd_go_last_page (NULL, window);
3800         } else if (g_ascii_strcasecmp (name, "GoToPage") == 0) {
3801                 ev_window_cmd_focus_page_selector (NULL, window);
3802         } else if (g_ascii_strcasecmp (name, "Find") == 0) {
3803                 ev_window_cmd_edit_find (NULL, window);
3804         } else {
3805                 g_warning ("Unimplemented named action: %s, please post a "
3806                            "bug report in Evince bugzilla "
3807                            "(http://bugzilla.gnome.org) with a testcase.",
3808                            name);
3809         }
3810 }
3811
3812 static void
3813 view_external_link_cb (EvView *view, EvLinkAction *action, EvWindow *window)
3814 {
3815         switch (ev_link_action_get_action_type (action)) {
3816                 case EV_LINK_ACTION_TYPE_EXTERNAL_URI:
3817                         launch_external_uri (window, action);
3818                         break;
3819                 case EV_LINK_ACTION_TYPE_LAUNCH:
3820                         launch_action (window, action);
3821                         break;
3822                 case EV_LINK_ACTION_TYPE_GOTO_REMOTE:
3823                         open_remote_link (window, action);
3824                         break;
3825                 case EV_LINK_ACTION_TYPE_NAMED:
3826                         do_action_named (window, action);
3827                         break;
3828                 default:
3829                         g_assert_not_reached ();
3830         }
3831 }
3832
3833 static void
3834 ev_view_popup_cmd_open_link (GtkAction *action, EvWindow *window)
3835 {
3836         ev_view_handle_link (EV_VIEW (window->priv->view), window->priv->link);
3837 }
3838
3839 static void
3840 ev_view_popup_cmd_copy_link_address (GtkAction *action, EvWindow *window)
3841 {
3842         GtkClipboard *clipboard;
3843         EvLinkAction *ev_action;
3844         const gchar *uri;
3845
3846         ev_action = ev_link_get_action (window->priv->link);
3847         if (!ev_action)
3848                 return;
3849
3850         uri = ev_link_action_get_uri (ev_action);
3851
3852         clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window),
3853                                               GDK_SELECTION_CLIPBOARD);
3854         gtk_clipboard_set_text (clipboard, uri, -1);
3855 }
3856
3857 static void
3858 ev_attachment_popup_cmd_open_attachment (GtkAction *action, EvWindow *window)
3859 {
3860         GList *l;
3861         
3862         if (!window->priv->attach_list)
3863                 return;
3864
3865         for (l = window->priv->attach_list; l && l->data; l = g_list_next (l)) {
3866                 EvAttachment *attachment;
3867                 GError       *error = NULL;
3868                 
3869                 attachment = (EvAttachment *) l->data;
3870                 
3871                 ev_attachment_open (attachment, &error);
3872
3873                 if (error) {
3874                         ev_window_error_dialog (GTK_WINDOW (window),
3875                                                 _("Unable to open attachment"),
3876                                                 error);
3877                         g_error_free (error);
3878                 }
3879         }
3880 }
3881
3882 static void
3883 attachment_save_dialog_response_cb (GtkWidget *fc,
3884                                     gint       response_id,
3885                                     EvWindow  *ev_window)
3886 {
3887         gchar                *uri;
3888         GList                *l;
3889         GtkFileChooserAction  fc_action;
3890         gboolean              is_dir;
3891         
3892         if (response_id != GTK_RESPONSE_OK) {
3893                 gtk_widget_destroy (fc);
3894                 return;
3895         }
3896
3897         uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (fc));
3898         
3899         g_object_get (G_OBJECT (fc), "action", &fc_action, NULL);
3900         is_dir = (fc_action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
3901         
3902         for (l = ev_window->priv->attach_list; l && l->data; l = g_list_next (l)) {
3903                 EvAttachment *attachment;
3904                 gchar        *filename;
3905                 GError       *error = NULL;
3906                 
3907                 attachment = (EvAttachment *) l->data;
3908
3909                 if (is_dir) {
3910                         filename = g_strjoin ("/", uri,
3911                                               ev_attachment_get_name (attachment),
3912                                               NULL);
3913                 } else {
3914                         filename = g_strdup (uri);
3915                 }
3916                 
3917                 ev_attachment_save (attachment, filename, &error);
3918                 g_free (filename);
3919                 
3920                 if (error) {
3921                         ev_window_error_dialog (GTK_WINDOW (fc),
3922                                                 _("The attachment could not be saved."),
3923                                                 error);
3924                         g_error_free (error);
3925                 }
3926         }
3927
3928         g_free (uri);
3929
3930         gtk_widget_destroy (fc);
3931 }
3932
3933 static void
3934 ev_attachment_popup_cmd_save_attachment_as (GtkAction *action, EvWindow *window)
3935 {
3936         GtkWidget    *fc;
3937         EvAttachment *attachment = NULL;
3938
3939         if (!window->priv->attach_list)
3940                 return;
3941
3942         if (g_list_length (window->priv->attach_list) == 1)
3943                 attachment = (EvAttachment *) window->priv->attach_list->data;
3944         
3945         fc = gtk_file_chooser_dialog_new (
3946                 _("Save a Copy"),
3947                 GTK_WINDOW (window),
3948                 attachment ? GTK_FILE_CHOOSER_ACTION_SAVE : GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
3949                 GTK_STOCK_CANCEL,
3950                 GTK_RESPONSE_CANCEL,
3951                 GTK_STOCK_SAVE, GTK_RESPONSE_OK,
3952                 NULL);
3953
3954         gtk_dialog_set_default_response (GTK_DIALOG (fc), GTK_RESPONSE_OK);
3955         gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (fc), TRUE);
3956
3957         if (attachment)
3958                 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (fc),
3959                                                    ev_attachment_get_name (attachment));
3960
3961         g_signal_connect (fc, "response",
3962                           G_CALLBACK (attachment_save_dialog_response_cb),
3963                           window);
3964
3965         gtk_widget_show (fc);
3966 }
3967
3968 static void
3969 ev_window_init (EvWindow *ev_window)
3970 {
3971         GtkActionGroup *action_group;
3972         GtkAccelGroup *accel_group;
3973         GError *error = NULL;
3974         GtkWidget *sidebar_widget, *toolbar_dock;
3975
3976         g_signal_connect (ev_window, "configure_event",
3977                           G_CALLBACK (window_configure_event_cb), NULL);
3978         g_signal_connect (ev_window, "window_state_event",
3979                           G_CALLBACK (window_state_event_cb), NULL);
3980
3981         ev_window->priv = EV_WINDOW_GET_PRIVATE (ev_window);
3982
3983         ev_window->priv->page_mode = PAGE_MODE_DOCUMENT;
3984         ev_window->priv->title = ev_window_title_new (ev_window);
3985
3986         ev_window->priv->main_box = gtk_vbox_new (FALSE, 0);
3987         gtk_container_add (GTK_CONTAINER (ev_window), ev_window->priv->main_box);
3988         gtk_widget_show (ev_window->priv->main_box);
3989
3990         action_group = gtk_action_group_new ("MenuActions");
3991         ev_window->priv->action_group = action_group;
3992         gtk_action_group_set_translation_domain (action_group, NULL);
3993         gtk_action_group_add_actions (action_group, entries,
3994                                       G_N_ELEMENTS (entries), ev_window);
3995         gtk_action_group_add_toggle_actions (action_group, toggle_entries,
3996                                              G_N_ELEMENTS (toggle_entries),
3997                                              ev_window);
3998         set_action_properties (action_group);
3999         register_custom_actions (ev_window, action_group);
4000
4001         ev_window->priv->ui_manager = gtk_ui_manager_new ();
4002         gtk_ui_manager_insert_action_group (ev_window->priv->ui_manager,
4003                                             action_group, 0);
4004
4005         accel_group =
4006                 gtk_ui_manager_get_accel_group (ev_window->priv->ui_manager);
4007         gtk_window_add_accel_group (GTK_WINDOW (ev_window), accel_group);
4008
4009         ev_window_set_view_accels_sensitivity (ev_window, FALSE);
4010
4011         action_group = gtk_action_group_new ("ViewPopupActions");
4012         ev_window->priv->view_popup_action_group = action_group;
4013         gtk_action_group_set_translation_domain (action_group, NULL);
4014         gtk_action_group_add_actions (action_group, view_popup_entries,
4015                                       G_N_ELEMENTS (view_popup_entries),
4016                                       ev_window);
4017         gtk_ui_manager_insert_action_group (ev_window->priv->ui_manager,
4018                                             action_group, 0);
4019
4020         action_group = gtk_action_group_new ("AttachmentPopupActions");
4021         ev_window->priv->attachment_popup_action_group = action_group;
4022         gtk_action_group_set_translation_domain (action_group, NULL);
4023         gtk_action_group_add_actions (action_group, attachment_popup_entries,
4024                                       G_N_ELEMENTS (attachment_popup_entries),
4025                                       ev_window);
4026         gtk_ui_manager_insert_action_group (ev_window->priv->ui_manager,
4027                                             action_group, 0);
4028
4029         if (!gtk_ui_manager_add_ui_from_file (ev_window->priv->ui_manager,
4030                                               DATADIR"/evince-ui.xml",
4031                                               &error)) {
4032                 g_warning ("building menus failed: %s", error->message);
4033                 g_error_free (error);
4034         }
4035         
4036 #ifdef HAVE_GTK_RECENT
4037         ev_window->priv->recent_manager = gtk_recent_manager_get_default ();
4038         ev_window->priv->recent_action_group = NULL;
4039         ev_window->priv->recent_ui_id = 0;
4040         g_signal_connect_swapped (ev_window->priv->recent_manager,
4041                                   "changed",
4042                                   G_CALLBACK (ev_window_setup_recent),
4043                                   ev_window);
4044 #endif /* HAVE_GTK_RECENT */
4045         
4046         ev_window->priv->menubar =
4047                  gtk_ui_manager_get_widget (ev_window->priv->ui_manager,
4048                                             "/MainMenu");
4049         gtk_box_pack_start (GTK_BOX (ev_window->priv->main_box),
4050                             ev_window->priv->menubar,
4051                             FALSE, FALSE, 0);
4052
4053         /* This sucks, but there is no way to have a draw=no, expand=true separator
4054          * in a GtkUIManager-built toolbar. So, just add another toolbar.
4055          * See gtk+ bug 166489.
4056          */
4057         toolbar_dock = ev_window->priv->toolbar_dock = gtk_hbox_new (FALSE, 0);
4058         gtk_box_pack_start (GTK_BOX (ev_window->priv->main_box), toolbar_dock,
4059                             FALSE, FALSE, 0);
4060         gtk_widget_show (toolbar_dock);
4061
4062         ev_window->priv->toolbar = egg_editable_toolbar_new_with_model
4063                                 (ev_window->priv->ui_manager, ev_application_get_toolbars_model (EV_APP), NULL);
4064         egg_editable_toolbar_show (EGG_EDITABLE_TOOLBAR (ev_window->priv->toolbar),
4065                                    "DefaultToolBar");
4066         gtk_box_pack_start (GTK_BOX (toolbar_dock), ev_window->priv->toolbar,
4067                             TRUE, TRUE, 0);
4068         gtk_widget_show (ev_window->priv->toolbar);
4069
4070         /* Add the main area */
4071         ev_window->priv->hpaned = gtk_hpaned_new ();
4072         g_signal_connect (ev_window->priv->hpaned,
4073                           "notify::position",
4074                           G_CALLBACK (ev_window_sidebar_position_change_cb),
4075                           ev_window);
4076         
4077         gtk_paned_set_position (GTK_PANED (ev_window->priv->hpaned), SIDEBAR_DEFAULT_SIZE);
4078         gtk_box_pack_start (GTK_BOX (ev_window->priv->main_box), ev_window->priv->hpaned,
4079                             TRUE, TRUE, 0);
4080         gtk_widget_show (ev_window->priv->hpaned);
4081         
4082         ev_window->priv->sidebar = ev_sidebar_new ();
4083         gtk_paned_pack1 (GTK_PANED (ev_window->priv->hpaned),
4084                          ev_window->priv->sidebar, FALSE, FALSE);
4085         gtk_widget_show (ev_window->priv->sidebar);
4086
4087         /* Stub sidebar, for now */
4088
4089         sidebar_widget = ev_sidebar_links_new ();
4090         ev_window->priv->sidebar_links = sidebar_widget;
4091         g_signal_connect (sidebar_widget,
4092                           "notify::model",
4093                           G_CALLBACK (sidebar_widget_model_set),
4094                           ev_window);
4095         g_signal_connect (sidebar_widget,
4096                           "link_activated",
4097                           G_CALLBACK (sidebar_links_link_activated_cb),
4098                           ev_window);
4099         sidebar_page_main_widget_update_cb (G_OBJECT (sidebar_widget), NULL, ev_window);
4100         gtk_widget_show (sidebar_widget);
4101         ev_sidebar_add_page (EV_SIDEBAR (ev_window->priv->sidebar),
4102                              sidebar_widget);
4103
4104         sidebar_widget = ev_sidebar_attachments_new ();
4105         ev_window->priv->sidebar_attachments = sidebar_widget;
4106         g_signal_connect_object (sidebar_widget,
4107                                  "popup",
4108                                  G_CALLBACK (attachment_bar_menu_popup_cb),
4109                                  ev_window, 0);
4110         gtk_widget_show (sidebar_widget);
4111         ev_sidebar_add_page (EV_SIDEBAR (ev_window->priv->sidebar),
4112                              sidebar_widget);
4113
4114         sidebar_widget = ev_sidebar_thumbnails_new ();
4115         ev_window->priv->sidebar_thumbs = sidebar_widget;
4116         g_signal_connect (sidebar_widget,
4117                           "notify::main-widget",
4118                           G_CALLBACK (sidebar_page_main_widget_update_cb),
4119                           ev_window);
4120         sidebar_page_main_widget_update_cb (G_OBJECT (sidebar_widget), NULL, ev_window);
4121         gtk_widget_show (sidebar_widget);
4122         ev_sidebar_add_page (EV_SIDEBAR (ev_window->priv->sidebar),
4123                              sidebar_widget);
4124
4125         ev_window->priv->scrolled_window =
4126                 GTK_WIDGET (g_object_new (GTK_TYPE_SCROLLED_WINDOW,
4127                                           "shadow-type", GTK_SHADOW_IN,
4128                                           NULL));
4129         gtk_widget_show (ev_window->priv->scrolled_window);
4130
4131         gtk_paned_add2 (GTK_PANED (ev_window->priv->hpaned),
4132                         ev_window->priv->scrolled_window);
4133
4134         ev_window->priv->view = ev_view_new ();
4135         ev_window->priv->password_view = ev_password_view_new ();
4136         g_signal_connect_swapped (ev_window->priv->password_view,
4137                                   "unlock",
4138                                   G_CALLBACK (ev_window_popup_password_dialog),
4139                                   ev_window);
4140         g_signal_connect_object (ev_window->priv->view, "focus_in_event",
4141                                  G_CALLBACK (view_actions_focus_in_cb),
4142                                  ev_window, 0);
4143         g_signal_connect_object (ev_window->priv->view, "focus_out_event",
4144                                  G_CALLBACK (view_actions_focus_out_cb),
4145                                  ev_window, 0);
4146         g_signal_connect_object (ev_window->priv->view, "external-link",
4147                                  G_CALLBACK (view_external_link_cb),
4148                                  ev_window, 0);
4149         g_signal_connect_object (ev_window->priv->view,
4150                                  "popup",
4151                                  G_CALLBACK (view_menu_popup_cb),
4152                                  ev_window, 0);
4153         gtk_widget_show (ev_window->priv->view);
4154         gtk_widget_show (ev_window->priv->password_view);
4155
4156         /* Find Bar */
4157         ev_window->priv->find_bar = egg_find_bar_new ();
4158         gtk_box_pack_end (GTK_BOX (ev_window->priv->main_box),
4159                           ev_window->priv->find_bar,
4160                           FALSE, TRUE, 0);
4161
4162         /* We own a ref on these widgets, as we can swap them in and out */
4163         g_object_ref (ev_window->priv->view);
4164         g_object_ref (ev_window->priv->password_view);
4165
4166         gtk_container_add (GTK_CONTAINER (ev_window->priv->scrolled_window),
4167                            ev_window->priv->view);
4168
4169         g_signal_connect (ev_window->priv->view,
4170                           "notify::find-status",
4171                           G_CALLBACK (view_find_status_changed_cb),
4172                           ev_window);
4173         g_signal_connect (ev_window->priv->view,
4174                           "notify::sizing-mode",
4175                           G_CALLBACK (ev_window_sizing_mode_changed_cb),
4176                           ev_window);
4177         g_signal_connect (ev_window->priv->view,
4178                           "notify::zoom",
4179                           G_CALLBACK (ev_window_zoom_changed_cb),
4180                           ev_window);
4181         g_signal_connect (ev_window->priv->view,
4182                           "notify::dual-page",
4183                           G_CALLBACK (ev_window_dual_mode_changed_cb),
4184                           ev_window);
4185         g_signal_connect (ev_window->priv->view,
4186                           "notify::continuous",
4187                           G_CALLBACK (ev_window_continuous_changed_cb),
4188                           ev_window);
4189         g_signal_connect (ev_window->priv->view,
4190                           "notify::rotation",
4191                           G_CALLBACK (ev_window_rotation_changed_cb),
4192                           ev_window);
4193         g_signal_connect (ev_window->priv->view,
4194                           "notify::has-selection",
4195                           G_CALLBACK (ev_window_has_selection_changed_cb),
4196                           ev_window);
4197
4198         /* Connect sidebar signals */
4199         g_signal_connect (ev_window->priv->sidebar,
4200                           "notify::visible",
4201                           G_CALLBACK (ev_window_sidebar_visibility_changed_cb),
4202                           ev_window);
4203         g_signal_connect (ev_window->priv->sidebar,
4204                           "notify::current-page",
4205                           G_CALLBACK (ev_window_sidebar_current_page_changed_cb),
4206                           ev_window);
4207
4208         /* Connect to find bar signals */
4209         g_signal_connect (ev_window->priv->find_bar,
4210                           "previous",
4211                           G_CALLBACK (find_bar_previous_cb),
4212                           ev_window);
4213         g_signal_connect (ev_window->priv->find_bar,
4214                           "next",
4215                           G_CALLBACK (find_bar_next_cb),
4216                           ev_window);
4217         g_signal_connect (ev_window->priv->find_bar,
4218                           "close",
4219                           G_CALLBACK (find_bar_close_cb),
4220                           ev_window);
4221         g_signal_connect (ev_window->priv->find_bar,
4222                           "notify::search-string",
4223                           G_CALLBACK (find_bar_search_changed_cb),
4224                           ev_window);
4225         g_signal_connect (ev_window->priv->find_bar,
4226                           "notify::case-sensitive",
4227                           G_CALLBACK (find_bar_search_changed_cb),
4228                           ev_window);
4229         g_signal_connect (ev_window->priv->find_bar,
4230                           "notify::visible",
4231                           G_CALLBACK (find_bar_search_changed_cb),
4232                           ev_window);
4233         g_signal_connect (ev_window->priv->find_bar,
4234                           "scroll",
4235                           G_CALLBACK (find_bar_scroll),
4236                           ev_window);
4237
4238         /* Popups */
4239         ev_window->priv->view_popup = gtk_ui_manager_get_widget (ev_window->priv->ui_manager,
4240                                                                  "/DocumentPopup");
4241         ev_window->priv->link = NULL;
4242
4243         ev_window->priv->attachment_popup = gtk_ui_manager_get_widget (ev_window->priv->ui_manager,
4244                                                                        "/AttachmentPopup");
4245         ev_window->priv->attach_list = NULL;
4246
4247         /* Give focus to the document view */
4248         gtk_widget_grab_focus (ev_window->priv->view);
4249
4250         /* Drag and Drop */
4251         gtk_drag_dest_unset (GTK_WIDGET (ev_window->priv->view));
4252         gtk_drag_dest_set (GTK_WIDGET (ev_window->priv->view),
4253                            GTK_DEST_DEFAULT_ALL,
4254                            ev_drop_types,
4255                            sizeof (ev_drop_types) / sizeof (ev_drop_types[0]),
4256                            GDK_ACTION_COPY);
4257         g_signal_connect_swapped (G_OBJECT (ev_window->priv->view), "drag-data-received",
4258                                   G_CALLBACK (drag_data_received_cb),
4259                                   ev_window);
4260         
4261         /* Set it user interface params */
4262
4263         ev_window_setup_recent (ev_window);
4264
4265         setup_chrome_from_metadata (ev_window);
4266         set_chrome_actions (ev_window);
4267         update_chrome_visibility (ev_window);
4268
4269         gtk_window_set_default_size (GTK_WINDOW (ev_window), 600, 600);
4270
4271         setup_view_from_metadata (ev_window);
4272         setup_sidebar_from_metadata (ev_window, NULL);
4273
4274         ev_window_sizing_mode_changed_cb (EV_VIEW (ev_window->priv->view), NULL, ev_window);
4275         ev_window_setup_action_sensitivity (ev_window);
4276 }
4277
4278 GtkWidget *
4279 ev_window_new (void)
4280 {
4281         GtkWidget *ev_window;
4282
4283         ev_window = GTK_WIDGET (g_object_new (EV_TYPE_WINDOW,
4284                                               "type", GTK_WINDOW_TOPLEVEL,
4285                                               NULL));
4286
4287         return ev_window;
4288 }