]> www.fi.muni.cz Git - evince.git/blob - shell/ev-window.c
[ui] Renamed menu entry to Page Setup
[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) 2008 Carlos Garcia Campos
5  *  Copyright (C) 2004 Martin Kretzschmar
6  *  Copyright (C) 2004 Red Hat, Inc.
7  *  Copyright (C) 2000, 2001, 2002, 2003, 2004 Marco Pesenti Gritti
8  *  Copyright (C) 2003, 2004, 2005 Christian Persch
9  *
10  *  Author:
11  *    Martin Kretzschmar <martink@gnome.org>
12  *
13  * Evince is free software; you can redistribute it and/or modify it
14  * under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * Evince is distributed in the hope that it will be useful, but
19  * WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21  * General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
26  */
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #include <errno.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <unistd.h>
36
37 #include <glib/gstdio.h>
38 #include <glib/gi18n.h>
39 #include <gio/gio.h>
40 #include <gtk/gtk.h>
41 #include <gtk/gtkunixprint.h>
42
43 #ifdef WITH_GCONF
44 #include <gconf/gconf-client.h>
45 #endif
46
47 #include "egg-editable-toolbar.h"
48 #include "egg-toolbar-editor.h"
49 #include "egg-toolbars-model.h"
50
51 #include "eggfindbar.h"
52
53 #include "ephy-zoom-action.h"
54 #include "ephy-zoom.h"
55
56 #include "ev-application.h"
57 #include "ev-document-factory.h"
58 #include "ev-document-find.h"
59 #include "ev-document-fonts.h"
60 #include "ev-document-images.h"
61 #include "ev-document-links.h"
62 #include "ev-document-thumbnails.h"
63 #include "ev-document-type-builtins.h"
64 #include "ev-file-exporter.h"
65 #include "ev-file-helpers.h"
66 #include "ev-file-monitor.h"
67 #include "ev-history.h"
68 #include "ev-image.h"
69 #include "ev-job-scheduler.h"
70 #include "ev-jobs.h"
71 #include "ev-message-area.h"
72 #include "ev-metadata-manager.h"
73 #include "ev-navigation-action.h"
74 #include "ev-open-recent-action.h"
75 #include "ev-page-action.h"
76 #include "ev-password-view.h"
77 #include "ev-properties-dialog.h"
78 #include "ev-sidebar-attachments.h"
79 #include "ev-sidebar.h"
80 #include "ev-sidebar-links.h"
81 #include "ev-sidebar-page.h"
82 #include "ev-sidebar-thumbnails.h"
83 #include "ev-sidebar-layers.h"
84 #include "ev-stock-icons.h"
85 #include "ev-utils.h"
86 #include "ev-keyring.h"
87 #include "ev-view.h"
88 #include "ev-view-type-builtins.h"
89 #include "ev-window.h"
90 #include "ev-window-title.h"
91 #include "ev-print-operation.h"
92 #include "ev-progress-message-area.h"
93
94 #ifdef ENABLE_DBUS
95 #include "ev-media-player-keys.h"
96 #endif /* ENABLE_DBUS */
97
98 #ifdef ENABLE_PDF
99 #include <poppler.h>
100 #endif
101
102 typedef enum {
103         PAGE_MODE_DOCUMENT,
104         PAGE_MODE_PASSWORD
105 } EvWindowPageMode;
106
107 typedef enum {
108         EV_CHROME_MENUBAR       = 1 << 0,
109         EV_CHROME_TOOLBAR       = 1 << 1,
110         EV_CHROME_FINDBAR       = 1 << 2,
111         EV_CHROME_RAISE_TOOLBAR = 1 << 3,
112         EV_CHROME_FULLSCREEN_TOOLBAR    = 1 << 4,
113         EV_CHROME_SIDEBAR       = 1 << 5,
114         EV_CHROME_NORMAL        = EV_CHROME_MENUBAR | EV_CHROME_TOOLBAR | EV_CHROME_SIDEBAR
115 } EvChrome;
116
117 typedef enum {
118         EV_SAVE_DOCUMENT,
119         EV_SAVE_ATTACHMENT,
120         EV_SAVE_IMAGE
121 } EvSaveType;
122
123 struct _EvWindowPrivate {
124         /* UI */
125         EvChrome chrome;
126
127         GtkWidget *main_box;
128         GtkWidget *menubar;
129         GtkWidget *toolbar;
130         GtkWidget *hpaned;
131         GtkWidget *view_box;
132         GtkWidget *sidebar;
133         GtkWidget *find_bar;
134         GtkWidget *scrolled_window;
135         GtkWidget *view;
136         GtkWidget *message_area;
137         GtkWidget *password_view;
138         GtkWidget *sidebar_thumbs;
139         GtkWidget *sidebar_links;
140         GtkWidget *sidebar_attachments;
141         GtkWidget *sidebar_layers;
142
143         /* Progress Messages */
144         guint progress_idle;
145         GCancellable *progress_cancellable;
146
147         /* Dialogs */
148         GtkWidget *properties;
149         GtkWidget *print_dialog;
150
151         /* UI Builders */
152         GtkActionGroup   *action_group;
153         GtkActionGroup   *view_popup_action_group;
154         GtkActionGroup   *attachment_popup_action_group;
155         GtkRecentManager *recent_manager;
156         GtkActionGroup   *recent_action_group;
157         guint             recent_ui_id;
158         GtkUIManager     *ui_manager;
159
160         /* Fullscreen mode */
161         GtkWidget *fullscreen_toolbar;
162
163         /* Presentation mode */
164         guint      presentation_timeout_id;
165
166         /* Popup view */
167         GtkWidget *view_popup;
168         EvLink    *link;
169         EvImage   *image;
170
171         /* Popup attachment */
172         GtkWidget    *attachment_popup;
173         GList        *attach_list;
174
175         /* Document */
176         char *uri;
177         glong uri_mtime;
178         char *local_uri;
179         gboolean in_reload;
180         EvFileMonitor *monitor;
181         guint setup_document_idle;
182         
183         EvDocument *document;
184         EvHistory *history;
185         EvPageCache *page_cache;
186         EvWindowPageMode page_mode;
187         EvWindowTitle *title;
188
189         /* Load params */
190         EvLinkDest       *dest;
191         gchar            *search_string;
192         EvWindowRunMode   window_mode;
193
194         EvJob            *load_job;
195         EvJob            *reload_job;
196         EvJob            *thumbnail_job;
197         EvJob            *save_job;
198         EvJob            *find_job;
199
200         /* Printing */
201         GQueue           *print_queue;
202         GtkPrinter       *printer;
203         GtkPrintSettings *print_settings;
204         GtkPageSetup     *print_page_setup;
205         gboolean          close_after_print;
206 };
207
208 #define EV_WINDOW_GET_PRIVATE(object) \
209         (G_TYPE_INSTANCE_GET_PRIVATE ((object), EV_TYPE_WINDOW, EvWindowPrivate))
210
211 #define PAGE_SELECTOR_ACTION    "PageSelector"
212 #define ZOOM_CONTROL_ACTION     "ViewZoom"
213 #define NAVIGATION_ACTION       "Navigation"
214
215 #define GCONF_OVERRIDE_RESTRICTIONS "/apps/evince/override_restrictions"
216 #define GCONF_LOCKDOWN_SAVE         "/desktop/gnome/lockdown/disable_save_to_disk"
217 #define GCONF_LOCKDOWN_PRINT        "/desktop/gnome/lockdown/disable_printing"
218
219 #define PRESENTATION_TIMEOUT 5
220
221 #define SIDEBAR_DEFAULT_SIZE    132
222 #define LINKS_SIDEBAR_ID "links"
223 #define THUMBNAILS_SIDEBAR_ID "thumbnails"
224 #define ATTACHMENTS_SIDEBAR_ID "attachments"
225 #define LAYERS_SIDEBAR_ID "layers"
226
227 static const gchar *document_print_settings[] = {
228         GTK_PRINT_SETTINGS_N_COPIES,
229         GTK_PRINT_SETTINGS_COLLATE,
230         GTK_PRINT_SETTINGS_REVERSE,
231         GTK_PRINT_SETTINGS_NUMBER_UP,
232         GTK_PRINT_SETTINGS_SCALE,
233         GTK_PRINT_SETTINGS_PRINT_PAGES,
234         GTK_PRINT_SETTINGS_PAGE_RANGES,
235         GTK_PRINT_SETTINGS_PAGE_SET,
236         GTK_PRINT_SETTINGS_OUTPUT_URI
237 };
238
239 static void     ev_window_update_actions                (EvWindow         *ev_window);
240 static void     ev_window_sidebar_visibility_changed_cb (EvSidebar        *ev_sidebar,
241                                                          GParamSpec       *pspec,
242                                                          EvWindow         *ev_window);
243 static void     ev_window_set_page_mode                 (EvWindow         *window,
244                                                          EvWindowPageMode  page_mode);
245 static void     ev_window_load_job_cb                   (EvJob            *job,
246                                                          gpointer          data);
247 static void     ev_window_reload_document               (EvWindow         *window);
248 static void     ev_window_reload_job_cb                 (EvJob            *job,
249                                                          EvWindow         *window);
250 static void     ev_window_set_icon_from_thumbnail       (EvJobThumbnail   *job,
251                                                          EvWindow         *ev_window);
252 static void     ev_window_save_job_cb                   (EvJob            *save,
253                                                          EvWindow         *window);
254 static void     ev_window_sizing_mode_changed_cb        (EvView           *view,
255                                                          GParamSpec       *pspec,
256                                                          EvWindow         *ev_window);
257 static void     ev_window_zoom_changed_cb               (EvView           *view,
258                                                          GParamSpec       *pspec,
259                                                          EvWindow         *ev_window);
260 static void     ev_window_add_recent                    (EvWindow         *window,
261                                                          const char       *filename);
262 static void     ev_window_run_fullscreen                (EvWindow         *window);
263 static void     ev_window_stop_fullscreen               (EvWindow         *window,
264                                                          gboolean          unfullscreen_window);
265 static void     ev_window_cmd_view_fullscreen           (GtkAction        *action,
266                                                          EvWindow         *window);
267 static void     ev_window_run_presentation              (EvWindow         *window);
268 static void     ev_window_stop_presentation             (EvWindow         *window,
269                                                          gboolean          unfullscreen_window);
270 static void     ev_window_cmd_view_presentation         (GtkAction        *action,
271                                                          EvWindow         *window);
272 static void     ev_view_popup_cmd_open_link             (GtkAction        *action,
273                                                          EvWindow         *window);
274 static void     ev_view_popup_cmd_open_link_new_window  (GtkAction        *action,
275                                                          EvWindow         *window);
276 static void     ev_view_popup_cmd_copy_link_address     (GtkAction        *action,
277                                                          EvWindow         *window);
278 static void     ev_view_popup_cmd_save_image_as         (GtkAction        *action,
279                                                          EvWindow         *window);
280 static void     ev_view_popup_cmd_copy_image            (GtkAction        *action,
281                                                          EvWindow         *window);
282 static void     ev_attachment_popup_cmd_open_attachment (GtkAction        *action,
283                                                          EvWindow         *window);
284 static void     ev_attachment_popup_cmd_save_attachment_as (GtkAction     *action, 
285                                                          EvWindow         *window);
286 static void     ev_window_cmd_view_best_fit             (GtkAction        *action, 
287                                                          EvWindow         *ev_window);
288 static void     ev_window_cmd_view_page_width           (GtkAction        *action, 
289                                                          EvWindow         *ev_window);
290 static void     view_handle_link_cb                     (EvView           *view, 
291                                                          EvLink           *link, 
292                                                          EvWindow         *window);
293 static void     ev_window_update_find_status_message    (EvWindow         *ev_window);
294 static void     ev_window_cmd_edit_find                 (GtkAction        *action,
295                                                          EvWindow         *ev_window);
296 static void     find_bar_search_changed_cb              (EggFindBar       *find_bar,
297                                                          GParamSpec       *param,
298                                                          EvWindow         *ev_window);
299 static void     ev_window_load_file_remote              (EvWindow         *ev_window,
300                                                          GFile            *source_file);
301 static void     ev_window_media_player_key_pressed      (EvWindow         *window,
302                                                          const gchar      *key,
303                                                          gpointer          user_data);
304 static void     ev_window_save_print_page_setup         (EvWindow         *window);
305
306 G_DEFINE_TYPE (EvWindow, ev_window, GTK_TYPE_WINDOW)
307
308 static void
309 ev_window_set_action_sensitive (EvWindow   *ev_window,
310                                 const char *name,
311                                 gboolean    sensitive)
312 {
313         GtkAction *action = gtk_action_group_get_action (ev_window->priv->action_group,
314                                                          name);
315         gtk_action_set_sensitive (action, sensitive);
316 }
317
318
319 static void
320 ev_window_setup_action_sensitivity (EvWindow *ev_window)
321 {
322         EvDocument *document = ev_window->priv->document;
323         const EvDocumentInfo *info = NULL;
324
325         gboolean has_document = FALSE;
326         gboolean ok_to_print = TRUE;
327         gboolean ok_to_copy = TRUE;
328         gboolean has_properties = TRUE;
329         gboolean override_restrictions = TRUE;
330         gboolean can_get_text = FALSE;
331         gboolean has_pages = FALSE;
332         gboolean can_find = FALSE;
333 #ifdef WITH_GCONF
334         GConfClient *client;
335 #endif
336
337         if (document) {
338                 has_document = TRUE;
339                 info = ev_page_cache_get_info (ev_window->priv->page_cache);
340         }
341
342         if (has_document && ev_window->priv->page_cache) {
343                 has_pages = ev_page_cache_get_n_pages (ev_window->priv->page_cache) > 0;
344         }
345
346         if (!info || info->fields_mask == 0) {
347                 has_properties = FALSE;
348         }
349
350         if (has_document && EV_IS_SELECTION (document)) {
351                 can_get_text = TRUE;
352         }
353         
354         if (has_pages && EV_IS_DOCUMENT_FIND (document)) {
355                 can_find = TRUE;
356         }
357
358 #ifdef WITH_GCONF
359         client = gconf_client_get_default ();
360         override_restrictions = gconf_client_get_bool (client, 
361                                                        GCONF_OVERRIDE_RESTRICTIONS, 
362                                                        NULL);
363 #endif
364         if (!override_restrictions && info && info->fields_mask & EV_DOCUMENT_INFO_PERMISSIONS) {
365                 ok_to_print = (info->permissions & EV_DOCUMENT_PERMISSIONS_OK_TO_PRINT);
366                 ok_to_copy = (info->permissions & EV_DOCUMENT_PERMISSIONS_OK_TO_COPY);
367         }
368
369         if (has_document && !EV_IS_FILE_EXPORTER(document))
370                 ok_to_print = FALSE;
371
372 #ifdef WITH_GCONF
373         if (gconf_client_get_bool (client, GCONF_LOCKDOWN_SAVE, NULL)) {
374                 ok_to_copy = FALSE;
375         }
376
377         if (gconf_client_get_bool (client, GCONF_LOCKDOWN_PRINT, NULL)) {
378                 ok_to_print = FALSE;
379         }
380
381         g_object_unref (client);
382 #endif
383
384         /* File menu */
385         ev_window_set_action_sensitive (ev_window, "FileOpenCopy", has_document);
386         ev_window_set_action_sensitive (ev_window, "FileSaveAs", has_document && ok_to_copy);
387         ev_window_set_action_sensitive (ev_window, "FilePageSetup", has_pages && ok_to_print);
388         ev_window_set_action_sensitive (ev_window, "FilePrint", has_pages && ok_to_print);
389         ev_window_set_action_sensitive (ev_window, "FileProperties", has_document && has_properties);
390
391         /* Edit menu */
392         ev_window_set_action_sensitive (ev_window, "EditSelectAll", has_pages && can_get_text);
393         ev_window_set_action_sensitive (ev_window, "EditFind", can_find);
394         ev_window_set_action_sensitive (ev_window, "Slash", can_find);
395         ev_window_set_action_sensitive (ev_window, "EditRotateLeft", has_pages);
396         ev_window_set_action_sensitive (ev_window, "EditRotateRight", has_pages);
397
398         /* View menu */
399         ev_window_set_action_sensitive (ev_window, "ViewContinuous", has_pages);
400         ev_window_set_action_sensitive (ev_window, "ViewDual", has_pages);
401         ev_window_set_action_sensitive (ev_window, "ViewBestFit", has_pages);
402         ev_window_set_action_sensitive (ev_window, "ViewPageWidth", has_pages);
403         ev_window_set_action_sensitive (ev_window, "ViewReload", has_pages);
404         ev_window_set_action_sensitive (ev_window, "ViewAutoscroll", has_pages);
405
406         /* Toolbar-specific actions: */
407         ev_window_set_action_sensitive (ev_window, PAGE_SELECTOR_ACTION, has_pages);
408         ev_window_set_action_sensitive (ev_window, ZOOM_CONTROL_ACTION,  has_pages);
409         ev_window_set_action_sensitive (ev_window, NAVIGATION_ACTION,  FALSE);
410
411         ev_window_update_actions (ev_window);
412 }
413
414 static void
415 ev_window_update_actions (EvWindow *ev_window)
416 {
417         EvView *view = EV_VIEW (ev_window->priv->view);
418         int n_pages = 0, page = -1;
419         gboolean has_pages = FALSE;
420         gboolean presentation_mode;
421         gboolean can_find_in_page = FALSE;
422
423         if (ev_window->priv->document && ev_window->priv->page_cache) {
424                 page = ev_page_cache_get_current_page (ev_window->priv->page_cache);
425                 n_pages = ev_page_cache_get_n_pages (ev_window->priv->page_cache);
426                 has_pages = n_pages > 0;
427         }
428
429         can_find_in_page = (ev_window->priv->find_job &&
430                             ev_job_find_has_results (EV_JOB_FIND (ev_window->priv->find_job)));
431
432         ev_window_set_action_sensitive (ev_window, "EditCopy",
433                                         has_pages &&
434                                         ev_view_get_has_selection (view));
435         ev_window_set_action_sensitive (ev_window, "EditFindNext",
436                                         has_pages && can_find_in_page);
437         ev_window_set_action_sensitive (ev_window, "EditFindPrevious",
438                                         has_pages && can_find_in_page);
439         ev_window_set_action_sensitive (ev_window, "F3",
440                                         has_pages && can_find_in_page);
441
442         presentation_mode = ev_view_get_presentation (view);
443         
444         ev_window_set_action_sensitive (ev_window, "ViewZoomIn",
445                                         has_pages &&
446                                         ev_view_can_zoom_in (view) &&
447                                         !presentation_mode);
448         ev_window_set_action_sensitive (ev_window, "ViewZoomOut",
449                                         has_pages &&
450                                         ev_view_can_zoom_out (view) &&
451                                         !presentation_mode);
452         
453         /* Go menu */
454         if (has_pages) {
455                 ev_window_set_action_sensitive (ev_window, "GoPreviousPage", page > 0);
456                 ev_window_set_action_sensitive (ev_window, "GoNextPage", page < n_pages - 1);
457                 ev_window_set_action_sensitive (ev_window, "GoFirstPage", page > 0);
458                 ev_window_set_action_sensitive (ev_window, "GoLastPage", page < n_pages - 1);
459         } else {
460                 ev_window_set_action_sensitive (ev_window, "GoFirstPage", FALSE);
461                 ev_window_set_action_sensitive (ev_window, "GoPreviousPage", FALSE);
462                 ev_window_set_action_sensitive (ev_window, "GoNextPage", FALSE);
463                 ev_window_set_action_sensitive (ev_window, "GoLastPage", FALSE);
464         }
465
466         if (has_pages &&
467             ev_view_get_sizing_mode (view) != EV_SIZING_FIT_WIDTH &&
468             ev_view_get_sizing_mode (view) != EV_SIZING_BEST_FIT) {
469                 GtkAction *action;
470                 float      zoom;
471                 float      real_zoom;
472
473                 action = gtk_action_group_get_action (ev_window->priv->action_group, 
474                                                       ZOOM_CONTROL_ACTION);
475
476                 real_zoom = ev_view_get_zoom (EV_VIEW (ev_window->priv->view));
477                 real_zoom *= 72.0 / get_screen_dpi (GTK_WINDOW (ev_window));
478                 zoom = ephy_zoom_get_nearest_zoom_level (real_zoom);
479
480                 ephy_zoom_action_set_zoom_level (EPHY_ZOOM_ACTION (action), zoom);
481         }
482 }
483
484 static void
485 ev_window_set_view_accels_sensitivity (EvWindow *window, gboolean sensitive)
486 {
487         gboolean can_find;
488
489         can_find = window->priv->document && 
490             EV_IS_DOCUMENT_FIND (window->priv->document);
491
492         if (window->priv->action_group) {
493                 ev_window_set_action_sensitive (window, "PageDown", sensitive);
494                 ev_window_set_action_sensitive (window, "PageUp", sensitive);
495                 ev_window_set_action_sensitive (window, "Space", sensitive);
496                 ev_window_set_action_sensitive (window, "ShiftSpace", sensitive);
497                 ev_window_set_action_sensitive (window, "BackSpace", sensitive);
498                 ev_window_set_action_sensitive (window, "ShiftBackSpace", sensitive);
499                 ev_window_set_action_sensitive (window, "Return", sensitive);
500                 ev_window_set_action_sensitive (window, "ShiftReturn", sensitive);
501                 ev_window_set_action_sensitive (window, "Plus", sensitive);
502                 ev_window_set_action_sensitive (window, "Minus", sensitive);
503                 ev_window_set_action_sensitive (window, "KpPlus", sensitive);
504                 ev_window_set_action_sensitive (window, "KpMinus", sensitive);
505                 ev_window_set_action_sensitive (window, "Equal", sensitive);
506
507                 ev_window_set_action_sensitive (window, "Slash", sensitive && can_find);
508         }
509 }
510
511 static void
512 set_widget_visibility (GtkWidget *widget, gboolean visible)
513 {
514         g_assert (GTK_IS_WIDGET (widget));
515         
516         if (visible)
517                 gtk_widget_show (widget);
518         else
519                 gtk_widget_hide (widget);
520 }
521
522 static void
523 update_chrome_visibility (EvWindow *window)
524 {
525         EvWindowPrivate *priv = window->priv;
526         gboolean menubar, toolbar, findbar, fullscreen_toolbar, sidebar;
527         gboolean fullscreen_mode, presentation, fullscreen;
528
529         presentation = ev_view_get_presentation (EV_VIEW (priv->view));
530         fullscreen = ev_view_get_fullscreen (EV_VIEW (priv->view));
531         fullscreen_mode = fullscreen || presentation;
532
533         menubar = (priv->chrome & EV_CHROME_MENUBAR) != 0 && !fullscreen_mode;
534         toolbar = ((priv->chrome & EV_CHROME_TOOLBAR) != 0  || 
535                    (priv->chrome & EV_CHROME_RAISE_TOOLBAR) != 0) && !fullscreen_mode;
536         fullscreen_toolbar = ((priv->chrome & EV_CHROME_FULLSCREEN_TOOLBAR) != 0 || 
537                               (priv->chrome & EV_CHROME_RAISE_TOOLBAR) != 0) && fullscreen;
538         findbar = (priv->chrome & EV_CHROME_FINDBAR) != 0;
539         sidebar = (priv->chrome & EV_CHROME_SIDEBAR) != 0 && !presentation;
540
541         set_widget_visibility (priv->menubar, menubar); 
542         set_widget_visibility (priv->toolbar, toolbar);
543         set_widget_visibility (priv->find_bar, findbar);
544         set_widget_visibility (priv->sidebar, sidebar);
545         
546         ev_window_set_action_sensitive (window, "EditToolbar", toolbar);
547         gtk_widget_set_sensitive (priv->menubar, menubar);
548
549         if (priv->fullscreen_toolbar != NULL) {
550                 set_widget_visibility (priv->fullscreen_toolbar, fullscreen_toolbar);
551         }
552 }
553
554 static void
555 update_chrome_flag (EvWindow *window, EvChrome flag, gboolean active)
556 {
557         EvWindowPrivate *priv = window->priv;
558         
559         if (active) {
560                 priv->chrome |= flag;
561         } else {
562                 priv->chrome &= ~flag;
563         }
564 }
565
566 static void
567 update_sizing_buttons (EvWindow *window)
568 {
569         GtkActionGroup *action_group = window->priv->action_group;
570         GtkAction *action;
571         gboolean best_fit, page_width;
572         EvSizingMode sizing_mode;
573
574         if (window->priv->view == NULL)
575                 return;
576
577         g_object_get (window->priv->view,
578                       "sizing_mode", &sizing_mode,
579                       NULL);
580
581         switch (sizing_mode) {
582                 case EV_SIZING_BEST_FIT:
583                         best_fit = TRUE;
584                         page_width = FALSE;
585                         break;
586                 case EV_SIZING_FIT_WIDTH:
587                         best_fit = FALSE;
588                         page_width = TRUE;
589                         break;
590                 default:
591                         best_fit = page_width = FALSE;
592                         break;
593         }
594
595         action = gtk_action_group_get_action (action_group, "ViewBestFit");
596         g_signal_handlers_block_by_func
597                 (action, G_CALLBACK (ev_window_cmd_view_best_fit), window);
598         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), best_fit);
599         g_signal_handlers_unblock_by_func
600                 (action, G_CALLBACK (ev_window_cmd_view_best_fit), window);
601
602         action = gtk_action_group_get_action (action_group, "ViewPageWidth");   
603         g_signal_handlers_block_by_func
604                 (action, G_CALLBACK (ev_window_cmd_view_page_width), window);
605         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), page_width);
606         g_signal_handlers_unblock_by_func
607                 (action, G_CALLBACK (ev_window_cmd_view_page_width), window);
608
609         action = gtk_action_group_get_action (window->priv->action_group, 
610                                               ZOOM_CONTROL_ACTION);     
611         if (best_fit) {
612                 ephy_zoom_action_set_zoom_level (EPHY_ZOOM_ACTION (action), 
613                                                  EPHY_ZOOM_BEST_FIT);
614         } else if (page_width) {
615                 ephy_zoom_action_set_zoom_level (EPHY_ZOOM_ACTION (action), 
616                                                  EPHY_ZOOM_FIT_WIDTH);
617         }
618 }
619
620 /**
621  * ev_window_is_empty:
622  * @ev_window: The instance of the #EvWindow.
623  *
624  * It does look if there is any document loaded or if there is any job to load
625  * a document.
626  *
627  * Returns: %TRUE if there isn't any document loaded or any any documente to be
628  *          loaded, %FALSE in other case.
629  */
630 gboolean
631 ev_window_is_empty (const EvWindow *ev_window)
632 {
633         g_return_val_if_fail (EV_IS_WINDOW (ev_window), FALSE);
634
635         return (ev_window->priv->document == NULL) && 
636                 (ev_window->priv->load_job == NULL);
637 }
638
639 static void
640 ev_window_set_message_area (EvWindow  *window,
641                             GtkWidget *area)
642 {
643         if (window->priv->message_area == area)
644                 return;
645
646         if (window->priv->message_area)
647                 gtk_widget_destroy (window->priv->message_area);
648         window->priv->message_area = area;
649
650         if (!area)
651                 return;
652
653         gtk_box_pack_start (GTK_BOX (window->priv->view_box),
654                             window->priv->message_area,
655                             FALSE, FALSE, 0);
656         gtk_box_reorder_child (GTK_BOX (window->priv->view_box),
657                                window->priv->message_area, 0);
658         g_object_add_weak_pointer (G_OBJECT (window->priv->message_area),
659                                    (gpointer) &(window->priv->message_area));
660 }
661
662 static void
663 ev_window_message_area_response_cb (EvMessageArea *area,
664                                     gint           response_id,
665                                     EvWindow      *window)
666 {
667         ev_window_set_message_area (window, NULL);
668 }
669
670 static void
671 ev_window_error_message (EvWindow    *window,
672                          GError      *error,
673                          const gchar *format,
674                          ...)
675 {
676         GtkWidget *area;
677         va_list    args;
678         gchar     *msg = NULL;
679
680         if (window->priv->message_area)
681                 return;
682
683         va_start (args, format);
684         msg = g_strdup_vprintf (format, args);
685         va_end (args);
686         
687         area = ev_message_area_new (GTK_MESSAGE_ERROR,
688                                     msg,
689                                     GTK_STOCK_CLOSE,
690                                     GTK_RESPONSE_CLOSE,
691                                     NULL);
692         g_free (msg);
693         
694         if (error)
695                 ev_message_area_set_secondary_text (EV_MESSAGE_AREA (area), error->message);
696         g_signal_connect (area, "response",
697                           G_CALLBACK (ev_window_message_area_response_cb),
698                           window);
699         gtk_widget_show (area);
700         ev_window_set_message_area (window, area);
701 }
702
703 static void
704 ev_window_warning_message (EvWindow    *window,
705                            const gchar *format,
706                            ...)
707 {
708         GtkWidget *area;
709         va_list    args;
710         gchar     *msg = NULL;
711
712         if (window->priv->message_area)
713                 return;
714
715         va_start (args, format);
716         msg = g_strdup_vprintf (format, args);
717         va_end (args);
718
719         area = ev_message_area_new (GTK_MESSAGE_WARNING,
720                                     msg,
721                                     GTK_STOCK_CLOSE,
722                                     GTK_RESPONSE_CLOSE,
723                                     NULL);
724         g_free (msg);
725         
726         g_signal_connect (area, "response",
727                           G_CALLBACK (ev_window_message_area_response_cb),
728                           window);
729         gtk_widget_show (area);
730         ev_window_set_message_area (window, area);
731 }
732
733 static void
734 page_changed_cb (EvPageCache *page_cache,
735                  gint         page,
736                  EvWindow    *ev_window)
737 {
738         ev_window_update_actions (ev_window);
739
740         ev_window_update_find_status_message (ev_window);
741
742         if (!ev_window_is_empty (ev_window))
743                 ev_metadata_manager_set_int (ev_window->priv->uri, "page", page);
744 }
745
746 typedef struct _FindTask {
747         const gchar *page_label;
748         gchar *chapter;
749 } FindTask;
750
751 static gboolean
752 ev_window_find_chapter (GtkTreeModel *tree_model,
753                         GtkTreePath  *path,
754                         GtkTreeIter  *iter,
755                         gpointer      data)
756 {
757         FindTask *task = (FindTask *)data;
758         gchar *page_string;
759         
760         gtk_tree_model_get (tree_model, iter,
761                             EV_DOCUMENT_LINKS_COLUMN_PAGE_LABEL, &page_string, 
762                             -1);
763         
764         if (!page_string)
765                 return FALSE;
766         
767         if (!strcmp (page_string, task->page_label)) {
768                 gtk_tree_model_get (tree_model, iter,
769                                     EV_DOCUMENT_LINKS_COLUMN_MARKUP, &task->chapter, 
770                                     -1);
771                 g_free (page_string);
772                 return TRUE;
773         }
774         
775         g_free (page_string);
776         return FALSE;
777 }
778
779 static void
780 ev_window_add_history (EvWindow *window, gint page, EvLink *link)
781 {
782         gchar *page_label = NULL;
783         gchar *link_title;
784         FindTask find_task;
785         EvLink *real_link;
786         EvLinkAction *action;
787         EvLinkDest *dest;
788         
789         if (window->priv->history == NULL)
790                 return;
791
792         if (!EV_IS_DOCUMENT_LINKS (window->priv->document))
793                 return;
794         
795         if (link) {
796                 action = g_object_ref (ev_link_get_action (link));
797                 dest = ev_link_action_get_dest (action);
798                 page = ev_link_dest_get_page (dest);
799                 page_label = ev_view_page_label_from_dest (EV_VIEW (window->priv->view), dest);
800         } else {
801                 dest = ev_link_dest_new_page (page);
802                 action = ev_link_action_new_dest (dest);
803                 page_label = ev_page_cache_get_page_label (window->priv->page_cache, page);
804         }
805
806         if (!page_label)
807                 return;
808         
809         find_task.page_label = page_label;
810         find_task.chapter = NULL;
811         
812         if (ev_document_links_has_document_links (EV_DOCUMENT_LINKS (window->priv->document))) {
813                 GtkTreeModel *model;
814         
815                 g_object_get (G_OBJECT (window->priv->sidebar_links), "model", &model, NULL);
816                 
817                 if (model) {
818                         gtk_tree_model_foreach (model,
819                                                 ev_window_find_chapter,
820                                                 &find_task);
821         
822                         g_object_unref (model);
823                 }
824         }
825
826         if (find_task.chapter)
827                 link_title = g_strdup_printf (_("Page %s - %s"), page_label, find_task.chapter);
828         else
829                 link_title = g_strdup_printf (_("Page %s"), page_label);
830         
831         real_link = ev_link_new (link_title, action);
832         
833         ev_history_add_link (window->priv->history, real_link);
834
835         g_free (find_task.chapter);
836         g_free (link_title);
837         g_free (page_label);
838         g_object_unref (real_link);
839 }
840
841 static void
842 view_handle_link_cb (EvView *view, EvLink *link, EvWindow *window)
843 {
844         int current_page = ev_page_cache_get_current_page (window->priv->page_cache);
845         
846         ev_window_add_history (window, 0, link);
847         ev_window_add_history (window, current_page, NULL);
848 }
849
850 static void
851 history_changed_cb (EvPageCache *page_cache,
852                     gint         page,
853                     EvWindow    *window)
854 {
855         int current_page = ev_page_cache_get_current_page (window->priv->page_cache);
856
857         ev_window_add_history (window, page, NULL);
858         ev_window_add_history (window, current_page, NULL);
859
860         return;
861 }
862
863 static void
864 update_document_mode (EvWindow *window, EvDocumentMode mode)
865 {
866         if (mode == EV_DOCUMENT_MODE_PRESENTATION) {
867                 ev_window_run_presentation (window);
868         }
869         else if (mode == EV_DOCUMENT_MODE_FULL_SCREEN) {
870                 ev_window_run_fullscreen (window);
871         }
872 }
873
874 static void
875 setup_chrome_from_metadata (EvWindow *window)
876 {
877         EvChrome chrome = EV_CHROME_NORMAL;
878         GValue show_toolbar = { 0, };
879
880         if (ev_metadata_manager_get (NULL, "show_toolbar", &show_toolbar, FALSE)) {
881                 if (!g_value_get_boolean (&show_toolbar))
882                         chrome &= ~EV_CHROME_TOOLBAR;
883                 g_value_unset (&show_toolbar);
884         }
885         window->priv->chrome = chrome;
886 }
887
888 static void
889 setup_sidebar_from_metadata (EvWindow *window)
890 {
891         gchar      *uri = window->priv->uri;
892         EvDocument *document = window->priv->document;
893         GtkWidget  *sidebar = window->priv->sidebar;
894         GtkWidget  *links = window->priv->sidebar_links;
895         GtkWidget  *thumbs = window->priv->sidebar_thumbs;
896         GtkWidget  *attachments = window->priv->sidebar_attachments;
897         GtkWidget  *layers = window->priv->sidebar_layers;
898         GValue      sidebar_size = { 0, };
899         GValue      sidebar_page = { 0, };
900         GValue      sidebar_visibility = { 0, };
901
902         if (ev_metadata_manager_get (uri, "sidebar_size", &sidebar_size, FALSE)) {
903                 gtk_paned_set_position (GTK_PANED (window->priv->hpaned),
904                                         g_value_get_int (&sidebar_size));
905                 g_value_unset(&sidebar_size);
906         }
907         
908         if (document && ev_metadata_manager_get (uri, "sidebar_page", &sidebar_page, TRUE)) {
909                 const char *page_id = g_value_get_string (&sidebar_page);
910
911                 if (strcmp (page_id, LINKS_SIDEBAR_ID) == 0 && ev_sidebar_page_support_document (EV_SIDEBAR_PAGE (links), document)) {
912                         ev_sidebar_set_page (EV_SIDEBAR (sidebar), links);
913                 } else if (strcmp (page_id, THUMBNAILS_SIDEBAR_ID) == 0 && ev_sidebar_page_support_document (EV_SIDEBAR_PAGE (thumbs), document)) {
914                         ev_sidebar_set_page (EV_SIDEBAR (sidebar), thumbs);
915                 } else if (strcmp (page_id, ATTACHMENTS_SIDEBAR_ID) == 0 && ev_sidebar_page_support_document (EV_SIDEBAR_PAGE (attachments), document)) {
916                         ev_sidebar_set_page (EV_SIDEBAR (sidebar), attachments);
917                 } else if (strcmp (page_id, LAYERS_SIDEBAR_ID) == 0 && ev_sidebar_page_support_document (EV_SIDEBAR_PAGE (layers), document)) {
918                         ev_sidebar_set_page (EV_SIDEBAR (sidebar), layers);
919                 }
920                 g_value_unset (&sidebar_page);
921         } else if (document) {
922                 if (ev_sidebar_page_support_document (EV_SIDEBAR_PAGE (links), document)) {
923                         ev_sidebar_set_page (EV_SIDEBAR (sidebar), links);
924                 } else if (ev_sidebar_page_support_document (EV_SIDEBAR_PAGE (thumbs), document)) {
925                         ev_sidebar_set_page (EV_SIDEBAR (sidebar), thumbs);
926                 } else if (ev_sidebar_page_support_document (EV_SIDEBAR_PAGE (attachments), document)) {
927                         ev_sidebar_set_page (EV_SIDEBAR (sidebar), attachments);
928                 } else if (ev_sidebar_page_support_document (EV_SIDEBAR_PAGE (layers), document)) {
929                         ev_sidebar_set_page (EV_SIDEBAR (sidebar), layers);
930                 }
931         }
932
933         if (ev_metadata_manager_get (uri, "sidebar_visibility", &sidebar_visibility, FALSE)) {
934                 update_chrome_flag (window, EV_CHROME_SIDEBAR, g_value_get_boolean (&sidebar_visibility));
935                 g_value_unset (&sidebar_visibility);
936                 update_chrome_visibility (window);
937         }
938 }
939
940 static void
941 setup_document_from_metadata (EvWindow *window)
942 {
943         gchar *uri = window->priv->uri;
944         GValue page = { 0, };
945         GValue width = { 0, };
946         GValue height = { 0, };
947         GValue width_ratio = { 0, };
948         GValue height_ratio = { 0, };
949
950         /* View the previously shown page, but make sure to not open a document on
951          * the last page, since closing it on the last page most likely means the
952          * user was finished reading the document. In that case, reopening should
953          * show the first page. */
954         if (uri && ev_metadata_manager_get (uri, "page", &page, TRUE)) {
955                 gint n_pages;
956                 gint new_page;
957                 
958                 n_pages = ev_page_cache_get_n_pages (window->priv->page_cache);
959                 new_page = CLAMP (g_value_get_int (&page), 0, n_pages - 1);
960                 ev_page_cache_set_current_page (window->priv->page_cache,
961                                                 new_page);
962                 g_value_unset (&page);
963         }
964
965         setup_sidebar_from_metadata (window);
966
967         if (ev_metadata_manager_get (uri, "window_width", &width, TRUE) &&
968             ev_metadata_manager_get (uri, "window_height", &height, TRUE))
969                 return; /* size was already set in setup_size_from_metadata */
970
971         if (ev_metadata_manager_get (uri, "window_width_ratio", &width_ratio, FALSE) &&
972             ev_metadata_manager_get (uri, "window_height_ratio", &height_ratio, FALSE)) {
973                 gint       document_width;
974                 gint       document_height;
975                 GdkScreen *screen;
976                 gint       request_width;
977                 gint       request_height;
978
979                 ev_page_cache_get_max_width (window->priv->page_cache, 
980                                              0, 1.0,
981                                              &document_width);
982                 ev_page_cache_get_max_height (window->priv->page_cache, 
983                                              0, 1.0,
984                                              &document_height);                 
985                 
986                 request_width = g_value_get_double (&width_ratio) * document_width;
987                 request_height = g_value_get_double (&height_ratio) * document_height;
988                 
989                 screen = gtk_window_get_screen (GTK_WINDOW (window));
990                 
991                 if (screen) {
992                         request_width = MIN (request_width, gdk_screen_get_width (screen));
993                         request_height = MIN (request_width, gdk_screen_get_height (screen));
994                 }
995                                 
996                 gtk_window_resize (GTK_WINDOW (window),
997                                    request_width,
998                                    request_height);
999                 g_value_unset (&width_ratio);
1000                 g_value_unset (&height_ratio);
1001         }
1002 }
1003
1004 static void
1005 setup_size_from_metadata (EvWindow *window)
1006 {
1007         char *uri = window->priv->uri;
1008         GValue width = { 0, };
1009         GValue height = { 0, };
1010         GValue maximized = { 0, };
1011         GValue x = { 0, };
1012         GValue y = { 0, };
1013
1014         if (ev_metadata_manager_get (uri, "window_maximized", &maximized, FALSE)) {
1015                 if (g_value_get_boolean (&maximized)) {
1016                         gtk_window_maximize (GTK_WINDOW (window));
1017                         g_value_unset (&maximized);
1018                         return;
1019                 } else {
1020                         gtk_window_unmaximize (GTK_WINDOW (window));
1021                 }
1022                 g_value_unset (&maximized);
1023         }
1024
1025         if (ev_metadata_manager_get (uri, "window_x", &x, TRUE) &&
1026             ev_metadata_manager_get (uri, "window_y", &y, TRUE)) {
1027                 gtk_window_move (GTK_WINDOW (window), g_value_get_int (&x),
1028                                  g_value_get_int (&y));
1029                 g_value_unset (&x);
1030                 g_value_unset (&y);
1031         }
1032
1033         if (ev_metadata_manager_get (uri, "window_width", &width, TRUE) &&
1034             ev_metadata_manager_get (uri, "window_height", &height, TRUE)) {
1035                 gtk_window_resize (GTK_WINDOW (window),
1036                                    g_value_get_int (&width),
1037                                    g_value_get_int (&height));
1038                 g_value_unset (&width);
1039                 g_value_unset (&height);
1040         }
1041 }
1042
1043 static void
1044 setup_view_from_metadata (EvWindow *window)
1045 {
1046         EvView *view = EV_VIEW (window->priv->view);
1047         gchar *uri = window->priv->uri;
1048         GEnumValue *enum_value;
1049         GValue sizing_mode = { 0, };
1050         GValue zoom = { 0, };
1051         GValue continuous = { 0, };
1052         GValue dual_page = { 0, };
1053         GValue presentation = { 0, };
1054         GValue fullscreen = { 0, };
1055         GValue rotation = { 0, };
1056
1057         /* Sizing mode */
1058         if (ev_metadata_manager_get (uri, "sizing_mode", &sizing_mode, FALSE)) {
1059                 enum_value = g_enum_get_value_by_nick
1060                         (g_type_class_peek (EV_TYPE_SIZING_MODE), g_value_get_string (&sizing_mode));
1061                 g_value_unset (&sizing_mode);
1062                 ev_view_set_sizing_mode (view, enum_value->value);
1063         }
1064
1065         /* Zoom */
1066         if (ev_metadata_manager_get (uri, "zoom", &zoom, FALSE) &&
1067             ev_view_get_sizing_mode (view) == EV_SIZING_FREE) {
1068                 gdouble zoom_value;
1069
1070                 zoom_value = g_value_get_double (&zoom);
1071                 zoom_value *= get_screen_dpi (GTK_WINDOW (window)) / 72.0;
1072                 ev_view_set_zoom (view, zoom_value, FALSE);
1073                 g_value_unset (&zoom);
1074         }
1075
1076         /* Continuous */
1077         if (ev_metadata_manager_get (uri, "continuous", &continuous, FALSE)) {
1078                 ev_view_set_continuous (view, g_value_get_boolean (&continuous));
1079                 g_value_unset (&continuous);
1080         }
1081
1082         /* Dual page */
1083         if (ev_metadata_manager_get (uri, "dual-page", &dual_page, FALSE)) {
1084                 ev_view_set_dual_page (view, g_value_get_boolean (&dual_page));
1085                 g_value_unset (&dual_page);
1086         }
1087
1088         /* Presentation */
1089         if (ev_metadata_manager_get (uri, "presentation", &presentation, FALSE)) {
1090                 if (g_value_get_boolean (&presentation) && uri) {
1091                         ev_window_run_presentation (window);
1092                 }
1093                 g_value_unset (&presentation);
1094         }
1095
1096         /* Fullscreen */
1097         if (ev_metadata_manager_get (uri, "fullscreen", &fullscreen, FALSE)) {
1098                 if (g_value_get_boolean (&fullscreen) && uri) {
1099                         ev_window_run_fullscreen (window);
1100                 }
1101                 g_value_unset (&fullscreen);
1102         }
1103
1104         /* Rotation */
1105         if (ev_metadata_manager_get (uri, "rotation", &rotation, TRUE)) {
1106                 if (g_value_get_int (&rotation)) {
1107                         switch (g_value_get_int (&rotation)) {
1108                                 case 90:
1109                                         ev_view_set_rotation (view, 90);
1110                                         break;
1111                                 case 180:
1112                                         ev_view_set_rotation (view, 180);
1113                                         break;
1114                                 case 270:
1115                                         ev_view_set_rotation (view, 270);
1116                                         break;
1117                                 default:
1118                                         break;
1119                         }
1120                 }
1121                 g_value_unset (&rotation);
1122         }
1123 }
1124
1125 static void
1126 ev_window_clear_thumbnail_job (EvWindow *ev_window)
1127 {
1128         if (ev_window->priv->thumbnail_job != NULL) {
1129                 if (!ev_job_is_finished (ev_window->priv->thumbnail_job))
1130                         ev_job_cancel (ev_window->priv->thumbnail_job);
1131                 
1132                 g_signal_handlers_disconnect_by_func (ev_window->priv->thumbnail_job,
1133                                                       ev_window_set_icon_from_thumbnail,
1134                                                       ev_window);
1135                 g_object_unref (ev_window->priv->thumbnail_job);
1136                 ev_window->priv->thumbnail_job = NULL;
1137         }
1138 }
1139
1140 static void
1141 ev_window_set_icon_from_thumbnail (EvJobThumbnail *job,
1142                                    EvWindow       *ev_window)
1143 {
1144         if (job->thumbnail) {
1145                 gtk_window_set_icon (GTK_WINDOW (ev_window),
1146                                      job->thumbnail);
1147         }
1148
1149         ev_window_clear_thumbnail_job (ev_window);
1150 }
1151
1152 static void
1153 ev_window_refresh_window_thumbnail (EvWindow *ev_window, int rotation)
1154 {
1155         gint page_width, page_height;
1156         gdouble scale;
1157         EvDocument *document = ev_window->priv->document;
1158         
1159         if (!EV_IS_DOCUMENT_THUMBNAILS (document) ||
1160             ev_page_cache_get_n_pages (ev_window->priv->page_cache) <= 0) {
1161                 return;
1162         }
1163         
1164         ev_window_clear_thumbnail_job (ev_window);
1165         
1166         ev_page_cache_get_size (ev_window->priv->page_cache,
1167                                 0, 0, 1.0,
1168                                 &page_width, &page_height);
1169         scale = (gdouble)128 / (gdouble)page_width;
1170         
1171         ev_window->priv->thumbnail_job = ev_job_thumbnail_new (document, 0, rotation, scale);
1172         g_signal_connect (ev_window->priv->thumbnail_job, "finished",
1173                           G_CALLBACK (ev_window_set_icon_from_thumbnail),
1174                           ev_window);
1175         ev_job_scheduler_push_job (ev_window->priv->thumbnail_job, EV_JOB_PRIORITY_NONE);
1176 }
1177
1178 static gboolean
1179 ev_window_setup_document (EvWindow *ev_window)
1180 {
1181         const EvDocumentInfo *info;
1182         EvDocument *document = ev_window->priv->document;
1183         EvSidebar *sidebar = EV_SIDEBAR (ev_window->priv->sidebar);
1184         GtkAction *action;
1185
1186         ev_window->priv->setup_document_idle = 0;
1187         
1188         ev_window_refresh_window_thumbnail (ev_window, 0);
1189
1190         ev_window_set_page_mode (ev_window, PAGE_MODE_DOCUMENT);
1191         ev_window_title_set_document (ev_window->priv->title, document);
1192         ev_window_title_set_uri (ev_window->priv->title, ev_window->priv->uri);
1193
1194         ev_sidebar_set_document (sidebar, document);
1195
1196         action = gtk_action_group_get_action (ev_window->priv->action_group, PAGE_SELECTOR_ACTION);
1197         ev_page_action_set_document (EV_PAGE_ACTION (action), document);
1198         ev_window_setup_action_sensitivity (ev_window);
1199
1200         if (ev_window->priv->history)
1201                 g_object_unref (ev_window->priv->history);
1202         ev_window->priv->history = ev_history_new ();
1203         action = gtk_action_group_get_action (ev_window->priv->action_group, NAVIGATION_ACTION);
1204         ev_navigation_action_set_history (EV_NAVIGATION_ACTION (action), ev_window->priv->history);
1205         
1206         if (ev_window->priv->properties) {
1207                 ev_properties_dialog_set_document (EV_PROPERTIES_DIALOG (ev_window->priv->properties),
1208                                                    ev_window->priv->uri,
1209                                                    ev_window->priv->document);
1210         }
1211         
1212         info = ev_page_cache_get_info (ev_window->priv->page_cache);
1213         update_document_mode (ev_window, info->mode);
1214
1215         return FALSE;
1216 }
1217
1218 static void
1219 ev_window_set_document (EvWindow *ev_window, EvDocument *document)
1220 {
1221         EvView *view = EV_VIEW (ev_window->priv->view);
1222
1223         if (ev_window->priv->document)
1224                 g_object_unref (ev_window->priv->document);
1225         ev_window->priv->document = g_object_ref (document);
1226
1227         ev_window_set_message_area (ev_window, NULL);
1228         
1229         ev_window->priv->page_cache = ev_page_cache_get (ev_window->priv->document);
1230         g_signal_connect (ev_window->priv->page_cache, "page-changed",
1231                           G_CALLBACK (page_changed_cb), ev_window);
1232         g_signal_connect (ev_window->priv->page_cache, "history-changed",
1233                           G_CALLBACK (history_changed_cb), ev_window);
1234
1235         if (ev_window->priv->in_reload && ev_window->priv->dest) {
1236                 gint page;
1237
1238                 /* Restart the current page */
1239                 page = CLAMP (ev_link_dest_get_page (ev_window->priv->dest),
1240                               0,
1241                               ev_page_cache_get_n_pages (ev_window->priv->page_cache) - 1);
1242                 ev_page_cache_set_current_page (ev_window->priv->page_cache, page);
1243                 g_object_unref (ev_window->priv->dest);
1244                 ev_window->priv->dest = NULL;
1245         }
1246
1247         if (ev_page_cache_get_n_pages (ev_window->priv->page_cache) > 0) {
1248                 ev_view_set_document (view, document);
1249         } else {
1250                 ev_window_warning_message (ev_window, "%s",
1251                                            _("The document contains no pages"));
1252         }
1253
1254         if (ev_window->priv->setup_document_idle > 0)
1255                 g_source_remove (ev_window->priv->setup_document_idle);
1256         ev_window->priv->setup_document_idle = g_idle_add ((GSourceFunc)ev_window_setup_document, ev_window);
1257 }
1258
1259 static void
1260 ev_window_document_changed (EvWindow *ev_window,
1261                             gpointer  user_data)
1262 {
1263         ev_window_reload_document (ev_window);
1264 }
1265
1266 static void
1267 ev_window_password_view_unlock (EvWindow *ev_window)
1268 {
1269         const gchar *password;
1270         
1271         g_assert (ev_window->priv->load_job);
1272
1273         password = ev_password_view_get_password (EV_PASSWORD_VIEW (ev_window->priv->password_view));
1274         ev_job_load_set_password (EV_JOB_LOAD (ev_window->priv->load_job), password);
1275         ev_job_scheduler_push_job (ev_window->priv->load_job, EV_JOB_PRIORITY_NONE);
1276 }
1277
1278 static void
1279 ev_window_clear_load_job (EvWindow *ev_window)
1280 {
1281         if (ev_window->priv->load_job != NULL) {
1282                 if (!ev_job_is_finished (ev_window->priv->load_job))
1283                         ev_job_cancel (ev_window->priv->load_job);
1284                 
1285                 g_signal_handlers_disconnect_by_func (ev_window->priv->load_job, ev_window_load_job_cb, ev_window);
1286                 g_object_unref (ev_window->priv->load_job);
1287                 ev_window->priv->load_job = NULL;
1288         }
1289 }
1290
1291 static void
1292 ev_window_clear_reload_job (EvWindow *ev_window)
1293 {
1294         if (ev_window->priv->reload_job != NULL) {
1295                 if (!ev_job_is_finished (ev_window->priv->reload_job))
1296                         ev_job_cancel (ev_window->priv->reload_job);
1297                 
1298                 g_signal_handlers_disconnect_by_func (ev_window->priv->reload_job, ev_window_reload_job_cb, ev_window);
1299                 g_object_unref (ev_window->priv->reload_job);
1300                 ev_window->priv->reload_job = NULL;
1301         }
1302 }
1303
1304 static void
1305 ev_window_clear_local_uri (EvWindow *ev_window)
1306 {
1307         if (ev_window->priv->local_uri) {
1308                 ev_tmp_uri_unlink (ev_window->priv->local_uri);
1309                 g_free (ev_window->priv->local_uri);
1310                 ev_window->priv->local_uri = NULL;
1311         }
1312 }
1313
1314 static void
1315 ev_window_clear_temp_symlink (EvWindow *ev_window)
1316 {
1317         GFile *file, *tempdir;
1318
1319         if (!ev_window->priv->uri)
1320                 return;
1321
1322         file = g_file_new_for_uri (ev_window->priv->uri);
1323         tempdir = g_file_new_for_path (ev_tmp_dir ());
1324
1325         if (g_file_has_prefix (file, tempdir)) {
1326                 GFileInfo *file_info;
1327                 GError    *error = NULL;
1328
1329                 file_info = g_file_query_info (file,
1330                                                G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK,
1331                                                G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
1332                                                NULL, &error);
1333                 if (file_info) {
1334                         if (g_file_info_get_is_symlink (file_info))
1335                                 g_file_delete (file, NULL, NULL);
1336                         g_object_unref (file_info);
1337                 } else {
1338                         g_warning ("Error deleting temp symlink: %s\n", error->message);
1339                         g_error_free (error);
1340                 }
1341         }
1342
1343         g_object_unref (file);
1344         g_object_unref (tempdir);
1345 }
1346
1347 /* This callback will executed when load job will be finished.
1348  *
1349  * Since the flow of the error dialog is very confusing, we assume that both
1350  * document and uri will go away after this function is called, and thus we need
1351  * to ref/dup them.  Additionally, it needs to clear
1352  * ev_window->priv->password_{uri,document}, and thus people who call this
1353  * function should _not_ necessarily expect those to exist after being
1354  * called. */
1355 static void
1356 ev_window_load_job_cb (EvJob *job,
1357                        gpointer data)
1358 {
1359         EvWindow *ev_window = EV_WINDOW (data);
1360         EvDocument *document = EV_JOB (job)->document;
1361         EvJobLoad *job_load = EV_JOB_LOAD (job);
1362
1363         g_assert (job_load->uri);
1364
1365         ev_view_set_loading (EV_VIEW (ev_window->priv->view), FALSE);
1366
1367         /* Success! */
1368         if (!ev_job_is_failed (job)) {
1369                 ev_window_set_document (ev_window, document);
1370
1371                 setup_document_from_metadata (ev_window);
1372                 setup_view_from_metadata (ev_window);
1373
1374                 ev_window_add_recent (ev_window, ev_window->priv->uri);
1375
1376                 ev_window_title_set_type (ev_window->priv->title,
1377                                           EV_WINDOW_TITLE_DOCUMENT);
1378                 if (job_load->password) {
1379                         GPasswordSave flags;
1380
1381                         flags = ev_password_view_get_password_save_flags (
1382                                 EV_PASSWORD_VIEW (ev_window->priv->password_view));
1383                         ev_keyring_save_password (ev_window->priv->uri,
1384                                                   job_load->password,
1385                                                   flags);
1386                 }
1387
1388                 if (ev_window->priv->dest) {
1389                         EvLink *link;
1390                         EvLinkAction *link_action;
1391         
1392                         link_action = ev_link_action_new_dest (ev_window->priv->dest);
1393                         link = ev_link_new (NULL, link_action);
1394                         ev_view_handle_link (EV_VIEW (ev_window->priv->view), link);
1395                         g_object_unref (link);
1396
1397                         /* Already unrefed by ev_link_action
1398                          * FIXME: link action should inc dest ref counting
1399                          * or not unref it at all
1400                          */
1401                         ev_window->priv->dest = NULL;
1402                 }
1403
1404                 switch (ev_window->priv->window_mode) {
1405                         case EV_WINDOW_MODE_FULLSCREEN:
1406                                 ev_window_run_fullscreen (ev_window);
1407                                 break;
1408                         case EV_WINDOW_MODE_PRESENTATION:
1409                                 ev_window_run_presentation (ev_window);
1410                                 break;
1411                         default:
1412                                 break;
1413                 }
1414
1415                 if (ev_window->priv->search_string && EV_IS_DOCUMENT_FIND (document)) {
1416                         ev_window_cmd_edit_find (NULL, ev_window);
1417                         egg_find_bar_set_search_string (EGG_FIND_BAR (ev_window->priv->find_bar),
1418                                                         ev_window->priv->search_string);
1419                 }
1420
1421                 g_free (ev_window->priv->search_string);
1422                 ev_window->priv->search_string = NULL;
1423
1424                 /* Create a monitor for the document */
1425                 ev_window->priv->monitor = ev_file_monitor_new (ev_window->priv->uri);
1426                 g_signal_connect_swapped (ev_window->priv->monitor, "changed",
1427                                           G_CALLBACK (ev_window_document_changed),
1428                                           ev_window);
1429                 
1430                 ev_window_clear_load_job (ev_window);
1431                 return;
1432         }
1433
1434         if (g_error_matches (job->error, EV_DOCUMENT_ERROR, EV_DOCUMENT_ERROR_ENCRYPTED)) {
1435                 gchar *password;
1436                 
1437                 setup_view_from_metadata (ev_window);
1438                 
1439                 /* First look whether password is in keyring */
1440                 password = ev_keyring_lookup_password (ev_window->priv->uri);
1441                 if (password) {
1442                         if (job_load->password && strcmp (password, job_load->password) == 0) {
1443                                 /* Password in kering is wrong */
1444                                 ev_job_load_set_password (job_load, NULL);
1445                                 /* FIXME: delete password from keyring? */
1446                         } else {
1447                                 ev_job_load_set_password (job_load, password);
1448                                 ev_job_scheduler_push_job (job, EV_JOB_PRIORITY_NONE);
1449                                 g_free (password);
1450                                 return;
1451                         }
1452
1453                         g_free (password);
1454                 }
1455
1456                 /* We need to ask the user for a password */
1457                 ev_window_title_set_uri (ev_window->priv->title,
1458                                          ev_window->priv->uri);
1459                 ev_window_title_set_type (ev_window->priv->title,
1460                                           EV_WINDOW_TITLE_PASSWORD);
1461
1462                 ev_password_view_set_uri (EV_PASSWORD_VIEW (ev_window->priv->password_view),
1463                                           job_load->uri);
1464
1465                 ev_window_set_page_mode (ev_window, PAGE_MODE_PASSWORD);
1466
1467                 ev_job_load_set_password (job_load, NULL);
1468                 ev_password_view_ask_password (EV_PASSWORD_VIEW (ev_window->priv->password_view));
1469         } else {
1470                 ev_window_error_message (ev_window, job->error, 
1471                                          "%s", _("Unable to open document"));
1472                 ev_window_clear_load_job (ev_window);
1473         }       
1474 }
1475
1476 static void
1477 ev_window_reload_job_cb (EvJob    *job,
1478                          EvWindow *ev_window)
1479 {
1480         GtkWidget *widget;
1481
1482         if (ev_job_is_failed (job)) {
1483                 ev_window_clear_reload_job (ev_window);
1484                 ev_window->priv->in_reload = FALSE;
1485                 g_object_unref (ev_window->priv->dest);
1486                 ev_window->priv->dest = NULL;
1487                 
1488                 return;
1489         }
1490         
1491         ev_window_set_document (ev_window, job->document);
1492         
1493         /* Restart the search after reloading */
1494         widget = gtk_window_get_focus (GTK_WINDOW (ev_window));
1495         if (widget && gtk_widget_get_ancestor (widget, EGG_TYPE_FIND_BAR)) {
1496                 find_bar_search_changed_cb (EGG_FIND_BAR (ev_window->priv->find_bar),
1497                                             NULL, ev_window);
1498         }
1499         
1500         ev_window_clear_reload_job (ev_window);
1501         ev_window->priv->in_reload = FALSE;
1502 }
1503
1504 /**
1505  * ev_window_get_uri:
1506  * @ev_window: The instance of the #EvWindow.
1507  *
1508  * It returns the uri of the document showed in the #EvWindow.
1509  *
1510  * Returns: the uri of the document showed in the #EvWindow.
1511  */
1512 const char *
1513 ev_window_get_uri (EvWindow *ev_window)
1514 {
1515         return ev_window->priv->uri;
1516 }
1517
1518 /**
1519  * ev_window_close_dialogs:
1520  * @ev_window: The window where dialogs will be closed.
1521  *
1522  * It looks for password, print and properties dialogs and closes them and
1523  * frees them from memory. If there is any print job it does free it too.
1524  */
1525 static void
1526 ev_window_close_dialogs (EvWindow *ev_window)
1527 {
1528         if (ev_window->priv->print_dialog)
1529                 gtk_widget_destroy (ev_window->priv->print_dialog);
1530         ev_window->priv->print_dialog = NULL;
1531         
1532         if (ev_window->priv->properties)
1533                 gtk_widget_destroy (ev_window->priv->properties);
1534         ev_window->priv->properties = NULL;
1535 }
1536
1537 static void
1538 ev_window_clear_progress_idle (EvWindow *ev_window)
1539 {
1540         if (ev_window->priv->progress_idle > 0)
1541                 g_source_remove (ev_window->priv->progress_idle);
1542         ev_window->priv->progress_idle = 0;
1543 }
1544
1545 static void
1546 reset_progress_idle (EvWindow *ev_window)
1547 {
1548         ev_window->priv->progress_idle = 0;
1549 }
1550
1551 static void
1552 ev_window_show_progress_message (EvWindow   *ev_window,
1553                                  guint       interval,
1554                                  GSourceFunc function)
1555 {
1556         if (ev_window->priv->progress_idle > 0)
1557                 g_source_remove (ev_window->priv->progress_idle);
1558         ev_window->priv->progress_idle =
1559                 g_timeout_add_seconds_full (G_PRIORITY_DEFAULT,
1560                                             interval, function,
1561                                             ev_window,
1562                                             (GDestroyNotify)reset_progress_idle);
1563 }
1564
1565 static void
1566 ev_window_reset_progress_cancellable (EvWindow *ev_window)
1567 {
1568         if (ev_window->priv->progress_cancellable)
1569                 g_cancellable_reset (ev_window->priv->progress_cancellable);
1570         else
1571                 ev_window->priv->progress_cancellable = g_cancellable_new ();
1572 }
1573
1574 static void
1575 ev_window_progress_response_cb (EvProgressMessageArea *area,
1576                                 gint                   response,
1577                                 EvWindow              *ev_window)
1578 {
1579         if (response == GTK_RESPONSE_CANCEL)
1580                 g_cancellable_cancel (ev_window->priv->progress_cancellable);
1581         ev_window_set_message_area (ev_window, NULL);
1582 }
1583
1584 static gboolean 
1585 show_loading_progress (EvWindow *ev_window)
1586 {
1587         GtkWidget *area;
1588         gchar     *text;
1589         
1590         if (ev_window->priv->message_area)
1591                 return FALSE;
1592         
1593         text = g_strdup_printf (_("Loading document from %s"),
1594                                 ev_window->priv->uri);
1595         area = ev_progress_message_area_new (GTK_STOCK_OPEN,
1596                                              text,
1597                                              GTK_STOCK_CLOSE,
1598                                              GTK_RESPONSE_CLOSE,
1599                                              GTK_STOCK_CANCEL,
1600                                              GTK_RESPONSE_CANCEL,
1601                                              NULL);
1602         g_signal_connect (area, "response",
1603                           G_CALLBACK (ev_window_progress_response_cb),
1604                           ev_window);
1605         gtk_widget_show (area);
1606         ev_window_set_message_area (ev_window, area);
1607         g_free (text);
1608
1609         return FALSE;
1610 }
1611
1612 static void
1613 ev_window_load_remote_failed (EvWindow *ev_window,
1614                               GError   *error)
1615 {
1616         ev_view_set_loading (EV_VIEW (ev_window->priv->view), FALSE);
1617         ev_window->priv->in_reload = FALSE;
1618         ev_window_error_message (ev_window, error, 
1619                                  "%s", _("Unable to open document"));
1620         g_free (ev_window->priv->local_uri);
1621         ev_window->priv->local_uri = NULL;
1622         ev_window->priv->uri_mtime = 0;
1623 }
1624
1625 static void
1626 set_uri_mtime (GFile        *source,
1627                GAsyncResult *async_result,
1628                EvWindow     *ev_window)
1629 {
1630         GFileInfo *info;
1631         GError *error = NULL;
1632
1633         info = g_file_query_info_finish (source, async_result, &error);
1634
1635         if (error) {
1636                 ev_window->priv->uri_mtime = 0;
1637                 g_error_free (error);
1638         } else {
1639                 GTimeVal mtime;
1640                 
1641                 g_file_info_get_modification_time (info, &mtime);
1642                 ev_window->priv->uri_mtime = mtime.tv_sec;
1643                 g_object_unref (info);
1644         }
1645
1646         g_object_unref (source);
1647 }
1648
1649 static void
1650 mount_volume_ready_cb (GFile        *source,
1651                        GAsyncResult *async_result,
1652                        EvWindow     *ev_window)
1653 {
1654         GError *error = NULL;
1655
1656         g_file_mount_enclosing_volume_finish (source, async_result, &error);
1657
1658         if (error) {
1659                 ev_window_load_remote_failed (ev_window, error);
1660                 g_object_unref (source);
1661                 g_error_free (error);
1662         } else {
1663                 /* Volume successfully mounted,
1664                    try opening the file again */
1665                 ev_window_load_file_remote (ev_window, source);
1666         }
1667 }
1668
1669 static void
1670 window_open_file_copy_ready_cb (GFile        *source,
1671                                 GAsyncResult *async_result,
1672                                 EvWindow     *ev_window)
1673 {
1674         GError *error = NULL;
1675
1676         ev_window_clear_progress_idle (ev_window);
1677         
1678         g_file_copy_finish (source, async_result, &error);
1679         if (!error) {
1680                 ev_job_scheduler_push_job (ev_window->priv->load_job, EV_JOB_PRIORITY_NONE);
1681                 g_file_query_info_async (source,
1682                                          G_FILE_ATTRIBUTE_TIME_MODIFIED,
1683                                          0, G_PRIORITY_DEFAULT,
1684                                          NULL,
1685                                          (GAsyncReadyCallback)set_uri_mtime,
1686                                          ev_window);
1687                 return;
1688         }
1689
1690         if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_MOUNTED)) {
1691                 GMountOperation *operation;
1692
1693                 operation = gtk_mount_operation_new (GTK_WINDOW (ev_window));
1694                 g_file_mount_enclosing_volume (source,
1695                                                G_MOUNT_MOUNT_NONE,
1696                                                operation, NULL,
1697                                                (GAsyncReadyCallback)mount_volume_ready_cb,
1698                                                ev_window);
1699                 g_object_unref (operation);
1700         } else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
1701                 ev_window_clear_load_job (ev_window);
1702                 ev_window_clear_local_uri (ev_window);
1703                 g_free (ev_window->priv->uri);
1704                 ev_window->priv->uri = NULL;
1705                 g_object_unref (source);
1706                 
1707                 ev_view_set_loading (EV_VIEW (ev_window->priv->view), FALSE);
1708         } else {
1709                 ev_window_load_remote_failed (ev_window, error);
1710                 g_object_unref (source);
1711         }
1712         
1713         g_error_free (error);
1714 }
1715
1716 static void
1717 window_open_file_copy_progress_cb (goffset   n_bytes,
1718                                    goffset   total_bytes,
1719                                    EvWindow *ev_window)
1720 {
1721         gchar *status;
1722         gdouble fraction;
1723         
1724         if (!ev_window->priv->message_area)
1725                 return;
1726
1727         fraction = n_bytes / (gdouble)total_bytes;
1728         status = g_strdup_printf (_("Downloading document (%d%%)"),
1729                                   (gint)(fraction * 100));
1730         
1731         ev_progress_message_area_set_status (EV_PROGRESS_MESSAGE_AREA (ev_window->priv->message_area),
1732                                              status);
1733         ev_progress_message_area_set_fraction (EV_PROGRESS_MESSAGE_AREA (ev_window->priv->message_area),
1734                                                fraction);
1735
1736         g_free (status);
1737 }
1738
1739 static void
1740 ev_window_load_file_remote (EvWindow *ev_window,
1741                             GFile    *source_file)
1742 {
1743         GFile *target_file;
1744         
1745         if (!ev_window->priv->local_uri) {
1746                 gchar *tmp_name;
1747                 gchar *base_name;
1748
1749                 /* We'd like to keep extension of source uri since
1750                  * it helps to resolve some mime types, say cbz */
1751                 tmp_name = ev_tmp_filename (NULL);
1752                 base_name = g_file_get_basename (source_file);
1753                 ev_window->priv->local_uri = g_strconcat ("file:", tmp_name, "-",
1754                                                           base_name, NULL);
1755                 ev_job_load_set_uri (EV_JOB_LOAD (ev_window->priv->load_job),
1756                                      ev_window->priv->local_uri);
1757                 g_free (base_name);
1758                 g_free (tmp_name);
1759         }
1760
1761         ev_window_reset_progress_cancellable (ev_window);
1762         
1763         target_file = g_file_new_for_uri (ev_window->priv->local_uri);
1764         g_file_copy_async (source_file, target_file,
1765                            0, G_PRIORITY_DEFAULT,
1766                            ev_window->priv->progress_cancellable,
1767                            (GFileProgressCallback)window_open_file_copy_progress_cb,
1768                            ev_window, 
1769                            (GAsyncReadyCallback)window_open_file_copy_ready_cb,
1770                            ev_window);
1771         g_object_unref (target_file);
1772
1773         ev_window_show_progress_message (ev_window, 1,
1774                                          (GSourceFunc)show_loading_progress);
1775 }
1776
1777 void
1778 ev_window_open_uri (EvWindow       *ev_window,
1779                     const char     *uri,
1780                     EvLinkDest     *dest,
1781                     EvWindowRunMode mode,
1782                     const gchar    *search_string)
1783 {
1784         GFile *source_file;
1785
1786         ev_window->priv->in_reload = FALSE;
1787         
1788         if (ev_window->priv->uri &&
1789             g_ascii_strcasecmp (ev_window->priv->uri, uri) == 0) {
1790                 ev_window_reload_document (ev_window);
1791                 return;
1792         }
1793
1794         if (ev_window->priv->monitor) {
1795                 g_object_unref (ev_window->priv->monitor);
1796                 ev_window->priv->monitor = NULL;
1797         }
1798         
1799         ev_window_close_dialogs (ev_window);
1800         ev_window_clear_load_job (ev_window);
1801         ev_window_clear_local_uri (ev_window);
1802         ev_view_set_loading (EV_VIEW (ev_window->priv->view), TRUE);
1803
1804         ev_window->priv->window_mode = mode;
1805
1806         if (ev_window->priv->uri)
1807                 g_free (ev_window->priv->uri);
1808         ev_window->priv->uri = g_strdup (uri);
1809
1810         if (ev_window->priv->search_string)
1811                 g_free (ev_window->priv->search_string);
1812         ev_window->priv->search_string = search_string ?
1813                 g_strdup (search_string) : NULL;
1814
1815         if (ev_window->priv->dest)
1816                 g_object_unref (ev_window->priv->dest);
1817         ev_window->priv->dest = dest ? g_object_ref (dest) : NULL;
1818
1819         setup_size_from_metadata (ev_window);
1820
1821         ev_window->priv->load_job = ev_job_load_new (uri);
1822         g_signal_connect (ev_window->priv->load_job,
1823                           "finished",
1824                           G_CALLBACK (ev_window_load_job_cb),
1825                           ev_window);
1826
1827         source_file = g_file_new_for_uri (uri);
1828         if (!g_file_is_native (source_file) && !ev_window->priv->local_uri) {
1829                 ev_window_load_file_remote (ev_window, source_file);
1830         } else {
1831                 g_object_unref (source_file);
1832                 ev_job_scheduler_push_job (ev_window->priv->load_job, EV_JOB_PRIORITY_NONE);
1833         }
1834 }
1835
1836 static void
1837 ev_window_reload_local (EvWindow *ev_window)
1838 {
1839         const gchar *uri;
1840         
1841         uri = ev_window->priv->local_uri ? ev_window->priv->local_uri : ev_window->priv->uri;
1842         ev_window->priv->reload_job = ev_job_load_new (uri);
1843         g_signal_connect (ev_window->priv->reload_job, "finished",
1844                           G_CALLBACK (ev_window_reload_job_cb),
1845                           ev_window);
1846         ev_job_scheduler_push_job (ev_window->priv->reload_job, EV_JOB_PRIORITY_NONE);
1847 }
1848
1849 static gboolean 
1850 show_reloading_progress (EvWindow *ev_window)
1851 {
1852         GtkWidget *area;
1853         gchar     *text;
1854         
1855         if (ev_window->priv->message_area)
1856                 return FALSE;
1857         
1858         text = g_strdup_printf (_("Reloading document from %s"),
1859                                 ev_window->priv->uri);
1860         area = ev_progress_message_area_new (GTK_STOCK_REFRESH,
1861                                              text,
1862                                              GTK_STOCK_CLOSE,
1863                                              GTK_RESPONSE_CLOSE,
1864                                              GTK_STOCK_CANCEL,
1865                                              GTK_RESPONSE_CANCEL,
1866                                              NULL);
1867         g_signal_connect (area, "response",
1868                           G_CALLBACK (ev_window_progress_response_cb),
1869                           ev_window);
1870         gtk_widget_show (area);
1871         ev_window_set_message_area (ev_window, area);
1872         g_free (text);
1873
1874         return FALSE;
1875 }
1876
1877 static void
1878 reload_remote_copy_ready_cb (GFile        *remote,
1879                              GAsyncResult *async_result,
1880                              EvWindow     *ev_window)
1881 {
1882         GError *error = NULL;
1883         
1884         ev_window_clear_progress_idle (ev_window);
1885         
1886         g_file_copy_finish (remote, async_result, &error);
1887         if (error) {
1888                 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
1889                         ev_window_error_message (ev_window, error,
1890                                                  "%s", _("Failed to reload document."));
1891                 g_error_free (error);
1892         } else {
1893                 ev_window_reload_local (ev_window);
1894         }
1895                 
1896         g_object_unref (remote);
1897 }
1898
1899 static void
1900 reload_remote_copy_progress_cb (goffset   n_bytes,
1901                                 goffset   total_bytes,
1902                                 EvWindow *ev_window)
1903 {
1904         gchar *status;
1905         gdouble fraction;
1906         
1907         if (!ev_window->priv->message_area)
1908                 return;
1909         
1910         fraction = n_bytes / (gdouble)total_bytes;
1911         status = g_strdup_printf (_("Downloading document (%d%%)"),
1912                                   (gint)(fraction * 100));
1913         
1914         ev_progress_message_area_set_status (EV_PROGRESS_MESSAGE_AREA (ev_window->priv->message_area),
1915                                              status);
1916         ev_progress_message_area_set_fraction (EV_PROGRESS_MESSAGE_AREA (ev_window->priv->message_area),
1917                                                fraction);
1918
1919         g_free (status);
1920 }
1921
1922 static void
1923 query_remote_uri_mtime_cb (GFile        *remote,
1924                            GAsyncResult *async_result,
1925                            EvWindow     *ev_window)
1926 {
1927         GFileInfo *info;
1928         GTimeVal   mtime;
1929         GError    *error = NULL;
1930
1931         info = g_file_query_info_finish (remote, async_result, &error);
1932         if (error) {
1933                 g_error_free (error);
1934                 g_object_unref (remote);
1935                 ev_window_reload_local (ev_window);
1936
1937                 return;
1938         }
1939         
1940         g_file_info_get_modification_time (info, &mtime);
1941         if (ev_window->priv->uri_mtime != mtime.tv_sec) {
1942                 GFile *target_file;
1943                         
1944                 /* Remote file has changed */
1945                 ev_window->priv->uri_mtime = mtime.tv_sec;
1946
1947                 ev_window_reset_progress_cancellable (ev_window);
1948                 
1949                 target_file = g_file_new_for_uri (ev_window->priv->local_uri);
1950                 g_file_copy_async (remote, target_file,
1951                                    G_FILE_COPY_OVERWRITE,
1952                                    G_PRIORITY_DEFAULT,
1953                                    ev_window->priv->progress_cancellable,
1954                                    (GFileProgressCallback)reload_remote_copy_progress_cb,
1955                                    ev_window, 
1956                                    (GAsyncReadyCallback)reload_remote_copy_ready_cb,
1957                                    ev_window);
1958                 g_object_unref (target_file);
1959                 ev_window_show_progress_message (ev_window, 1,
1960                                                  (GSourceFunc)show_reloading_progress);
1961         } else {
1962                 g_object_unref (remote);
1963                 ev_window_reload_local (ev_window);
1964         }
1965         
1966         g_object_unref (info);
1967 }
1968
1969 static void
1970 ev_window_reload_remote (EvWindow *ev_window)
1971 {
1972         GFile *remote;
1973         
1974         remote = g_file_new_for_uri (ev_window->priv->uri);
1975         /* Reload the remote uri only if it has changed */
1976         g_file_query_info_async (remote,
1977                                  G_FILE_ATTRIBUTE_TIME_MODIFIED,
1978                                  0, G_PRIORITY_DEFAULT,
1979                                  NULL,
1980                                  (GAsyncReadyCallback)query_remote_uri_mtime_cb,
1981                                  ev_window);
1982 }
1983
1984 static void
1985 ev_window_reload_document (EvWindow *ev_window)
1986 {
1987         gint page;
1988
1989         
1990         ev_window_clear_reload_job (ev_window);
1991         ev_window->priv->in_reload = TRUE;
1992
1993         page = ev_page_cache_get_current_page (ev_window->priv->page_cache);
1994         
1995         if (ev_window->priv->dest)
1996                 g_object_unref (ev_window->priv->dest);
1997         /* FIXME: save the scroll position too (xyz dest) */
1998         ev_window->priv->dest = ev_link_dest_new_page (page);
1999
2000         if (ev_window->priv->local_uri) {
2001                 ev_window_reload_remote (ev_window);
2002         } else {
2003                 ev_window_reload_local (ev_window);
2004         }
2005 }
2006
2007 static void
2008 file_open_dialog_response_cb (GtkWidget *chooser,
2009                               gint       response_id,
2010                               EvWindow  *ev_window)
2011 {
2012         gchar *uri;
2013
2014         if (response_id == GTK_RESPONSE_OK) {
2015                 GSList *uris;
2016
2017                 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (chooser));
2018
2019                 ev_application_open_uri_list (EV_APP, uris,
2020                                               gtk_window_get_screen (GTK_WINDOW (ev_window)),
2021                                               GDK_CURRENT_TIME);
2022         
2023                 g_slist_foreach (uris, (GFunc)g_free, NULL);    
2024                 g_slist_free (uris);
2025         }
2026
2027         uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (chooser));
2028         ev_application_set_chooser_uri (EV_APP, uri);
2029         g_free (uri);
2030
2031         gtk_widget_destroy (chooser);
2032 }
2033
2034 static void
2035 ev_window_cmd_file_open (GtkAction *action, EvWindow *window)
2036 {
2037         GtkWidget *chooser;
2038
2039         chooser = gtk_file_chooser_dialog_new (_("Open Document"),
2040                                                GTK_WINDOW (window),
2041                                                GTK_FILE_CHOOSER_ACTION_OPEN,
2042                                                GTK_STOCK_CANCEL,
2043                                                GTK_RESPONSE_CANCEL,
2044                                                GTK_STOCK_OPEN, GTK_RESPONSE_OK,
2045                                                NULL);
2046
2047         ev_document_factory_add_filters (chooser, NULL);
2048         gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (chooser), TRUE);
2049         gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (chooser), FALSE);
2050         if (ev_application_get_chooser_uri (EV_APP) != NULL) {
2051                 gtk_file_chooser_set_uri (GTK_FILE_CHOOSER (chooser),
2052                                           ev_application_get_chooser_uri (EV_APP));
2053         } else if (window->priv->uri != NULL) {
2054                 gtk_file_chooser_set_uri (GTK_FILE_CHOOSER (chooser),
2055                                           window->priv->uri);
2056         } else {
2057                 const gchar *folder;
2058
2059                 folder = g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS);
2060                 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (chooser),
2061                                                      folder ? folder : g_get_home_dir ());
2062         }
2063         
2064         g_signal_connect (chooser, "response",
2065                           G_CALLBACK (file_open_dialog_response_cb),
2066                           window);
2067
2068         gtk_widget_show (chooser);
2069 }
2070
2071 static gchar *
2072 ev_window_create_tmp_symlink (const gchar *filename, GError **error)
2073 {
2074         gchar  *tmp_filename = NULL;
2075         gchar  *name;
2076         guint   i = 0;
2077         GError *link_error = NULL;
2078         GFile  *tmp_file = NULL;
2079
2080         name = g_path_get_basename (filename);
2081         
2082         do {
2083                 gchar *basename;
2084
2085                 if (tmp_filename)
2086                         g_free (tmp_filename);
2087                 if (tmp_file)
2088                         g_object_unref (tmp_file);
2089                 g_clear_error (&link_error);
2090
2091                 basename = g_strdup_printf ("%s-%d", name, i++);
2092                 tmp_filename = g_build_filename (ev_tmp_dir (),
2093                                                  basename, NULL);
2094                 
2095                 g_free (basename);
2096                 tmp_file = g_file_new_for_path (tmp_filename);
2097         } while (!g_file_make_symbolic_link (tmp_file, filename, NULL, &link_error) &&
2098                  g_error_matches (link_error, G_IO_ERROR, G_IO_ERROR_EXISTS));
2099         
2100         g_free (name);
2101         g_object_unref (tmp_file);
2102
2103         if (link_error) {
2104                 g_propagate_prefixed_error (error, 
2105                                             link_error,
2106                                             _("Couldn't create symlink “%s”: "),
2107                                             tmp_filename);
2108                 g_free (tmp_filename);
2109                 
2110                 return NULL;
2111         }
2112
2113         return tmp_filename;
2114 }
2115
2116 static void
2117 ev_window_cmd_file_open_copy_at_dest (EvWindow *window, EvLinkDest *dest)
2118 {
2119         GError      *error = NULL;
2120         gchar       *symlink_uri;
2121         gchar       *old_filename;
2122         gchar       *new_filename;
2123         const gchar *uri_unc;
2124
2125         uri_unc = g_object_get_data (G_OBJECT (window->priv->document),
2126                                      "uri-uncompressed");
2127         old_filename = g_filename_from_uri (uri_unc ? uri_unc : window->priv->uri,
2128                                             NULL, NULL);
2129         new_filename = ev_window_create_tmp_symlink (old_filename, &error);
2130
2131         if (error) {
2132                 ev_window_error_message (window, error, 
2133                                          "%s", _("Cannot open a copy."));
2134                 g_error_free (error);
2135                 g_free (old_filename);
2136                 g_free (new_filename);
2137
2138                 return;
2139         }
2140                 
2141         g_free (old_filename);
2142
2143         symlink_uri = g_filename_to_uri (new_filename, NULL, NULL);
2144         g_free (new_filename);
2145
2146         ev_application_open_uri_at_dest (EV_APP,
2147                                          symlink_uri,
2148                                          gtk_window_get_screen (GTK_WINDOW (window)),
2149                                          dest,
2150                                          0,
2151                                          NULL, 
2152                                          GDK_CURRENT_TIME);
2153         g_free (symlink_uri);
2154 }
2155
2156 static void
2157 ev_window_cmd_file_open_copy (GtkAction *action, EvWindow *window)
2158 {
2159         EvPageCache *page_cache;
2160         EvLinkDest  *dest;
2161         gint         current_page;
2162
2163         page_cache = ev_page_cache_get (window->priv->document);
2164         current_page = ev_page_cache_get_current_page (page_cache);
2165         
2166         dest = ev_link_dest_new_page (current_page);
2167         ev_window_cmd_file_open_copy_at_dest (window, dest);
2168         g_object_unref (dest);
2169 }
2170
2171 static void
2172 ev_window_cmd_recent_file_activate (GtkAction *action,
2173                                     EvWindow  *window)
2174 {
2175         GtkRecentInfo *info;
2176         const gchar   *uri;
2177
2178         info = g_object_get_data (G_OBJECT (action), "gtk-recent-info");
2179         g_assert (info != NULL);
2180         
2181         uri = gtk_recent_info_get_uri (info);
2182         
2183         ev_application_open_uri_at_dest (EV_APP, uri,
2184                                          gtk_window_get_screen (GTK_WINDOW (window)),
2185                                          NULL, 0, NULL, GDK_CURRENT_TIME);
2186 }
2187
2188 static void
2189 ev_window_open_recent_action_item_activated (EvOpenRecentAction *action,
2190                                              const gchar        *uri,
2191                                              EvWindow           *window)
2192 {
2193         ev_application_open_uri_at_dest (EV_APP, uri,
2194                                          gtk_window_get_screen (GTK_WINDOW (window)),
2195                                          NULL, 0, NULL, GDK_CURRENT_TIME);
2196 }
2197
2198 static void
2199 ev_window_add_recent (EvWindow *window, const char *filename)
2200 {
2201         gtk_recent_manager_add_item (window->priv->recent_manager, filename);
2202 }
2203
2204 static gint
2205 compare_recent_items (GtkRecentInfo *a, GtkRecentInfo *b)
2206 {
2207         gboolean     has_ev_a, has_ev_b;
2208         const gchar *evince = g_get_application_name ();
2209
2210         has_ev_a = gtk_recent_info_has_application (a, evince);
2211         has_ev_b = gtk_recent_info_has_application (b, evince);
2212         
2213         if (has_ev_a && has_ev_b) {
2214                 time_t time_a, time_b;
2215
2216                 time_a = gtk_recent_info_get_modified (a);
2217                 time_b = gtk_recent_info_get_modified (b);
2218
2219                 return (time_b - time_a);
2220         } else if (has_ev_a) {
2221                 return -1;
2222         } else if (has_ev_b) {
2223                 return 1;
2224         }
2225
2226         return 0;
2227 }
2228
2229 /*
2230  * Doubles underscore to avoid spurious menu accels.
2231  */
2232 static gchar * 
2233 ev_window_get_recent_file_label (gint index, const gchar *filename)
2234 {
2235         GString *str;
2236         gint length;
2237         const gchar *p;
2238         const gchar *end;
2239         gboolean is_rtl;
2240         
2241         is_rtl = (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL);
2242
2243         g_return_val_if_fail (filename != NULL, NULL);
2244         
2245         length = strlen (filename);
2246         str = g_string_sized_new (length + 10);
2247         g_string_printf (str, "%s_%d.  ", is_rtl ? "\xE2\x80\x8F" : "", index);
2248
2249         p = filename;
2250         end = filename + length;
2251  
2252         while (p != end) {
2253                 const gchar *next;
2254                 next = g_utf8_next_char (p);
2255  
2256                 switch (*p) {
2257                         case '_':
2258                                 g_string_append (str, "__");
2259                                 break;
2260                         default:
2261                                 g_string_append_len (str, p, next - p);
2262                                 break;
2263                 }
2264  
2265                 p = next;
2266         }
2267  
2268         return g_string_free (str, FALSE);
2269 }
2270
2271 static void
2272 ev_window_setup_recent (EvWindow *ev_window)
2273 {
2274         GList        *items, *l;
2275         guint         n_items = 0;
2276         const gchar  *evince = g_get_application_name ();
2277         static guint  i = 0;
2278
2279         if (ev_window->priv->recent_ui_id > 0) {
2280                 gtk_ui_manager_remove_ui (ev_window->priv->ui_manager,
2281                                           ev_window->priv->recent_ui_id);
2282                 gtk_ui_manager_ensure_update (ev_window->priv->ui_manager);
2283         }
2284         ev_window->priv->recent_ui_id = gtk_ui_manager_new_merge_id (ev_window->priv->ui_manager);
2285
2286         if (ev_window->priv->recent_action_group) {
2287                 gtk_ui_manager_remove_action_group (ev_window->priv->ui_manager,
2288                                                     ev_window->priv->recent_action_group);
2289                 g_object_unref (ev_window->priv->recent_action_group);
2290         }
2291         ev_window->priv->recent_action_group = gtk_action_group_new ("RecentFilesActions");
2292         gtk_ui_manager_insert_action_group (ev_window->priv->ui_manager,
2293                                             ev_window->priv->recent_action_group, 0);
2294
2295         items = gtk_recent_manager_get_items (ev_window->priv->recent_manager);
2296         items = g_list_sort (items, (GCompareFunc) compare_recent_items);
2297
2298         for (l = items; l && l->data; l = g_list_next (l)) {
2299                 GtkRecentInfo *info;
2300                 GtkAction     *action;
2301                 gchar         *action_name;
2302                 gchar         *label;
2303
2304                 info = (GtkRecentInfo *) l->data;
2305
2306                 if (!gtk_recent_info_has_application (info, evince) ||
2307                     (gtk_recent_info_is_local (info) && !gtk_recent_info_exists (info)))
2308                         continue;
2309
2310                 action_name = g_strdup_printf ("RecentFile%u", i++);
2311                 label = ev_window_get_recent_file_label (
2312                         n_items + 1, gtk_recent_info_get_display_name (info));
2313                 
2314                 action = g_object_new (GTK_TYPE_ACTION,
2315                                        "name", action_name,
2316                                        "label", label,
2317                                        NULL);
2318
2319                 g_object_set_data_full (G_OBJECT (action),
2320                                         "gtk-recent-info",
2321                                         gtk_recent_info_ref (info),
2322                                         (GDestroyNotify) gtk_recent_info_unref);
2323                 
2324                 g_signal_connect (action, "activate",
2325                                   G_CALLBACK (ev_window_cmd_recent_file_activate),
2326                                   (gpointer) ev_window);
2327
2328                 gtk_action_group_add_action (ev_window->priv->recent_action_group,
2329                                              action);
2330                 g_object_unref (action);
2331
2332                 gtk_ui_manager_add_ui (ev_window->priv->ui_manager,
2333                                        ev_window->priv->recent_ui_id,
2334                                        "/MainMenu/FileMenu/RecentFilesMenu",
2335                                        label,
2336                                        action_name,
2337                                        GTK_UI_MANAGER_MENUITEM,
2338                                        FALSE);
2339                 g_free (action_name);
2340                 g_free (label);
2341
2342                 if (++n_items == 5)
2343                         break;
2344         }
2345         
2346         g_list_foreach (items, (GFunc) gtk_recent_info_unref, NULL);
2347         g_list_free (items);
2348 }
2349
2350 static gboolean 
2351 show_saving_progress (GFile *dst)
2352 {
2353         EvWindow  *ev_window;
2354         GtkWidget *area;
2355         gchar     *text;
2356         gchar     *uri;
2357         EvSaveType save_type;
2358
2359         ev_window = EV_WINDOW (g_object_get_data (G_OBJECT (dst), "ev-window"));
2360         ev_window->priv->progress_idle = 0;
2361         
2362         if (ev_window->priv->message_area)
2363                 return FALSE;
2364
2365         save_type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dst), "save-type"));
2366         uri = g_file_get_uri (dst);
2367         switch (save_type) {
2368         case EV_SAVE_DOCUMENT:
2369                 text = g_strdup_printf (_("Saving document to %s"), uri);
2370                 break;
2371         case EV_SAVE_ATTACHMENT:
2372                 text = g_strdup_printf (_("Saving attachment to %s"), uri);
2373                 break;
2374         case EV_SAVE_IMAGE:
2375                 text = g_strdup_printf (_("Saving image to %s"), uri);
2376                 break;
2377         default:
2378                 g_assert_not_reached ();
2379         }
2380         g_free (uri);
2381         area = ev_progress_message_area_new (GTK_STOCK_SAVE,
2382                                              text,
2383                                              GTK_STOCK_CLOSE,
2384                                              GTK_RESPONSE_CLOSE,
2385                                              GTK_STOCK_CANCEL,
2386                                              GTK_RESPONSE_CANCEL,
2387                                              NULL);
2388         g_signal_connect (area, "response",
2389                           G_CALLBACK (ev_window_progress_response_cb),
2390                           ev_window);
2391         gtk_widget_show (area);
2392         ev_window_set_message_area (ev_window, area);
2393         g_free (text);
2394
2395         return FALSE;
2396 }
2397
2398 static void
2399 window_save_file_copy_ready_cb (GFile        *src,
2400                                 GAsyncResult *async_result,
2401                                 GFile        *dst)
2402 {
2403         EvWindow *ev_window;
2404         GError   *error = NULL;
2405
2406         ev_window = EV_WINDOW (g_object_get_data (G_OBJECT (dst), "ev-window"));
2407         ev_window_clear_progress_idle (ev_window);
2408         
2409         if (g_file_copy_finish (src, async_result, &error)) {
2410                 ev_tmp_file_unlink (src);
2411                 return;
2412         }
2413
2414         if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
2415                 gchar *name;
2416                 
2417                 name = g_file_get_basename (dst);
2418                 ev_window_error_message (ev_window, error,
2419                                          _("The file could not be saved as “%s”."),
2420                                          name);
2421                 g_free (name);
2422         }
2423         ev_tmp_file_unlink (src);
2424         g_error_free (error);
2425 }
2426
2427 static void
2428 window_save_file_copy_progress_cb (goffset n_bytes,
2429                                    goffset total_bytes,
2430                                    GFile  *dst)
2431 {
2432         EvWindow  *ev_window;
2433         EvSaveType save_type;
2434         gchar     *status;
2435         gdouble    fraction;
2436
2437         ev_window = EV_WINDOW (g_object_get_data (G_OBJECT (dst), "ev-window"));
2438         
2439         if (!ev_window->priv->message_area)
2440                 return;
2441         
2442         fraction = n_bytes / (gdouble)total_bytes;
2443         save_type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dst), "save-type"));
2444
2445         switch (save_type) {
2446         case EV_SAVE_DOCUMENT:
2447                 status = g_strdup_printf (_("Uploading document (%d%%)"),
2448                                           (gint)(fraction * 100));
2449                 break;
2450         case EV_SAVE_ATTACHMENT:
2451                 status = g_strdup_printf (_("Uploading attachment (%d%%)"),
2452                                           (gint)(fraction * 100));
2453                 break;
2454         case EV_SAVE_IMAGE:
2455                 status = g_strdup_printf (_("Uploading image (%d%%)"),
2456                                           (gint)(fraction * 100));
2457                 break;
2458         default:
2459                 g_assert_not_reached ();
2460         }
2461         
2462         ev_progress_message_area_set_status (EV_PROGRESS_MESSAGE_AREA (ev_window->priv->message_area),
2463                                              status);
2464         ev_progress_message_area_set_fraction (EV_PROGRESS_MESSAGE_AREA (ev_window->priv->message_area),
2465                                                fraction);
2466
2467         g_free (status);
2468 }
2469
2470 static void
2471 ev_window_save_remote (EvWindow  *ev_window,
2472                        EvSaveType save_type,
2473                        GFile     *src,
2474                        GFile     *dst)
2475 {
2476         ev_window_reset_progress_cancellable (ev_window);
2477         g_object_set_data (G_OBJECT (dst), "ev-window", ev_window);
2478         g_object_set_data (G_OBJECT (dst), "save-type", GINT_TO_POINTER (save_type));
2479         g_file_copy_async (src, dst,
2480                            G_FILE_COPY_OVERWRITE,
2481                            G_PRIORITY_DEFAULT,
2482                            ev_window->priv->progress_cancellable,
2483                            (GFileProgressCallback)window_save_file_copy_progress_cb,
2484                            dst,
2485                            (GAsyncReadyCallback)window_save_file_copy_ready_cb,
2486                            dst);
2487         ev_window->priv->progress_idle =
2488                 g_timeout_add_seconds_full (G_PRIORITY_DEFAULT,
2489                                             1,
2490                                             (GSourceFunc)show_saving_progress,
2491                                             dst,
2492                                             NULL);
2493 }
2494
2495 static void
2496 ev_window_clear_save_job (EvWindow *ev_window)
2497 {
2498         if (ev_window->priv->save_job != NULL) {
2499                 if (!ev_job_is_finished (ev_window->priv->save_job))
2500                         ev_job_cancel (ev_window->priv->save_job);
2501                 
2502                 g_signal_handlers_disconnect_by_func (ev_window->priv->save_job,
2503                                                       ev_window_save_job_cb,
2504                                                       ev_window);
2505                 g_object_unref (ev_window->priv->save_job);
2506                 ev_window->priv->save_job = NULL;
2507         }
2508 }
2509
2510 static void
2511 ev_window_save_job_cb (EvJob     *job,
2512                        EvWindow  *window)
2513 {
2514         if (ev_job_is_failed (job)) {
2515                 ev_window_error_message (window, job->error,
2516                                          _("The file could not be saved as “%s”."),
2517                                          EV_JOB_SAVE (job)->uri);
2518         }
2519
2520         ev_window_clear_save_job (window);
2521 }
2522
2523 static void
2524 file_save_dialog_response_cb (GtkWidget *fc,
2525                               gint       response_id,
2526                               EvWindow  *ev_window)
2527 {
2528         gchar *uri;
2529         
2530         if (response_id != GTK_RESPONSE_OK) {
2531                 gtk_widget_destroy (fc);
2532                 return;
2533         }
2534         
2535         uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (fc));
2536         /* FIXME: remote copy should be done here rather than in the save job, 
2537          * so that we can track progress and cancel the operation
2538          */
2539         
2540         ev_window_clear_save_job (ev_window);
2541         ev_window->priv->save_job = ev_job_save_new (ev_window->priv->document,
2542                                                      uri, ev_window->priv->uri);
2543         g_signal_connect (ev_window->priv->save_job, "finished",
2544                           G_CALLBACK (ev_window_save_job_cb),
2545                           ev_window);
2546         /* The priority doesn't matter for this job */
2547         ev_job_scheduler_push_job (ev_window->priv->save_job, EV_JOB_PRIORITY_NONE);
2548
2549         g_free (uri);
2550         gtk_widget_destroy (fc);
2551 }
2552
2553 static void
2554 ev_window_cmd_save_as (GtkAction *action, EvWindow *ev_window)
2555 {
2556         GtkWidget *fc;
2557         gchar *base_name;
2558         GFile *file;
2559         const gchar *folder;
2560
2561         fc = gtk_file_chooser_dialog_new (
2562                 _("Save a Copy"),
2563                 GTK_WINDOW (ev_window), GTK_FILE_CHOOSER_ACTION_SAVE,
2564                 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
2565                 GTK_STOCK_SAVE, GTK_RESPONSE_OK,
2566                 NULL);
2567
2568         ev_document_factory_add_filters (fc, ev_window->priv->document);
2569         gtk_dialog_set_default_response (GTK_DIALOG (fc), GTK_RESPONSE_OK);
2570         gtk_dialog_set_alternative_button_order (GTK_DIALOG (fc),
2571                                                 GTK_RESPONSE_OK,
2572                                                 GTK_RESPONSE_CANCEL,
2573                                                 -1);
2574
2575         gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (fc), FALSE);
2576         gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (fc), TRUE);
2577         file = g_file_new_for_uri (ev_window->priv->uri);
2578         base_name = g_file_get_basename (file);
2579         gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (fc), base_name);
2580         
2581         folder = g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS);
2582         gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (fc),
2583                                              folder ? folder : g_get_home_dir ());
2584         
2585         g_object_unref (file);
2586         g_free (base_name);
2587         
2588         g_signal_connect (fc, "response",
2589                           G_CALLBACK (file_save_dialog_response_cb),
2590                           ev_window);
2591
2592         gtk_widget_show (fc);
2593 }
2594
2595 static void
2596 ev_window_load_print_settings_from_metadata (EvWindow *window)
2597 {
2598         gchar *uri = window->priv->uri;
2599         gint   i;
2600         
2601         /* Load print setting that are specific to the document */
2602         for (i = 0; i < G_N_ELEMENTS (document_print_settings); i++) {
2603                 GValue   value = { 0, };
2604                 gboolean success;
2605
2606                 success = ev_metadata_manager_get (uri, document_print_settings[i], &value, TRUE);
2607                 gtk_print_settings_set (window->priv->print_settings,
2608                                         document_print_settings[i],
2609                                         success ? g_value_get_string (&value) : NULL);
2610                 if (success)
2611                         g_value_unset (&value);
2612         }
2613 }
2614
2615 static void
2616 ev_window_save_print_settings (EvWindow *window)
2617 {
2618         gchar *uri = window->priv->uri;
2619         gint   i;
2620         
2621         /* Save print settings that are specific to the document */
2622         for (i = 0; i < G_N_ELEMENTS (document_print_settings); i++) {
2623                 const gchar *value;
2624
2625                 value = gtk_print_settings_get (window->priv->print_settings,
2626                                                 document_print_settings[i]);
2627                 ev_metadata_manager_set_string (uri, document_print_settings[i], value);
2628         }
2629 }
2630
2631 static void
2632 ev_window_save_print_page_setup (EvWindow *window)
2633 {
2634         gchar        *uri = window->priv->uri;
2635         GtkPageSetup *page_setup = window->priv->print_page_setup;
2636
2637         /* Save page setup options that are specific to the document */
2638         ev_metadata_manager_set_int (uri, "page-setup-orientation",
2639                                      gtk_page_setup_get_orientation (page_setup));
2640         ev_metadata_manager_set_double (uri, "page-setup-margin-top",
2641                                         gtk_page_setup_get_top_margin (page_setup, GTK_UNIT_MM));
2642         ev_metadata_manager_set_double (uri, "page-setup-margin-bottom",
2643                                         gtk_page_setup_get_bottom_margin (page_setup, GTK_UNIT_MM));
2644         ev_metadata_manager_set_double (uri, "page-setup-margin-left",
2645                                         gtk_page_setup_get_left_margin (page_setup, GTK_UNIT_MM));
2646         ev_metadata_manager_set_double (uri, "page-setup-margin-right",
2647                                         gtk_page_setup_get_right_margin (page_setup, GTK_UNIT_MM));
2648 }
2649
2650 static void
2651 ev_window_load_print_page_setup_from_metadata (EvWindow *window)
2652 {
2653         gchar        *uri = window->priv->uri;
2654         GtkPageSetup *page_setup = window->priv->print_page_setup;
2655         GtkPaperSize *paper_size;
2656         GValue        value = { 0, };
2657
2658         paper_size = gtk_page_setup_get_paper_size (page_setup);
2659         
2660         /* Load page setup options that are specific to the document */
2661         if (ev_metadata_manager_get (uri, "page-setup-orientation", &value, TRUE)) {
2662                 gtk_page_setup_set_orientation (page_setup, g_value_get_int (&value));
2663                 g_value_unset (&value);
2664         } else {
2665                 gtk_page_setup_set_orientation (page_setup, GTK_PAGE_ORIENTATION_PORTRAIT);
2666         }
2667         
2668         if (ev_metadata_manager_get (uri, "page-setup-margin-top", &value, TRUE)) {
2669                 gtk_page_setup_set_top_margin (page_setup, g_value_get_double (&value), GTK_UNIT_MM);
2670                 g_value_unset (&value);
2671         } else {
2672                 gtk_page_setup_set_top_margin (page_setup,
2673                                                gtk_paper_size_get_default_top_margin (paper_size, GTK_UNIT_MM),
2674                                                GTK_UNIT_MM);
2675         }
2676
2677         if (ev_metadata_manager_get (uri, "page-setup-margin-bottom", &value, TRUE)) {
2678                 gtk_page_setup_set_bottom_margin (page_setup, g_value_get_double (&value), GTK_UNIT_MM);
2679                 g_value_unset (&value);
2680         } else {
2681                 gtk_page_setup_set_bottom_margin (page_setup,
2682                                                   gtk_paper_size_get_default_bottom_margin (paper_size, GTK_UNIT_MM),
2683                                                   GTK_UNIT_MM);
2684         }
2685
2686         if (ev_metadata_manager_get (uri, "page-setup-margin-left", &value, TRUE)) {
2687                 gtk_page_setup_set_left_margin (page_setup, g_value_get_double (&value), GTK_UNIT_MM);
2688                 g_value_unset (&value);
2689         } else {
2690                 gtk_page_setup_set_left_margin (page_setup,
2691                                                 gtk_paper_size_get_default_left_margin (paper_size, GTK_UNIT_MM),
2692                                                 GTK_UNIT_MM);
2693         }       
2694
2695         if (ev_metadata_manager_get (uri, "page-setup-margin-right", &value, TRUE)) {
2696                 gtk_page_setup_set_right_margin (page_setup, g_value_get_double (&value), GTK_UNIT_MM);
2697                 g_value_unset (&value);
2698         } else {
2699                 gtk_page_setup_set_right_margin (page_setup,
2700                                                  gtk_paper_size_get_default_right_margin (paper_size, GTK_UNIT_MM),
2701                                                  GTK_UNIT_MM);
2702         }       
2703 }
2704
2705 static void
2706 ev_window_print_page_setup_done_cb (GtkPageSetup *page_setup,
2707                                     EvWindow     *window)
2708 {
2709         /* Dialog was canceled */
2710         if (!page_setup)
2711                 return;
2712
2713         if (window->priv->print_page_setup != page_setup) {
2714                 if (window->priv->print_page_setup)
2715                         g_object_unref (window->priv->print_page_setup);
2716                 window->priv->print_page_setup = g_object_ref (page_setup);
2717         }
2718         
2719         ev_application_set_page_setup (EV_APP, page_setup);
2720         ev_window_save_print_page_setup (window);
2721 }
2722
2723 static void
2724 ev_window_cmd_file_print_setup (GtkAction *action, EvWindow *ev_window)
2725 {
2726         if (!ev_window->priv->print_page_setup) {
2727                 ev_window->priv->print_page_setup = gtk_page_setup_copy (
2728                         ev_application_get_page_setup (EV_APP));
2729                 ev_window_load_print_page_setup_from_metadata (ev_window);
2730         }
2731         
2732         gtk_print_run_page_setup_dialog_async (
2733                 GTK_WINDOW (ev_window),
2734                 ev_window->priv->print_page_setup,
2735                 ev_window->priv->print_settings,
2736                 (GtkPageSetupDoneFunc) ev_window_print_page_setup_done_cb,
2737                 ev_window);
2738 }
2739
2740 static void
2741 ev_window_print_cancel (EvWindow *ev_window)
2742 {
2743         EvPrintOperation *op;
2744         
2745         if (!ev_window->priv->print_queue)
2746                 return;
2747
2748         while ((op = g_queue_peek_tail (ev_window->priv->print_queue))) {
2749                 ev_print_operation_cancel (op);
2750         }
2751 }
2752
2753 static void
2754 ev_window_print_update_pending_jobs_message (EvWindow *ev_window,
2755                                              gint      n_jobs)
2756 {
2757         gchar *text = NULL;
2758         
2759         if (!EV_IS_PROGRESS_MESSAGE_AREA (ev_window->priv->message_area) ||
2760             !ev_window->priv->print_queue)
2761                 return;
2762
2763         if (n_jobs == 0) {
2764                 ev_window_set_message_area (ev_window, NULL);
2765                 return;
2766         }
2767         
2768         if (n_jobs > 1) {
2769                 text = g_strdup_printf (ngettext ("%d pending job in queue",
2770                                                   "%d pending jobs in queue",
2771                                                   n_jobs - 1), n_jobs - 1);
2772         }
2773
2774         ev_message_area_set_secondary_text (EV_MESSAGE_AREA (ev_window->priv->message_area),
2775                                             text);
2776         g_free (text);
2777 }
2778
2779 static gboolean
2780 destroy_window (GtkWidget *window)
2781 {
2782         gtk_widget_destroy (window);
2783         
2784         return FALSE;
2785 }
2786
2787 static void
2788 ev_window_print_operation_done (EvPrintOperation       *op,
2789                                 GtkPrintOperationResult result,
2790                                 EvWindow               *ev_window)
2791 {
2792         gint n_jobs;
2793         
2794         switch (result) {
2795         case GTK_PRINT_OPERATION_RESULT_APPLY: {
2796                 GtkPrintSettings *print_settings;
2797                 
2798                 print_settings = ev_print_operation_get_print_settings (op);
2799                 if (ev_window->priv->print_settings != print_settings) {
2800                         if (ev_window->priv->print_settings)
2801                                 g_object_unref (ev_window->priv->print_settings);
2802                         ev_window->priv->print_settings = g_object_ref (print_settings);
2803                 }
2804                 
2805                 ev_application_set_print_settings (EV_APP, print_settings);
2806                 ev_window_save_print_settings (ev_window);
2807         }
2808
2809                 break;
2810         case GTK_PRINT_OPERATION_RESULT_ERROR: {
2811                 GtkWidget *dialog;
2812                 GError    *error = NULL;
2813
2814
2815                 ev_print_operation_get_error (op, &error);
2816                 
2817                 /* The message area is already used by
2818                  * the printing progress, so it's better to
2819                  * use a popup dialog in this case
2820                  */
2821                 dialog = gtk_message_dialog_new (GTK_WINDOW (ev_window),
2822                                                  GTK_DIALOG_DESTROY_WITH_PARENT,
2823                                                  GTK_MESSAGE_ERROR,
2824                                                  GTK_BUTTONS_CLOSE,
2825                                                  "%s", _("Failed to print document"));
2826                 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
2827                                                           "%s", error->message);
2828                 g_signal_connect (dialog, "response",
2829                                   G_CALLBACK (gtk_widget_destroy),
2830                                   NULL);
2831                 gtk_widget_show (dialog);
2832                 
2833                 g_error_free (error);
2834         }
2835                 break;
2836         case GTK_PRINT_OPERATION_RESULT_CANCEL:
2837         default:
2838                 break;
2839         }
2840
2841         g_queue_remove (ev_window->priv->print_queue, op);
2842         g_object_unref (op);
2843         n_jobs = g_queue_get_length (ev_window->priv->print_queue);
2844         ev_window_print_update_pending_jobs_message (ev_window, n_jobs);
2845
2846         if (n_jobs == 0 && ev_window->priv->close_after_print)
2847                 g_idle_add ((GSourceFunc)destroy_window,
2848                             ev_window);
2849 }
2850
2851 static void
2852 ev_window_print_progress_response_cb (EvProgressMessageArea *area,
2853                                       gint                   response,
2854                                       EvWindow              *ev_window)
2855 {
2856         if (response == GTK_RESPONSE_CANCEL) {
2857                 EvPrintOperation *op;
2858
2859                 op = g_queue_peek_tail (ev_window->priv->print_queue);
2860                 ev_print_operation_cancel (op);
2861         } else {
2862                 gtk_widget_hide (GTK_WIDGET (area));
2863         }
2864 }
2865
2866 static void
2867 ev_window_print_operation_status_changed (EvPrintOperation *op,
2868                                           EvWindow         *ev_window)
2869 {
2870         const gchar *status;
2871         gdouble      fraction;
2872
2873         status = ev_print_operation_get_status (op);
2874         fraction = ev_print_operation_get_progress (op);
2875         
2876         if (!ev_window->priv->message_area) {
2877                 GtkWidget   *area;
2878                 const gchar *job_name;
2879                 gchar       *text;
2880
2881                 job_name = ev_print_operation_get_job_name (op);
2882                 text = g_strdup_printf (_("Printing job “%s”"), job_name);
2883
2884                 area = ev_progress_message_area_new (GTK_STOCK_PRINT,
2885                                                      text,
2886                                                      GTK_STOCK_CLOSE,
2887                                                      GTK_RESPONSE_CLOSE,
2888                                                      GTK_STOCK_CANCEL,
2889                                                      GTK_RESPONSE_CANCEL,
2890                                                      NULL);
2891                 ev_window_print_update_pending_jobs_message (ev_window, 1);
2892                 g_signal_connect (area, "response",
2893                                   G_CALLBACK (ev_window_print_progress_response_cb),
2894                                   ev_window);
2895                 gtk_widget_show (area);
2896                 ev_window_set_message_area (ev_window, area);
2897                 g_free (text);
2898         }
2899
2900         ev_progress_message_area_set_status (EV_PROGRESS_MESSAGE_AREA (ev_window->priv->message_area),
2901                                              status);
2902         ev_progress_message_area_set_fraction (EV_PROGRESS_MESSAGE_AREA (ev_window->priv->message_area),
2903                                                fraction);
2904 }
2905
2906 static void
2907 ev_window_print_operation_begin_print (EvPrintOperation *op,
2908                                        EvWindow         *ev_window)
2909 {
2910         GtkPrintSettings *print_settings;
2911         
2912         if (!ev_window->priv->print_queue)
2913                 ev_window->priv->print_queue = g_queue_new ();
2914
2915         g_queue_push_head (ev_window->priv->print_queue, op);
2916         ev_window_print_update_pending_jobs_message (ev_window,
2917                                                      g_queue_get_length (ev_window->priv->print_queue));
2918         
2919         if (ev_window->priv->print_settings)
2920                 g_object_unref (ev_window->priv->print_settings);
2921         print_settings = ev_print_operation_get_print_settings (op);
2922         ev_window->priv->print_settings = g_object_ref (print_settings);
2923 }
2924
2925 void
2926 ev_window_print_range (EvWindow *ev_window,
2927                        gint      first_page,
2928                        gint      last_page)
2929 {
2930         EvPrintOperation *op;
2931         EvPageCache      *page_cache;
2932         gint              current_page;
2933         gint              document_last_page;
2934
2935         g_return_if_fail (EV_IS_WINDOW (ev_window));
2936         g_return_if_fail (ev_window->priv->document != NULL);
2937
2938         if (!ev_window->priv->print_queue)
2939                 ev_window->priv->print_queue = g_queue_new ();
2940
2941         op = ev_print_operation_new (ev_window->priv->document);
2942         g_signal_connect (op, "begin_print",
2943                           G_CALLBACK (ev_window_print_operation_begin_print),
2944                           (gpointer)ev_window);
2945         g_signal_connect (op, "status_changed",
2946                           G_CALLBACK (ev_window_print_operation_status_changed),
2947                           (gpointer)ev_window);
2948         g_signal_connect (op, "done",
2949                           G_CALLBACK (ev_window_print_operation_done),
2950                           (gpointer)ev_window);
2951
2952         page_cache = ev_page_cache_get (ev_window->priv->document);
2953         current_page = ev_page_cache_get_current_page (page_cache);
2954         document_last_page = ev_page_cache_get_n_pages (page_cache);
2955
2956         if (!ev_window->priv->print_settings) {
2957                 ev_window->priv->print_settings = gtk_print_settings_copy (
2958                         ev_application_get_print_settings (EV_APP));
2959                 ev_window_load_print_settings_from_metadata (ev_window);
2960         }
2961
2962         if (first_page != 1 || last_page != document_last_page) {
2963                 GtkPageRange range;
2964
2965                 /* Ranges in GtkPrint are 0 - N */
2966                 range.start = first_page - 1;
2967                 range.end = last_page - 1;
2968                 
2969                 gtk_print_settings_set_print_pages (ev_window->priv->print_settings,
2970                                                     GTK_PRINT_PAGES_RANGES);
2971                 gtk_print_settings_set_page_ranges (ev_window->priv->print_settings,
2972                                                     &range, 1);
2973         }
2974
2975         ev_print_operation_set_job_name (op, gtk_window_get_title (GTK_WINDOW (ev_window)));
2976         ev_print_operation_set_current_page (op, current_page);
2977         ev_print_operation_set_print_settings (op, ev_window->priv->print_settings);
2978         if (ev_window->priv->print_page_setup)
2979                 ev_print_operation_set_default_page_setup (op, ev_window->priv->print_page_setup);
2980
2981         ev_print_operation_run (op, GTK_WINDOW (ev_window));
2982 }
2983
2984 static void
2985 ev_window_print (EvWindow *window)
2986 {
2987         EvPageCache *page_cache;
2988         gint         last_page;
2989
2990         page_cache = ev_page_cache_get (window->priv->document);
2991         last_page = ev_page_cache_get_n_pages (page_cache);
2992
2993         ev_window_print_range (window, 1, last_page);
2994 }
2995
2996 static void
2997 ev_window_cmd_file_print (GtkAction *action, EvWindow *ev_window)
2998 {
2999         ev_window_print (ev_window);
3000 }
3001
3002 static void
3003 ev_window_cmd_file_properties (GtkAction *action, EvWindow *ev_window)
3004 {
3005         if (ev_window->priv->properties == NULL) {
3006                 ev_window->priv->properties = ev_properties_dialog_new ();
3007                 ev_properties_dialog_set_document (EV_PROPERTIES_DIALOG (ev_window->priv->properties),
3008                                                    ev_window->priv->uri,
3009                                                    ev_window->priv->document);
3010                 g_object_add_weak_pointer (G_OBJECT (ev_window->priv->properties),
3011                                            (gpointer) &(ev_window->priv->properties));
3012                 gtk_window_set_transient_for (GTK_WINDOW (ev_window->priv->properties),
3013                                               GTK_WINDOW (ev_window));
3014         }
3015
3016         ev_document_fc_mutex_lock ();
3017         gtk_widget_show (ev_window->priv->properties);
3018         ev_document_fc_mutex_unlock ();
3019 }
3020
3021 static void
3022 print_jobs_confirmation_dialog_response (GtkDialog *dialog,
3023                                          gint       response,
3024                                          EvWindow  *ev_window)
3025 {
3026         gtk_widget_destroy (GTK_WIDGET (dialog));       
3027         
3028         switch (response) {
3029         case GTK_RESPONSE_YES:
3030                 if (!ev_window->priv->print_queue ||
3031                     g_queue_is_empty (ev_window->priv->print_queue))
3032                         gtk_widget_destroy (GTK_WIDGET (ev_window));
3033                 else
3034                         ev_window->priv->close_after_print = TRUE;
3035                 break;
3036         case GTK_RESPONSE_NO:
3037                 ev_window->priv->close_after_print = TRUE;
3038                 if (ev_window->priv->print_queue &&
3039                     !g_queue_is_empty (ev_window->priv->print_queue)) {
3040                         gtk_widget_set_sensitive (GTK_WIDGET (ev_window), FALSE);
3041                         ev_window_print_cancel (ev_window);
3042                 } else {
3043                         gtk_widget_destroy (GTK_WIDGET (ev_window));
3044                 }
3045                 break;
3046         case GTK_RESPONSE_CANCEL:
3047         default:
3048                 ev_window->priv->close_after_print = FALSE;
3049         }
3050 }
3051
3052 static void
3053 ev_window_cmd_file_close_window (GtkAction *action, EvWindow *ev_window)
3054 {
3055         GtkWidget *dialog;
3056         gchar     *text, *markup;
3057         gint       n_print_jobs;
3058
3059         n_print_jobs = ev_window->priv->print_queue ?
3060                 g_queue_get_length (ev_window->priv->print_queue) : 0;
3061         
3062         if (n_print_jobs == 0) {
3063                 gtk_widget_destroy (GTK_WIDGET (ev_window));
3064                 return;
3065         }
3066
3067         dialog = gtk_message_dialog_new (GTK_WINDOW (ev_window),
3068                                          GTK_DIALOG_MODAL,
3069                                          GTK_MESSAGE_QUESTION,
3070                                          GTK_BUTTONS_NONE,
3071                                          NULL);
3072         if (n_print_jobs == 1) {
3073                 EvPrintOperation *op;
3074                 const gchar      *job_name;
3075
3076                 op = g_queue_peek_tail (ev_window->priv->print_queue);
3077                 job_name = ev_print_operation_get_job_name (op);
3078
3079                 text = g_strdup_printf (_("Wait until print job “%s” finishes before closing?"),
3080                                         job_name);
3081         } else {
3082                 text = g_strdup_printf (_("There are %d print jobs active. "
3083                                           "Wait until print finishes before closing?"),
3084                                         n_print_jobs);
3085         }
3086
3087         markup = g_strdup_printf ("<b>%s</b>", text);
3088         g_free (text);
3089
3090         gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog), markup);
3091         g_free (markup);
3092
3093         gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s",
3094                                                   _("If you close the window, pending print "
3095                                                     "jobs will not be printed."));
3096         
3097         gtk_dialog_add_buttons (GTK_DIALOG (dialog),
3098                                 _("Cancel _print and Close"),
3099                                 GTK_RESPONSE_NO,
3100                                 GTK_STOCK_CANCEL,
3101                                 GTK_RESPONSE_CANCEL,
3102                                 _("Close _after Printing"),
3103                                 GTK_RESPONSE_YES,
3104                                 NULL);
3105         gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_YES);
3106         gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
3107                                                  GTK_RESPONSE_YES,
3108                                                  GTK_RESPONSE_NO,
3109                                                  GTK_RESPONSE_CANCEL,
3110                                                  -1);
3111
3112         g_signal_connect (dialog, "response",
3113                           G_CALLBACK (print_jobs_confirmation_dialog_response),
3114                           ev_window);
3115         gtk_widget_show (dialog);
3116 }
3117
3118 static void
3119 ev_window_cmd_focus_page_selector (GtkAction *act, EvWindow *window)
3120 {
3121         GtkAction *action;
3122         
3123         update_chrome_flag (window, EV_CHROME_RAISE_TOOLBAR, TRUE);
3124         ev_window_set_action_sensitive (window, "ViewToolbar", FALSE);
3125         update_chrome_visibility (window);
3126         
3127         action = gtk_action_group_get_action (window->priv->action_group,
3128                                               PAGE_SELECTOR_ACTION);
3129         ev_page_action_grab_focus (EV_PAGE_ACTION (action));
3130 }
3131
3132 static void
3133 ev_window_cmd_scroll_forward (GtkAction *action, EvWindow *window)
3134 {
3135         ev_view_scroll (EV_VIEW (window->priv->view), GTK_SCROLL_PAGE_FORWARD, FALSE);
3136 }
3137
3138 static void
3139 ev_window_cmd_scroll_backward (GtkAction *action, EvWindow *window)
3140 {
3141         ev_view_scroll (EV_VIEW (window->priv->view), GTK_SCROLL_PAGE_BACKWARD, FALSE);
3142 }
3143
3144 static void
3145 ev_window_cmd_continuous (GtkAction *action, EvWindow *ev_window)
3146 {
3147         gboolean continuous;
3148
3149         ev_window_stop_presentation (ev_window, TRUE);
3150         continuous = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
3151         g_object_set (G_OBJECT (ev_window->priv->view),
3152                       "continuous", continuous,
3153                       NULL);
3154         ev_window_update_actions (ev_window);
3155 }
3156
3157 static void
3158 ev_window_cmd_dual (GtkAction *action, EvWindow *ev_window)
3159 {
3160         gboolean dual_page;
3161
3162         ev_window_stop_presentation (ev_window, TRUE);
3163         dual_page = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
3164         g_object_set (G_OBJECT (ev_window->priv->view),
3165                       "dual-page", dual_page,
3166                       NULL);
3167         ev_window_update_actions (ev_window);
3168 }
3169
3170 static void
3171 ev_window_cmd_view_best_fit (GtkAction *action, EvWindow *ev_window)
3172 {
3173         ev_window_stop_presentation (ev_window, TRUE);
3174
3175         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
3176                 ev_view_set_sizing_mode (EV_VIEW (ev_window->priv->view), EV_SIZING_BEST_FIT);
3177         } else {
3178                 ev_view_set_sizing_mode (EV_VIEW (ev_window->priv->view), EV_SIZING_FREE);
3179         }
3180         ev_window_update_actions (ev_window);
3181 }
3182
3183 static void
3184 ev_window_cmd_view_page_width (GtkAction *action, EvWindow *ev_window)
3185 {
3186         ev_window_stop_presentation (ev_window, TRUE);
3187
3188         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
3189                 ev_view_set_sizing_mode (EV_VIEW (ev_window->priv->view), EV_SIZING_FIT_WIDTH);
3190         } else {
3191                 ev_view_set_sizing_mode (EV_VIEW (ev_window->priv->view), EV_SIZING_FREE);
3192         }
3193         ev_window_update_actions (ev_window);
3194 }
3195
3196
3197 static void
3198 ev_window_cmd_edit_select_all (GtkAction *action, EvWindow *ev_window)
3199 {
3200         g_return_if_fail (EV_IS_WINDOW (ev_window));
3201
3202         ev_view_select_all (EV_VIEW (ev_window->priv->view));
3203 }
3204
3205 static void
3206 ev_window_cmd_edit_find (GtkAction *action, EvWindow *ev_window)
3207 {
3208         g_return_if_fail (EV_IS_WINDOW (ev_window));
3209
3210         if (ev_window->priv->document == NULL || !EV_IS_DOCUMENT_FIND (ev_window->priv->document)) {
3211                 g_error ("Find action should be insensitive since document doesn't support find");
3212                 return;
3213         } 
3214
3215         update_chrome_flag (ev_window, EV_CHROME_FINDBAR, TRUE);
3216         update_chrome_visibility (ev_window);
3217         gtk_widget_grab_focus (ev_window->priv->find_bar);
3218 }
3219
3220 static void
3221 ev_window_cmd_edit_find_next (GtkAction *action, EvWindow *ev_window)
3222 {
3223         g_return_if_fail (EV_IS_WINDOW (ev_window));
3224
3225         update_chrome_flag (ev_window, EV_CHROME_FINDBAR, TRUE);
3226         update_chrome_visibility (ev_window);
3227         gtk_widget_grab_focus (ev_window->priv->find_bar);
3228         ev_view_find_next (EV_VIEW (ev_window->priv->view));
3229 }
3230
3231 static void
3232 ev_window_cmd_edit_find_previous (GtkAction *action, EvWindow *ev_window)
3233 {
3234         g_return_if_fail (EV_IS_WINDOW (ev_window));
3235
3236         update_chrome_flag (ev_window, EV_CHROME_FINDBAR, TRUE);
3237         update_chrome_visibility (ev_window);
3238         gtk_widget_grab_focus (ev_window->priv->find_bar);
3239         ev_view_find_previous (EV_VIEW (ev_window->priv->view));
3240 }
3241
3242 static void
3243 ev_window_cmd_edit_copy (GtkAction *action, EvWindow *ev_window)
3244 {
3245         g_return_if_fail (EV_IS_WINDOW (ev_window));
3246
3247         ev_view_copy (EV_VIEW (ev_window->priv->view));
3248 }
3249
3250 static void
3251 ev_window_sidebar_position_change_cb (GObject *object, GParamSpec *pspec,
3252                                       EvWindow *ev_window)
3253 {
3254         if (!ev_window_is_empty (ev_window))
3255                 ev_metadata_manager_set_int (ev_window->priv->uri, "sidebar_size",
3256                                              gtk_paned_get_position (GTK_PANED (object)));
3257 }
3258
3259 static void
3260 ev_window_update_fullscreen_action (EvWindow *window)
3261 {
3262         GtkAction *action;
3263
3264         action = gtk_action_group_get_action (window->priv->action_group, "ViewFullscreen");
3265         g_signal_handlers_block_by_func
3266                 (action, G_CALLBACK (ev_window_cmd_view_fullscreen), window);
3267         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
3268                                       ev_view_get_fullscreen (EV_VIEW (window->priv->view)));
3269         g_signal_handlers_unblock_by_func
3270                 (action, G_CALLBACK (ev_window_cmd_view_fullscreen), window);
3271 }
3272
3273 static void
3274 fullscreen_toolbar_setup_item_properties (GtkUIManager *ui_manager)
3275 {
3276         GtkWidget *item;
3277
3278         item = gtk_ui_manager_get_widget (ui_manager, "/FullscreenToolbar/GoPreviousPage");
3279         g_object_set (item, "is-important", FALSE, NULL);
3280
3281         item = gtk_ui_manager_get_widget (ui_manager, "/FullscreenToolbar/GoNextPage");
3282         g_object_set (item, "is-important", FALSE, NULL);
3283
3284         item = gtk_ui_manager_get_widget (ui_manager, "/FullscreenToolbar/StartPresentation");
3285         g_object_set (item, "is-important", TRUE, NULL);
3286         
3287         item = gtk_ui_manager_get_widget (ui_manager, "/FullscreenToolbar/LeaveFullscreen");
3288         g_object_set (item, "is-important", TRUE, NULL);
3289 }
3290
3291 static void
3292 fullscreen_toolbar_remove_shadow (GtkWidget *toolbar)
3293 {
3294         static gboolean done = FALSE;
3295
3296         if (!done) {
3297                 gtk_rc_parse_string (
3298                         "\n"
3299                         "   style \"fullscreen-toolbar-style\"\n"
3300                         "   {\n"
3301                         "      GtkToolbar::shadow-type=GTK_SHADOW_NONE\n"
3302                         "   }\n"
3303                         "\n"
3304                         "    widget \"*.fullscreen-toolbar\" style \"fullscreen-toolbar-style\"\n"
3305                         "\n");
3306                 done = TRUE;
3307         }
3308         
3309         gtk_widget_set_name (toolbar, "fullscreen-toolbar");
3310 }
3311
3312 static void
3313 ev_window_run_fullscreen (EvWindow *window)
3314 {
3315         EvView  *view = EV_VIEW (window->priv->view);
3316         gboolean fullscreen_window = TRUE;
3317
3318         if (ev_view_get_fullscreen (view))
3319                 return;
3320         
3321         if (!window->priv->fullscreen_toolbar) {
3322                 window->priv->fullscreen_toolbar =
3323                         gtk_ui_manager_get_widget (window->priv->ui_manager,
3324                                                    "/FullscreenToolbar");
3325
3326                 gtk_toolbar_set_style (GTK_TOOLBAR (window->priv->fullscreen_toolbar),
3327                                        GTK_TOOLBAR_BOTH_HORIZ);
3328                 fullscreen_toolbar_remove_shadow (window->priv->fullscreen_toolbar);
3329                 fullscreen_toolbar_setup_item_properties (window->priv->ui_manager);
3330
3331                 gtk_box_pack_start (GTK_BOX (window->priv->main_box),
3332                                     window->priv->fullscreen_toolbar,
3333                                     FALSE, FALSE, 0);
3334                 gtk_box_reorder_child (GTK_BOX (window->priv->main_box),
3335                                        window->priv->fullscreen_toolbar, 1);
3336         }
3337
3338         if (ev_view_get_presentation (view)) {
3339                 ev_window_stop_presentation (window, FALSE);
3340                 fullscreen_window = FALSE;
3341         }
3342
3343         g_object_set (G_OBJECT (window->priv->scrolled_window),
3344                       "shadow-type", GTK_SHADOW_NONE,
3345                       NULL);
3346
3347         ev_view_set_fullscreen (view, TRUE);
3348         ev_window_update_fullscreen_action (window);
3349
3350         /* If the user doesn't have the main toolbar he/she won't probably want
3351          * the toolbar in fullscreen mode. See bug #483048
3352          */
3353         update_chrome_flag (window, EV_CHROME_FULLSCREEN_TOOLBAR,
3354                             (window->priv->chrome & EV_CHROME_TOOLBAR) != 0);
3355         update_chrome_visibility (window);
3356
3357         if (fullscreen_window)
3358                 gtk_window_fullscreen (GTK_WINDOW (window));
3359         gtk_widget_grab_focus (window->priv->view);
3360
3361         if (!ev_window_is_empty (window))
3362                 ev_metadata_manager_set_boolean (window->priv->uri, "fullscreen", TRUE);
3363 }
3364
3365 static void
3366 ev_window_stop_fullscreen (EvWindow *window,
3367                            gboolean  unfullscreen_window)
3368 {
3369         EvView *view = EV_VIEW (window->priv->view);
3370
3371         if (!ev_view_get_fullscreen (view))
3372                 return;
3373
3374         g_object_set (G_OBJECT (window->priv->scrolled_window),
3375                       "shadow-type", GTK_SHADOW_IN,
3376                       NULL);
3377
3378         ev_view_set_fullscreen (view, FALSE);
3379         ev_window_update_fullscreen_action (window);
3380         update_chrome_flag (window, EV_CHROME_FULLSCREEN_TOOLBAR, FALSE);
3381         update_chrome_visibility (window);
3382         if (unfullscreen_window)
3383                 gtk_window_unfullscreen (GTK_WINDOW (window));
3384
3385         if (!ev_window_is_empty (window))
3386                 ev_metadata_manager_set_boolean (window->priv->uri, "fullscreen", FALSE);
3387 }
3388
3389 static void
3390 ev_window_cmd_view_fullscreen (GtkAction *action, EvWindow *window)
3391 {
3392         gboolean fullscreen;
3393
3394         fullscreen = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
3395         if (fullscreen) {
3396                 ev_window_run_fullscreen (window);
3397         } else {
3398                 ev_window_stop_fullscreen (window, TRUE);
3399         }
3400 }
3401
3402 static gboolean
3403 presentation_timeout_cb (EvWindow *window)
3404 {
3405         EvView *view = EV_VIEW (window->priv->view);
3406
3407         if (!view || !ev_view_get_presentation (EV_VIEW (view)))
3408                 return FALSE;
3409
3410         ev_view_hide_cursor (EV_VIEW (window->priv->view));
3411         window->priv->presentation_timeout_id = 0;
3412
3413         return FALSE;
3414 }
3415
3416 static void
3417 presentation_set_timeout (EvWindow *window)
3418 {
3419         if (window->priv->presentation_timeout_id > 0) {
3420                 g_source_remove (window->priv->presentation_timeout_id);
3421         }
3422
3423         window->priv->presentation_timeout_id =
3424                 g_timeout_add_seconds (PRESENTATION_TIMEOUT,
3425                                        (GSourceFunc)presentation_timeout_cb, window);
3426
3427         ev_view_show_cursor (EV_VIEW (window->priv->view));
3428 }
3429
3430 static void
3431 presentation_clear_timeout (EvWindow *window)
3432 {
3433         if (window->priv->presentation_timeout_id > 0) {
3434                 g_source_remove (window->priv->presentation_timeout_id);
3435         }
3436         
3437         window->priv->presentation_timeout_id = 0;
3438
3439         ev_view_show_cursor (EV_VIEW (window->priv->view));
3440 }
3441
3442 static gboolean
3443 presentation_motion_notify_cb (GtkWidget *widget,
3444                                GdkEventMotion *event,
3445                                gpointer user_data)
3446 {
3447         EvWindow *window = EV_WINDOW (user_data);
3448
3449         presentation_set_timeout (window);
3450
3451         return FALSE;
3452 }
3453
3454 static gboolean
3455 presentation_leave_notify_cb (GtkWidget *widget,
3456                               GdkEventCrossing *event,
3457                               gpointer user_data)
3458 {
3459         EvWindow *window = EV_WINDOW (user_data);
3460
3461         presentation_clear_timeout (window);
3462
3463         return FALSE;
3464 }
3465
3466 static void
3467 ev_window_update_presentation_action (EvWindow *window)
3468 {
3469         GtkAction *action;
3470
3471         action = gtk_action_group_get_action (window->priv->action_group, "ViewPresentation");
3472         g_signal_handlers_block_by_func
3473                 (action, G_CALLBACK (ev_window_cmd_view_presentation), window);
3474         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
3475                                       ev_view_get_presentation (EV_VIEW (window->priv->view)));
3476         g_signal_handlers_unblock_by_func
3477                 (action, G_CALLBACK (ev_window_cmd_view_presentation), window);
3478 }
3479
3480 static void
3481 ev_window_run_presentation (EvWindow *window)
3482 {
3483         EvView  *view = EV_VIEW (window->priv->view);
3484         gboolean fullscreen_window = TRUE;
3485
3486         if (ev_view_get_presentation (view))
3487                 return;
3488
3489         if (ev_view_get_fullscreen (view)) {
3490                 ev_window_stop_fullscreen (window, FALSE);
3491                 fullscreen_window = FALSE;
3492         }
3493         
3494         g_object_set (G_OBJECT (window->priv->scrolled_window),
3495                       "shadow-type", GTK_SHADOW_NONE,
3496                       NULL);
3497
3498         ev_view_set_presentation (view, TRUE);
3499         ev_window_update_presentation_action (window);
3500
3501         update_chrome_visibility (window);
3502         
3503         gtk_widget_grab_focus (window->priv->view);
3504         if (fullscreen_window)
3505                 gtk_window_fullscreen (GTK_WINDOW (window));
3506
3507         g_signal_connect (window->priv->view,
3508                           "motion-notify-event",
3509                           G_CALLBACK (presentation_motion_notify_cb),
3510                           window);
3511         g_signal_connect (window->priv->view,
3512                           "leave-notify-event",
3513                           G_CALLBACK (presentation_leave_notify_cb),
3514                           window);
3515         presentation_set_timeout (window);
3516
3517         ev_application_screensaver_disable (EV_APP);
3518         
3519         if (!ev_window_is_empty (window))
3520                 ev_metadata_manager_set_boolean (window->priv->uri, "presentation", TRUE);
3521 }
3522
3523 static void
3524 ev_window_stop_presentation (EvWindow *window,
3525                              gboolean  unfullscreen_window)
3526 {
3527         EvView *view = EV_VIEW (window->priv->view);
3528         
3529         if (!ev_view_get_presentation (view))
3530                 return;
3531
3532         g_object_set (G_OBJECT (window->priv->scrolled_window),
3533                       "shadow-type", GTK_SHADOW_IN,
3534                       NULL);
3535
3536         ev_view_set_presentation (EV_VIEW (window->priv->view), FALSE);
3537         ev_window_update_presentation_action (window);
3538         update_chrome_visibility (window);
3539         if (unfullscreen_window)
3540                 gtk_window_unfullscreen (GTK_WINDOW (window));
3541
3542         g_signal_handlers_disconnect_by_func (window->priv->view,
3543                                               (gpointer) presentation_motion_notify_cb,
3544                                               window);
3545         g_signal_handlers_disconnect_by_func (window->priv->view,
3546                                               (gpointer) presentation_leave_notify_cb,
3547                                               window);
3548         presentation_clear_timeout (window);
3549
3550         ev_application_screensaver_enable (EV_APP);
3551
3552         if (!ev_window_is_empty (window))
3553                 ev_metadata_manager_set_boolean (window->priv->uri, "presentation", FALSE);
3554 }
3555
3556 static void
3557 ev_window_cmd_view_presentation (GtkAction *action, EvWindow *window)
3558 {
3559         gboolean presentation;
3560
3561         presentation = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
3562         if (presentation) {
3563                 ev_window_run_presentation (window);
3564         }
3565 }
3566
3567 static void
3568 ev_window_screen_changed (GtkWidget *widget,
3569                           GdkScreen *old_screen)
3570 {
3571         EvWindow *window = EV_WINDOW (widget);
3572         EvWindowPrivate *priv = window->priv;
3573         GdkScreen *screen;
3574
3575         screen = gtk_widget_get_screen (widget);
3576         if (screen == old_screen)
3577                 return;
3578
3579         ev_view_set_screen_dpi (EV_VIEW (priv->view),
3580                                 get_screen_dpi (GTK_WINDOW (window)));
3581         
3582         if (GTK_WIDGET_CLASS (ev_window_parent_class)->screen_changed) {
3583                 GTK_WIDGET_CLASS (ev_window_parent_class)->screen_changed (widget, old_screen);
3584         }
3585 }
3586
3587 static gboolean
3588 ev_window_state_event (GtkWidget           *widget,
3589                        GdkEventWindowState *event)
3590 {
3591         EvWindow *window = EV_WINDOW (widget);
3592         EvView   *view = EV_VIEW (window->priv->view);
3593
3594         if (GTK_WIDGET_CLASS (ev_window_parent_class)->window_state_event) {
3595                 GTK_WIDGET_CLASS (ev_window_parent_class)->window_state_event (widget, event);
3596         }
3597
3598         if ((event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) == 0)
3599                 return FALSE;
3600
3601         if (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) {
3602                 if (ev_view_get_fullscreen (view) || ev_view_get_presentation (view))
3603                         return FALSE;
3604                 
3605                 ev_window_run_fullscreen (window);
3606         } else {
3607                 if (ev_view_get_fullscreen (view))
3608                         ev_window_stop_fullscreen (window, FALSE);
3609                 else if (ev_view_get_presentation (view))
3610                         ev_window_stop_presentation (window, FALSE);
3611         }
3612
3613         return FALSE;
3614 }
3615
3616 static void
3617 ev_window_set_page_mode (EvWindow         *window,
3618                          EvWindowPageMode  page_mode)
3619 {
3620         GtkWidget *child = NULL;
3621         GtkWidget *real_child;
3622
3623         if (window->priv->page_mode == page_mode)
3624                 return;
3625
3626         window->priv->page_mode = page_mode;
3627
3628         switch (page_mode) {
3629                 case PAGE_MODE_DOCUMENT:
3630                         child = window->priv->view;
3631                         break;
3632                 case PAGE_MODE_PASSWORD:
3633                         child = window->priv->password_view;
3634                         break;
3635                 default:
3636                         g_assert_not_reached ();
3637         }
3638
3639         real_child = gtk_bin_get_child (GTK_BIN (window->priv->scrolled_window));
3640         if (child != real_child) {
3641                 gtk_container_remove (GTK_CONTAINER (window->priv->scrolled_window),
3642                                       real_child);
3643                 gtk_container_add (GTK_CONTAINER (window->priv->scrolled_window),
3644                                    child);
3645         }
3646         ev_window_update_actions (window);
3647 }
3648
3649
3650 static void
3651 ev_window_cmd_edit_rotate_left (GtkAction *action, EvWindow *ev_window)
3652 {
3653         ev_view_rotate_left (EV_VIEW (ev_window->priv->view));
3654 }
3655
3656 static void
3657 ev_window_cmd_edit_rotate_right (GtkAction *action, EvWindow *ev_window)
3658 {
3659         ev_view_rotate_right (EV_VIEW (ev_window->priv->view));
3660 }
3661
3662 static void
3663 ev_window_cmd_edit_toolbar_cb (GtkDialog *dialog, gint response, gpointer data)
3664 {
3665         EvWindow *ev_window = EV_WINDOW (data);
3666         egg_editable_toolbar_set_edit_mode
3667                         (EGG_EDITABLE_TOOLBAR (ev_window->priv->toolbar), FALSE);
3668         ev_application_save_toolbars_model (EV_APP);
3669         gtk_widget_destroy (GTK_WIDGET (dialog));
3670 }
3671
3672 static void
3673 ev_window_cmd_edit_toolbar (GtkAction *action, EvWindow *ev_window)
3674 {
3675         GtkWidget *dialog;
3676         GtkWidget *editor;
3677
3678         dialog = gtk_dialog_new_with_buttons (_("Toolbar Editor"),
3679                                               GTK_WINDOW (ev_window), 
3680                                               GTK_DIALOG_DESTROY_WITH_PARENT, 
3681                                               GTK_STOCK_CLOSE,
3682                                               GTK_RESPONSE_CLOSE, 
3683                                               NULL);
3684         gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE);
3685         gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)), 5);
3686         gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 2);
3687         gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
3688         gtk_window_set_default_size (GTK_WINDOW (dialog), 500, 400);
3689           
3690         editor = egg_toolbar_editor_new (ev_window->priv->ui_manager,
3691                                          ev_application_get_toolbars_model (EV_APP));
3692         gtk_container_set_border_width (GTK_CONTAINER (editor), 5);
3693         gtk_box_set_spacing (GTK_BOX (EGG_TOOLBAR_EDITOR (editor)), 5);
3694              
3695         gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), editor);
3696
3697         egg_editable_toolbar_set_edit_mode
3698                 (EGG_EDITABLE_TOOLBAR (ev_window->priv->toolbar), TRUE);
3699
3700         g_signal_connect (dialog, "response",
3701                           G_CALLBACK (ev_window_cmd_edit_toolbar_cb),
3702                           ev_window);
3703         gtk_widget_show_all (dialog);
3704 }
3705
3706 static void
3707 ev_window_cmd_view_zoom_in (GtkAction *action, EvWindow *ev_window)
3708 {
3709         g_return_if_fail (EV_IS_WINDOW (ev_window));
3710
3711         ev_view_set_sizing_mode (EV_VIEW (ev_window->priv->view), EV_SIZING_FREE);
3712         ev_view_zoom_in (EV_VIEW (ev_window->priv->view));
3713 }
3714
3715 static void
3716 ev_window_cmd_view_zoom_out (GtkAction *action, EvWindow *ev_window)
3717 {
3718         g_return_if_fail (EV_IS_WINDOW (ev_window));
3719
3720         ev_view_set_sizing_mode (EV_VIEW (ev_window->priv->view), EV_SIZING_FREE);
3721         ev_view_zoom_out (EV_VIEW (ev_window->priv->view));
3722 }
3723
3724 static void
3725 ev_window_cmd_go_previous_page (GtkAction *action, EvWindow *ev_window)
3726 {
3727         g_return_if_fail (EV_IS_WINDOW (ev_window));
3728
3729         ev_view_previous_page (EV_VIEW (ev_window->priv->view));
3730 }
3731
3732 static void
3733 ev_window_cmd_go_next_page (GtkAction *action, EvWindow *ev_window)
3734 {
3735         g_return_if_fail (EV_IS_WINDOW (ev_window));
3736
3737         ev_view_next_page (EV_VIEW (ev_window->priv->view));
3738 }
3739
3740 static void
3741 ev_window_cmd_go_first_page (GtkAction *action, EvWindow *ev_window)
3742 {
3743         g_return_if_fail (EV_IS_WINDOW (ev_window));
3744
3745         ev_page_cache_set_current_page (ev_window->priv->page_cache, 0);
3746 }
3747
3748 static void
3749 ev_window_cmd_go_last_page (GtkAction *action, EvWindow *ev_window)
3750 {
3751         int n_pages;
3752
3753         g_return_if_fail (EV_IS_WINDOW (ev_window));
3754
3755         n_pages = ev_page_cache_get_n_pages (ev_window->priv->page_cache);
3756         ev_page_cache_set_current_page (ev_window->priv->page_cache, n_pages - 1);
3757 }
3758
3759 static void
3760 ev_window_cmd_go_forward (GtkAction *action, EvWindow *ev_window)
3761 {
3762         int n_pages, current_page;
3763         
3764         g_return_if_fail (EV_IS_WINDOW (ev_window));
3765
3766         n_pages = ev_page_cache_get_n_pages (ev_window->priv->page_cache);
3767         current_page = ev_page_cache_get_current_page (ev_window->priv->page_cache);
3768         
3769         if (current_page + 10 < n_pages)
3770                 ev_page_cache_set_current_page (ev_window->priv->page_cache, current_page + 10);
3771 }
3772
3773 static void
3774 ev_window_cmd_go_backward (GtkAction *action, EvWindow *ev_window)
3775 {
3776         int current_page;
3777         
3778         g_return_if_fail (EV_IS_WINDOW (ev_window));
3779
3780         current_page = ev_page_cache_get_current_page (ev_window->priv->page_cache);
3781         
3782         if (current_page - 10 >= 0)
3783                 ev_page_cache_set_current_page (ev_window->priv->page_cache, current_page - 10);
3784 }
3785
3786 static void
3787 ev_window_cmd_view_reload (GtkAction *action, EvWindow *ev_window)
3788 {
3789         ev_window_reload_document (ev_window);
3790 }
3791
3792 static void
3793 ev_window_cmd_view_autoscroll (GtkAction *action, EvWindow *ev_window)
3794 {
3795         ev_view_autoscroll_start (EV_VIEW (ev_window->priv->view));
3796 }
3797
3798 static void
3799 ev_window_cmd_help_contents (GtkAction *action, EvWindow *ev_window)
3800 {
3801         GError  *error = NULL;
3802
3803         gtk_show_uri (gtk_window_get_screen (GTK_WINDOW (ev_window)),
3804                       "ghelp:evince",
3805                       GDK_CURRENT_TIME,
3806                       &error);
3807         if (error) {
3808                 ev_window_error_message (ev_window, error, 
3809                                          "%s", _("There was an error displaying help"));
3810                 g_error_free (error);
3811         }
3812 }
3813
3814 static void
3815 ev_window_cmd_leave_fullscreen (GtkAction *action, EvWindow *window)
3816 {
3817         ev_window_stop_fullscreen (window, TRUE);
3818 }
3819
3820 static void
3821 ev_window_cmd_start_presentation (GtkAction *action, EvWindow *window)
3822 {
3823         ev_window_run_presentation (window);
3824 }
3825
3826 static void
3827 ev_window_cmd_escape (GtkAction *action, EvWindow *window)
3828 {
3829         GtkWidget *widget;
3830
3831         ev_view_autoscroll_stop (EV_VIEW (window->priv->view));
3832         
3833         widget = gtk_window_get_focus (GTK_WINDOW (window));
3834         if (widget && gtk_widget_get_ancestor (widget, EGG_TYPE_FIND_BAR)) {
3835                 update_chrome_flag (window, EV_CHROME_FINDBAR, FALSE);
3836                 update_chrome_visibility (window);
3837                 gtk_widget_grab_focus (window->priv->view);
3838         } else {
3839                 gboolean fullscreen;
3840                 gboolean presentation;
3841
3842                 g_object_get (window->priv->view,
3843                               "fullscreen", &fullscreen,
3844                               "presentation", &presentation,
3845                               NULL);
3846
3847                 if (fullscreen) {
3848                         ev_window_stop_fullscreen (window, TRUE);
3849                 } else if (presentation) {
3850                         ev_window_stop_presentation (window, TRUE);
3851                         gtk_widget_grab_focus (window->priv->view);
3852                 } else {
3853                         gtk_widget_grab_focus (window->priv->view);
3854                 }
3855
3856                 if (fullscreen && presentation)
3857                         g_warning ("Both fullscreen and presentation set somehow");
3858         }
3859 }
3860
3861 static void
3862 save_sizing_mode (EvWindow *window)
3863 {
3864         EvSizingMode mode;
3865         GEnumValue *enum_value;
3866
3867         mode = ev_view_get_sizing_mode (EV_VIEW (window->priv->view));
3868         enum_value = g_enum_get_value (g_type_class_peek (EV_TYPE_SIZING_MODE), mode);
3869
3870         if (!ev_window_is_empty (window))
3871                 ev_metadata_manager_set_string (window->priv->uri, "sizing_mode",
3872                                                 enum_value->value_nick);
3873 }
3874
3875 static void
3876 ev_window_set_view_size (EvWindow *window)
3877 {
3878         gint width, height;
3879         GtkRequisition vsb_requisition;
3880         GtkRequisition hsb_requisition;
3881         gint scrollbar_spacing;
3882         GtkWidget *scrolled_window = window->priv->scrolled_window;
3883
3884         if (!window->priv->view)
3885                 return;
3886
3887         /* Calculate the width available for the content */
3888         width  = scrolled_window->allocation.width;
3889         height = scrolled_window->allocation.height;
3890
3891         if (gtk_scrolled_window_get_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window)) == GTK_SHADOW_IN) {
3892                 width -=  2 * window->priv->view->style->xthickness;
3893                 height -= 2 * window->priv->view->style->ythickness;
3894         }
3895
3896         gtk_widget_size_request (GTK_SCROLLED_WINDOW (scrolled_window)->vscrollbar,
3897                                  &vsb_requisition);
3898         gtk_widget_size_request (GTK_SCROLLED_WINDOW (scrolled_window)->hscrollbar,
3899                                  &hsb_requisition);
3900         gtk_widget_style_get (scrolled_window,
3901                               "scrollbar_spacing",
3902                               &scrollbar_spacing,
3903                               NULL);
3904
3905         ev_view_set_zoom_for_size (EV_VIEW (window->priv->view),
3906                                    MAX (1, width),
3907                                    MAX (1, height),
3908                                    vsb_requisition.width + scrollbar_spacing,
3909                                    hsb_requisition.height + scrollbar_spacing);
3910 }
3911
3912 static void     
3913 ev_window_sizing_mode_changed_cb (EvView *view, GParamSpec *pspec,
3914                                   EvWindow   *ev_window)
3915 {
3916         EvSizingMode sizing_mode;
3917
3918         g_object_get (ev_window->priv->view,
3919                       "sizing-mode", &sizing_mode,
3920                       NULL);
3921
3922         g_object_set (ev_window->priv->scrolled_window,
3923                       "hscrollbar-policy",
3924                       sizing_mode == EV_SIZING_FREE ?
3925                       GTK_POLICY_AUTOMATIC : GTK_POLICY_NEVER,
3926                       "vscrollbar-policy", GTK_POLICY_AUTOMATIC,
3927                       NULL);
3928
3929         update_sizing_buttons (ev_window);
3930         save_sizing_mode (ev_window);
3931 }
3932
3933 static void     
3934 ev_window_zoom_changed_cb (EvView *view, GParamSpec *pspec, EvWindow *ev_window)
3935 {
3936         ev_window_update_actions (ev_window);
3937
3938         if (ev_view_get_sizing_mode (view) == EV_SIZING_FREE && !ev_window_is_empty (ev_window)) {
3939                 gdouble zoom;
3940
3941                 zoom = ev_view_get_zoom (view);
3942                 zoom *= 72.0 / get_screen_dpi (GTK_WINDOW(ev_window));
3943                 ev_metadata_manager_set_double (ev_window->priv->uri, "zoom", zoom);
3944         }
3945 }
3946
3947 static void
3948 ev_window_update_continuous_action (EvWindow *window)
3949 {
3950         GtkAction *action;
3951
3952         action = gtk_action_group_get_action (window->priv->action_group, "ViewContinuous");
3953         g_signal_handlers_block_by_func
3954                 (action, G_CALLBACK (ev_window_cmd_continuous), window);
3955         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
3956                                       ev_view_get_continuous (EV_VIEW (window->priv->view)));
3957         g_signal_handlers_unblock_by_func
3958                 (action, G_CALLBACK (ev_window_cmd_continuous), window);
3959 }
3960
3961 static void
3962 ev_window_update_dual_page_action (EvWindow *window)
3963 {
3964         GtkAction *action;
3965
3966         action = gtk_action_group_get_action (window->priv->action_group, "ViewDual");
3967         g_signal_handlers_block_by_func
3968                 (action, G_CALLBACK (ev_window_cmd_dual), window);
3969         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
3970                                       ev_view_get_dual_page (EV_VIEW (window->priv->view)));
3971         g_signal_handlers_unblock_by_func
3972                 (action, G_CALLBACK (ev_window_cmd_dual), window);
3973 }
3974
3975 static void     
3976 ev_window_continuous_changed_cb (EvView *view, GParamSpec *pspec, EvWindow *ev_window)
3977 {
3978         ev_window_update_continuous_action (ev_window);
3979
3980         if (!ev_window_is_empty (ev_window))
3981                 ev_metadata_manager_set_boolean (ev_window->priv->uri, "continuous",
3982                                                  ev_view_get_continuous (EV_VIEW (ev_window->priv->view)));
3983 }
3984
3985 static void     
3986 ev_window_rotation_changed_cb (EvView *view, GParamSpec *pspec, EvWindow *window)
3987 {
3988         int rotation;
3989
3990         rotation = ev_view_get_rotation (EV_VIEW (window->priv->view));
3991
3992         if (!ev_window_is_empty (window))
3993                 ev_metadata_manager_set_int (window->priv->uri, "rotation",
3994                                              rotation);
3995
3996         ev_sidebar_thumbnails_refresh (EV_SIDEBAR_THUMBNAILS (window->priv->sidebar_thumbs),
3997                                        rotation);
3998         ev_window_refresh_window_thumbnail (window, rotation);
3999 }
4000
4001 static void
4002 ev_window_has_selection_changed_cb (EvView *view, GParamSpec *pspec, EvWindow *window)
4003 {
4004         ev_window_update_actions (window);
4005 }
4006
4007 static void     
4008 ev_window_dual_mode_changed_cb (EvView *view, GParamSpec *pspec, EvWindow *ev_window)
4009 {
4010         ev_window_update_dual_page_action (ev_window);
4011
4012         if (!ev_window_is_empty (ev_window))
4013                 ev_metadata_manager_set_boolean (ev_window->priv->uri, "dual-page",
4014                                                  ev_view_get_dual_page (EV_VIEW (ev_window->priv->view)));
4015 }
4016
4017 static char *
4018 build_comments_string (void)
4019 {
4020 #ifdef ENABLE_PDF
4021         PopplerBackend backend;
4022         const char *backend_name;
4023         const char *version;
4024
4025         backend = poppler_get_backend ();
4026         version = poppler_get_version ();
4027         switch (backend) {
4028                 case POPPLER_BACKEND_CAIRO:
4029                         backend_name = "cairo";
4030                         break;
4031                 case POPPLER_BACKEND_SPLASH:
4032                         backend_name = "splash";
4033                         break;
4034                 default:
4035                         backend_name = "unknown";
4036                         break;
4037         }
4038
4039         return g_strdup_printf (_("Document Viewer.\n"
4040                                   "Using poppler %s (%s)"),
4041                                 version, backend_name);
4042 #else
4043         return g_strdup_printf (_("Document Viewer"));
4044 #endif
4045 }
4046
4047 static void
4048 ev_window_cmd_help_about (GtkAction *action, EvWindow *ev_window)
4049 {
4050         const char *authors[] = {
4051                 "Martin Kretzschmar <m_kretzschmar@gmx.net>",
4052                 "Jonathan Blandford <jrb@gnome.org>",
4053                 "Marco Pesenti Gritti <marco@gnome.org>",
4054                 "Nickolay V. Shmyrev <nshmyrev@yandex.ru>",
4055                 "Bryan Clark <clarkbw@gnome.org>",
4056                 "Carlos Garcia Campos <carlosgc@gnome.org>",
4057                 "Wouter Bolsterlee <wbolster@gnome.org>",
4058                 NULL
4059         };
4060
4061         const char *documenters[] = {
4062                 "Nickolay V. Shmyrev <nshmyrev@yandex.ru>",
4063                 NULL
4064         };
4065
4066         const char *license[] = {
4067                 N_("Evince is free software; you can redistribute it and/or modify "
4068                    "it under the terms of the GNU General Public License as published by "
4069                    "the Free Software Foundation; either version 2 of the License, or "
4070                    "(at your option) any later version.\n"),
4071                 N_("Evince is distributed in the hope that it will be useful, "
4072                    "but WITHOUT ANY WARRANTY; without even the implied warranty of "
4073                    "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the "
4074                    "GNU General Public License for more details.\n"),
4075                 N_("You should have received a copy of the GNU General Public License "
4076                    "along with Evince; if not, write to the Free Software Foundation, Inc., "
4077                    "59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n")
4078         };
4079
4080         char *license_trans;
4081         char *comments;
4082
4083 #ifdef ENABLE_NLS
4084         const char **p;
4085
4086         for (p = authors; *p; ++p)
4087                 *p = _(*p);
4088
4089         for (p = documenters; *p; ++p)
4090                 *p = _(*p);
4091 #endif
4092
4093         license_trans = g_strconcat (_(license[0]), "\n", _(license[1]), "\n",
4094                                      _(license[2]), "\n", NULL);
4095         comments = build_comments_string ();
4096
4097         gtk_show_about_dialog (
4098                 GTK_WINDOW (ev_window),
4099                 "name", _("Evince"),
4100                 "version", VERSION,
4101                 "copyright",
4102                 _("\xc2\xa9 1996-2007 The Evince authors"),
4103                 "license", license_trans,
4104                 "website", "http://www.gnome.org/projects/evince",
4105                 "comments", comments,
4106                 "authors", authors,
4107                 "documenters", documenters,
4108                 "translator-credits", _("translator-credits"),
4109                 "logo-icon-name", "evince",
4110                 "wrap-license", TRUE,
4111                 NULL);
4112
4113         g_free (comments);
4114         g_free (license_trans);
4115 }
4116
4117 static void
4118 ev_window_view_toolbar_cb (GtkAction *action, EvWindow *ev_window)
4119 {
4120         gboolean active;
4121         
4122         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
4123         update_chrome_flag (ev_window, EV_CHROME_TOOLBAR, active);
4124         update_chrome_visibility (ev_window);
4125         ev_metadata_manager_set_boolean (NULL, "show_toolbar", active);
4126 }
4127
4128 static void
4129 ev_window_view_sidebar_cb (GtkAction *action, EvWindow *ev_window)
4130 {
4131         if (ev_view_get_presentation (EV_VIEW (ev_window->priv->view)))
4132                 return;
4133             
4134         update_chrome_flag (ev_window, EV_CHROME_SIDEBAR,
4135                             gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
4136         update_chrome_visibility (ev_window);
4137 }
4138
4139 static void
4140 ev_window_sidebar_current_page_changed_cb (EvSidebar  *ev_sidebar,
4141                                            GParamSpec *pspec,
4142                                            EvWindow   *ev_window)
4143 {
4144         GtkWidget *current_page;
4145         const char *id;
4146
4147         g_object_get (G_OBJECT (ev_sidebar), "current_page", &current_page, NULL);
4148
4149         if (current_page == ev_window->priv->sidebar_links) {
4150                 id = LINKS_SIDEBAR_ID;
4151         } else if (current_page == ev_window->priv->sidebar_thumbs) {
4152                 id = THUMBNAILS_SIDEBAR_ID;
4153         } else if (current_page == ev_window->priv->sidebar_attachments) {
4154                 id = ATTACHMENTS_SIDEBAR_ID;
4155         } else if (current_page == ev_window->priv->sidebar_layers) {
4156                 id = LAYERS_SIDEBAR_ID;
4157         } else {
4158                 g_assert_not_reached();
4159         }
4160
4161         g_object_unref (current_page);
4162
4163         if (!ev_window_is_empty (ev_window))
4164                 ev_metadata_manager_set_string (ev_window->priv->uri, "sidebar_page", id);
4165 }
4166
4167 static void
4168 ev_window_sidebar_visibility_changed_cb (EvSidebar  *ev_sidebar,
4169                                          GParamSpec *pspec,
4170                                          EvWindow   *ev_window)
4171 {
4172         EvView *view = EV_VIEW (ev_window->priv->view);
4173         GtkAction *action;
4174
4175         action = gtk_action_group_get_action (ev_window->priv->action_group, "ViewSidebar");
4176
4177         if (!ev_view_get_presentation (view)) {
4178                 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
4179                                               GTK_WIDGET_VISIBLE (ev_sidebar));
4180
4181                 ev_metadata_manager_set_boolean (ev_window->priv->uri, "sidebar_visibility",
4182                                                  GTK_WIDGET_VISIBLE (ev_sidebar));
4183         }
4184 }
4185
4186 static void
4187 view_menu_link_popup (EvWindow *ev_window,
4188                       EvLink   *link)
4189 {
4190         gboolean   show_external = FALSE;
4191         gboolean   show_internal = FALSE;
4192         GtkAction *action;
4193         
4194         if (ev_window->priv->link)
4195                 g_object_unref (ev_window->priv->link);
4196         
4197         if (link)
4198                 ev_window->priv->link = g_object_ref (link);
4199         else    
4200                 ev_window->priv->link = NULL;
4201
4202         if (ev_window->priv->link) {
4203                 EvLinkAction *ev_action;
4204
4205                 ev_action = ev_link_get_action (link);
4206                 if (ev_action) {
4207                         switch (ev_link_action_get_action_type (ev_action)) {
4208                                 case EV_LINK_ACTION_TYPE_GOTO_DEST:
4209                                 case EV_LINK_ACTION_TYPE_GOTO_REMOTE:
4210                                         show_internal = TRUE;
4211                                         break;
4212                                 case EV_LINK_ACTION_TYPE_EXTERNAL_URI:
4213                                 case EV_LINK_ACTION_TYPE_LAUNCH:
4214                                         show_external = TRUE;
4215                                         break;
4216                                 default:
4217                                         break;
4218                         }
4219                 }
4220         }
4221         
4222         action = gtk_action_group_get_action (ev_window->priv->view_popup_action_group,
4223                                               "OpenLink");
4224         gtk_action_set_visible (action, show_external);
4225
4226         action = gtk_action_group_get_action (ev_window->priv->view_popup_action_group,
4227                                               "CopyLinkAddress");
4228         gtk_action_set_visible (action, show_external);
4229
4230         action = gtk_action_group_get_action (ev_window->priv->view_popup_action_group,
4231                                               "GoLink");
4232         gtk_action_set_visible (action, show_internal);
4233
4234         action = gtk_action_group_get_action (ev_window->priv->view_popup_action_group,
4235                                               "OpenLinkNewWindow");
4236         gtk_action_set_visible (action, show_internal);
4237 }
4238
4239 static void
4240 view_menu_image_popup (EvWindow  *ev_window,
4241                        EvImage   *image)
4242 {
4243         GtkAction *action;
4244         gboolean   show_image = FALSE;
4245         
4246         if (ev_window->priv->image)
4247                 g_object_unref (ev_window->priv->image);
4248         
4249         if (image)
4250                 ev_window->priv->image = g_object_ref (image);
4251         else    
4252                 ev_window->priv->image = NULL;
4253
4254         show_image = (ev_window->priv->image != NULL);
4255         
4256         action = gtk_action_group_get_action (ev_window->priv->view_popup_action_group,
4257                                               "SaveImageAs");
4258         gtk_action_set_visible (action, show_image);
4259
4260         action = gtk_action_group_get_action (ev_window->priv->view_popup_action_group,
4261                                               "CopyImage");
4262         gtk_action_set_visible (action, show_image);
4263 }
4264
4265 static gboolean
4266 view_menu_popup_cb (EvView   *view,
4267                     GObject  *object,
4268                     EvWindow *ev_window)
4269 {
4270         if (ev_view_get_presentation (EV_VIEW (ev_window->priv->view)))
4271                 return FALSE;
4272
4273         view_menu_link_popup (ev_window,
4274                               EV_IS_LINK (object) ? EV_LINK (object) : NULL);
4275         view_menu_image_popup (ev_window,
4276                                EV_IS_IMAGE (object) ? EV_IMAGE (object) : NULL);
4277         
4278         gtk_menu_popup (GTK_MENU (ev_window->priv->view_popup),
4279                         NULL, NULL, NULL, NULL,
4280                         3, gtk_get_current_event_time ());
4281         return TRUE;
4282 }
4283
4284 static gboolean
4285 attachment_bar_menu_popup_cb (EvSidebarAttachments *attachbar,
4286                               GList           *attach_list,
4287                               EvWindow        *ev_window)
4288 {
4289         GtkWidget *popup;
4290
4291         g_assert (attach_list != NULL);
4292
4293         if (ev_window->priv->attach_list) {
4294                 g_list_foreach (ev_window->priv->attach_list,
4295                                 (GFunc) g_object_unref, NULL);
4296                 g_list_free (ev_window->priv->attach_list);
4297         }
4298         
4299         ev_window->priv->attach_list = attach_list;
4300         
4301         popup = ev_window->priv->attachment_popup;
4302
4303         gtk_menu_popup (GTK_MENU (popup), NULL, NULL,
4304                         NULL, NULL,
4305                         3, gtk_get_current_event_time ());
4306
4307         return TRUE;
4308 }
4309
4310 static void
4311 ev_window_update_find_status_message (EvWindow *ev_window)
4312 {
4313         gchar *message;
4314
4315         if (!ev_window->priv->find_job)
4316                 return;
4317         
4318         if (ev_job_is_finished (ev_window->priv->find_job)) {
4319                 gint n_results;
4320
4321                 n_results = ev_job_find_get_n_results (EV_JOB_FIND (ev_window->priv->find_job),
4322                                                        ev_page_cache_get_current_page (ev_window->priv->page_cache));
4323                 /* TRANS: Sometimes this could be better translated as
4324                                       "%d hit(s) on this page".  Therefore this string
4325                                       contains plural cases. */
4326                 message = g_strdup_printf (ngettext ("%d found on this page",
4327                                                      "%d found on this page",
4328                                                      n_results),
4329                                            n_results);
4330         } else {
4331                 gdouble percent;
4332
4333                 percent = ev_job_find_get_progress (EV_JOB_FIND (ev_window->priv->find_job));
4334                 message = g_strdup_printf (_("%3d%% remaining to search"),
4335                                            (gint) ((1.0 - percent) * 100));
4336         }
4337         
4338         egg_find_bar_set_status_text (EGG_FIND_BAR (ev_window->priv->find_bar), message);
4339         g_free (message);
4340 }
4341
4342 static void
4343 ev_window_find_job_finished_cb (EvJobFind *job,
4344                                 EvWindow  *ev_window)
4345 {
4346         ev_window_update_find_status_message (ev_window);
4347 }
4348
4349 static void
4350 ev_window_find_job_updated_cb (EvJobFind *job,
4351                                gint       page,
4352                                EvWindow  *ev_window)
4353 {
4354         ev_window_update_actions (ev_window);
4355         
4356         ev_view_find_changed (EV_VIEW (ev_window->priv->view),
4357                               ev_job_find_get_results (job),
4358                               page);
4359         ev_window_update_find_status_message (ev_window);
4360 }
4361
4362 static void
4363 ev_window_clear_find_job (EvWindow *ev_window)
4364 {
4365         if (ev_window->priv->find_job != NULL) {
4366                 if (!ev_job_is_finished (ev_window->priv->find_job))
4367                         ev_job_cancel (ev_window->priv->find_job);
4368
4369                 g_signal_handlers_disconnect_by_func (ev_window->priv->find_job,
4370                                                       ev_window_find_job_finished_cb,
4371                                                       ev_window);
4372                 g_signal_handlers_disconnect_by_func (ev_window->priv->find_job,
4373                                                       ev_window_find_job_updated_cb,
4374                                                       ev_window);
4375                 g_object_unref (ev_window->priv->find_job);
4376                 ev_window->priv->find_job = NULL;
4377         }
4378 }
4379
4380 static void
4381 find_bar_previous_cb (EggFindBar *find_bar,
4382                       EvWindow   *ev_window)
4383 {
4384         ev_view_find_previous (EV_VIEW (ev_window->priv->view));
4385 }
4386
4387 static void
4388 find_bar_next_cb (EggFindBar *find_bar,
4389                   EvWindow   *ev_window)
4390 {
4391         ev_view_find_next (EV_VIEW (ev_window->priv->view));
4392 }
4393
4394 static void
4395 find_bar_close_cb (EggFindBar *find_bar,
4396                    EvWindow   *ev_window)
4397 {
4398         ev_view_find_cancel (EV_VIEW (ev_window->priv->view));
4399         ev_window_clear_find_job (ev_window);
4400         update_chrome_flag (ev_window, EV_CHROME_FINDBAR, FALSE);
4401         update_chrome_visibility (ev_window);
4402 }
4403
4404 static void
4405 find_bar_search_changed_cb (EggFindBar *find_bar,
4406                             GParamSpec *param,
4407                             EvWindow   *ev_window)
4408 {
4409         gboolean case_sensitive;
4410         const char *search_string;
4411
4412         if (!ev_window->priv->document || !EV_IS_DOCUMENT_FIND (ev_window->priv->document))
4413                 return;
4414         
4415         /* Either the string or case sensitivity could have changed. */
4416         case_sensitive = egg_find_bar_get_case_sensitive (find_bar);
4417         search_string = egg_find_bar_get_search_string (find_bar);
4418
4419         ev_view_find_search_changed (EV_VIEW (ev_window->priv->view));
4420
4421         ev_window_clear_find_job (ev_window);
4422
4423         if (search_string && search_string[0]) {
4424                 ev_window->priv->find_job = ev_job_find_new (ev_window->priv->document,
4425                                                              ev_page_cache_get_current_page (ev_window->priv->page_cache),
4426                                                              ev_page_cache_get_n_pages (ev_window->priv->page_cache),
4427                                                              search_string,
4428                                                              case_sensitive);
4429                 g_signal_connect (ev_window->priv->find_job, "finished",
4430                                   G_CALLBACK (ev_window_find_job_finished_cb),
4431                                   ev_window);
4432                 g_signal_connect (ev_window->priv->find_job, "updated",
4433                                   G_CALLBACK (ev_window_find_job_updated_cb),
4434                                   ev_window);
4435                 ev_job_scheduler_push_job (ev_window->priv->find_job, EV_JOB_PRIORITY_NONE);
4436         } else {
4437                 ev_window_update_actions (ev_window);
4438                 egg_find_bar_set_status_text (EGG_FIND_BAR (ev_window->priv->find_bar),
4439                                               NULL);
4440                 gtk_widget_queue_draw (GTK_WIDGET (ev_window->priv->view));
4441         }
4442 }
4443
4444 static void
4445 find_bar_visibility_changed_cb (EggFindBar *find_bar,
4446                                 GParamSpec *param,
4447                                 EvWindow   *ev_window)
4448 {
4449         gboolean visible;
4450
4451         visible = GTK_WIDGET_VISIBLE (find_bar);
4452
4453         if (ev_window->priv->document &&
4454             EV_IS_DOCUMENT_FIND (ev_window->priv->document)) {
4455                 ev_view_find_set_highlight_search (EV_VIEW (ev_window->priv->view), visible);
4456                 ev_view_find_search_changed (EV_VIEW (ev_window->priv->view));
4457                 ev_window_update_actions (ev_window);
4458
4459                 if (visible)
4460                         find_bar_search_changed_cb (find_bar, NULL, ev_window);
4461                 else
4462                         egg_find_bar_set_status_text (EGG_FIND_BAR (ev_window->priv->find_bar), NULL);
4463         }
4464 }
4465
4466 static void
4467 find_bar_scroll (EggFindBar   *find_bar,
4468                  GtkScrollType scroll,
4469                  EvWindow     *ev_window)
4470 {
4471         ev_view_scroll (EV_VIEW (ev_window->priv->view), scroll, FALSE);
4472 }
4473
4474 static void
4475 zoom_control_changed_cb (EphyZoomAction *action,
4476                          float           zoom,
4477                          EvWindow       *ev_window)
4478 {
4479         EvSizingMode mode;
4480         
4481         g_return_if_fail (EV_IS_WINDOW (ev_window));
4482
4483         if (zoom == EPHY_ZOOM_BEST_FIT) {
4484                 mode = EV_SIZING_BEST_FIT;
4485         } else if (zoom == EPHY_ZOOM_FIT_WIDTH) {
4486                 mode = EV_SIZING_FIT_WIDTH;
4487         } else {
4488                 mode = EV_SIZING_FREE;
4489         }
4490
4491         ev_view_set_sizing_mode (EV_VIEW (ev_window->priv->view), mode);
4492         
4493         if (mode == EV_SIZING_FREE) {
4494                 ev_view_set_zoom (EV_VIEW (ev_window->priv->view),
4495                                   zoom * get_screen_dpi (GTK_WINDOW (ev_window)) / 72.0,
4496                                   FALSE);
4497         }
4498 }
4499
4500 static void
4501 ev_window_drag_data_received (GtkWidget        *widget,
4502                               GdkDragContext   *context,
4503                               gint              x,
4504                               gint              y,
4505                               GtkSelectionData *selection_data,
4506                               guint             info,
4507                               guint             time)
4508
4509 {
4510         EvWindow *window = EV_WINDOW (widget);
4511         gchar   **uris;
4512         gint      i = 0;
4513         GSList   *uri_list = NULL;
4514
4515         uris = gtk_selection_data_get_uris (selection_data);
4516         if (!uris) {
4517                 gtk_drag_finish (context, FALSE, FALSE, time);
4518                 return;
4519         }
4520
4521         for (i = 0; uris[i]; i++) {
4522                 uri_list = g_slist_prepend (uri_list, (gpointer) uris[i]);
4523         }
4524
4525         ev_application_open_uri_list (EV_APP, uri_list,
4526                                       gtk_window_get_screen (GTK_WINDOW (window)),
4527                                       0);
4528         gtk_drag_finish (context, TRUE, FALSE, time);
4529
4530         g_strfreev (uris);
4531         g_slist_free (uri_list);
4532 }
4533
4534 static void
4535 ev_window_finalize (GObject *object)
4536 {
4537         GList *windows = ev_application_get_windows (EV_APP);
4538
4539         if (windows == NULL) {
4540                 ev_application_shutdown (EV_APP);
4541         } else {
4542                 g_list_free (windows);
4543         }
4544         
4545         G_OBJECT_CLASS (ev_window_parent_class)->finalize (object);
4546 }
4547
4548 static void
4549 ev_window_dispose (GObject *object)
4550 {
4551         EvWindow *window = EV_WINDOW (object);
4552         EvWindowPrivate *priv = window->priv;
4553         GObject *mpkeys = ev_application_get_media_keys (EV_APP);
4554
4555         if (mpkeys) {
4556                 g_signal_handlers_disconnect_by_func (mpkeys,
4557                                                       ev_window_media_player_key_pressed,
4558                                                       window);
4559         }
4560         
4561         if (priv->setup_document_idle > 0) {
4562                 g_source_remove (priv->setup_document_idle);
4563                 priv->setup_document_idle = 0;
4564         }
4565         
4566         if (priv->monitor) {
4567                 g_object_unref (priv->monitor);
4568                 priv->monitor = NULL;
4569         }
4570         
4571         if (priv->title) {
4572                 ev_window_title_free (priv->title);
4573                 priv->title = NULL;
4574         }
4575
4576         if (priv->ui_manager) {
4577                 g_object_unref (priv->ui_manager);
4578                 priv->ui_manager = NULL;
4579         }
4580
4581         if (priv->action_group) {
4582                 g_object_unref (priv->action_group);
4583                 priv->action_group = NULL;
4584         }
4585
4586         if (priv->view_popup_action_group) {
4587                 g_object_unref (priv->view_popup_action_group);
4588                 priv->view_popup_action_group = NULL;
4589         }
4590
4591         if (priv->attachment_popup_action_group) {
4592                 g_object_unref (priv->attachment_popup_action_group);
4593                 priv->attachment_popup_action_group = NULL;
4594         }
4595
4596         if (priv->recent_action_group) {
4597                 g_object_unref (priv->recent_action_group);
4598                 priv->recent_action_group = NULL;
4599         }
4600
4601         if (priv->recent_manager) {
4602                 g_signal_handlers_disconnect_by_func (priv->recent_manager,
4603                                                       ev_window_setup_recent,
4604                                                       window);
4605                 priv->recent_manager = NULL;
4606         }
4607
4608         priv->recent_ui_id = 0;
4609
4610         if (priv->page_cache) {
4611                 g_signal_handlers_disconnect_by_func (priv->page_cache, page_changed_cb, window);
4612                 priv->page_cache = NULL;
4613         }
4614
4615         if (priv->document) {
4616                 g_object_unref (priv->document);
4617                 priv->document = NULL;
4618         }
4619         
4620         if (priv->view) {
4621                 g_object_unref (priv->view);
4622                 priv->view = NULL;
4623         }
4624
4625         if (priv->password_view) {
4626                 g_object_unref (priv->password_view);
4627                 priv->password_view = NULL;
4628         }
4629
4630         if (priv->load_job) {
4631                 ev_window_clear_load_job (window);
4632         }
4633
4634         if (priv->reload_job) {
4635                 ev_window_clear_reload_job (window);
4636         }
4637
4638         if (priv->save_job) {
4639                 ev_window_clear_save_job (window);
4640         }
4641
4642         if (priv->thumbnail_job) {
4643                 ev_window_clear_thumbnail_job (window);
4644         }
4645
4646         if (priv->find_job) {
4647                 ev_window_clear_find_job (window);
4648         }
4649         
4650         if (priv->local_uri) {
4651                 ev_window_clear_local_uri (window);
4652                 priv->local_uri = NULL;
4653         }
4654
4655         ev_window_clear_progress_idle (window);
4656         if (priv->progress_cancellable) {
4657                 g_object_unref (priv->progress_cancellable);
4658                 priv->progress_cancellable = NULL;
4659         }
4660         
4661         ev_window_close_dialogs (window);
4662
4663         if (window->priv->printer) {
4664                 g_object_unref (window->priv->printer);
4665                 window->priv->printer = NULL;
4666         }
4667
4668         if (window->priv->print_settings) {
4669                 g_object_unref (window->priv->print_settings);
4670                 window->priv->print_settings = NULL;
4671         }
4672
4673         if (window->priv->print_page_setup) {
4674                 g_object_unref (window->priv->print_page_setup);
4675                 window->priv->print_page_setup = NULL;
4676         }
4677
4678         if (priv->link) {
4679                 g_object_unref (priv->link);
4680                 priv->link = NULL;
4681         }
4682
4683         if (priv->image) {
4684                 g_object_unref (priv->image);
4685                 priv->image = NULL;
4686         }
4687
4688         if (priv->attach_list) {
4689                 g_list_foreach (priv->attach_list,
4690                                 (GFunc) g_object_unref,
4691                                 NULL);
4692                 g_list_free (priv->attach_list);
4693                 priv->attach_list = NULL;
4694         }
4695
4696         if (priv->find_bar) {
4697                 g_signal_handlers_disconnect_by_func
4698                         (window->priv->find_bar,
4699                          G_CALLBACK (find_bar_close_cb),
4700                          window);
4701                 priv->find_bar = NULL;
4702         }
4703
4704         if (priv->uri) {
4705                 /* Delete the uri if it's a temp symlink (open a copy) */
4706                 ev_window_clear_temp_symlink (window);
4707                 g_free (priv->uri);
4708                 priv->uri = NULL;
4709         }
4710
4711         if (priv->search_string) {
4712                 g_free (priv->search_string);
4713                 priv->search_string = NULL;
4714         }
4715         
4716         if (priv->dest) {
4717                 g_object_unref (priv->dest);
4718                 priv->dest = NULL;
4719         }
4720
4721         if (priv->history) {
4722                 g_object_unref (priv->history);
4723                 priv->history = NULL;
4724         }
4725
4726         if (priv->presentation_timeout_id > 0) {
4727                 g_source_remove (priv->presentation_timeout_id);
4728                 priv->presentation_timeout_id = 0;
4729         }
4730
4731         if (priv->print_queue) {
4732                 g_queue_free (priv->print_queue);
4733                 priv->print_queue = NULL;
4734         }
4735
4736         G_OBJECT_CLASS (ev_window_parent_class)->dispose (object);
4737 }
4738
4739 static void
4740 ev_window_class_init (EvWindowClass *ev_window_class)
4741 {
4742         GObjectClass *g_object_class = G_OBJECT_CLASS (ev_window_class);
4743         GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (ev_window_class);
4744
4745         g_object_class->dispose = ev_window_dispose;
4746         g_object_class->finalize = ev_window_finalize;
4747
4748         widget_class->screen_changed = ev_window_screen_changed;
4749         widget_class->window_state_event = ev_window_state_event;
4750         widget_class->drag_data_received = ev_window_drag_data_received;
4751
4752         g_type_class_add_private (g_object_class, sizeof (EvWindowPrivate));
4753 }
4754
4755 /* Normal items */
4756 static const GtkActionEntry entries[] = {
4757         { "File", NULL, N_("_File") },
4758         { "Edit", NULL, N_("_Edit") },
4759         { "View", NULL, N_("_View") },
4760         { "Go", NULL, N_("_Go") },
4761         { "Help", NULL, N_("_Help") },
4762
4763         /* File menu */
4764         { "FileOpen", GTK_STOCK_OPEN, N_("_Open..."), "<control>O",
4765           N_("Open an existing document"),
4766           G_CALLBACK (ev_window_cmd_file_open) },
4767         { "FileOpenCopy", NULL, N_("Op_en a Copy"), "<control>N",
4768           N_("Open a copy of the current document in a new window"),
4769           G_CALLBACK (ev_window_cmd_file_open_copy) },
4770         { "FileSaveAs", GTK_STOCK_SAVE_AS, N_("_Save a Copy..."), "<control>S",
4771           N_("Save a copy of the current document"),
4772           G_CALLBACK (ev_window_cmd_save_as) },
4773         { "FilePageSetup", NULL, N_("Page Set_up..."), NULL,
4774           N_("Setup the page settings for printing"),
4775           G_CALLBACK (ev_window_cmd_file_print_setup) },
4776         { "FilePrint", GTK_STOCK_PRINT, N_("_Print..."), "<control>P",
4777           N_("Print this document"),
4778           G_CALLBACK (ev_window_cmd_file_print) },
4779         { "FileProperties", GTK_STOCK_PROPERTIES, N_("P_roperties"), "<alt>Return", NULL,
4780           G_CALLBACK (ev_window_cmd_file_properties) },                       
4781         { "FileCloseWindow", GTK_STOCK_CLOSE, NULL, "<control>W", NULL,
4782           G_CALLBACK (ev_window_cmd_file_close_window) },
4783
4784         /* Edit menu */
4785         { "EditCopy", GTK_STOCK_COPY, NULL, "<control>C", NULL,
4786           G_CALLBACK (ev_window_cmd_edit_copy) },
4787         { "EditSelectAll", GTK_STOCK_SELECT_ALL, N_("Select _All"), "<control>A", NULL,
4788           G_CALLBACK (ev_window_cmd_edit_select_all) },
4789         { "EditFind", GTK_STOCK_FIND, N_("_Find..."), "<control>F",
4790           N_("Find a word or phrase in the document"),
4791           G_CALLBACK (ev_window_cmd_edit_find) },
4792         { "EditFindNext", NULL, N_("Find Ne_xt"), "<control>G", NULL,
4793           G_CALLBACK (ev_window_cmd_edit_find_next) },
4794         { "EditFindPrevious", NULL, N_("Find Pre_vious"), "<shift><control>G", NULL,
4795           G_CALLBACK (ev_window_cmd_edit_find_previous) },
4796         { "EditToolbar", NULL, N_("T_oolbar"), NULL, NULL,
4797           G_CALLBACK (ev_window_cmd_edit_toolbar) },
4798         { "EditRotateLeft", EV_STOCK_ROTATE_LEFT, N_("Rotate _Left"), "<control>Left", NULL,
4799           G_CALLBACK (ev_window_cmd_edit_rotate_left) },
4800         { "EditRotateRight", EV_STOCK_ROTATE_RIGHT, N_("Rotate _Right"), "<control>Right", NULL,
4801           G_CALLBACK (ev_window_cmd_edit_rotate_right) },
4802
4803         /* View menu */
4804         { "ViewZoomIn", GTK_STOCK_ZOOM_IN, NULL, "<control>plus",
4805           N_("Enlarge the document"),
4806           G_CALLBACK (ev_window_cmd_view_zoom_in) },
4807         { "ViewZoomOut", GTK_STOCK_ZOOM_OUT, NULL, "<control>minus",
4808           N_("Shrink the document"),
4809           G_CALLBACK (ev_window_cmd_view_zoom_out) },
4810         { "ViewReload", GTK_STOCK_REFRESH, N_("_Reload"), "<control>R",
4811           N_("Reload the document"),
4812           G_CALLBACK (ev_window_cmd_view_reload) },
4813
4814         { "ViewAutoscroll", GTK_STOCK_MEDIA_PLAY, N_("Auto_scroll"), NULL, NULL,
4815           G_CALLBACK (ev_window_cmd_view_autoscroll) },
4816
4817         /* Go menu */
4818         { "GoPreviousPage", GTK_STOCK_GO_UP, N_("_Previous Page"), "<control>Page_Up",
4819           N_("Go to the previous page"),
4820           G_CALLBACK (ev_window_cmd_go_previous_page) },
4821         { "GoNextPage", GTK_STOCK_GO_DOWN, N_("_Next Page"), "<control>Page_Down",
4822           N_("Go to the next page"),
4823           G_CALLBACK (ev_window_cmd_go_next_page) },
4824         { "GoFirstPage", GTK_STOCK_GOTO_TOP, N_("_First Page"), "<control>Home",
4825           N_("Go to the first page"),
4826           G_CALLBACK (ev_window_cmd_go_first_page) },
4827         { "GoLastPage", GTK_STOCK_GOTO_BOTTOM, N_("_Last Page"), "<control>End",
4828           N_("Go to the last page"),
4829           G_CALLBACK (ev_window_cmd_go_last_page) },
4830
4831         /* Help menu */
4832         { "HelpContents", GTK_STOCK_HELP, N_("_Contents"), "F1", NULL,
4833           G_CALLBACK (ev_window_cmd_help_contents) },
4834
4835         { "HelpAbout", GTK_STOCK_ABOUT, N_("_About"), NULL, NULL,
4836           G_CALLBACK (ev_window_cmd_help_about) },
4837
4838         /* Toolbar-only */
4839         { "LeaveFullscreen", GTK_STOCK_LEAVE_FULLSCREEN, N_("Leave Fullscreen"), NULL,
4840           N_("Leave fullscreen mode"),
4841           G_CALLBACK (ev_window_cmd_leave_fullscreen) },
4842         { "StartPresentation", EV_STOCK_RUN_PRESENTATION, N_("Start Presentation"), NULL,
4843           N_("Start a presentation"),
4844           G_CALLBACK (ev_window_cmd_start_presentation) },
4845
4846         /* Accellerators */
4847         { "Escape", NULL, "", "Escape", "",
4848           G_CALLBACK (ev_window_cmd_escape) },
4849         { "Slash", GTK_STOCK_FIND, NULL, "slash", NULL,
4850           G_CALLBACK (ev_window_cmd_edit_find) },
4851         { "F3", NULL, "", "F3", NULL,
4852           G_CALLBACK (ev_window_cmd_edit_find_next) },
4853         { "PageDown", NULL, "", "Page_Down", NULL,
4854           G_CALLBACK (ev_window_cmd_scroll_forward) },
4855         { "PageUp", NULL, "", "Page_Up", NULL,
4856           G_CALLBACK (ev_window_cmd_scroll_backward) },
4857         { "Space", NULL, "", "space", NULL,
4858           G_CALLBACK (ev_window_cmd_scroll_forward) },
4859         { "ShiftSpace", NULL, "", "<shift>space", NULL,
4860           G_CALLBACK (ev_window_cmd_scroll_backward) },
4861         { "BackSpace", NULL, "", "BackSpace", NULL,
4862           G_CALLBACK (ev_window_cmd_scroll_backward) },
4863         { "ShiftBackSpace", NULL, "", "<shift>BackSpace", NULL,
4864           G_CALLBACK (ev_window_cmd_scroll_forward) },
4865         { "Return", NULL, "", "Return", NULL,
4866           G_CALLBACK (ev_window_cmd_scroll_forward) },
4867         { "ShiftReturn", NULL, "", "<shift>Return", NULL,
4868           G_CALLBACK (ev_window_cmd_scroll_backward) },
4869         { "Plus", GTK_STOCK_ZOOM_IN, NULL, "plus", NULL,
4870           G_CALLBACK (ev_window_cmd_view_zoom_in) },
4871         { "CtrlEqual", GTK_STOCK_ZOOM_IN, NULL, "<control>equal", NULL,
4872           G_CALLBACK (ev_window_cmd_view_zoom_in) },
4873         { "Equal", GTK_STOCK_ZOOM_IN, NULL, "equal", NULL,
4874           G_CALLBACK (ev_window_cmd_view_zoom_in) },
4875         { "Minus", GTK_STOCK_ZOOM_OUT, NULL, "minus", NULL,
4876           G_CALLBACK (ev_window_cmd_view_zoom_out) },
4877         { "FocusPageSelector", NULL, "", "<control>l", NULL,
4878           G_CALLBACK (ev_window_cmd_focus_page_selector) },
4879         { "GoBackwardFast", NULL, "", "<shift>Page_Up", NULL,
4880           G_CALLBACK (ev_window_cmd_go_backward) },
4881         { "GoForwardFast", NULL, "", "<shift>Page_Down", NULL,
4882           G_CALLBACK (ev_window_cmd_go_forward) },
4883         { "KpPlus", GTK_STOCK_ZOOM_IN, NULL, "KP_Add", NULL,
4884           G_CALLBACK (ev_window_cmd_view_zoom_in) },
4885         { "KpMinus", GTK_STOCK_ZOOM_OUT, NULL, "KP_Subtract", NULL,
4886           G_CALLBACK (ev_window_cmd_view_zoom_out) },
4887         { "CtrlKpPlus", GTK_STOCK_ZOOM_IN, NULL, "<control>KP_Add", NULL,
4888           G_CALLBACK (ev_window_cmd_view_zoom_in) },
4889         { "CtrlKpMinus", GTK_STOCK_ZOOM_OUT, NULL, "<control>KP_Subtract", NULL,
4890           G_CALLBACK (ev_window_cmd_view_zoom_out) },
4891         { "CtrlInsert", GTK_STOCK_COPY, NULL, "<control>Insert", NULL,
4892           G_CALLBACK (ev_window_cmd_edit_copy) },
4893 };
4894
4895 /* Toggle items */
4896 static const GtkToggleActionEntry toggle_entries[] = {
4897         /* View Menu */
4898         { "ViewToolbar", NULL, N_("_Toolbar"), NULL,
4899           N_("Show or hide the toolbar"),
4900           G_CALLBACK (ev_window_view_toolbar_cb), TRUE },
4901         { "ViewSidebar", GTK_STOCK_INDEX, N_("Side _Pane"), "F9",
4902           N_("Show or hide the side pane"),
4903           G_CALLBACK (ev_window_view_sidebar_cb), TRUE },
4904         { "ViewContinuous", EV_STOCK_VIEW_CONTINUOUS, N_("_Continuous"), NULL,
4905           N_("Show the entire document"),
4906           G_CALLBACK (ev_window_cmd_continuous), TRUE },
4907         { "ViewDual", EV_STOCK_VIEW_DUAL, N_("_Dual"), NULL,
4908           N_("Show two pages at once"),
4909           G_CALLBACK (ev_window_cmd_dual), FALSE },
4910         { "ViewFullscreen", GTK_STOCK_FULLSCREEN, N_("_Fullscreen"), "F11",
4911           N_("Expand the window to fill the screen"),
4912           G_CALLBACK (ev_window_cmd_view_fullscreen) },
4913         { "ViewPresentation", EV_STOCK_RUN_PRESENTATION, N_("Pre_sentation"), "F5",
4914           N_("Run document as a presentation"),
4915           G_CALLBACK (ev_window_cmd_view_presentation) },
4916         { "ViewBestFit", EV_STOCK_ZOOM_PAGE, N_("_Best Fit"), NULL,
4917           N_("Make the current document fill the window"),
4918           G_CALLBACK (ev_window_cmd_view_best_fit) },
4919         { "ViewPageWidth", EV_STOCK_ZOOM_WIDTH, N_("Fit Page _Width"), NULL,
4920           N_("Make the current document fill the window width"),
4921           G_CALLBACK (ev_window_cmd_view_page_width) },
4922 };
4923
4924 /* Popups specific items */
4925 static const GtkActionEntry view_popup_entries [] = {
4926         /* Links */
4927         { "OpenLink", GTK_STOCK_OPEN, N_("_Open Link"), NULL,
4928           NULL, G_CALLBACK (ev_view_popup_cmd_open_link) },
4929         { "GoLink", GTK_STOCK_GO_FORWARD, N_("_Go To"), NULL,
4930           NULL, G_CALLBACK (ev_view_popup_cmd_open_link) },
4931         { "OpenLinkNewWindow", NULL, N_("Open in New _Window"), NULL,
4932           NULL, G_CALLBACK (ev_view_popup_cmd_open_link_new_window) },
4933         { "CopyLinkAddress", NULL, N_("_Copy Link Address"), NULL,
4934           NULL, G_CALLBACK (ev_view_popup_cmd_copy_link_address) },
4935         { "SaveImageAs", NULL, N_("_Save Image As..."), NULL,
4936           NULL, G_CALLBACK (ev_view_popup_cmd_save_image_as) },
4937         { "CopyImage", NULL, N_("Copy _Image"), NULL,
4938           NULL, G_CALLBACK (ev_view_popup_cmd_copy_image) },
4939 };
4940
4941 static const GtkActionEntry attachment_popup_entries [] = {
4942         { "OpenAttachment", GTK_STOCK_OPEN, N_("_Open..."), NULL,
4943           NULL, G_CALLBACK (ev_attachment_popup_cmd_open_attachment) },
4944         { "SaveAttachmentAs", GTK_STOCK_SAVE_AS, N_("_Save a Copy..."), NULL,
4945           NULL, G_CALLBACK (ev_attachment_popup_cmd_save_attachment_as) },
4946 };
4947
4948 static void
4949 sidebar_links_link_activated_cb (EvSidebarLinks *sidebar_links, EvLink *link, EvWindow *window)
4950 {
4951         ev_view_handle_link (EV_VIEW (window->priv->view), link);
4952 }
4953
4954 static void
4955 activate_link_cb (EvPageAction *page_action, EvLink *link, EvWindow *window)
4956 {
4957         ev_view_handle_link (EV_VIEW (window->priv->view), link);
4958         gtk_widget_grab_focus (window->priv->view);
4959 }
4960
4961 static void
4962 navigation_action_activate_link_cb (EvNavigationAction *action, EvLink *link, EvWindow *window)
4963 {
4964         
4965         ev_view_handle_link (EV_VIEW (window->priv->view), link);
4966         gtk_widget_grab_focus (window->priv->view);
4967 }
4968
4969 static void
4970 sidebar_layers_visibility_changed (EvSidebarLayers *layers,
4971                                    EvWindow        *window)
4972 {
4973         ev_view_reload (EV_VIEW (window->priv->view));
4974 }
4975
4976 static void
4977 register_custom_actions (EvWindow *window, GtkActionGroup *group)
4978 {
4979         GtkAction *action;
4980
4981         action = g_object_new (EV_TYPE_PAGE_ACTION,
4982                                "name", PAGE_SELECTOR_ACTION,
4983                                "label", _("Page"),
4984                                "tooltip", _("Select Page"),
4985                                "icon_name", "text-x-generic",
4986                                "visible_overflown", FALSE,
4987                                NULL);
4988         g_signal_connect (action, "activate_link",
4989                           G_CALLBACK (activate_link_cb), window);
4990         gtk_action_group_add_action (group, action);
4991         g_object_unref (action);
4992
4993         action = g_object_new (EPHY_TYPE_ZOOM_ACTION,
4994                                "name", ZOOM_CONTROL_ACTION,
4995                                "label", _("Zoom"),
4996                                "stock_id", EV_STOCK_ZOOM,
4997                                "tooltip", _("Adjust the zoom level"),
4998                                "zoom", 1.0,
4999                                NULL);
5000         g_signal_connect (action, "zoom_to_level",
5001                           G_CALLBACK (zoom_control_changed_cb), window);
5002         gtk_action_group_add_action (group, action);
5003         g_object_unref (action);
5004
5005         action = g_object_new (EV_TYPE_NAVIGATION_ACTION,
5006                                "name", NAVIGATION_ACTION,
5007                                "label", _("Navigation"),
5008                                "is_important", TRUE,
5009                                "short_label", _("Back"),
5010                                "stock_id", GTK_STOCK_GO_DOWN,
5011                                /*translators: this is the history action*/
5012                                "tooltip", _("Move across visited pages"),
5013                                NULL);
5014         g_signal_connect (action, "activate_link",
5015                           G_CALLBACK (navigation_action_activate_link_cb), window);
5016         gtk_action_group_add_action (group, action);
5017         g_object_unref (action);
5018
5019         action = g_object_new (EV_TYPE_OPEN_RECENT_ACTION,
5020                                "name", "FileOpenRecent",
5021                                "label", _("_Open..."),
5022                                "tooltip", _("Open an existing document"),
5023                                "stock_id", GTK_STOCK_OPEN,
5024                                NULL);
5025         g_signal_connect (action, "activate",
5026                           G_CALLBACK (ev_window_cmd_file_open), window);
5027         g_signal_connect (action, "item_activated",
5028                           G_CALLBACK (ev_window_open_recent_action_item_activated),
5029                           window);
5030         gtk_action_group_add_action (group, action);
5031         g_object_unref (action);
5032 }
5033
5034 static void
5035 set_action_properties (GtkActionGroup *action_group)
5036 {
5037         GtkAction *action;
5038
5039         action = gtk_action_group_get_action (action_group, "GoPreviousPage");
5040         g_object_set (action, "is-important", TRUE, NULL);
5041         /*translators: this is the label for toolbar button*/
5042         g_object_set (action, "short_label", _("Previous"), NULL);
5043
5044         action = gtk_action_group_get_action (action_group, "GoNextPage");
5045         g_object_set (action, "is-important", TRUE, NULL);
5046         /*translators: this is the label for toolbar button*/
5047         g_object_set (action, "short_label", _("Next"), NULL);
5048
5049         action = gtk_action_group_get_action (action_group, "ViewZoomIn");
5050         /*translators: this is the label for toolbar button*/
5051         g_object_set (action, "short_label", _("Zoom In"), NULL);
5052
5053         action = gtk_action_group_get_action (action_group, "ViewZoomOut");
5054         /*translators: this is the label for toolbar button*/
5055         g_object_set (action, "short_label", _("Zoom Out"), NULL);
5056
5057         action = gtk_action_group_get_action (action_group, "ViewBestFit");
5058         /*translators: this is the label for toolbar button*/
5059         g_object_set (action, "short_label", _("Best Fit"), NULL);
5060
5061         action = gtk_action_group_get_action (action_group, "ViewPageWidth");
5062         /*translators: this is the label for toolbar button*/
5063         g_object_set (action, "short_label", _("Fit Width"), NULL);
5064
5065         action = gtk_action_group_get_action (action_group, "LeaveFullscreen");
5066         g_object_set (action, "is-important", TRUE, NULL);
5067 }
5068
5069 static void
5070 set_chrome_actions (EvWindow *window)
5071 {
5072         EvWindowPrivate *priv = window->priv;
5073         GtkActionGroup *action_group = priv->action_group;
5074         GtkAction *action;
5075
5076         action= gtk_action_group_get_action (action_group, "ViewToolbar");
5077         g_signal_handlers_block_by_func
5078                 (action, G_CALLBACK (ev_window_view_toolbar_cb), window);
5079         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
5080                                       (priv->chrome & EV_CHROME_TOOLBAR) != 0);
5081         g_signal_handlers_unblock_by_func
5082                 (action, G_CALLBACK (ev_window_view_toolbar_cb), window);
5083 }
5084
5085 static void
5086 sidebar_widget_model_set (EvSidebarLinks *ev_sidebar_links,
5087                           GParamSpec     *pspec,
5088                           EvWindow       *ev_window)
5089 {
5090         GtkTreeModel *model;
5091         GtkAction *action;
5092
5093         g_object_get (G_OBJECT (ev_sidebar_links),
5094                       "model", &model,
5095                       NULL);
5096
5097         action = gtk_action_group_get_action (ev_window->priv->action_group, PAGE_SELECTOR_ACTION);
5098         ev_page_action_set_model (EV_PAGE_ACTION (action), model);
5099         g_object_unref (model);
5100 }
5101
5102 static gboolean
5103 view_actions_focus_in_cb (GtkWidget *widget, GdkEventFocus *event, EvWindow *window)
5104 {
5105 #ifdef ENABLE_DBUS
5106         GObject *keys;
5107
5108         keys = ev_application_get_media_keys (EV_APP);
5109         ev_media_player_keys_focused (EV_MEDIA_PLAYER_KEYS (keys));
5110 #endif /* ENABLE_DBUS */
5111
5112         update_chrome_flag (window, EV_CHROME_RAISE_TOOLBAR, FALSE);
5113         ev_window_set_action_sensitive (window, "ViewToolbar", TRUE);
5114
5115         ev_window_set_view_accels_sensitivity (window, TRUE);
5116
5117         update_chrome_visibility (window);
5118
5119         return FALSE;
5120 }
5121
5122 static gboolean
5123 view_actions_focus_out_cb (GtkWidget *widget, GdkEventFocus *event, EvWindow *window)
5124 {
5125         ev_window_set_view_accels_sensitivity (window, FALSE);
5126
5127         return FALSE;
5128 }
5129
5130 static void
5131 sidebar_page_main_widget_update_cb (GObject *ev_sidebar_page,
5132                                     GParamSpec         *pspec,
5133                                     EvWindow           *ev_window)
5134 {
5135         GtkWidget *widget;
5136         
5137         g_object_get (ev_sidebar_page, "main_widget", &widget, NULL);
5138
5139         if (widget != NULL) {           
5140                 g_signal_connect_object (widget, "focus_in_event",
5141                                          G_CALLBACK (view_actions_focus_in_cb),
5142                                          ev_window, 0);
5143                 g_signal_connect_object (widget, "focus_out_event",
5144                                          G_CALLBACK (view_actions_focus_out_cb),
5145                                          ev_window, 0);
5146                 g_object_unref (widget);
5147         }
5148 }
5149
5150 static gboolean
5151 window_state_event_cb (EvWindow *window, GdkEventWindowState *event, gpointer dummy)
5152 {
5153         if (!(event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) {
5154                 gboolean maximized;
5155
5156                 maximized = event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED;
5157                 if (!ev_window_is_empty (window))
5158                         ev_metadata_manager_set_boolean (window->priv->uri, "window_maximized", maximized);
5159         }
5160
5161         return FALSE;
5162 }
5163
5164 static gboolean
5165 window_configure_event_cb (EvWindow *window, GdkEventConfigure *event, gpointer dummy)
5166 {
5167         char *uri = window->priv->uri;
5168         GdkWindowState state;
5169         int x, y, width, height, document_width, document_height;
5170
5171         state = gdk_window_get_state (GTK_WIDGET (window)->window);
5172
5173         if (!(state & GDK_WINDOW_STATE_FULLSCREEN)) {
5174                 gtk_window_get_position (GTK_WINDOW (window), &x, &y);
5175                 gtk_window_get_size (GTK_WINDOW (window), &width, &height);
5176
5177                 if (!ev_window_is_empty (window) && window->priv->page_cache) {
5178                         ev_page_cache_get_max_width (window->priv->page_cache, 
5179                                                      0, 1.0,
5180                                                      &document_width);
5181                         ev_page_cache_get_max_height (window->priv->page_cache, 
5182                                                       0, 1.0,
5183                                                       &document_height);                        
5184                         ev_metadata_manager_set_double (uri, "window_width_ratio", 
5185                                                         (double)width / document_width);
5186                         ev_metadata_manager_set_double (uri, "window_height_ratio", 
5187                                                         (double)height / document_height);
5188                         
5189                         ev_metadata_manager_set_int (uri, "window_x", x);
5190                         ev_metadata_manager_set_int (uri, "window_y", y);
5191                         ev_metadata_manager_set_int (uri, "window_width", width);
5192                         ev_metadata_manager_set_int (uri, "window_height", height);
5193                 }
5194         }
5195
5196         return FALSE;
5197 }
5198
5199 static void
5200 launch_action (EvWindow *window, EvLinkAction *action)
5201 {
5202         const char *filename = ev_link_action_get_filename (action);
5203         GAppInfo *app_info;
5204         GFile *file;
5205         GList file_list = {NULL};
5206         GAppLaunchContext *context;
5207         GError *error = NULL;
5208
5209         if (filename == NULL)
5210                 return;
5211
5212         if (g_path_is_absolute (filename)) {
5213                 file = g_file_new_for_path (filename);
5214         } else {
5215                 GFile *base_file;
5216                 gchar *dir;
5217
5218                 dir = g_path_get_dirname (window->priv->uri);
5219                 base_file = g_file_new_for_uri (dir);
5220                 g_free (dir);
5221                 
5222                 file = g_file_resolve_relative_path (base_file, filename);
5223                 g_object_unref (base_file);
5224         }
5225
5226         app_info = g_file_query_default_handler (file, NULL, &error);
5227         if (!app_info) {
5228                 ev_window_error_message (window, error,
5229                                          "%s",
5230                                          _("Unable to launch external application."));
5231                 g_object_unref (file);
5232                 g_error_free (error);
5233
5234                 return;
5235         }
5236
5237         context = G_APP_LAUNCH_CONTEXT (gdk_app_launch_context_new ());
5238         gdk_app_launch_context_set_screen (GDK_APP_LAUNCH_CONTEXT (context),
5239                                            gtk_window_get_screen (GTK_WINDOW (window)));
5240         gdk_app_launch_context_set_timestamp (GDK_APP_LAUNCH_CONTEXT (context), GDK_CURRENT_TIME);
5241         
5242         file_list.data = file;
5243         if (!g_app_info_launch (app_info, &file_list, context, &error)) {
5244                 ev_window_error_message (window, error,
5245                                          "%s",
5246                                          _("Unable to launch external application."));
5247                 g_error_free (error);
5248         }
5249         
5250         g_object_unref (app_info);
5251         g_object_unref (file);
5252
5253         /* According to the PDF spec filename can be an executable. I'm not sure
5254            allowing to launch executables is a good idea though. -- marco */
5255 }
5256
5257 static void
5258 launch_external_uri (EvWindow *window, EvLinkAction *action)
5259 {
5260         const gchar *uri = ev_link_action_get_uri (action);
5261         GError *error = NULL;
5262         gboolean ret;
5263         GAppLaunchContext *context;
5264
5265         context = G_APP_LAUNCH_CONTEXT (gdk_app_launch_context_new ());
5266         gdk_app_launch_context_set_screen (GDK_APP_LAUNCH_CONTEXT (context),
5267                                            gtk_window_get_screen (GTK_WINDOW (window)));
5268         gdk_app_launch_context_set_timestamp (GDK_APP_LAUNCH_CONTEXT (context),
5269                                               GDK_CURRENT_TIME);
5270
5271         if (!g_strstr_len (uri, strlen (uri), "://") &&
5272             !g_str_has_prefix (uri, "mailto:")) {
5273                 gchar *http;
5274                 
5275                 /* Not a valid uri, assuming it's http */
5276                 http = g_strdup_printf ("http://%s", uri);
5277                 ret = g_app_info_launch_default_for_uri (http, NULL, &error);
5278                 g_free (http);
5279         } else {
5280                 ret = g_app_info_launch_default_for_uri (uri, NULL, &error);
5281         }
5282         
5283         if (ret == FALSE) {
5284                 ev_window_error_message (window, error, 
5285                                          "%s", _("Unable to open external link"));
5286                 g_error_free (error);
5287         }
5288 }
5289
5290 static void
5291 open_remote_link (EvWindow *window, EvLinkAction *action)
5292 {
5293         gchar *uri;
5294         gchar *dir;
5295
5296         dir = g_path_get_dirname (window->priv->uri);
5297         
5298         uri = g_build_filename (dir, ev_link_action_get_filename (action),
5299                                 NULL);
5300         g_free (dir);
5301
5302         ev_application_open_uri_at_dest (EV_APP, uri,
5303                                          gtk_window_get_screen (GTK_WINDOW (window)),
5304                                          ev_link_action_get_dest (action),
5305                                          0,
5306                                          NULL, 
5307                                          GDK_CURRENT_TIME);
5308
5309         g_free (uri);
5310 }
5311
5312 static void
5313 do_action_named (EvWindow *window, EvLinkAction *action)
5314 {
5315         const gchar *name = ev_link_action_get_name (action);
5316
5317         if (g_ascii_strcasecmp (name, "FirstPage") == 0) {
5318                 ev_window_cmd_go_first_page (NULL, window);
5319         } else if (g_ascii_strcasecmp (name, "PrevPage") == 0) {
5320                 ev_window_cmd_go_previous_page (NULL, window);
5321         } else if (g_ascii_strcasecmp (name, "NextPage") == 0) {
5322                 ev_window_cmd_go_next_page (NULL, window);
5323         } else if (g_ascii_strcasecmp (name, "LastPage") == 0) {
5324                 ev_window_cmd_go_last_page (NULL, window);
5325         } else if (g_ascii_strcasecmp (name, "GoToPage") == 0) {
5326                 ev_window_cmd_focus_page_selector (NULL, window);
5327         } else if (g_ascii_strcasecmp (name, "Find") == 0) {
5328                 ev_window_cmd_edit_find (NULL, window);
5329         } else if (g_ascii_strcasecmp (name, "Close") == 0) {
5330                 ev_window_cmd_file_close_window (NULL, window);
5331         } else {
5332                 g_warning ("Unimplemented named action: %s, please post a "
5333                            "bug report in Evince bugzilla "
5334                            "(http://bugzilla.gnome.org) with a testcase.",
5335                            name);
5336         }
5337 }
5338
5339 static void
5340 view_external_link_cb (EvView *view, EvLinkAction *action, EvWindow *window)
5341 {
5342         switch (ev_link_action_get_action_type (action)) {
5343                 case EV_LINK_ACTION_TYPE_GOTO_DEST: {
5344                         EvLinkDest *dest;
5345                         
5346                         dest = ev_link_action_get_dest (action);
5347                         if (!dest)
5348                                 return;
5349
5350                         ev_window_cmd_file_open_copy_at_dest (window, dest);
5351                 }
5352                         break;
5353                 case EV_LINK_ACTION_TYPE_EXTERNAL_URI:
5354                         launch_external_uri (window, action);
5355                         break;
5356                 case EV_LINK_ACTION_TYPE_LAUNCH:
5357                         launch_action (window, action);
5358                         break;
5359                 case EV_LINK_ACTION_TYPE_GOTO_REMOTE:
5360                         open_remote_link (window, action);
5361                         break;
5362                 case EV_LINK_ACTION_TYPE_NAMED:
5363                         do_action_named (window, action);
5364                         break;
5365                 default:
5366                         g_assert_not_reached ();
5367         }
5368 }
5369
5370 static void
5371 ev_view_popup_cmd_open_link (GtkAction *action, EvWindow *window)
5372 {
5373         ev_view_handle_link (EV_VIEW (window->priv->view), window->priv->link);
5374 }
5375
5376 static void
5377 ev_view_popup_cmd_open_link_new_window (GtkAction *action, EvWindow *window)
5378 {
5379         EvLinkAction *ev_action = NULL;
5380         EvLinkDest   *dest;
5381
5382         ev_action = ev_link_get_action (window->priv->link);
5383         if (!ev_action)
5384                 return;
5385
5386         dest = ev_link_action_get_dest (ev_action);
5387         if (!dest)
5388                 return;
5389
5390         ev_window_cmd_file_open_copy_at_dest (window, dest);
5391 }
5392
5393 static void
5394 ev_view_popup_cmd_copy_link_address (GtkAction *action, EvWindow *window)
5395 {
5396         EvLinkAction *ev_action;
5397
5398         ev_action = ev_link_get_action (window->priv->link);
5399         if (!ev_action)
5400                 return;
5401
5402         ev_view_copy_link_address (EV_VIEW (window->priv->view),
5403                                    ev_action);
5404 }
5405
5406
5407 static void
5408 image_save_dialog_response_cb (GtkWidget *fc,
5409                                gint       response_id,
5410                                EvWindow  *ev_window)
5411 {
5412         GFile           *target_file;
5413         gboolean         is_native;
5414         GError          *error = NULL;
5415         GdkPixbuf       *pixbuf;
5416         gchar           *uri;
5417         gchar          **extensions;
5418         gchar           *filename;
5419         gchar           *file_format;
5420         GdkPixbufFormat *format;
5421         GtkFileFilter   *filter;
5422         
5423         if (response_id != GTK_RESPONSE_OK) {
5424                 gtk_widget_destroy (fc);
5425                 return;
5426         }
5427
5428         uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (fc));
5429         filter = gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (fc));
5430         format = g_object_get_data (G_OBJECT (filter), "pixbuf-format");
5431         
5432         if (format == NULL) {
5433                 format = get_gdk_pixbuf_format_by_extension (uri);
5434         }
5435
5436         if (format == NULL) {
5437                 ev_window_error_message (ev_window, NULL, 
5438                                          "%s",
5439                                          _("Couldn't find appropriate format to save image"));
5440                 g_free (uri);
5441                 gtk_widget_destroy (fc);
5442
5443                 return;
5444         }
5445
5446         extensions = gdk_pixbuf_format_get_extensions (format);
5447         if (!g_str_has_suffix (uri, extensions[0])) {
5448                 gchar *uri_extension;
5449                 
5450                 uri_extension = g_strconcat (uri, ".", extensions[0], NULL);
5451                 target_file = g_file_new_for_uri (uri_extension);
5452                 g_free (uri_extension);
5453         } else {
5454                 target_file = g_file_new_for_uri (uri);
5455         }
5456         g_strfreev (extensions);
5457         g_free (uri);
5458         
5459         is_native = g_file_is_native (target_file);
5460         if (is_native) {
5461                 filename = g_file_get_path (target_file);
5462         } else {
5463                 filename = ev_tmp_filename ("saveimage");
5464         }
5465
5466         ev_document_doc_mutex_lock ();
5467         pixbuf = ev_document_images_get_image (EV_DOCUMENT_IMAGES (ev_window->priv->document),
5468                                                ev_window->priv->image);
5469         ev_document_doc_mutex_unlock ();
5470
5471         file_format = gdk_pixbuf_format_get_name (format);
5472         gdk_pixbuf_save (pixbuf, filename, file_format, &error, NULL);
5473         g_free (file_format);
5474         g_object_unref (pixbuf);
5475         
5476         if (error) {
5477                 ev_window_error_message (ev_window, error, 
5478                                          "%s", _("The image could not be saved."));
5479                 g_error_free (error);
5480                 g_free (filename);
5481                 g_object_unref (target_file);
5482                 gtk_widget_destroy (fc);
5483
5484                 return;
5485         }
5486
5487         if (!is_native) {
5488                 GFile *source_file;
5489                 
5490                 source_file = g_file_new_for_path (filename);
5491                 
5492                 ev_window_save_remote (ev_window, EV_SAVE_IMAGE,
5493                                        source_file, target_file);
5494                 g_object_unref (source_file);
5495         }
5496         
5497         g_free (filename);
5498         g_object_unref (target_file);
5499         gtk_widget_destroy (fc);
5500 }
5501
5502 static void
5503 ev_view_popup_cmd_save_image_as (GtkAction *action, EvWindow *window)
5504 {
5505         GtkWidget *fc;
5506
5507         if (!window->priv->image)
5508                 return;
5509
5510         fc = gtk_file_chooser_dialog_new (_("Save Image"),
5511                                           GTK_WINDOW (window),
5512                                           GTK_FILE_CHOOSER_ACTION_SAVE,
5513                                           GTK_STOCK_CANCEL,
5514                                           GTK_RESPONSE_CANCEL,
5515                                           GTK_STOCK_SAVE, GTK_RESPONSE_OK,
5516                                           NULL);
5517
5518         gtk_dialog_set_default_response (GTK_DIALOG (fc), GTK_RESPONSE_OK);
5519         gtk_dialog_set_alternative_button_order (GTK_DIALOG (fc),
5520                                                  GTK_RESPONSE_OK,
5521                                                  GTK_RESPONSE_CANCEL,
5522                                                  -1);
5523
5524         gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (fc), FALSE);
5525         gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (fc), TRUE);
5526         
5527         file_chooser_dialog_add_writable_pixbuf_formats (GTK_FILE_CHOOSER (fc));
5528         
5529         g_signal_connect (fc, "response",
5530                           G_CALLBACK (image_save_dialog_response_cb),
5531                           window);
5532
5533         gtk_widget_show (fc);
5534 }
5535
5536 static void
5537 ev_view_popup_cmd_copy_image (GtkAction *action, EvWindow *window)
5538 {
5539         GtkClipboard *clipboard;
5540         GdkPixbuf    *pixbuf;
5541
5542         if (!window->priv->image)
5543                 return;
5544         
5545         clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window),
5546                                               GDK_SELECTION_CLIPBOARD);
5547         ev_document_doc_mutex_lock ();
5548         pixbuf = ev_document_images_get_image (EV_DOCUMENT_IMAGES (window->priv->document),
5549                                                window->priv->image);
5550         ev_document_doc_mutex_unlock ();
5551         
5552         gtk_clipboard_set_image (clipboard, pixbuf);
5553         g_object_unref (pixbuf);
5554 }
5555
5556 static void
5557 ev_attachment_popup_cmd_open_attachment (GtkAction *action, EvWindow *window)
5558 {
5559         GList     *l;
5560         GdkScreen *screen;
5561         
5562         if (!window->priv->attach_list)
5563                 return;
5564
5565         screen = gtk_window_get_screen (GTK_WINDOW (window));
5566
5567         for (l = window->priv->attach_list; l && l->data; l = g_list_next (l)) {
5568                 EvAttachment *attachment;
5569                 GError       *error = NULL;
5570                 
5571                 attachment = (EvAttachment *) l->data;
5572                 
5573                 ev_attachment_open (attachment, screen, GDK_CURRENT_TIME, &error);
5574
5575                 if (error) {
5576                         ev_window_error_message (window, error, 
5577                                                  "%s", _("Unable to open attachment"));
5578                         g_error_free (error);
5579                 }
5580         }
5581 }
5582
5583 static void
5584 attachment_save_dialog_response_cb (GtkWidget *fc,
5585                                     gint       response_id,
5586                                     EvWindow  *ev_window)
5587 {
5588         GFile                *target_file;
5589         gchar                *uri;
5590         GList                *l;
5591         GtkFileChooserAction  fc_action;
5592         gboolean              is_dir;
5593         gboolean              is_native;
5594         
5595         if (response_id != GTK_RESPONSE_OK) {
5596                 gtk_widget_destroy (fc);
5597                 return;
5598         }
5599
5600         uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (fc));
5601         target_file = g_file_new_for_uri (uri);
5602         g_object_get (G_OBJECT (fc), "action", &fc_action, NULL);
5603         is_dir = (fc_action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
5604         is_native = g_file_is_native (target_file);
5605         
5606         for (l = ev_window->priv->attach_list; l && l->data; l = g_list_next (l)) {
5607                 EvAttachment *attachment;
5608                 GFile        *save_to;
5609                 GError       *error = NULL;
5610                 
5611                 attachment = (EvAttachment *) l->data;
5612
5613                 if (is_native) {
5614                         if (is_dir) {
5615                                 save_to = g_file_get_child (target_file,
5616                                                             ev_attachment_get_name (attachment));
5617                         } else {
5618                                 save_to = g_object_ref (target_file);
5619                         }
5620                 } else {
5621                         save_to = ev_tmp_file_get ("saveattachment");
5622                 }
5623
5624                 ev_attachment_save (attachment, save_to, &error);
5625                 
5626                 if (error) {
5627                         ev_window_error_message (ev_window, error, 
5628                                                  "%s", _("The attachment could not be saved."));
5629                         g_error_free (error);
5630                         g_object_unref (save_to);
5631
5632                         continue;
5633                 }
5634
5635                 if (!is_native) {
5636                         GFile *dest_file;
5637
5638                         if (is_dir) {
5639                                 dest_file = g_file_get_child (target_file,
5640                                                               ev_attachment_get_name (attachment));
5641                         } else {
5642                                 dest_file = g_object_ref (target_file);
5643                         }
5644
5645                         ev_window_save_remote (ev_window, EV_SAVE_ATTACHMENT,
5646                                                save_to, dest_file);
5647
5648                         g_object_unref (dest_file);
5649                 }
5650
5651                 g_object_unref (save_to);
5652         }
5653
5654         g_free (uri);
5655         g_object_unref (target_file);
5656
5657         gtk_widget_destroy (fc);
5658 }
5659
5660 static void
5661 ev_attachment_popup_cmd_save_attachment_as (GtkAction *action, EvWindow *window)
5662 {
5663         GtkWidget    *fc;
5664         EvAttachment *attachment = NULL;
5665
5666         if (!window->priv->attach_list)
5667                 return;
5668
5669         if (g_list_length (window->priv->attach_list) == 1)
5670                 attachment = (EvAttachment *) window->priv->attach_list->data;
5671         
5672         fc = gtk_file_chooser_dialog_new (
5673                 _("Save Attachment"),
5674                 GTK_WINDOW (window),
5675                 attachment ? GTK_FILE_CHOOSER_ACTION_SAVE : GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
5676                 GTK_STOCK_CANCEL,
5677                 GTK_RESPONSE_CANCEL,
5678                 GTK_STOCK_SAVE, GTK_RESPONSE_OK,
5679                 NULL);
5680
5681         gtk_dialog_set_default_response (GTK_DIALOG (fc), GTK_RESPONSE_OK);
5682         gtk_dialog_set_alternative_button_order (GTK_DIALOG (fc),
5683                                                  GTK_RESPONSE_OK,
5684                                                  GTK_RESPONSE_CANCEL,
5685                                                  -1);
5686
5687         gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (fc), TRUE);
5688         gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (fc), FALSE);
5689
5690         if (attachment)
5691                 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (fc),
5692                                                    ev_attachment_get_name (attachment));
5693
5694         g_signal_connect (fc, "response",
5695                           G_CALLBACK (attachment_save_dialog_response_cb),
5696                           window);
5697
5698         gtk_widget_show (fc);
5699 }
5700
5701 static void
5702 ev_window_media_player_key_pressed (EvWindow    *window,
5703                                     const gchar *key,
5704                                     gpointer     user_data)
5705 {
5706         if (!gtk_window_is_active (GTK_WINDOW (window))) 
5707                 return;
5708         
5709         /* Note how Previous/Next only go to the
5710          * next/previous page despite their icon telling you
5711          * they should go to the beginning/end.
5712          *
5713          * There's very few keyboards with FFW/RWD though,
5714          * so we stick the most useful keybinding on the most
5715          * often seen keys
5716          */
5717         if (strcmp (key, "Play") == 0) {
5718                 ev_window_run_presentation (window);
5719         } else if (strcmp (key, "Previous") == 0) {
5720                 ev_window_cmd_go_previous_page (NULL, window);
5721         } else if (strcmp (key, "Next") == 0) {
5722                 ev_window_cmd_go_next_page (NULL, window);
5723         } else if (strcmp (key, "FastForward") == 0) {
5724                 ev_window_cmd_go_last_page (NULL, window);
5725         } else if (strcmp (key, "Rewind") == 0) {
5726                 ev_window_cmd_go_first_page (NULL, window);
5727         }
5728 }
5729
5730 static void
5731 ev_window_init (EvWindow *ev_window)
5732 {
5733         GtkActionGroup *action_group;
5734         GtkAccelGroup *accel_group;
5735         GError *error = NULL;
5736         GtkWidget *sidebar_widget;
5737         GObject *mpkeys;
5738
5739         g_signal_connect (ev_window, "configure_event",
5740                           G_CALLBACK (window_configure_event_cb), NULL);
5741         g_signal_connect (ev_window, "window_state_event",
5742                           G_CALLBACK (window_state_event_cb), NULL);
5743
5744         ev_window->priv = EV_WINDOW_GET_PRIVATE (ev_window);
5745
5746         ev_window->priv->page_mode = PAGE_MODE_DOCUMENT;
5747         ev_window->priv->title = ev_window_title_new (ev_window);
5748
5749         ev_window->priv->main_box = gtk_vbox_new (FALSE, 0);
5750         gtk_container_add (GTK_CONTAINER (ev_window), ev_window->priv->main_box);
5751         gtk_widget_show (ev_window->priv->main_box);
5752
5753         action_group = gtk_action_group_new ("MenuActions");
5754         ev_window->priv->action_group = action_group;
5755         gtk_action_group_set_translation_domain (action_group, NULL);
5756         gtk_action_group_add_actions (action_group, entries,
5757                                       G_N_ELEMENTS (entries), ev_window);
5758         gtk_action_group_add_toggle_actions (action_group, toggle_entries,
5759                                              G_N_ELEMENTS (toggle_entries),
5760                                              ev_window);
5761         set_action_properties (action_group);
5762         register_custom_actions (ev_window, action_group);
5763
5764         ev_window->priv->ui_manager = gtk_ui_manager_new ();
5765         gtk_ui_manager_insert_action_group (ev_window->priv->ui_manager,
5766                                             action_group, 0);
5767
5768         accel_group =
5769                 gtk_ui_manager_get_accel_group (ev_window->priv->ui_manager);
5770         gtk_window_add_accel_group (GTK_WINDOW (ev_window), accel_group);
5771
5772         ev_window_set_view_accels_sensitivity (ev_window, FALSE);
5773
5774         action_group = gtk_action_group_new ("ViewPopupActions");
5775         ev_window->priv->view_popup_action_group = action_group;
5776         gtk_action_group_set_translation_domain (action_group, NULL);
5777         gtk_action_group_add_actions (action_group, view_popup_entries,
5778                                       G_N_ELEMENTS (view_popup_entries),
5779                                       ev_window);
5780         gtk_ui_manager_insert_action_group (ev_window->priv->ui_manager,
5781                                             action_group, 0);
5782
5783         action_group = gtk_action_group_new ("AttachmentPopupActions");
5784         ev_window->priv->attachment_popup_action_group = action_group;
5785         gtk_action_group_set_translation_domain (action_group, NULL);
5786         gtk_action_group_add_actions (action_group, attachment_popup_entries,
5787                                       G_N_ELEMENTS (attachment_popup_entries),
5788                                       ev_window);
5789         gtk_ui_manager_insert_action_group (ev_window->priv->ui_manager,
5790                                             action_group, 0);
5791
5792         if (!gtk_ui_manager_add_ui_from_file (ev_window->priv->ui_manager,
5793                                               DATADIR"/evince-ui.xml",
5794                                               &error)) {
5795                 g_warning ("building menus failed: %s", error->message);
5796                 g_error_free (error);
5797         }
5798         
5799         ev_window->priv->recent_manager = gtk_recent_manager_get_default ();
5800         ev_window->priv->recent_action_group = NULL;
5801         ev_window->priv->recent_ui_id = 0;
5802         g_signal_connect_swapped (ev_window->priv->recent_manager,
5803                                   "changed",
5804                                   G_CALLBACK (ev_window_setup_recent),
5805                                   ev_window);
5806
5807         ev_window->priv->menubar =
5808                  gtk_ui_manager_get_widget (ev_window->priv->ui_manager,
5809                                             "/MainMenu");
5810         gtk_box_pack_start (GTK_BOX (ev_window->priv->main_box),
5811                             ev_window->priv->menubar,
5812                             FALSE, FALSE, 0);
5813
5814         ev_window->priv->toolbar = GTK_WIDGET 
5815           (g_object_new (EGG_TYPE_EDITABLE_TOOLBAR,
5816                          "ui-manager", ev_window->priv->ui_manager,
5817                          "popup-path", "/ToolbarPopup",
5818                          "model", ev_application_get_toolbars_model (EV_APP),
5819                          NULL));
5820
5821         egg_editable_toolbar_show (EGG_EDITABLE_TOOLBAR (ev_window->priv->toolbar),
5822                                    "DefaultToolBar");
5823         gtk_box_pack_start (GTK_BOX (ev_window->priv->main_box),
5824                             ev_window->priv->toolbar,
5825                             FALSE, FALSE, 0);
5826         gtk_widget_show (ev_window->priv->toolbar);
5827
5828         /* Add the main area */
5829         ev_window->priv->hpaned = gtk_hpaned_new ();
5830         g_signal_connect (ev_window->priv->hpaned,
5831                           "notify::position",
5832                           G_CALLBACK (ev_window_sidebar_position_change_cb),
5833                           ev_window);
5834         
5835         gtk_paned_set_position (GTK_PANED (ev_window->priv->hpaned), SIDEBAR_DEFAULT_SIZE);
5836         gtk_box_pack_start (GTK_BOX (ev_window->priv->main_box), ev_window->priv->hpaned,
5837                             TRUE, TRUE, 0);
5838         gtk_widget_show (ev_window->priv->hpaned);
5839         
5840         ev_window->priv->sidebar = ev_sidebar_new ();
5841         gtk_paned_pack1 (GTK_PANED (ev_window->priv->hpaned),
5842                          ev_window->priv->sidebar, FALSE, FALSE);
5843         gtk_widget_show (ev_window->priv->sidebar);
5844
5845         /* Stub sidebar, for now */
5846
5847         sidebar_widget = ev_sidebar_thumbnails_new ();
5848         ev_window->priv->sidebar_thumbs = sidebar_widget;
5849         g_signal_connect (sidebar_widget,
5850                           "notify::main-widget",
5851                           G_CALLBACK (sidebar_page_main_widget_update_cb),
5852                           ev_window);
5853         sidebar_page_main_widget_update_cb (G_OBJECT (sidebar_widget), NULL, ev_window);
5854         gtk_widget_show (sidebar_widget);
5855         ev_sidebar_add_page (EV_SIDEBAR (ev_window->priv->sidebar),
5856                              sidebar_widget);
5857
5858         sidebar_widget = ev_sidebar_links_new ();
5859         ev_window->priv->sidebar_links = sidebar_widget;
5860         g_signal_connect (sidebar_widget,
5861                           "notify::model",
5862                           G_CALLBACK (sidebar_widget_model_set),
5863                           ev_window);
5864         g_signal_connect (sidebar_widget,
5865                           "link_activated",
5866                           G_CALLBACK (sidebar_links_link_activated_cb),
5867                           ev_window);
5868         sidebar_page_main_widget_update_cb (G_OBJECT (sidebar_widget), NULL, ev_window);
5869         gtk_widget_show (sidebar_widget);
5870         ev_sidebar_add_page (EV_SIDEBAR (ev_window->priv->sidebar),
5871                              sidebar_widget);
5872
5873         sidebar_widget = ev_sidebar_attachments_new ();
5874         ev_window->priv->sidebar_attachments = sidebar_widget;
5875         g_signal_connect_object (sidebar_widget,
5876                                  "popup",
5877                                  G_CALLBACK (attachment_bar_menu_popup_cb),
5878                                  ev_window, 0);
5879         gtk_widget_show (sidebar_widget);
5880         ev_sidebar_add_page (EV_SIDEBAR (ev_window->priv->sidebar),
5881                              sidebar_widget);
5882
5883         sidebar_widget = ev_sidebar_layers_new ();
5884         ev_window->priv->sidebar_layers = sidebar_widget;
5885         g_signal_connect (sidebar_widget,
5886                           "layers_visibility_changed",
5887                           G_CALLBACK (sidebar_layers_visibility_changed),
5888                           ev_window);
5889         gtk_widget_show (sidebar_widget);
5890         ev_sidebar_add_page (EV_SIDEBAR (ev_window->priv->sidebar),
5891                              sidebar_widget);
5892
5893         ev_window->priv->view_box = gtk_vbox_new (FALSE, 0);
5894         ev_window->priv->scrolled_window =
5895                 GTK_WIDGET (g_object_new (GTK_TYPE_SCROLLED_WINDOW,
5896                                           "shadow-type", GTK_SHADOW_IN,
5897                                           NULL));
5898         gtk_box_pack_start (GTK_BOX (ev_window->priv->view_box),
5899                             ev_window->priv->scrolled_window,
5900                             TRUE, TRUE, 0);
5901         gtk_widget_show (ev_window->priv->scrolled_window);
5902
5903         gtk_paned_add2 (GTK_PANED (ev_window->priv->hpaned),
5904                         ev_window->priv->view_box);
5905         gtk_widget_show (ev_window->priv->view_box);
5906
5907         ev_window->priv->view = ev_view_new ();
5908         ev_view_set_screen_dpi (EV_VIEW (ev_window->priv->view),
5909                                 get_screen_dpi (GTK_WINDOW (ev_window)));
5910         ev_window->priv->password_view = ev_password_view_new (GTK_WINDOW (ev_window));
5911         g_signal_connect_swapped (ev_window->priv->password_view,
5912                                   "unlock",
5913                                   G_CALLBACK (ev_window_password_view_unlock),
5914                                   ev_window);
5915         g_signal_connect_object (ev_window->priv->view, "focus_in_event",
5916                                  G_CALLBACK (view_actions_focus_in_cb),
5917                                  ev_window, 0);
5918         g_signal_connect_object (ev_window->priv->view, "focus_out_event",
5919                                  G_CALLBACK (view_actions_focus_out_cb),
5920                                  ev_window, 0);
5921         g_signal_connect_object (ev_window->priv->view, "external-link",
5922                                  G_CALLBACK (view_external_link_cb),
5923                                  ev_window, 0);
5924         g_signal_connect_object (ev_window->priv->view, "handle-link",
5925                                  G_CALLBACK (view_handle_link_cb),
5926                                  ev_window, 0);
5927         g_signal_connect_swapped (ev_window->priv->view, "zoom_invalid",
5928                                  G_CALLBACK (ev_window_set_view_size),
5929                                  ev_window);
5930         g_signal_connect_object (ev_window->priv->view,
5931                                  "popup",
5932                                  G_CALLBACK (view_menu_popup_cb),
5933                                  ev_window, 0);
5934         gtk_widget_show (ev_window->priv->view);
5935         gtk_widget_show (ev_window->priv->password_view);
5936
5937         /* Find Bar */
5938         ev_window->priv->find_bar = egg_find_bar_new ();
5939         gtk_box_pack_end (GTK_BOX (ev_window->priv->main_box),
5940                           ev_window->priv->find_bar,
5941                           FALSE, TRUE, 0);
5942
5943         /* We own a ref on these widgets, as we can swap them in and out */
5944         g_object_ref (ev_window->priv->view);
5945         g_object_ref (ev_window->priv->password_view);
5946
5947         gtk_container_add (GTK_CONTAINER (ev_window->priv->scrolled_window),
5948                            ev_window->priv->view);
5949
5950         g_signal_connect (ev_window->priv->view,
5951                           "notify::sizing-mode",
5952                           G_CALLBACK (ev_window_sizing_mode_changed_cb),
5953                           ev_window);
5954         g_signal_connect (ev_window->priv->view,
5955                           "notify::zoom",
5956                           G_CALLBACK (ev_window_zoom_changed_cb),
5957                           ev_window);
5958         g_signal_connect (ev_window->priv->view,
5959                           "notify::dual-page",
5960                           G_CALLBACK (ev_window_dual_mode_changed_cb),
5961                           ev_window);
5962         g_signal_connect (ev_window->priv->view,
5963                           "notify::continuous",
5964                           G_CALLBACK (ev_window_continuous_changed_cb),
5965                           ev_window);
5966         g_signal_connect (ev_window->priv->view,
5967                           "notify::rotation",
5968                           G_CALLBACK (ev_window_rotation_changed_cb),
5969                           ev_window);
5970         g_signal_connect (ev_window->priv->view,
5971                           "notify::has-selection",
5972                           G_CALLBACK (ev_window_has_selection_changed_cb),
5973                           ev_window);
5974
5975         /* Connect sidebar signals */
5976         g_signal_connect (ev_window->priv->sidebar,
5977                           "notify::visible",
5978                           G_CALLBACK (ev_window_sidebar_visibility_changed_cb),
5979                           ev_window);
5980         g_signal_connect (ev_window->priv->sidebar,
5981                           "notify::current-page",
5982                           G_CALLBACK (ev_window_sidebar_current_page_changed_cb),
5983                           ev_window);
5984
5985         /* Connect to find bar signals */
5986         g_signal_connect (ev_window->priv->find_bar,
5987                           "previous",
5988                           G_CALLBACK (find_bar_previous_cb),
5989                           ev_window);
5990         g_signal_connect (ev_window->priv->find_bar,
5991                           "next",
5992                           G_CALLBACK (find_bar_next_cb),
5993                           ev_window);
5994         g_signal_connect (ev_window->priv->find_bar,
5995                           "close",
5996                           G_CALLBACK (find_bar_close_cb),
5997                           ev_window);
5998         g_signal_connect (ev_window->priv->find_bar,
5999                           "notify::search-string",
6000                           G_CALLBACK (find_bar_search_changed_cb),
6001                           ev_window);
6002         g_signal_connect (ev_window->priv->find_bar,
6003                           "notify::case-sensitive",
6004                           G_CALLBACK (find_bar_search_changed_cb),
6005                           ev_window);
6006         g_signal_connect (ev_window->priv->find_bar,
6007                           "notify::visible",
6008                           G_CALLBACK (find_bar_visibility_changed_cb),
6009                           ev_window);
6010         g_signal_connect (ev_window->priv->find_bar,
6011                           "scroll",
6012                           G_CALLBACK (find_bar_scroll),
6013                           ev_window);
6014
6015         /* Popups */
6016         ev_window->priv->view_popup = gtk_ui_manager_get_widget (ev_window->priv->ui_manager,
6017                                                                  "/DocumentPopup");
6018         ev_window->priv->link = NULL;
6019
6020         ev_window->priv->attachment_popup = gtk_ui_manager_get_widget (ev_window->priv->ui_manager,
6021                                                                        "/AttachmentPopup");
6022         ev_window->priv->attach_list = NULL;
6023
6024         /* Media player keys */
6025         mpkeys = ev_application_get_media_keys (EV_APP);
6026         if (mpkeys) {
6027                 g_signal_connect_swapped (mpkeys, "key_pressed",
6028                                           G_CALLBACK (ev_window_media_player_key_pressed),
6029                                           ev_window);
6030         }
6031         
6032         /* Give focus to the document view */
6033         gtk_widget_grab_focus (ev_window->priv->view);
6034
6035         /* Set it user interface params */
6036         ev_window_setup_recent (ev_window);
6037
6038         setup_chrome_from_metadata (ev_window);
6039         set_chrome_actions (ev_window);
6040         update_chrome_visibility (ev_window);
6041
6042         gtk_window_set_default_size (GTK_WINDOW (ev_window), 600, 600);
6043
6044         setup_view_from_metadata (ev_window);
6045         setup_sidebar_from_metadata (ev_window);
6046
6047         ev_window_sizing_mode_changed_cb (EV_VIEW (ev_window->priv->view), NULL, ev_window);
6048         ev_window_setup_action_sensitivity (ev_window);
6049
6050         /* Drag and Drop */
6051         gtk_drag_dest_set (GTK_WIDGET (ev_window),
6052                            GTK_DEST_DEFAULT_ALL,
6053                            NULL, 0,
6054                            GDK_ACTION_COPY);
6055         gtk_drag_dest_add_uri_targets (GTK_WIDGET (ev_window));
6056 }
6057
6058 /**
6059  * ev_window_new:
6060  *
6061  * Creates a #GtkWidget that represents the window.
6062  *
6063  * Returns: the #GtkWidget that represents the window.
6064  */
6065 GtkWidget *
6066 ev_window_new (void)
6067 {
6068         GtkWidget *ev_window;
6069
6070         ev_window = GTK_WIDGET (g_object_new (EV_TYPE_WINDOW,
6071                                               "type", GTK_WINDOW_TOPLEVEL,
6072                                               NULL));
6073
6074         return ev_window;
6075 }