Evince
Evince is a document viewer capable of displaying multiple and single page document formats like PDF and Postscript.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ev-window.c
Go to the documentation of this file.
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) 2009 Juanjo Marín <juanj.marin@juntadeandalucia.es>
5  * Copyright (C) 2008 Carlos Garcia Campos
6  * Copyright (C) 2004 Martin Kretzschmar
7  * Copyright (C) 2004 Red Hat, Inc.
8  * Copyright (C) 2000, 2001, 2002, 2003, 2004 Marco Pesenti Gritti
9  * Copyright © 2003, 2004, 2005, 2009, 2012 Christian Persch
10  *
11  * Author:
12  * Martin Kretzschmar <martink@gnome.org>
13  *
14  * Evince is free software; you can redistribute it and/or modify it
15  * under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (at your option) any later version.
18  *
19  * Evince is distributed in the hope that it will be useful, but
20  * WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22  * General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
27  */
28 
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32 
33 #include <errno.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <unistd.h>
37 #include <math.h>
38 
39 #include <glib/gstdio.h>
40 #include <glib/gi18n.h>
41 #include <gio/gio.h>
42 #include <gtk/gtk.h>
43 
44 #include "ev-find-sidebar.h"
45 #include "ev-annotations-toolbar.h"
46 #include "ev-application.h"
47 #include "ev-document-factory.h"
48 #include "ev-document-find.h"
49 #include "ev-document-fonts.h"
50 #include "ev-document-images.h"
51 #include "ev-document-links.h"
53 #include "ev-document-misc.h"
54 #include "ev-file-exporter.h"
55 #include "ev-file-helpers.h"
56 #include "ev-file-monitor.h"
57 #include "ev-history.h"
58 #include "ev-image.h"
59 #include "ev-job-scheduler.h"
60 #include "ev-jobs.h"
61 #include "ev-loading-message.h"
62 #include "ev-message-area.h"
63 #include "ev-metadata.h"
64 #include "ev-page-action-widget.h"
65 #include "ev-password-view.h"
66 #include "ev-properties-dialog.h"
67 #include "ev-sidebar-annotations.h"
68 #include "ev-sidebar-attachments.h"
69 #include "ev-sidebar-bookmarks.h"
70 #include "ev-sidebar.h"
71 #include "ev-sidebar-links.h"
72 #include "ev-sidebar-page.h"
73 #include "ev-sidebar-thumbnails.h"
74 #include "ev-sidebar-layers.h"
75 #include "ev-stock-icons.h"
76 #include "ev-utils.h"
77 #include "ev-keyring.h"
78 #include "ev-view.h"
79 #include "ev-view-presentation.h"
80 #include "ev-view-type-builtins.h"
81 #include "ev-window.h"
82 #include "ev-window-title.h"
83 #include "ev-print-operation.h"
86 #include "ev-bookmark-action.h"
87 #include "ev-zoom-action.h"
88 #include "ev-toolbar.h"
89 #include "ev-bookmarks.h"
90 #include "ev-recent-view.h"
91 #include "ev-search-box.h"
92 
93 #ifdef ENABLE_DBUS
94 #include "ev-gdbus-generated.h"
95 #include "ev-media-player-keys.h"
96 #endif /* ENABLE_DBUS */
97 
98 #ifdef GDK_WINDOWING_X11
99 #include <gdk/gdkx.h>
100 #include <X11/extensions/XInput2.h>
101 #endif
102 
103 typedef enum {
107 
108 typedef enum {
115 } EvChrome;
116 
117 typedef enum {
121 } EvSaveType;
122 
123 typedef enum {
127 
129  /* UI */
131 
132  GtkWidget *main_box;
133  GtkWidget *toolbar;
134  GtkWidget *hpaned;
135  GtkWidget *view_box;
136  GtkWidget *sidebar;
137  GtkWidget *search_box;
138  GtkWidget *search_bar;
139  GtkWidget *scrolled_window;
140  GtkWidget *view;
141  GtkWidget *loading_message;
142  GtkWidget *presentation_view;
143  GtkWidget *message_area;
144  GtkWidget *password_view;
145  GtkWidget *sidebar_thumbs;
146  GtkWidget *sidebar_links;
147  GtkWidget *find_sidebar;
149  GtkWidget *sidebar_layers;
150  GtkWidget *sidebar_annots;
151  GtkWidget *sidebar_bookmarks;
152  GtkWidget *annots_toolbar;
153 
154  /* Settings */
155  GSettings *settings;
156  GSettings *default_settings;
157  GSettings *lockdown_settings;
158 
159  /* Progress Messages */
161  GCancellable *progress_cancellable;
162 
163  /* Fullscreen */
164  GtkWidget *fs_overlay;
165  GtkWidget *fs_eventbox;
166  GtkWidget *fs_revealer;
167  GtkWidget *fs_toolbar;
170 
171  /* Loading message */
173 
174  /* Dialogs */
175  GtkWidget *properties;
176  GtkWidget *print_dialog;
177 
178  GtkRecentManager *recent_manager;
179 
180  /* Popup view */
181  GMenuModel *view_popup_menu;
182  GtkWidget *view_popup;
186 
187  /* Popup attachment */
189  GtkWidget *attachment_popup;
190  GList *attach_list;
191 
192  /* For bookshelf view of recent items*/
194 
195  /* Document */
197  char *uri;
198  glong uri_mtime;
199  char *local_uri;
200  gboolean in_reload;
203 
211 
212  /* Load params */
216 
220 
221  /* Printing */
222  GQueue *print_queue;
223  GtkPrintSettings *print_settings;
224  GtkPageSetup *print_page_setup;
226 
227 #ifdef ENABLE_DBUS
228  /* DBus */
229  EvEvinceWindow *skeleton;
230  gchar *dbus_object_path;
231 #endif
232 
234 
235  /* Caret navigation */
237 
238  /* Send to */
240 };
241 
242 #define EV_WINDOW_GET_PRIVATE(object) \
243  (G_TYPE_INSTANCE_GET_PRIVATE ((object), EV_TYPE_WINDOW, EvWindowPrivate))
244 
245 #define EV_WINDOW_IS_PRESENTATION(w) (w->priv->presentation_view != NULL)
246 
247 #define GS_LOCKDOWN_SCHEMA_NAME "org.gnome.desktop.lockdown"
248 #define GS_LOCKDOWN_SAVE "disable-save-to-disk"
249 #define GS_LOCKDOWN_PRINT "disable-printing"
250 #define GS_LOCKDOWN_PRINT_SETUP "disable-print-setup"
251 
252 #ifdef ENABLE_DBUS
253 #define EV_WINDOW_DBUS_OBJECT_PATH "/org/gnome/evince/Window/%d"
254 #define EV_WINDOW_DBUS_INTERFACE "org.gnome.evince.Window"
255 #endif
256 
257 #define GS_SCHEMA_NAME "org.gnome.Evince"
258 #define GS_OVERRIDE_RESTRICTIONS "override-restrictions"
259 #define GS_PAGE_CACHE_SIZE "page-cache-size"
260 #define GS_AUTO_RELOAD "auto-reload"
261 #define GS_LAST_DOCUMENT_DIRECTORY "document-directory"
262 #define GS_LAST_PICTURES_DIRECTORY "pictures-directory"
263 #define GS_ALLOW_LINKS_CHANGE_ZOOM "allow-links-change-zoom"
264 
265 #define SIDEBAR_DEFAULT_SIZE 132
266 #define LINKS_SIDEBAR_ID "links"
267 #define THUMBNAILS_SIDEBAR_ID "thumbnails"
268 #define ATTACHMENTS_SIDEBAR_ID "attachments"
269 #define LAYERS_SIDEBAR_ID "layers"
270 #define ANNOTS_SIDEBAR_ID "annotations"
271 #define BOOKMARKS_SIDEBAR_ID "bookmarks"
272 
273 #define EV_PRINT_SETTINGS_FILE "print-settings"
274 #define EV_PRINT_SETTINGS_GROUP "Print Settings"
275 #define EV_PAGE_SETUP_GROUP "Page Setup"
276 
277 #define EV_TOOLBARS_FILENAME "evince-toolbar.xml"
278 
279 #define TOOLBAR_RESOURCE_PATH "/org/gnome/evince/shell/ui/toolbar.xml"
280 
281 #define FULLSCREEN_POPUP_TIMEOUT 2
282 #define FULLSCREEN_TRANSITION_DURATION 1000 /* in milliseconds */
283 
284 static const gchar *document_print_settings[] = {
285  GTK_PRINT_SETTINGS_COLLATE,
286  GTK_PRINT_SETTINGS_REVERSE,
287  GTK_PRINT_SETTINGS_NUMBER_UP,
288  GTK_PRINT_SETTINGS_SCALE,
289  GTK_PRINT_SETTINGS_PRINT_PAGES,
290  GTK_PRINT_SETTINGS_PAGE_RANGES,
291  GTK_PRINT_SETTINGS_PAGE_SET,
292  GTK_PRINT_SETTINGS_OUTPUT_URI
293 };
294 
295 static void ev_window_update_actions_sensitivity (EvWindow *ev_window);
296 static void ev_window_sidebar_visibility_changed_cb (EvSidebar *ev_sidebar,
297  GParamSpec *pspec,
298  EvWindow *ev_window);
300  EvWindowPageMode page_mode);
301 static void ev_window_load_job_cb (EvJob *job,
302  gpointer data);
304  EvLinkDest *dest);
305 static void ev_window_reload_job_cb (EvJob *job,
306  EvWindow *window);
307 static void ev_window_save_job_cb (EvJob *save,
308  EvWindow *window);
310  GParamSpec *pspec,
311  EvWindow *ev_window);
312 static void ev_window_zoom_changed_cb (EvDocumentModel *model,
313  GParamSpec *pspec,
314  EvWindow *ev_window);
315 static void ev_window_add_recent (EvWindow *window,
316  const char *filename);
319  gboolean unfullscreen_window);
322  gboolean unfullscreen_window);
323 static void ev_window_popup_cmd_open_link (GSimpleAction *action,
324  GVariant *parameter,
325  gpointer user_data);
326 static void ev_window_popup_cmd_open_link_new_window(GSimpleAction *action,
327  GVariant *parameter,
328  gpointer user_data);
329 static void ev_window_popup_cmd_copy_link_address (GSimpleAction *action,
330  GVariant *parameter,
331  gpointer user_data);
332 static void ev_window_popup_cmd_save_image_as (GSimpleAction *action,
333  GVariant *parameter,
334  gpointer user_data);
335 static void ev_window_popup_cmd_copy_image (GSimpleAction *action,
336  GVariant *parameter,
337  gpointer user_data);
338 static void ev_window_popup_cmd_annot_properties (GSimpleAction *action,
339  GVariant *parameter,
340  gpointer user_data);
341 static void ev_window_popup_cmd_remove_annotation (GSimpleAction *action,
342  GVariant *parameter,
343  gpointer user_data);
344 static void ev_window_popup_cmd_open_attachment (GSimpleAction *action,
345  GVariant *parameter,
346  gpointer user_data);
347 static void ev_window_popup_cmd_save_attachment_as (GSimpleAction *action,
348  GVariant *parameter,
349  gpointer user_data);
350 static void view_handle_link_cb (EvView *view,
351  EvLink *link,
352  EvWindow *window);
353 static void activate_link_cb (GObject *object,
354  EvLink *link,
355  EvWindow *window);
357  EvLinkAction *action);
358 static void ev_window_load_file_remote (EvWindow *ev_window,
359  GFile *source_file);
361  const gchar *key,
362  gpointer user_data);
363 #ifdef ENABLE_DBUS
364 static void ev_window_emit_closed (EvWindow *window);
365 static void ev_window_emit_doc_loaded (EvWindow *window);
366 #endif
368 
369 static void ev_window_show_find_bar (EvWindow *ev_window,
370  gboolean restart);
371 static void ev_window_close_find_bar (EvWindow *ev_window);
372 static void ev_window_destroy_recent_view (EvWindow *ev_window);
373 static void recent_view_item_activated_cb (EvRecentView *recent_view,
374  const char *uri,
375  EvWindow *ev_window);
376 
377 static gchar *nautilus_sendto = NULL;
378 
379 G_DEFINE_TYPE (EvWindow, ev_window, GTK_TYPE_APPLICATION_WINDOW)
380 
381 static gdouble
383 {
384  GdkScreen *screen;
385 
386  screen = gtk_window_get_screen (GTK_WINDOW (window));
387  return ev_document_misc_get_screen_dpi (screen);
388 }
389 
390 static gboolean
392 {
394 }
395 
396 static void
398  const char *name,
399  gboolean enabled)
400 {
401  GAction *action;
402 
403  action = g_action_map_lookup_action (G_ACTION_MAP (ev_window), name);
404  g_simple_action_set_enabled (G_SIMPLE_ACTION (action), enabled);
405 }
406 
407 static void
409 {
410  EvDocument *document = ev_window->priv->document;
411  EvView *view = EV_VIEW (ev_window->priv->view);
412  const EvDocumentInfo *info = NULL;
413  gboolean has_document = FALSE;
414  gboolean ok_to_print = TRUE;
415  gboolean ok_to_copy = TRUE;
416  gboolean has_properties = TRUE;
417  gboolean override_restrictions = TRUE;
418  gboolean can_get_text = FALSE;
419  gboolean can_find = FALSE;
420  gboolean can_find_in_page;
421  gboolean can_annotate = FALSE;
422  gboolean presentation_mode;
423  gboolean recent_view_mode;
424  gboolean dual_mode = FALSE;
425  gboolean has_pages = FALSE;
426  int n_pages = 0, page = -1;
427 
428  if (document) {
429  has_document = TRUE;
430  info = ev_document_get_info (document);
431  page = ev_document_model_get_page (ev_window->priv->model);
432  n_pages = ev_document_get_n_pages (ev_window->priv->document);
433  has_pages = n_pages > 0;
434  dual_mode = ev_document_model_get_dual_page (ev_window->priv->model);
435  }
436 
437  if (!info || info->fields_mask == 0) {
438  has_properties = FALSE;
439  }
440 
441  if (has_document && EV_IS_SELECTION (document)) {
442  can_get_text = TRUE;
443  }
444 
445  if (has_pages && EV_IS_DOCUMENT_FIND (document)) {
446  can_find = TRUE;
447  }
448 
449  if (has_document && EV_IS_DOCUMENT_ANNOTATIONS (document)) {
451  }
452 
453  if (has_document && ev_window->priv->settings) {
454  override_restrictions =
455  g_settings_get_boolean (ev_window->priv->settings,
457  }
458 
459  if (!override_restrictions && info && info->fields_mask & EV_DOCUMENT_INFO_PERMISSIONS) {
460  ok_to_print = (info->permissions & EV_DOCUMENT_PERMISSIONS_OK_TO_PRINT);
461  ok_to_copy = (info->permissions & EV_DOCUMENT_PERMISSIONS_OK_TO_COPY);
462  }
463 
464  if (has_document && !ev_print_operation_exists_for_document(document))
465  ok_to_print = FALSE;
466 
467  if (has_document && ev_window->priv->lockdown_settings &&
468  g_settings_get_boolean (ev_window->priv->lockdown_settings, GS_LOCKDOWN_SAVE)) {
469  ok_to_copy = FALSE;
470  }
471 
472  if (has_document && ev_window->priv->lockdown_settings &&
473  g_settings_get_boolean (ev_window->priv->lockdown_settings, GS_LOCKDOWN_PRINT)) {
474  ok_to_print = FALSE;
475  }
476 
477  /* Get modes */
478  presentation_mode = EV_WINDOW_IS_PRESENTATION (ev_window);
479  recent_view_mode = ev_window_is_recent_view (ev_window);
480 
481  /* File menu */
482  ev_window_set_action_enabled (ev_window, "open-copy", has_document);
483  ev_window_set_action_enabled (ev_window, "save-copy", has_document &&
484  ok_to_copy && !recent_view_mode);
485  ev_window_set_action_enabled (ev_window, "print", has_pages &&
486  ok_to_print && !recent_view_mode);
487  ev_window_set_action_enabled (ev_window, "show-properties",
488  has_document && has_properties &&
489  !recent_view_mode);
490  ev_window_set_action_enabled (ev_window, "open-containing-folder",
491  has_document && !recent_view_mode);
492  ev_window_set_action_enabled (ev_window, "send-to", has_document &&
493  ev_window->priv->has_mailto_handler &&
494  nautilus_sendto &&
495  !recent_view_mode);
496  ev_window_set_action_enabled (ev_window, "fullscreen",
497  has_document && !recent_view_mode);
498  ev_window_set_action_enabled (ev_window, "presentation",
499  has_document && !recent_view_mode);
500 
501  /* Edit menu */
502  ev_window_set_action_enabled (ev_window, "select-all", has_pages &&
503  can_get_text && !recent_view_mode);
504  ev_window_set_action_enabled (ev_window, "find", can_find &&
505  !recent_view_mode);
506  ev_window_set_action_enabled (ev_window, "toggle-find", can_find &&
507  !recent_view_mode);
508  ev_window_set_action_enabled (ev_window, "toggle-edit-annots", can_annotate &&
509  !recent_view_mode);
510  ev_window_set_action_enabled (ev_window, "rotate-left", has_pages &&
511  !recent_view_mode);
512  ev_window_set_action_enabled (ev_window, "rotate-right", has_pages &&
513  !recent_view_mode);
514 
515  /* View menu */
516  ev_window_set_action_enabled (ev_window, "continuous", has_pages &&
517  !recent_view_mode);
518  ev_window_set_action_enabled (ev_window, "dual-page", has_pages &&
519  !recent_view_mode);
520  ev_window_set_action_enabled (ev_window, "dual-odd-left", has_pages &&
521  !recent_view_mode);
522  ev_window_set_action_enabled (ev_window, "reload", has_pages &&
523  !recent_view_mode);
524  ev_window_set_action_enabled (ev_window, "auto-scroll", has_pages &&
525  !recent_view_mode);
526  ev_window_set_action_enabled (ev_window, "inverted-colors",
527  has_pages && !recent_view_mode);
528 
529  /* Bookmarks menu */
530  ev_window_set_action_enabled (ev_window, "add-bookmark",
531  has_pages && ev_window->priv->bookmarks &&
532  !recent_view_mode);
533 
534  /* Other actions that must be disabled in recent view, in
535  * case they have a shortcut or gesture associated
536  */
537  ev_window_set_action_enabled (ev_window, "save-settings", !recent_view_mode);
538  ev_window_set_action_enabled (ev_window, "show-side-pane", !recent_view_mode);
539  ev_window_set_action_enabled (ev_window, "goto-bookmark", !recent_view_mode);
540  ev_window_set_action_enabled (ev_window, "scroll-forward", !recent_view_mode);
541  ev_window_set_action_enabled (ev_window, "scroll-backwards", !recent_view_mode);
542  ev_window_set_action_enabled (ev_window, "sizing-mode", !recent_view_mode);
543  ev_window_set_action_enabled (ev_window, "zoom", !recent_view_mode);
544  ev_window_set_action_enabled (ev_window, "escape", !recent_view_mode);
545  ev_window_set_action_enabled (ev_window, "open-menu", !recent_view_mode);
546 
547  /* Same for popups specific actions */
548  ev_window_set_action_enabled (ev_window, "open-link", !recent_view_mode);
549  ev_window_set_action_enabled (ev_window, "open-link-new-window", !recent_view_mode);
550  ev_window_set_action_enabled (ev_window, "go-to-link", !recent_view_mode);
551  ev_window_set_action_enabled (ev_window, "copy-link-address", !recent_view_mode);
552  ev_window_set_action_enabled (ev_window, "save-image", !recent_view_mode);
553  ev_window_set_action_enabled (ev_window, "copy-image", !recent_view_mode);
554  ev_window_set_action_enabled (ev_window, "open-attachment", !recent_view_mode);
555  ev_window_set_action_enabled (ev_window, "save-attachment", !recent_view_mode);
556  ev_window_set_action_enabled (ev_window, "annot-properties", !recent_view_mode);
557  ev_window_set_action_enabled (ev_window, "remove-annot", !recent_view_mode);
558 
559  can_find_in_page = ev_search_box_has_results (EV_SEARCH_BOX (ev_window->priv->search_box));
560 
561  ev_window_set_action_enabled (ev_window, "copy",
562  has_pages &&
563  ev_view_get_has_selection (view) &&
564  !recent_view_mode);
565  ev_window_set_action_enabled (ev_window, "find-next",
566  has_pages && can_find_in_page &&
567  !recent_view_mode);
568  ev_window_set_action_enabled (ev_window, "find-previous",
569  has_pages && can_find_in_page &&
570  !recent_view_mode);
571  ev_window_set_action_enabled (ev_window, "dual-odd-left", dual_mode &&
572  !recent_view_mode);
573 
574  ev_window_set_action_enabled (ev_window, "zoom-in",
575  has_pages &&
576  ev_view_can_zoom_in (view) &&
577  !presentation_mode &&
578  !recent_view_mode);
579  ev_window_set_action_enabled (ev_window, "zoom-out",
580  has_pages &&
581  ev_view_can_zoom_out (view) &&
582  !presentation_mode &&
583  !recent_view_mode);
584 
585  /* Go menu */
586  if (has_pages) {
587  ev_window_set_action_enabled (ev_window, "go-previous-page", page > 0);
588  ev_window_set_action_enabled (ev_window, "go-next-page", page < n_pages - 1);
589  ev_window_set_action_enabled (ev_window, "go-first-page", page > 0);
590  ev_window_set_action_enabled (ev_window, "go-last-page", page < n_pages - 1);
591  ev_window_set_action_enabled (ev_window, "select-page", TRUE);
592  } else {
593  ev_window_set_action_enabled (ev_window, "go-first-page", FALSE);
594  ev_window_set_action_enabled (ev_window, "go-previous-page", FALSE);
595  ev_window_set_action_enabled (ev_window, "go-next-page", FALSE);
596  ev_window_set_action_enabled (ev_window, "go-last-page", FALSE);
597  ev_window_set_action_enabled (ev_window, "select-page", FALSE);
598  }
599 
600  ev_window_set_action_enabled (ev_window, "go-back-history",
601  !ev_history_is_frozen (ev_window->priv->history) &&
602  ev_history_can_go_back (ev_window->priv->history) &&
603  !recent_view_mode);
604  ev_window_set_action_enabled (ev_window, "go-forward-history",
605  !ev_history_is_frozen (ev_window->priv->history) &&
606  ev_history_can_go_forward (ev_window->priv->history) &&
607  !recent_view_mode);
608 
609  ev_window_set_action_enabled (ev_window, "caret-navigation",
610  has_pages &&
612  !presentation_mode &&
613  !recent_view_mode);
614 }
615 
616 static void
617 set_widget_visibility (GtkWidget *widget, gboolean visible)
618 {
619  g_assert (GTK_IS_WIDGET (widget));
620 
621  if (visible)
622  gtk_widget_show (widget);
623  else
624  gtk_widget_hide (widget);
625 }
626 
627 static void
629 {
630  EvWindowPrivate *priv = window->priv;
631  gboolean toolbar, sidebar;
632  gboolean presentation;
633 
634  presentation = EV_WINDOW_IS_PRESENTATION (window);
635 
636  toolbar = ((priv->chrome & EV_CHROME_TOOLBAR) != 0 ||
637  (priv->chrome & EV_CHROME_RAISE_TOOLBAR) != 0) && !presentation;
638  sidebar = (priv->chrome & EV_CHROME_SIDEBAR) != 0 && priv->document && !presentation;
639 
640  set_widget_visibility (priv->toolbar, toolbar);
641  set_widget_visibility (priv->sidebar, sidebar);
642 }
643 
644 static void
645 update_chrome_flag (EvWindow *window, EvChrome flag, gboolean active)
646 {
647  EvWindowPrivate *priv = window->priv;
648 
649  if (active) {
650  priv->chrome |= flag;
651  } else {
652  priv->chrome &= ~flag;
653  }
654 }
655 
656 static void
658 {
659  GAction *action;
660  const gchar *mode = NULL;
661 
662  action = g_action_map_lookup_action (G_ACTION_MAP (window), "sizing-mode");
663 
664  switch (ev_document_model_get_sizing_mode (window->priv->model)) {
665  case EV_SIZING_FIT_PAGE:
666  mode = "fit-page";
667  break;
668  case EV_SIZING_FIT_WIDTH:
669  mode = "fit-width";
670  break;
671  case EV_SIZING_AUTOMATIC:
672  mode = "automatic";
673  break;
674  case EV_SIZING_FREE:
675  mode = "free";
676  break;
677  }
678 
679  g_simple_action_set_state (G_SIMPLE_ACTION (action), g_variant_new_string (mode));
680 }
681 
692 gboolean
693 ev_window_is_empty (const EvWindow *ev_window)
694 {
695  g_return_val_if_fail (EV_IS_WINDOW (ev_window), FALSE);
696 
697  return (ev_window->priv->document == NULL) &&
698  (ev_window->priv->load_job == NULL);
699 }
700 
701 static void
703  GtkWidget *area)
704 {
705  if (window->priv->message_area == area)
706  return;
707 
708  if (window->priv->message_area)
709  gtk_widget_destroy (window->priv->message_area);
710  window->priv->message_area = area;
711 
712  if (!area)
713  return;
714 
715  gtk_box_pack_start (GTK_BOX (window->priv->main_box),
716  window->priv->message_area,
717  FALSE, FALSE, 0);
718  /* Pack the message area right after the search bar */
719  gtk_box_reorder_child (GTK_BOX (window->priv->main_box),
720  window->priv->message_area, 2);
721  g_object_add_weak_pointer (G_OBJECT (window->priv->message_area),
722  (gpointer) &(window->priv->message_area));
723 }
724 
725 static void
727  gint response_id,
728  EvWindow *window)
729 {
730  ev_window_set_message_area (window, NULL);
731 }
732 
733 G_GNUC_PRINTF (3, 4) static void
734 ev_window_error_message (EvWindow *window,
735  GError *error,
736  const gchar *format,
737  ...)
738 {
739  GtkWidget *area;
740  va_list args;
741  gchar *msg = NULL;
742 
743  if (window->priv->message_area)
744  return;
745 
746  va_start (args, format);
747  msg = g_strdup_vprintf (format, args);
748  va_end (args);
749 
750  area = ev_message_area_new (GTK_MESSAGE_ERROR,
751  msg,
752  GTK_STOCK_CLOSE,
753  GTK_RESPONSE_CLOSE,
754  NULL);
755  g_free (msg);
756 
757  if (error)
758  ev_message_area_set_secondary_text (EV_MESSAGE_AREA (area), error->message);
759  g_signal_connect (area, "response",
761  window);
762  gtk_widget_show (area);
763  ev_window_set_message_area (window, area);
764 }
765 
766 G_GNUC_PRINTF (2, 3) static void
767 ev_window_warning_message (EvWindow *window,
768  const gchar *format,
769  ...)
770 {
771  GtkWidget *area;
772  va_list args;
773  gchar *msg = NULL;
774 
775  if (window->priv->message_area)
776  return;
777 
778  va_start (args, format);
779  msg = g_strdup_vprintf (format, args);
780  va_end (args);
781 
782  area = ev_message_area_new (GTK_MESSAGE_WARNING,
783  msg,
784  GTK_STOCK_CLOSE,
785  GTK_RESPONSE_CLOSE,
786  NULL);
787  g_free (msg);
788 
789  g_signal_connect (area, "response",
791  window);
792  gtk_widget_show (area);
793  ev_window_set_message_area (window, area);
794 }
795 
796 static gboolean
798 {
799  window->priv->loading_message_timeout = 0;
800  gtk_widget_show (window->priv->loading_message);
801 
802  return FALSE;
803 }
804 
805 static void
807 {
808  if (window->priv->loading_message_timeout)
809  return;
810  window->priv->loading_message_timeout =
811  g_timeout_add_full (G_PRIORITY_LOW, 0.5, (GSourceFunc)show_loading_message_cb, window, NULL);
812 }
813 
814 static void
816 {
817  if (window->priv->loading_message_timeout) {
818  g_source_remove (window->priv->loading_message_timeout);
819  window->priv->loading_message_timeout = 0;
820  }
821 
822  gtk_widget_hide (window->priv->loading_message);
823 }
824 
825 typedef struct _LinkTitleData {
827  const gchar *link_title;
828 } LinkTitleData;
829 
830 static gboolean
831 find_link_cb (GtkTreeModel *tree_model,
832  GtkTreePath *path,
833  GtkTreeIter *iter,
834  LinkTitleData *data)
835 {
836  EvLink *link;
837  gboolean retval = FALSE;
838 
839  gtk_tree_model_get (tree_model, iter,
841  -1);
842  if (!link)
843  return retval;
844 
846  data->link_title = ev_link_get_title (link);
847  retval = TRUE;
848  }
849 
850  g_object_unref (link);
851 
852  return retval;
853 }
854 
855 static const gchar *
857  EvLink *link)
858 {
859  if (EV_IS_DOCUMENT_LINKS (window->priv->document) &&
861  LinkTitleData data;
862  GtkTreeModel *model;
863 
864  data.link = link;
865  data.link_title = NULL;
866 
867  g_object_get (G_OBJECT (window->priv->sidebar_links),
868  "model", &model,
869  NULL);
870  if (model) {
871  gtk_tree_model_foreach (model,
872  (GtkTreeModelForeachFunc)find_link_cb,
873  &data);
874 
875  g_object_unref (model);
876  }
877 
878  return data.link_title;
879  }
880 
881  return NULL;
882 }
883 
884 static void
886 {
887  EvLink *new_link = NULL;
888 
889  if (!ev_link_get_title (link)) {
890  const gchar *link_title;
891 
892  link_title = ev_window_find_title_for_link (window, link);
893  if (link_title) {
894  new_link = ev_link_new (link_title, ev_link_get_action (link));
895  } else {
896  EvLinkAction *action;
897  EvLinkDest *dest;
898  gchar *page_label;
899  gchar *title;
900 
901  action = ev_link_get_action (link);
902  dest = ev_link_action_get_dest (action);
904  if (!page_label)
905  return;
906 
907  title = g_strdup_printf (_("Page %s"), page_label);
908  g_free (page_label);
909 
910  new_link = ev_link_new (title, action);
911  g_free (title);
912  }
913  }
914  ev_history_add_link (window->priv->history, new_link ? new_link : link);
915  if (new_link)
916  g_object_unref (new_link);
917 }
918 
919 static void
921  EvWindow *window)
922 {
923  ev_window_set_action_enabled (window, "copy",
925 }
926 
927 static void
929  EvWindow *window)
930 {
932 }
933 
934 static void
936  GParamSpec *spec,
937  EvWindow *window)
938 {
939  if (ev_view_is_loading (view))
941  else
943 }
944 
945 static void
947  guint page,
948  guint offset,
949  EvWindow *window)
950 {
951  GVariant *position;
952  gchar *caret_position;
953 
954  if (!window->priv->metadata)
955  return;
956 
957  position = g_variant_new ("(uu)", page, offset);
958  caret_position = g_variant_print (position, FALSE);
959  g_variant_unref (position);
960 
961  ev_metadata_set_string (window->priv->metadata, "caret-position", caret_position);
962  g_free (caret_position);
963 }
964 
965 static void
967  gint old_page,
968  gint new_page,
969  EvDocumentModel *model)
970 {
972 
973  if (ev_window->priv->metadata && !ev_window_is_empty (ev_window))
974  ev_metadata_set_int (ev_window->priv->metadata, "page", new_page);
975 }
976 
977 static const gchar *
979 {
980  GtkWidget *current_page;
981  const gchar *id;
982 
983  g_object_get (ev_window->priv->sidebar,
984  "current_page", &current_page,
985  NULL);
986 
987  if (current_page == ev_window->priv->sidebar_links) {
988  id = LINKS_SIDEBAR_ID;
989  } else if (current_page == ev_window->priv->sidebar_thumbs) {
991  } else if (current_page == ev_window->priv->sidebar_attachments) {
993  } else if (current_page == ev_window->priv->sidebar_layers) {
994  id = LAYERS_SIDEBAR_ID;
995  } else if (current_page == ev_window->priv->sidebar_annots) {
996  id = ANNOTS_SIDEBAR_ID;
997  } else if (current_page == ev_window->priv->sidebar_bookmarks) {
999  } else {
1000  g_assert_not_reached();
1001  }
1002 
1003  g_object_unref (current_page);
1004 
1005  return id;
1006 }
1007 
1008 static void
1010  const gchar *page_id)
1011 {
1012  EvDocument *document = window->priv->document;
1013  EvSidebar *sidebar = EV_SIDEBAR (window->priv->sidebar);
1014  GtkWidget *links = window->priv->sidebar_links;
1015  GtkWidget *thumbs = window->priv->sidebar_thumbs;
1016  GtkWidget *attachments = window->priv->sidebar_attachments;
1017  GtkWidget *annots = window->priv->sidebar_annots;
1018  GtkWidget *layers = window->priv->sidebar_layers;
1019  GtkWidget *bookmarks = window->priv->sidebar_bookmarks;
1020 
1021  if (strcmp (page_id, LINKS_SIDEBAR_ID) == 0 &&
1022  ev_sidebar_page_support_document (EV_SIDEBAR_PAGE (links), document)) {
1023  ev_sidebar_set_page (sidebar, links);
1024  } else if (strcmp (page_id, THUMBNAILS_SIDEBAR_ID) == 0 &&
1025  ev_sidebar_page_support_document (EV_SIDEBAR_PAGE (thumbs), document)) {
1026  ev_sidebar_set_page (sidebar, thumbs);
1027  } else if (strcmp (page_id, ATTACHMENTS_SIDEBAR_ID) == 0 &&
1028  ev_sidebar_page_support_document (EV_SIDEBAR_PAGE (attachments), document)) {
1029  ev_sidebar_set_page (sidebar, attachments);
1030  } else if (strcmp (page_id, LAYERS_SIDEBAR_ID) == 0 &&
1031  ev_sidebar_page_support_document (EV_SIDEBAR_PAGE (layers), document)) {
1032  ev_sidebar_set_page (sidebar, layers);
1033  } else if (strcmp (page_id, ANNOTS_SIDEBAR_ID) == 0 &&
1034  ev_sidebar_page_support_document (EV_SIDEBAR_PAGE (annots), document)) {
1035  ev_sidebar_set_page (sidebar, annots);
1036  } else if (strcmp (page_id, BOOKMARKS_SIDEBAR_ID) == 0 &&
1037  ev_sidebar_page_support_document (EV_SIDEBAR_PAGE (bookmarks), document)) {
1038  ev_sidebar_set_page (sidebar, bookmarks);
1039  } else {
1040  /* setup thumbnails by default */
1041  ev_sidebar_set_page (sidebar, thumbs);
1042  }
1043 }
1044 
1045 static void
1047 {
1048  if (mode == EV_DOCUMENT_MODE_PRESENTATION) {
1049  ev_window_run_presentation (window);
1050  }
1051  else if (mode == EV_DOCUMENT_MODE_FULL_SCREEN) {
1052  ev_window_run_fullscreen (window);
1053  }
1054 }
1055 
1056 static void
1058 {
1059  GSettings *settings = window->priv->default_settings;
1060  EvMetadata *metadata = window->priv->metadata;
1061 
1062  /* Chrome */
1063  if (!ev_metadata_has_key (metadata, "sidebar_visibility")) {
1064  ev_metadata_set_boolean (metadata, "sidebar_visibility",
1065  g_settings_get_boolean (settings, "show-sidebar"));
1066  }
1067 
1068  /* Sidebar */
1069  if (!ev_metadata_has_key (metadata, "sidebar_size")) {
1070  ev_metadata_set_int (metadata, "sidebar_size",
1071  g_settings_get_int (settings, "sidebar-size"));
1072  }
1073  if (!ev_metadata_has_key (metadata, "sidebar_page")) {
1074  gchar *sidebar_page_id = g_settings_get_string (settings, "sidebar-page");
1075 
1076  ev_metadata_set_string (metadata, "sidebar_page", sidebar_page_id);
1077  g_free (sidebar_page_id);
1078  }
1079 
1080  /* Document model */
1081  if (!ev_metadata_has_key (metadata, "continuous")) {
1082  ev_metadata_set_boolean (metadata, "continuous",
1083  g_settings_get_boolean (settings, "continuous"));
1084  }
1085  if (!ev_metadata_has_key (metadata, "dual-page")) {
1086  ev_metadata_set_boolean (metadata, "dual-page",
1087  g_settings_get_boolean (settings, "dual-page"));
1088  }
1089  if (!ev_metadata_has_key (metadata, "dual-page-odd-left")) {
1090  ev_metadata_set_boolean (metadata, "dual-page-odd-left",
1091  g_settings_get_boolean (settings, "dual-page-odd-left"));
1092  }
1093  if (!ev_metadata_has_key (metadata, "inverted-colors")) {
1094  ev_metadata_set_boolean (metadata, "inverted-colors",
1095  g_settings_get_boolean (settings, "inverted-colors"));
1096  }
1097  if (!ev_metadata_has_key (metadata, "sizing_mode")) {
1098  EvSizingMode mode = g_settings_get_enum (settings, "sizing-mode");
1099  GEnumValue *enum_value = g_enum_get_value (g_type_class_peek (EV_TYPE_SIZING_MODE), mode);
1100 
1101  ev_metadata_set_string (metadata, "sizing_mode", enum_value->value_nick);
1102  }
1103 
1104  if (!ev_metadata_has_key (metadata, "zoom")) {
1105  ev_metadata_set_double (metadata, "zoom",
1106  g_settings_get_double (settings, "zoom"));
1107  }
1108 
1109  if (!ev_metadata_has_key (metadata, "fullscreen")) {
1110  ev_metadata_set_boolean (metadata, "fullscreen",
1111  g_settings_get_boolean (settings, "fullscreen"));
1112  }
1113 }
1114 
1115 static void
1117 {
1118  gboolean show_toolbar;
1119  gboolean show_sidebar;
1120 
1121  if (!window->priv->metadata)
1122  return;
1123 
1124  if (ev_metadata_get_boolean (window->priv->metadata, "show_toolbar", &show_toolbar))
1125  update_chrome_flag (window, EV_CHROME_TOOLBAR, show_toolbar);
1126  if (ev_metadata_get_boolean (window->priv->metadata, "sidebar_visibility", &show_sidebar))
1127  update_chrome_flag (window, EV_CHROME_SIDEBAR, show_sidebar);
1128  update_chrome_visibility (window);
1129 }
1130 
1131 static void
1133 {
1134  gchar *page_id;
1135  gint sidebar_size;
1136 
1137  if (!window->priv->metadata)
1138  return;
1139 
1140  if (ev_metadata_get_int (window->priv->metadata, "sidebar_size", &sidebar_size))
1141  gtk_paned_set_position (GTK_PANED (window->priv->hpaned), sidebar_size);
1142 
1143  if (ev_metadata_get_string (window->priv->metadata, "sidebar_page", &page_id))
1144  ev_window_sidebar_set_current_page (window, page_id);
1145 }
1146 
1147 static void
1149 {
1150  gint page;
1151  gchar *sizing_mode;
1152  gdouble zoom;
1153  gint rotation;
1154  gboolean inverted_colors = FALSE;
1155  gboolean continuous = FALSE;
1156  gboolean dual_page = FALSE;
1157  gboolean dual_page_odd_left = FALSE;
1158  gboolean fullscreen = FALSE;
1159 
1160  if (!window->priv->metadata)
1161  return;
1162 
1163  /* Current page */
1164  if (!window->priv->dest &&
1165  ev_metadata_get_int (window->priv->metadata, "page", &page)) {
1166  ev_document_model_set_page (window->priv->model, page);
1167  }
1168 
1169  /* Sizing mode */
1170  if (ev_metadata_get_string (window->priv->metadata, "sizing_mode", &sizing_mode)) {
1171  GEnumValue *enum_value;
1172 
1173  enum_value = g_enum_get_value_by_nick
1174  (g_type_class_peek (EV_TYPE_SIZING_MODE), sizing_mode);
1175  ev_document_model_set_sizing_mode (window->priv->model, enum_value->value);
1176  }
1177 
1178  /* Zoom */
1180  if (ev_metadata_get_double (window->priv->metadata, "zoom", &zoom)) {
1181  zoom *= get_screen_dpi (window) / 72.0;
1182  ev_document_model_set_scale (window->priv->model, zoom);
1183  }
1184  }
1185 
1186  /* Rotation */
1187  if (ev_metadata_get_int (window->priv->metadata, "rotation", &rotation)) {
1188  switch (rotation) {
1189  case 90:
1190  rotation = 90;
1191  break;
1192  case 180:
1193  rotation = 180;
1194  break;
1195  case 270:
1196  rotation = 270;
1197  break;
1198  default:
1199  rotation = 0;
1200  break;
1201  }
1202  ev_document_model_set_rotation (window->priv->model, rotation);
1203  }
1204 
1205  /* Inverted Colors */
1206  if (ev_metadata_get_boolean (window->priv->metadata, "inverted-colors", &inverted_colors)) {
1207  ev_document_model_set_inverted_colors (window->priv->model, inverted_colors);
1208  }
1209 
1210  /* Continuous */
1211  if (ev_metadata_get_boolean (window->priv->metadata, "continuous", &continuous)) {
1212  ev_document_model_set_continuous (window->priv->model, continuous);
1213  }
1214 
1215  /* Dual page */
1216  if (ev_metadata_get_boolean (window->priv->metadata, "dual-page", &dual_page)) {
1217  ev_document_model_set_dual_page (window->priv->model, dual_page);
1218  }
1219 
1220  /* Dual page odd pages left */
1221  if (ev_metadata_get_boolean (window->priv->metadata, "dual-page-odd-left", &dual_page_odd_left)) {
1222  ev_document_model_set_dual_page_odd_pages_left (window->priv->model, dual_page_odd_left);
1223  }
1224 
1225  /* Fullscreen */
1226  if (ev_metadata_get_boolean (window->priv->metadata, "fullscreen", &fullscreen)) {
1227  if (fullscreen)
1228  ev_window_run_fullscreen (window);
1229  }
1230 }
1231 
1232 static void
1234 {
1235  gint page, n_pages;
1236  gint width;
1237  gint height;
1238  gdouble width_ratio;
1239  gdouble height_ratio;
1240 
1241  if (!window->priv->metadata)
1242  return;
1243 
1244  setup_sidebar_from_metadata (window);
1245 
1246  /* Make sure to not open a document on the last page,
1247  * since closing it on the last page most likely means the
1248  * user was finished reading the document. In that case, reopening should
1249  * show the first page. */
1250  page = ev_document_model_get_page (window->priv->model);
1251  n_pages = ev_document_get_n_pages (window->priv->document);
1252  if (page == n_pages - 1)
1253  ev_document_model_set_page (window->priv->model, 0);
1254 
1255  if (ev_metadata_get_int (window->priv->metadata, "window_width", &width) &&
1256  ev_metadata_get_int (window->priv->metadata, "window_height", &height))
1257  return; /* size was already set in setup_size_from_metadata */
1258 
1259  if (n_pages == 1)
1261 
1262  g_settings_get (window->priv->default_settings, "window-ratio", "(dd)", &width_ratio, &height_ratio);
1263  if (width_ratio > 0. && height_ratio > 0.) {
1264  gdouble document_width;
1265  gdouble document_height;
1266  GdkScreen *screen;
1267  gint request_width;
1268  gint request_height;
1269 
1271  &document_width, &document_height);
1272 
1273  request_width = (gint)(width_ratio * document_width + 0.5);
1274  request_height = (gint)(height_ratio * document_height + 0.5);
1275 
1276  screen = gtk_window_get_screen (GTK_WINDOW (window));
1277  if (screen) {
1278  request_width = MIN (request_width, gdk_screen_get_width (screen));
1279  request_height = MIN (request_height, gdk_screen_get_height (screen));
1280  }
1281 
1282  if (request_width > 0 && request_height > 0) {
1283  gtk_window_resize (GTK_WINDOW (window),
1284  request_width,
1285  request_height);
1286  }
1287  }
1288 }
1289 
1290 static void
1292 {
1293  gint width;
1294  gint height;
1295  gboolean maximized;
1296  gint x;
1297  gint y;
1298 
1299  if (!window->priv->metadata)
1300  return;
1301 
1302  if (ev_metadata_get_boolean (window->priv->metadata, "window_maximized", &maximized)) {
1303  if (maximized) {
1304  gtk_window_maximize (GTK_WINDOW (window));
1305  return;
1306  } else {
1307  gtk_window_unmaximize (GTK_WINDOW (window));
1308  }
1309  }
1310 
1311  if (ev_metadata_get_int (window->priv->metadata, "window_x", &x) &&
1312  ev_metadata_get_int (window->priv->metadata, "window_y", &y)) {
1313  gtk_window_move (GTK_WINDOW (window), x, y);
1314  }
1315 
1316  if (ev_metadata_get_int (window->priv->metadata, "window_width", &width) &&
1317  ev_metadata_get_int (window->priv->metadata, "window_height", &height)) {
1318  gtk_window_resize (GTK_WINDOW (window), width, height);
1319  }
1320 }
1321 
1322 static void
1324 {
1325  gboolean presentation;
1326 
1327  if (!window->priv->metadata)
1328  return;
1329 
1330  /* Presentation */
1331  if (ev_metadata_get_boolean (window->priv->metadata, "presentation", &presentation)) {
1332  if (presentation)
1333  ev_window_run_presentation (window);
1334  }
1335 
1336  /* Caret navigation mode */
1338  gboolean caret_navigation;
1339  gchar *caret_position;
1340 
1341  if (ev_metadata_get_string (window->priv->metadata, "caret-position", &caret_position)) {
1342  GVariant *position;
1343 
1344  position = g_variant_parse (G_VARIANT_TYPE ("(uu)"), caret_position, NULL, NULL, NULL);
1345  if (position) {
1346  guint page, offset;
1347 
1348  g_variant_get (position, "(uu)", &page, &offset);
1349  g_variant_unref (position);
1350 
1352  page, offset);
1353  }
1354  }
1355 
1356  if (ev_metadata_get_boolean (window->priv->metadata, "caret-navigation", &caret_navigation))
1357  ev_view_set_caret_navigation_enabled (EV_VIEW (window->priv->view), caret_navigation);
1358  }
1359 }
1360 
1361 static void
1362 page_cache_size_changed (GSettings *settings,
1363  gchar *key,
1364  EvWindow *ev_window)
1365 {
1366  guint page_cache_mb;
1367 
1368  page_cache_mb = g_settings_get_uint (settings, GS_PAGE_CACHE_SIZE);
1370  page_cache_mb * 1024 * 1024);
1371 }
1372 
1373 static void
1374 allow_links_change_zoom_changed (GSettings *settings,
1375  gchar *key,
1376  EvWindow *ev_window)
1377 {
1378  gboolean allow_links_change_zoom = g_settings_get_boolean (settings, GS_ALLOW_LINKS_CHANGE_ZOOM);
1379 
1380  ev_view_set_allow_links_change_zoom (EV_VIEW (ev_window->priv->view), allow_links_change_zoom);
1381 }
1382 
1383 static void
1385 {
1386  EvDocumentModel *model = ev_window->priv->model;
1387  GSettings *settings = ev_window->priv->default_settings;
1388 
1389  /* Chrome */
1391  g_settings_get_boolean (settings, "show-sidebar"));
1392  update_chrome_visibility (ev_window);
1393 
1394  /* Sidebar */
1395  gtk_paned_set_position (GTK_PANED (ev_window->priv->hpaned),
1396  g_settings_get_int (settings, "sidebar-size"));
1397 
1398  /* Document model */
1399  ev_document_model_set_continuous (model, g_settings_get_boolean (settings, "continuous"));
1400  ev_document_model_set_dual_page (model, g_settings_get_boolean (settings, "dual-page"));
1401  ev_document_model_set_dual_page_odd_pages_left (model, g_settings_get_boolean (settings, "dual-page-odd-left"));
1402  ev_document_model_set_inverted_colors (model, g_settings_get_boolean (settings, "inverted-colors"));
1403  ev_document_model_set_sizing_mode (model, g_settings_get_enum (settings, "sizing-mode"));
1405  ev_document_model_set_scale (model, g_settings_get_double (settings, "zoom"));
1406 }
1407 
1408 static void
1409 override_restrictions_changed (GSettings *settings,
1410  gchar *key,
1411  EvWindow *ev_window)
1412 {
1414 }
1415 
1416 #ifdef HAVE_DESKTOP_SCHEMAS
1417 static void
1418 lockdown_changed (GSettings *lockdown,
1419  const gchar *key,
1420  EvWindow *ev_window)
1421 {
1423 }
1424 #endif
1425 
1426 static GSettings *
1428 {
1429  EvWindowPrivate *priv = ev_window->priv;
1430 
1431  if (priv->settings != NULL)
1432  return priv->settings;
1433 
1434  priv->settings = g_settings_new (GS_SCHEMA_NAME);
1435  g_signal_connect (priv->settings,
1436  "changed::"GS_OVERRIDE_RESTRICTIONS,
1437  G_CALLBACK (override_restrictions_changed),
1438  ev_window);
1439  g_signal_connect (priv->settings,
1440  "changed::"GS_PAGE_CACHE_SIZE,
1441  G_CALLBACK (page_cache_size_changed),
1442  ev_window);
1443  g_signal_connect (priv->settings,
1444  "changed::"GS_ALLOW_LINKS_CHANGE_ZOOM,
1445  G_CALLBACK (allow_links_change_zoom_changed),
1446  ev_window);
1447 
1448  return priv->settings;
1449 }
1450 
1451 static gboolean
1453 {
1454  const EvDocumentInfo *info;
1455  EvDocument *document = ev_window->priv->document;
1456 
1457  ev_window->priv->setup_document_idle = 0;
1458 
1460  ev_window_title_set_document (ev_window->priv->title, document);
1461  ev_window_title_set_uri (ev_window->priv->title, ev_window->priv->uri);
1462 
1463  ev_window_ensure_settings (ev_window);
1464 
1465 #ifdef HAVE_DESKTOP_SCHEMAS
1466  if (!ev_window->priv->lockdown_settings) {
1467  ev_window->priv->lockdown_settings = g_settings_new (GS_LOCKDOWN_SCHEMA_NAME);
1468  g_signal_connect (ev_window->priv->lockdown_settings,
1469  "changed",
1470  G_CALLBACK (lockdown_changed),
1471  ev_window);
1472  }
1473 #endif
1474 
1476 
1477  if (ev_window->priv->properties) {
1479  ev_window->priv->uri,
1480  ev_window->priv->document);
1481  }
1482 
1483  info = ev_document_get_info (document);
1484  update_document_mode (ev_window, info->mode);
1485 
1486  if (ev_window->priv->search_string && EV_IS_DOCUMENT_FIND (document) &&
1487  !EV_WINDOW_IS_PRESENTATION (ev_window)) {
1488  GtkSearchEntry *entry;
1489 
1490  ev_window_show_find_bar (ev_window, FALSE);
1491  entry = ev_search_box_get_entry (EV_SEARCH_BOX (ev_window->priv->search_box));
1492  gtk_entry_set_text (GTK_ENTRY (entry), ev_window->priv->search_string);
1493  }
1494 
1495  g_clear_pointer (&ev_window->priv->search_string, g_free);
1496 
1497  if (EV_WINDOW_IS_PRESENTATION (ev_window))
1498  gtk_widget_grab_focus (ev_window->priv->presentation_view);
1499  else if (!gtk_search_bar_get_search_mode (GTK_SEARCH_BAR (ev_window->priv->search_bar)))
1500  gtk_widget_grab_focus (ev_window->priv->view);
1501 
1502  return FALSE;
1503 }
1504 
1505 static void
1507 {
1508  const EvDocumentInfo *info;
1509 
1510  if (!window->priv->metadata)
1511  return;
1512 
1513  info = ev_document_get_info (window->priv->document);
1514  if (info->fields_mask & EV_DOCUMENT_INFO_TITLE && info->title && info->title[0] != '\0')
1515  ev_metadata_set_string (window->priv->metadata, "title", info->title);
1516  else
1517  ev_metadata_set_string (window->priv->metadata, "title", "");
1518 
1519  if (info->fields_mask & EV_DOCUMENT_INFO_AUTHOR && info->author && info->author[0] != '\0')
1520  ev_metadata_set_string (window->priv->metadata, "author", info->author);
1521  else
1522  ev_metadata_set_string (window->priv->metadata, "author", "");
1523 }
1524 
1525 static void
1527 {
1528  if (ev_window->priv->document == document)
1529  return;
1530 
1531  if (ev_window->priv->document)
1532  g_object_unref (ev_window->priv->document);
1533  ev_window->priv->document = g_object_ref (document);
1534 
1535  ev_window_set_message_area (ev_window, NULL);
1536 
1537  ev_window_set_document_metadata (ev_window);
1538 
1539  if (ev_document_get_n_pages (document) <= 0) {
1540  ev_window_warning_message (ev_window, "%s",
1541  _("The document contains no pages"));
1542  } else if (!ev_document_check_dimensions (document)) {
1543  ev_window_warning_message (ev_window, "%s",
1544  _("The document contains only empty pages"));
1545  }
1546 
1547  ev_window_destroy_recent_view (ev_window);
1548 
1549  ev_toolbar_set_mode (EV_TOOLBAR (ev_window->priv->toolbar),
1553 
1554  if (EV_WINDOW_IS_PRESENTATION (ev_window)) {
1555  gint current_page;
1556 
1557  current_page = ev_view_presentation_get_current_page (
1559  gtk_widget_destroy (ev_window->priv->presentation_view);
1560  ev_window->priv->presentation_view = NULL;
1561 
1562  /* Update the model with the current presentation page */
1563  ev_document_model_set_page (ev_window->priv->model, current_page);
1564  ev_window_run_presentation (ev_window);
1565  }
1566 
1567  if (ev_window->priv->setup_document_idle > 0)
1568  g_source_remove (ev_window->priv->setup_document_idle);
1569 
1570  ev_window->priv->setup_document_idle = g_idle_add ((GSourceFunc)ev_window_setup_document, ev_window);
1571 }
1572 
1573 static void
1575  gpointer user_data)
1576 {
1577  if (ev_window->priv->settings &&
1578  g_settings_get_boolean (ev_window->priv->settings, GS_AUTO_RELOAD))
1579  ev_window_reload_document (ev_window, NULL);
1580 }
1581 
1582 static void
1584 {
1585  const gchar *password;
1586 
1587  g_assert (ev_window->priv->load_job);
1588 
1590  ev_job_load_set_password (EV_JOB_LOAD (ev_window->priv->load_job), password);
1592 }
1593 
1594 static void
1596 {
1597  if (ev_window->priv->load_job != NULL) {
1598  if (!ev_job_is_finished (ev_window->priv->load_job))
1599  ev_job_cancel (ev_window->priv->load_job);
1600 
1601  g_signal_handlers_disconnect_by_func (ev_window->priv->load_job, ev_window_load_job_cb, ev_window);
1602  g_object_unref (ev_window->priv->load_job);
1603  ev_window->priv->load_job = NULL;
1604  }
1605 }
1606 
1607 static void
1609 {
1610  if (ev_window->priv->reload_job != NULL) {
1611  if (!ev_job_is_finished (ev_window->priv->reload_job))
1612  ev_job_cancel (ev_window->priv->reload_job);
1613 
1614  g_signal_handlers_disconnect_by_func (ev_window->priv->reload_job, ev_window_reload_job_cb, ev_window);
1615  g_object_unref (ev_window->priv->reload_job);
1616  ev_window->priv->reload_job = NULL;
1617  }
1618 }
1619 
1620 static void
1622 {
1623  if (ev_window->priv->local_uri) {
1624  ev_tmp_uri_unlink (ev_window->priv->local_uri);
1625  g_free (ev_window->priv->local_uri);
1626  ev_window->priv->local_uri = NULL;
1627  }
1628 }
1629 
1630 static void
1632  EvLinkDest *dest)
1633 {
1634  if (dest) {
1635  EvLink *link;
1636  EvLinkAction *link_action;
1637 
1638  link_action = ev_link_action_new_dest (dest);
1639  link = ev_link_new (NULL, link_action);
1640  ev_view_handle_link (EV_VIEW (ev_window->priv->view), link);
1641  g_object_unref (link_action);
1642  g_object_unref (link);
1643  }
1644 }
1645 
1646 /* This callback will executed when load job will be finished.
1647  *
1648  * Since the flow of the error dialog is very confusing, we assume that both
1649  * document and uri will go away after this function is called, and thus we need
1650  * to ref/dup them. Additionally, it needs to clear
1651  * ev_window->priv->password_{uri,document}, and thus people who call this
1652  * function should _not_ necessarily expect those to exist after being
1653  * called. */
1654 static void
1656  gpointer data)
1657 {
1658  EvWindow *ev_window = EV_WINDOW (data);
1659  EvDocument *document = EV_JOB (job)->document;
1660  EvJobLoad *job_load = EV_JOB_LOAD (job);
1661  gchar *text;
1662  gchar *display_name;
1663 
1664  g_assert (job_load->uri);
1665 
1666  ev_window_hide_loading_message (ev_window);
1667 
1668  /* Success! */
1669  if (!ev_job_is_failed (job)) {
1670  ev_document_model_set_document (ev_window->priv->model, document);
1671 
1672 #ifdef ENABLE_DBUS
1673  ev_window_emit_doc_loaded (ev_window);
1674 #endif
1675  setup_chrome_from_metadata (ev_window);
1676  setup_document_from_metadata (ev_window);
1677  setup_view_from_metadata (ev_window);
1678 
1679  ev_window_add_recent (ev_window, ev_window->priv->uri);
1680 
1681  ev_window_title_set_type (ev_window->priv->title,
1683  if (job_load->password) {
1684  GPasswordSave flags;
1685 
1687  EV_PASSWORD_VIEW (ev_window->priv->password_view));
1688  ev_keyring_save_password (ev_window->priv->uri,
1689  job_load->password,
1690  flags);
1691  }
1692 
1693  ev_window_handle_link (ev_window, ev_window->priv->dest);
1694  g_clear_object (&ev_window->priv->dest);
1695 
1696  switch (ev_window->priv->window_mode) {
1698  ev_window_run_fullscreen (ev_window);
1699  break;
1701  ev_window_run_presentation (ev_window);
1702  break;
1703  default:
1704  break;
1705  }
1706 
1707  /* Create a monitor for the document */
1708  ev_window->priv->monitor = ev_file_monitor_new (ev_window->priv->uri);
1709  g_signal_connect_swapped (ev_window->priv->monitor, "changed",
1710  G_CALLBACK (ev_window_file_changed),
1711  ev_window);
1712 
1713  ev_window_clear_load_job (ev_window);
1714  return;
1715  }
1716 
1717  if (g_error_matches (job->error, EV_DOCUMENT_ERROR, EV_DOCUMENT_ERROR_ENCRYPTED)) {
1718  gchar *password;
1719 
1720  setup_view_from_metadata (ev_window);
1721 
1722  /* First look whether password is in keyring */
1723  password = ev_keyring_lookup_password (ev_window->priv->uri);
1724  if (password) {
1725  if (job_load->password && strcmp (password, job_load->password) == 0) {
1726  /* Password in kering is wrong */
1727  ev_job_load_set_password (job_load, NULL);
1728  /* FIXME: delete password from keyring? */
1729  } else {
1730  ev_job_load_set_password (job_load, password);
1732  g_free (password);
1733  return;
1734  }
1735 
1736  g_free (password);
1737  }
1738 
1739  /* We need to ask the user for a password */
1740  ev_window_title_set_uri (ev_window->priv->title,
1741  ev_window->priv->uri);
1742  ev_window_title_set_type (ev_window->priv->title,
1744 
1746  job_load->uri);
1747 
1749 
1750  ev_job_load_set_password (job_load, NULL);
1752  } else {
1753  text = g_uri_unescape_string (job_load->uri, NULL);
1754  display_name = g_markup_escape_text (text, -1);
1755  g_free (text);
1756  ev_window_error_message (ev_window, job->error,
1757  _("Unable to open document “%s”."),
1758  display_name);
1759  g_free (display_name);
1760  ev_window_clear_load_job (ev_window);
1761  }
1762 }
1763 
1764 static void
1766  EvWindow *ev_window)
1767 {
1768  if (ev_job_is_failed (job)) {
1769  ev_window_clear_reload_job (ev_window);
1770  ev_window->priv->in_reload = FALSE;
1771  if (ev_window->priv->dest) {
1772  g_object_unref (ev_window->priv->dest);
1773  ev_window->priv->dest = NULL;
1774  }
1775 
1776  return;
1777  }
1778 
1780  job->document);
1781  if (ev_window->priv->dest) {
1782  ev_window_handle_link (ev_window, ev_window->priv->dest);
1783  g_clear_object (&ev_window->priv->dest);
1784  }
1785 
1786  /* Restart the search after reloading */
1787  if (gtk_search_bar_get_search_mode (GTK_SEARCH_BAR (ev_window->priv->search_bar)))
1789 
1790  ev_window_clear_reload_job (ev_window);
1791  ev_window->priv->in_reload = FALSE;
1792 }
1793 
1802 const char *
1804 {
1805  return ev_window->priv->uri;
1806 }
1807 
1815 static void
1817 {
1818  if (ev_window->priv->print_dialog)
1819  gtk_widget_destroy (ev_window->priv->print_dialog);
1820  ev_window->priv->print_dialog = NULL;
1821 
1822  if (ev_window->priv->properties)
1823  gtk_widget_destroy (ev_window->priv->properties);
1824  ev_window->priv->properties = NULL;
1825 }
1826 
1827 static void
1829 {
1830  if (ev_window->priv->progress_idle > 0)
1831  g_source_remove (ev_window->priv->progress_idle);
1832  ev_window->priv->progress_idle = 0;
1833 }
1834 
1835 static void
1837 {
1838  ev_window->priv->progress_idle = 0;
1839 }
1840 
1841 static void
1843  guint interval,
1844  GSourceFunc function)
1845 {
1846  if (ev_window->priv->progress_idle > 0)
1847  g_source_remove (ev_window->priv->progress_idle);
1848  ev_window->priv->progress_idle =
1849  g_timeout_add_seconds_full (G_PRIORITY_DEFAULT,
1850  interval, function,
1851  ev_window,
1852  (GDestroyNotify)reset_progress_idle);
1853 }
1854 
1855 static void
1857 {
1858  if (ev_window->priv->progress_cancellable)
1859  g_cancellable_reset (ev_window->priv->progress_cancellable);
1860  else
1861  ev_window->priv->progress_cancellable = g_cancellable_new ();
1862 }
1863 
1864 static void
1866  gint response,
1867  EvWindow *ev_window)
1868 {
1869  if (response == GTK_RESPONSE_CANCEL)
1870  g_cancellable_cancel (ev_window->priv->progress_cancellable);
1871  ev_window_set_message_area (ev_window, NULL);
1872 }
1873 
1874 static gboolean
1876 {
1877  GtkWidget *area;
1878  gchar *text;
1879  gchar *display_name;
1880 
1881  if (ev_window->priv->message_area)
1882  return FALSE;
1883 
1884  text = g_uri_unescape_string (ev_window->priv->uri, NULL);
1885  display_name = g_markup_escape_text (text, -1);
1886  g_free (text);
1887  text = g_strdup_printf (_("Loading document from “%s”"),
1888  display_name);
1889 
1890  area = ev_progress_message_area_new (GTK_STOCK_OPEN,
1891  text,
1892  GTK_STOCK_CLOSE,
1893  GTK_RESPONSE_CLOSE,
1894  GTK_STOCK_CANCEL,
1895  GTK_RESPONSE_CANCEL,
1896  NULL);
1897  g_signal_connect (area, "response",
1898  G_CALLBACK (ev_window_progress_response_cb),
1899  ev_window);
1900  gtk_widget_show (area);
1901  ev_window_set_message_area (ev_window, area);
1902 
1903  g_free (text);
1904  g_free (display_name);
1905 
1906  return FALSE;
1907 }
1908 
1909 static void
1911  GError *error)
1912 {
1913  gchar *text;
1914  gchar *display_name;
1915 
1916  ev_window_hide_loading_message (ev_window);
1917  ev_window->priv->in_reload = FALSE;
1918 
1919  text = g_uri_unescape_string (ev_window->priv->local_uri, NULL);
1920  display_name = g_markup_escape_text (text, -1);
1921  g_free (text);
1922  ev_window_error_message (ev_window, error,
1923  _("Unable to open document “%s”."),
1924  display_name);
1925  g_free (display_name);
1926  g_free (ev_window->priv->local_uri);
1927  ev_window->priv->local_uri = NULL;
1928  ev_window->priv->uri_mtime = 0;
1929 }
1930 
1931 static void
1932 set_uri_mtime (GFile *source,
1933  GAsyncResult *async_result,
1934  EvWindow *ev_window)
1935 {
1936  GFileInfo *info;
1937  GError *error = NULL;
1938 
1939  info = g_file_query_info_finish (source, async_result, &error);
1940 
1941  if (error) {
1942  ev_window->priv->uri_mtime = 0;
1943  g_error_free (error);
1944  } else {
1945  GTimeVal mtime;
1946 
1947  g_file_info_get_modification_time (info, &mtime);
1948  ev_window->priv->uri_mtime = mtime.tv_sec;
1949  g_object_unref (info);
1950  }
1951 
1952  g_object_unref (source);
1953 }
1954 
1955 static void
1956 mount_volume_ready_cb (GFile *source,
1957  GAsyncResult *async_result,
1958  EvWindow *ev_window)
1959 {
1960  GError *error = NULL;
1961 
1962  g_file_mount_enclosing_volume_finish (source, async_result, &error);
1963 
1964  if (error) {
1965  ev_window_load_remote_failed (ev_window, error);
1966  g_object_unref (source);
1967  g_error_free (error);
1968  } else {
1969  /* Volume successfully mounted,
1970  try opening the file again */
1971  ev_window_load_file_remote (ev_window, source);
1972  }
1973 }
1974 
1975 static void
1977  GAsyncResult *async_result,
1978  EvWindow *ev_window)
1979 {
1980  GError *error = NULL;
1981 
1982  ev_window_clear_progress_idle (ev_window);
1983  ev_window_set_message_area (ev_window, NULL);
1984 
1985  g_file_copy_finish (source, async_result, &error);
1986  if (!error) {
1988  g_file_query_info_async (source,
1989  G_FILE_ATTRIBUTE_TIME_MODIFIED,
1990  0, G_PRIORITY_DEFAULT,
1991  NULL,
1992  (GAsyncReadyCallback)set_uri_mtime,
1993  ev_window);
1994  return;
1995  }
1996 
1997  if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_MOUNTED)) {
1998  GMountOperation *operation;
1999 
2000  operation = gtk_mount_operation_new (GTK_WINDOW (ev_window));
2001  g_file_mount_enclosing_volume (source,
2002  G_MOUNT_MOUNT_NONE,
2003  operation, NULL,
2004  (GAsyncReadyCallback)mount_volume_ready_cb,
2005  ev_window);
2006  g_object_unref (operation);
2007  } else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
2008  ev_window_clear_load_job (ev_window);
2009  ev_window_clear_local_uri (ev_window);
2010  g_free (ev_window->priv->uri);
2011  ev_window->priv->uri = NULL;
2012  g_object_unref (source);
2013 
2014  ev_window_hide_loading_message (ev_window);
2015  } else {
2016  ev_window_load_remote_failed (ev_window, error);
2017  g_object_unref (source);
2018  }
2019 
2020  g_error_free (error);
2021 }
2022 
2023 static void
2025  goffset total_bytes,
2026  EvWindow *ev_window)
2027 {
2028  gchar *status;
2029  gdouble fraction;
2030 
2031  if (!ev_window->priv->message_area)
2032  return;
2033 
2034  if (total_bytes <= 0)
2035  return;
2036 
2037  fraction = n_bytes / (gdouble)total_bytes;
2038  status = g_strdup_printf (_("Downloading document (%d%%)"),
2039  (gint)(fraction * 100));
2040 
2042  status);
2044  fraction);
2045 
2046  g_free (status);
2047 }
2048 
2049 static void
2051  GFile *source_file)
2052 {
2053  GFile *target_file;
2054 
2055  if (!ev_window->priv->local_uri) {
2056  char *base_name, *template;
2057  GFile *tmp_file;
2058  GError *err = NULL;
2059 
2060  /* We'd like to keep extension of source uri since
2061  * it helps to resolve some mime types, say cbz.
2062  */
2063  base_name = g_file_get_basename (source_file);
2064  template = g_strdup_printf ("document.XXXXXX-%s", base_name);
2065  g_free (base_name);
2066 
2067  tmp_file = ev_mkstemp_file (template, &err);
2068  g_free (template);
2069  if (tmp_file == NULL) {
2070  ev_window_error_message (ev_window, err,
2071  "%s", _("Failed to load remote file."));
2072  g_error_free (err);
2073  return;
2074  }
2075 
2076  ev_window->priv->local_uri = g_file_get_uri (tmp_file);
2077  g_object_unref (tmp_file);
2078 
2080  ev_window->priv->local_uri);
2081  }
2082 
2084 
2085  target_file = g_file_new_for_uri (ev_window->priv->local_uri);
2086  g_file_copy_async (source_file, target_file,
2087  G_FILE_COPY_OVERWRITE,
2088  G_PRIORITY_DEFAULT,
2089  ev_window->priv->progress_cancellable,
2090  (GFileProgressCallback)window_open_file_copy_progress_cb,
2091  ev_window,
2092  (GAsyncReadyCallback)window_open_file_copy_ready_cb,
2093  ev_window);
2094  g_object_unref (target_file);
2095 
2096  ev_window_show_progress_message (ev_window, 1,
2097  (GSourceFunc)show_loading_progress);
2098 }
2099 
2100 void
2102  const char *uri,
2103  EvLinkDest *dest,
2104  EvWindowRunMode mode,
2105  const gchar *search_string)
2106 {
2107  GFile *source_file;
2108 
2109  ev_window->priv->in_reload = FALSE;
2110 
2111  g_clear_pointer (&ev_window->priv->search_string, g_free);
2112  ev_window->priv->search_string = search_string ?
2113  g_strdup (search_string) : NULL;
2114 
2115  if (ev_window->priv->uri &&
2116  g_ascii_strcasecmp (ev_window->priv->uri, uri) == 0) {
2117  ev_window_reload_document (ev_window, dest);
2118  return;
2119  }
2120 
2121  if (ev_window->priv->monitor) {
2122  g_object_unref (ev_window->priv->monitor);
2123  ev_window->priv->monitor = NULL;
2124  }
2125 
2126  ev_window_close_dialogs (ev_window);
2127  ev_window_clear_load_job (ev_window);
2128  ev_window_clear_local_uri (ev_window);
2129 
2130  ev_window->priv->window_mode = mode;
2131 
2132  if (ev_window->priv->uri)
2133  g_free (ev_window->priv->uri);
2134  ev_window->priv->uri = g_strdup (uri);
2135 
2136  if (ev_window->priv->metadata)
2137  g_object_unref (ev_window->priv->metadata);
2138  if (ev_window->priv->bookmarks)
2139  g_object_unref (ev_window->priv->bookmarks);
2140 
2141  source_file = g_file_new_for_uri (uri);
2142  if (ev_is_metadata_supported_for_file (source_file)) {
2143  ev_window->priv->metadata = ev_metadata_new (source_file);
2145  } else {
2146  ev_window->priv->metadata = NULL;
2147  }
2148 
2149  if (ev_window->priv->metadata) {
2150  ev_window->priv->bookmarks = ev_bookmarks_new (ev_window->priv->metadata);
2152  ev_window->priv->bookmarks);
2153  g_signal_connect_swapped (ev_window->priv->bookmarks, "changed",
2154  G_CALLBACK (ev_window_setup_bookmarks),
2155  ev_window);
2156  ev_window_setup_bookmarks (ev_window);
2157  } else {
2158  ev_window->priv->bookmarks = NULL;
2159  }
2160 
2161  if (ev_window->priv->dest)
2162  g_object_unref (ev_window->priv->dest);
2163  ev_window->priv->dest = dest ? g_object_ref (dest) : NULL;
2164 
2165  setup_size_from_metadata (ev_window);
2166  setup_model_from_metadata (ev_window);
2167 
2168  ev_window->priv->load_job = ev_job_load_new (uri);
2169  g_signal_connect (ev_window->priv->load_job,
2170  "finished",
2171  G_CALLBACK (ev_window_load_job_cb),
2172  ev_window);
2173 
2174  if (!g_file_is_native (source_file) && !ev_window->priv->local_uri) {
2175  ev_window_load_file_remote (ev_window, source_file);
2176  } else {
2177  ev_window_show_loading_message (ev_window);
2178  g_object_unref (source_file);
2180  }
2181 }
2182 
2183 void
2185  EvDocument *document,
2186  EvLinkDest *dest,
2187  EvWindowRunMode mode,
2188  const gchar *search_string)
2189 {
2190  if (document == ev_window->priv->document)
2191  return;
2192 
2193  ev_window_close_dialogs (ev_window);
2194  ev_window_clear_load_job (ev_window);
2195  ev_window_clear_local_uri (ev_window);
2196 
2197  if (ev_window->priv->monitor) {
2198  g_object_unref (ev_window->priv->monitor);
2199  ev_window->priv->monitor = NULL;
2200  }
2201 
2202  if (ev_window->priv->uri)
2203  g_free (ev_window->priv->uri);
2204  ev_window->priv->uri = g_strdup (ev_document_get_uri (document));
2205 
2206  setup_size_from_metadata (ev_window);
2207  setup_model_from_metadata (ev_window);
2208 
2209  ev_document_model_set_document (ev_window->priv->model, document);
2210 
2211  setup_document_from_metadata (ev_window);
2212  setup_view_from_metadata (ev_window);
2213 
2214  if (dest) {
2215  EvLink *link;
2216  EvLinkAction *link_action;
2217 
2218  link_action = ev_link_action_new_dest (dest);
2219  link = ev_link_new (NULL, link_action);
2220  ev_view_handle_link (EV_VIEW (ev_window->priv->view), link);
2221  g_object_unref (link_action);
2222  g_object_unref (link);
2223  }
2224 
2225  switch (mode) {
2227  ev_window_run_fullscreen (ev_window);
2228  break;
2230  ev_window_run_presentation (ev_window);
2231  break;
2232  default:
2233  break;
2234  }
2235 
2236  if (search_string && EV_IS_DOCUMENT_FIND (document) &&
2237  mode != EV_WINDOW_MODE_PRESENTATION) {
2238  GtkSearchEntry *entry;
2239 
2240  ev_window_show_find_bar (ev_window, FALSE);
2241  entry = ev_search_box_get_entry (EV_SEARCH_BOX (ev_window->priv->search_box));
2242  gtk_entry_set_text (GTK_ENTRY (entry), search_string);
2243  }
2244 
2245  /* Create a monitor for the document */
2246  ev_window->priv->monitor = ev_file_monitor_new (ev_window->priv->uri);
2247  g_signal_connect_swapped (ev_window->priv->monitor, "changed",
2248  G_CALLBACK (ev_window_file_changed),
2249  ev_window);
2250 }
2251 
2252 void
2254 {
2255  if (ev_window->priv->recent_view)
2256  return;
2257 
2258  gtk_widget_hide (ev_window->priv->hpaned);
2259 
2261  g_signal_connect_object (ev_window->priv->recent_view,
2262  "item-activated",
2263  G_CALLBACK (recent_view_item_activated_cb),
2264  ev_window, 0);
2265  gtk_box_pack_start (GTK_BOX (ev_window->priv->main_box),
2266  GTK_WIDGET (ev_window->priv->recent_view),
2267  TRUE, TRUE, 0);
2268 
2269  gtk_widget_show (GTK_WIDGET (ev_window->priv->recent_view));
2270  ev_toolbar_set_mode (EV_TOOLBAR (ev_window->priv->toolbar),
2273 
2275 }
2276 
2277 static void
2279 {
2280  if (!ev_window->priv->recent_view)
2281  return;
2282 
2283  gtk_widget_destroy (GTK_WIDGET (ev_window->priv->recent_view));
2284  ev_window->priv->recent_view = NULL;
2285  gtk_widget_show (ev_window->priv->hpaned);
2286 }
2287 
2288 static void
2290 {
2291  const gchar *uri;
2292 
2293  uri = ev_window->priv->local_uri ? ev_window->priv->local_uri : ev_window->priv->uri;
2294  ev_window->priv->reload_job = ev_job_load_new (uri);
2295  g_signal_connect (ev_window->priv->reload_job, "finished",
2296  G_CALLBACK (ev_window_reload_job_cb),
2297  ev_window);
2299 }
2300 
2301 static gboolean
2303 {
2304  GtkWidget *area;
2305  gchar *text;
2306 
2307  if (ev_window->priv->message_area)
2308  return FALSE;
2309 
2310  text = g_strdup_printf (_("Reloading document from %s"),
2311  ev_window->priv->uri);
2312  area = ev_progress_message_area_new (GTK_STOCK_REFRESH,
2313  text,
2314  GTK_STOCK_CLOSE,
2315  GTK_RESPONSE_CLOSE,
2316  GTK_STOCK_CANCEL,
2317  GTK_RESPONSE_CANCEL,
2318  NULL);
2319  g_signal_connect (area, "response",
2320  G_CALLBACK (ev_window_progress_response_cb),
2321  ev_window);
2322  gtk_widget_show (area);
2323  ev_window_set_message_area (ev_window, area);
2324  g_free (text);
2325 
2326  return FALSE;
2327 }
2328 
2329 static void
2331  GAsyncResult *async_result,
2332  EvWindow *ev_window)
2333 {
2334  GError *error = NULL;
2335 
2336  ev_window_clear_progress_idle (ev_window);
2337 
2338  g_file_copy_finish (remote, async_result, &error);
2339  if (error) {
2340  if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
2341  ev_window_error_message (ev_window, error,
2342  "%s", _("Failed to reload document."));
2343  g_error_free (error);
2344  } else {
2345  ev_window_reload_local (ev_window);
2346  }
2347 
2348  g_object_unref (remote);
2349 }
2350 
2351 static void
2353  goffset total_bytes,
2354  EvWindow *ev_window)
2355 {
2356  gchar *status;
2357  gdouble fraction;
2358 
2359  if (!ev_window->priv->message_area)
2360  return;
2361 
2362  if (total_bytes <= 0)
2363  return;
2364 
2365  fraction = n_bytes / (gdouble)total_bytes;
2366  status = g_strdup_printf (_("Downloading document (%d%%)"),
2367  (gint)(fraction * 100));
2368 
2370  status);
2372  fraction);
2373 
2374  g_free (status);
2375 }
2376 
2377 static void
2379  GAsyncResult *async_result,
2380  EvWindow *ev_window)
2381 {
2382  GFileInfo *info;
2383  GTimeVal mtime;
2384  GError *error = NULL;
2385 
2386  info = g_file_query_info_finish (remote, async_result, &error);
2387  if (error) {
2388  g_error_free (error);
2389  g_object_unref (remote);
2390  ev_window_reload_local (ev_window);
2391 
2392  return;
2393  }
2394 
2395  g_file_info_get_modification_time (info, &mtime);
2396  if (ev_window->priv->uri_mtime != mtime.tv_sec) {
2397  GFile *target_file;
2398 
2399  /* Remote file has changed */
2400  ev_window->priv->uri_mtime = mtime.tv_sec;
2401 
2403 
2404  target_file = g_file_new_for_uri (ev_window->priv->local_uri);
2405  g_file_copy_async (remote, target_file,
2406  G_FILE_COPY_OVERWRITE,
2407  G_PRIORITY_DEFAULT,
2408  ev_window->priv->progress_cancellable,
2409  (GFileProgressCallback)reload_remote_copy_progress_cb,
2410  ev_window,
2411  (GAsyncReadyCallback)reload_remote_copy_ready_cb,
2412  ev_window);
2413  g_object_unref (target_file);
2414  ev_window_show_progress_message (ev_window, 1,
2415  (GSourceFunc)show_reloading_progress);
2416  } else {
2417  g_object_unref (remote);
2418  ev_window_reload_local (ev_window);
2419  }
2420 
2421  g_object_unref (info);
2422 }
2423 
2424 static void
2426 {
2427  GFile *remote;
2428 
2429  remote = g_file_new_for_uri (ev_window->priv->uri);
2430  /* Reload the remote uri only if it has changed */
2431  g_file_query_info_async (remote,
2432  G_FILE_ATTRIBUTE_TIME_MODIFIED,
2433  0, G_PRIORITY_DEFAULT,
2434  NULL,
2435  (GAsyncReadyCallback)query_remote_uri_mtime_cb,
2436  ev_window);
2437 }
2438 
2439 static void
2441  EvLinkDest *dest)
2442 {
2443  ev_window_clear_reload_job (ev_window);
2444  ev_window->priv->in_reload = TRUE;
2445 
2446  if (ev_window->priv->dest)
2447  g_object_unref (ev_window->priv->dest);
2448  ev_window->priv->dest = dest ? g_object_ref (dest) : NULL;
2449 
2450  if (ev_window->priv->local_uri) {
2451  ev_window_reload_remote (ev_window);
2452  } else {
2453  ev_window_reload_local (ev_window);
2454  }
2455 }
2456 
2457 static const gchar *
2458 get_settings_key_for_directory (GUserDirectory directory)
2459 {
2460  switch (directory) {
2461  case G_USER_DIRECTORY_PICTURES:
2463  case G_USER_DIRECTORY_DOCUMENTS:
2464  default:
2466  }
2467 }
2468 
2469 static void
2471  GtkFileChooser *file_chooser,
2472  const gchar *uri,
2473  GUserDirectory directory)
2474 {
2475  const gchar *dir;
2476  gchar *folder_uri;
2477 
2478  g_settings_get (ev_window_ensure_settings (window),
2479  get_settings_key_for_directory (directory),
2480  "ms", &folder_uri);
2481  if (folder_uri == NULL && uri != NULL) {
2482  GFile *file, *parent;
2483 
2484  file = g_file_new_for_uri (uri);
2485  parent = g_file_get_parent (file);
2486  g_object_unref (file);
2487  if (parent) {
2488  folder_uri = g_file_get_uri (parent);
2489  g_object_unref (parent);
2490  }
2491  }
2492 
2493  if (folder_uri) {
2494  gtk_file_chooser_set_current_folder_uri (file_chooser, folder_uri);
2495  } else {
2496  dir = g_get_user_special_dir (directory);
2497  gtk_file_chooser_set_current_folder (file_chooser,
2498  dir ? dir : g_get_home_dir ());
2499  }
2500 
2501  g_free (folder_uri);
2502 }
2503 
2504 static void
2506  GtkFileChooser *file_chooser,
2507  GUserDirectory directory)
2508 {
2509  gchar *uri, *folder;
2510 
2511  folder = gtk_file_chooser_get_current_folder (file_chooser);
2512  if (g_strcmp0 (folder, g_get_user_special_dir (directory)) == 0) {
2513  /* Store 'nothing' if the folder is the default one */
2514  uri = NULL;
2515  } else {
2516  uri = gtk_file_chooser_get_current_folder_uri (file_chooser);
2517  }
2518  g_free (folder);
2519 
2520  g_settings_set (ev_window_ensure_settings (window),
2521  get_settings_key_for_directory (directory),
2522  "ms", uri);
2523  g_free (uri);
2524 }
2525 
2526 static void
2527 file_open_dialog_response_cb (GtkWidget *chooser,
2528  gint response_id,
2529  EvWindow *ev_window)
2530 {
2531  if (response_id == GTK_RESPONSE_OK) {
2532  GSList *uris;
2533 
2534  ev_window_file_chooser_save_folder (ev_window, GTK_FILE_CHOOSER (chooser),
2535  G_USER_DIRECTORY_DOCUMENTS);
2536 
2537  uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (chooser));
2538 
2540  gtk_window_get_screen (GTK_WINDOW (ev_window)),
2541  gtk_get_current_event_time ());
2542 
2543  g_slist_foreach (uris, (GFunc)g_free, NULL);
2544  g_slist_free (uris);
2545  }
2546 
2547  gtk_widget_destroy (chooser);
2548 }
2549 
2550 static void
2551 ev_window_cmd_file_open (GSimpleAction *action,
2552  GVariant *parameter,
2553  gpointer user_data)
2554 {
2555  EvWindow *window = user_data;
2556  GtkWidget *chooser;
2557 
2558  chooser = gtk_file_chooser_dialog_new (_("Open Document"),
2559  GTK_WINDOW (window),
2560  GTK_FILE_CHOOSER_ACTION_OPEN,
2561  GTK_STOCK_CANCEL,
2562  GTK_RESPONSE_CANCEL,
2563  GTK_STOCK_OPEN, GTK_RESPONSE_OK,
2564  NULL);
2565 
2566  ev_document_factory_add_filters (chooser, NULL);
2567  gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (chooser), TRUE);
2568  gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (chooser), FALSE);
2569 
2570  ev_window_file_chooser_restore_folder (window, GTK_FILE_CHOOSER (chooser),
2571  NULL, G_USER_DIRECTORY_DOCUMENTS);
2572 
2573  g_signal_connect (chooser, "response",
2574  G_CALLBACK (file_open_dialog_response_cb),
2575  window);
2576 
2577  gtk_widget_show (chooser);
2578 }
2579 
2580 static void
2582  EvLinkDest *dest)
2583 {
2584  EvWindow *new_window = EV_WINDOW (ev_window_new ());
2585 
2586  if (window->priv->metadata)
2587  new_window->priv->metadata = g_object_ref (window->priv->metadata);
2588  ev_window_open_document (new_window,
2589  window->priv->document,
2590  dest, 0, NULL);
2591  new_window->priv->chrome = window->priv->chrome;
2592 
2593  gtk_window_present (GTK_WINDOW (new_window));
2594 }
2595 
2596 static void
2597 ev_window_cmd_file_open_copy (GSimpleAction *action,
2598  GVariant *parameter,
2599  gpointer user_data)
2600 {
2601  EvWindow *window = user_data;
2602 
2603  ev_window_open_copy_at_dest (window, NULL);
2604 }
2605 
2606 static void
2607 ev_window_add_recent (EvWindow *window, const char *filename)
2608 {
2609  gtk_recent_manager_add_item (window->priv->recent_manager, filename);
2610 }
2611 
2612 static gboolean
2614 {
2615  EvWindow *ev_window;
2616  GtkWidget *area;
2617  gchar *text;
2618  gchar *uri;
2619  EvSaveType save_type;
2620 
2621  ev_window = EV_WINDOW (g_object_get_data (G_OBJECT (dst), "ev-window"));
2622  ev_window->priv->progress_idle = 0;
2623 
2624  if (ev_window->priv->message_area)
2625  return FALSE;
2626 
2627  save_type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dst), "save-type"));
2628  uri = g_file_get_uri (dst);
2629  switch (save_type) {
2630  case EV_SAVE_DOCUMENT:
2631  text = g_strdup_printf (_("Saving document to %s"), uri);
2632  break;
2633  case EV_SAVE_ATTACHMENT:
2634  text = g_strdup_printf (_("Saving attachment to %s"), uri);
2635  break;
2636  case EV_SAVE_IMAGE:
2637  text = g_strdup_printf (_("Saving image to %s"), uri);
2638  break;
2639  default:
2640  g_assert_not_reached ();
2641  }
2642  g_free (uri);
2643  area = ev_progress_message_area_new (GTK_STOCK_SAVE,
2644  text,
2645  GTK_STOCK_CLOSE,
2646  GTK_RESPONSE_CLOSE,
2647  GTK_STOCK_CANCEL,
2648  GTK_RESPONSE_CANCEL,
2649  NULL);
2650  g_signal_connect (area, "response",
2651  G_CALLBACK (ev_window_progress_response_cb),
2652  ev_window);
2653  gtk_widget_show (area);
2654  ev_window_set_message_area (ev_window, area);
2655  g_free (text);
2656 
2657  return FALSE;
2658 }
2659 
2660 static void
2662  GAsyncResult *async_result,
2663  GFile *dst)
2664 {
2665  EvWindow *ev_window;
2666  GError *error = NULL;
2667 
2668  ev_window = EV_WINDOW (g_object_get_data (G_OBJECT (dst), "ev-window"));
2669  ev_window_clear_progress_idle (ev_window);
2670 
2671  if (g_file_copy_finish (src, async_result, &error)) {
2672  ev_tmp_file_unlink (src);
2673  return;
2674  }
2675 
2676  if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
2677  gchar *name;
2678 
2679  name = g_file_get_basename (dst);
2680  ev_window_error_message (ev_window, error,
2681  _("The file could not be saved as “%s”."),
2682  name);
2683  g_free (name);
2684  }
2685  ev_tmp_file_unlink (src);
2686  g_error_free (error);
2687 }
2688 
2689 static void
2691  goffset total_bytes,
2692  GFile *dst)
2693 {
2694  EvWindow *ev_window;
2695  EvSaveType save_type;
2696  gchar *status;
2697  gdouble fraction;
2698 
2699  ev_window = EV_WINDOW (g_object_get_data (G_OBJECT (dst), "ev-window"));
2700 
2701  if (!ev_window->priv->message_area)
2702  return;
2703 
2704  if (total_bytes <= 0)
2705  return;
2706 
2707  fraction = n_bytes / (gdouble)total_bytes;
2708  save_type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dst), "save-type"));
2709 
2710  switch (save_type) {
2711  case EV_SAVE_DOCUMENT:
2712  status = g_strdup_printf (_("Uploading document (%d%%)"),
2713  (gint)(fraction * 100));
2714  break;
2715  case EV_SAVE_ATTACHMENT:
2716  status = g_strdup_printf (_("Uploading attachment (%d%%)"),
2717  (gint)(fraction * 100));
2718  break;
2719  case EV_SAVE_IMAGE:
2720  status = g_strdup_printf (_("Uploading image (%d%%)"),
2721  (gint)(fraction * 100));
2722  break;
2723  default:
2724  g_assert_not_reached ();
2725  }
2726 
2728  status);
2730  fraction);
2731 
2732  g_free (status);
2733 }
2734 
2735 static void
2737  EvSaveType save_type,
2738  GFile *src,
2739  GFile *dst)
2740 {
2742  g_object_set_data (G_OBJECT (dst), "ev-window", ev_window);
2743  g_object_set_data (G_OBJECT (dst), "save-type", GINT_TO_POINTER (save_type));
2744  g_file_copy_async (src, dst,
2745  G_FILE_COPY_OVERWRITE,
2746  G_PRIORITY_DEFAULT,
2747  ev_window->priv->progress_cancellable,
2748  (GFileProgressCallback)window_save_file_copy_progress_cb,
2749  dst,
2750  (GAsyncReadyCallback)window_save_file_copy_ready_cb,
2751  dst);
2752  ev_window->priv->progress_idle =
2753  g_timeout_add_seconds_full (G_PRIORITY_DEFAULT,
2754  1,
2755  (GSourceFunc)show_saving_progress,
2756  dst,
2757  NULL);
2758 }
2759 
2760 static void
2762 {
2763  if (ev_window->priv->save_job != NULL) {
2764  if (!ev_job_is_finished (ev_window->priv->save_job))
2765  ev_job_cancel (ev_window->priv->save_job);
2766 
2767  g_signal_handlers_disconnect_by_func (ev_window->priv->save_job,
2769  ev_window);
2770  g_object_unref (ev_window->priv->save_job);
2771  ev_window->priv->save_job = NULL;
2772  }
2773 }
2774 
2775 static void
2777  EvWindow *window)
2778 {
2779  if (ev_job_is_failed (job)) {
2780  ev_window_error_message (window, job->error,
2781  _("The file could not be saved as “%s”."),
2782  EV_JOB_SAVE (job)->uri);
2783  } else {
2784  ev_window_add_recent (window, EV_JOB_SAVE (job)->uri);
2785  }
2786 
2787  ev_window_clear_save_job (window);
2788 }
2789 
2790 static void
2792  gint response_id,
2793  EvWindow *ev_window)
2794 {
2795  gchar *uri;
2796 
2797  if (response_id != GTK_RESPONSE_OK) {
2798  gtk_widget_destroy (fc);
2799  return;
2800  }
2801 
2802  ev_window_file_chooser_save_folder (ev_window, GTK_FILE_CHOOSER (fc),
2803  G_USER_DIRECTORY_DOCUMENTS);
2804 
2805  uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (fc));
2806 
2807  /* FIXME: remote copy should be done here rather than in the save job,
2808  * so that we can track progress and cancel the operation
2809  */
2810 
2811  ev_window_clear_save_job (ev_window);
2812  ev_window->priv->save_job = ev_job_save_new (ev_window->priv->document,
2813  uri, ev_window->priv->uri);
2814  g_signal_connect (ev_window->priv->save_job, "finished",
2815  G_CALLBACK (ev_window_save_job_cb),
2816  ev_window);
2817  /* The priority doesn't matter for this job */
2819 
2820  g_free (uri);
2821  gtk_widget_destroy (fc);
2822 }
2823 
2824 static void
2826 {
2827  GtkWidget *fc;
2828  gchar *base_name;
2829  GFile *file;
2830 
2831  fc = gtk_file_chooser_dialog_new (
2832  _("Save a Copy"),
2833  GTK_WINDOW (ev_window), GTK_FILE_CHOOSER_ACTION_SAVE,
2834  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
2835  GTK_STOCK_SAVE, GTK_RESPONSE_OK,
2836  NULL);
2837 
2838  ev_document_factory_add_filters (fc, ev_window->priv->document);
2839  gtk_dialog_set_default_response (GTK_DIALOG (fc), GTK_RESPONSE_OK);
2840  gtk_dialog_set_alternative_button_order (GTK_DIALOG (fc),
2841  GTK_RESPONSE_OK,
2842  GTK_RESPONSE_CANCEL,
2843  -1);
2844 
2845  gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (fc), FALSE);
2846  gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (fc), TRUE);
2847  file = g_file_new_for_uri (ev_window->priv->uri);
2848  base_name = g_file_get_basename (file);
2849  gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (fc), base_name);
2850  g_object_unref (file);
2851  g_free (base_name);
2852 
2853  ev_window_file_chooser_restore_folder (ev_window, GTK_FILE_CHOOSER (fc),
2854  ev_window->priv->uri,
2855  G_USER_DIRECTORY_DOCUMENTS);
2856 
2857  g_signal_connect (fc, "response",
2858  G_CALLBACK (file_save_dialog_response_cb),
2859  ev_window);
2860 
2861  gtk_widget_show (fc);
2862 }
2863 
2864 static void
2865 ev_window_cmd_save_as (GSimpleAction *action,
2866  GVariant *parameter,
2867  gpointer user_data)
2868 {
2869  EvWindow *window = user_data;
2870 
2871  ev_window_save_a_copy (window);
2872 }
2873 
2874 static void
2875 ev_window_cmd_send_to (GSimpleAction *action,
2876  GVariant *parameter,
2877  gpointer user_data)
2878 {
2879  EvWindow *ev_window = user_data;
2880  GAppInfo *app_info;
2881  gchar *command;
2882  const char *uri;
2883  char *unescaped_uri;
2884  GError *error = NULL;
2885 
2886  uri = ev_window->priv->local_uri ? ev_window->priv->local_uri : ev_window->priv->uri;
2887  unescaped_uri = g_uri_unescape_string (uri, NULL);
2888  command = g_strdup_printf ("%s \"%s\"", nautilus_sendto, unescaped_uri);
2889  g_free (unescaped_uri);
2890  app_info = g_app_info_create_from_commandline (command, NULL, 0, &error);
2891  if (app_info) {
2892  GdkAppLaunchContext *context;
2893  GdkScreen *screen;
2894 
2895  screen = gtk_window_get_screen (GTK_WINDOW (ev_window));
2896  context = gdk_display_get_app_launch_context (gdk_screen_get_display (screen));
2897  gdk_app_launch_context_set_screen (context, screen);
2898  gdk_app_launch_context_set_timestamp (context, gtk_get_current_event_time ());
2899  g_app_info_launch (app_info, NULL, G_APP_LAUNCH_CONTEXT (context), &error);
2900  g_object_unref (context);
2901 
2902  g_object_unref (app_info);
2903  }
2904  g_free (command);
2905 
2906  if (error) {
2907  ev_window_error_message (ev_window, error, "%s",
2908  _("Could not send current document"));
2909  g_error_free (error);
2910  }
2911 }
2912 
2913 static void
2915  GVariant *parameter,
2916  gpointer user_data)
2917 {
2918  EvWindow *window = user_data;
2919 
2920  guint32 timestamp;
2921  GAppInfo *app = NULL;
2922  GdkAppLaunchContext *context;
2923  GdkDisplay *display;
2924  GdkScreen *screen;
2925  GFile *file;
2926  GList list;
2927  GError *error = NULL;
2928 
2929  app = g_app_info_get_default_for_type ("inode/directory", FALSE);
2930 
2931  if (app == NULL) {
2932  return;
2933  }
2934 
2935  file = g_file_new_for_uri (window->priv->uri);
2936  list.next = list.prev = NULL;
2937  list.data = file;
2938 
2939  display = gtk_widget_get_display (GTK_WIDGET (window));
2940  screen = gtk_widget_get_screen (GTK_WIDGET (window));
2941  timestamp = gtk_get_current_event_time ();
2942 
2943  context = gdk_display_get_app_launch_context (display);
2944  gdk_app_launch_context_set_screen (context, screen);
2945  gdk_app_launch_context_set_timestamp (context, timestamp);
2946 
2947  g_app_info_launch (app, &list,
2948  G_APP_LAUNCH_CONTEXT (context), &error);
2949 
2950  if (error != NULL) {
2951  gchar *uri;
2952 
2953  uri = g_file_get_uri (file);
2954  g_warning ("Could not show containing folder for \"%s\": %s",
2955  uri, error->message);
2956 
2957  g_error_free (error);
2958  g_free (uri);
2959  }
2960 
2961  g_object_unref (context);
2962  g_object_unref (app);
2963 }
2964 
2965 static GKeyFile *
2967 {
2968  GKeyFile *print_settings_file;
2969  gchar *filename;
2970  GError *error = NULL;
2971 
2972  print_settings_file = g_key_file_new ();
2973 
2974  filename = g_build_filename (ev_application_get_dot_dir (EV_APP, FALSE),
2975  EV_PRINT_SETTINGS_FILE, NULL);
2976  if (!g_key_file_load_from_file (print_settings_file,
2977  filename,
2978  G_KEY_FILE_KEEP_COMMENTS |
2979  G_KEY_FILE_KEEP_TRANSLATIONS,
2980  &error)) {
2981 
2982  /* Don't warn if the file simply doesn't exist */
2983  if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
2984  g_warning ("%s", error->message);
2985 
2986  g_error_free (error);
2987  }
2988 
2989  g_free (filename);
2990 
2991  return print_settings_file;
2992 }
2993 
2994 static void
2995 save_print_setting_file (GKeyFile *key_file)
2996 {
2997  gchar *filename;
2998  gchar *data;
2999  gsize data_length;
3000  GError *error = NULL;
3001 
3002  filename = g_build_filename (ev_application_get_dot_dir (EV_APP, TRUE),
3003  EV_PRINT_SETTINGS_FILE, NULL);
3004  data = g_key_file_to_data (key_file, &data_length, NULL);
3005  g_file_set_contents (filename, data, data_length, &error);
3006  if (error) {
3007  g_warning ("Failed to save print settings: %s", error->message);
3008  g_error_free (error);
3009  }
3010  g_free (data);
3011  g_free (filename);
3012 }
3013 
3014 static void
3016  GtkPrintSettings *print_settings)
3017 {
3018  GKeyFile *key_file;
3019  gint i;
3020 
3021  key_file = get_print_settings_file ();
3022  gtk_print_settings_to_key_file (print_settings, key_file, EV_PRINT_SETTINGS_GROUP);
3023 
3024  /* Always Remove n_copies from global settings */
3025  g_key_file_remove_key (key_file, EV_PRINT_SETTINGS_GROUP, GTK_PRINT_SETTINGS_N_COPIES, NULL);
3026 
3027  /* Save print settings that are specific to the document */
3028  for (i = 0; i < G_N_ELEMENTS (document_print_settings); i++) {
3029  /* Remove it from global settings */
3030  g_key_file_remove_key (key_file, EV_PRINT_SETTINGS_GROUP,
3031  document_print_settings[i], NULL);
3032 
3033  if (window->priv->metadata) {
3034  const gchar *value;
3035 
3036  value = gtk_print_settings_get (print_settings,
3039  document_print_settings[i], value);
3040  }
3041  }
3042 
3043  save_print_setting_file (key_file);
3044  g_key_file_free (key_file);
3045 }
3046 
3047 static void
3049  GtkPageSetup *page_setup)
3050 {
3051  GKeyFile *key_file;
3052 
3053  key_file = get_print_settings_file ();
3054  gtk_page_setup_to_key_file (page_setup, key_file, EV_PAGE_SETUP_GROUP);
3055 
3056  /* Do not save document settings in global file */
3057  g_key_file_remove_key (key_file, EV_PAGE_SETUP_GROUP,
3058  "page-setup-orientation", NULL);
3059  g_key_file_remove_key (key_file, EV_PAGE_SETUP_GROUP,
3060  "page-setup-margin-top", NULL);
3061  g_key_file_remove_key (key_file, EV_PAGE_SETUP_GROUP,
3062  "page-setup-margin-bottom", NULL);
3063  g_key_file_remove_key (key_file, EV_PAGE_SETUP_GROUP,
3064  "page-setup-margin-left", NULL);
3065  g_key_file_remove_key (key_file, EV_PAGE_SETUP_GROUP,
3066  "page-setup-margin-right", NULL);
3067 
3068  save_print_setting_file (key_file);
3069  g_key_file_free (key_file);
3070 
3071  if (!window->priv->metadata)
3072  return;
3073 
3074  /* Save page setup options that are specific to the document */
3075  ev_metadata_set_int (window->priv->metadata, "page-setup-orientation",
3076  gtk_page_setup_get_orientation (page_setup));
3077  ev_metadata_set_double (window->priv->metadata, "page-setup-margin-top",
3078  gtk_page_setup_get_top_margin (page_setup, GTK_UNIT_MM));
3079  ev_metadata_set_double (window->priv->metadata, "page-setup-margin-bottom",
3080  gtk_page_setup_get_bottom_margin (page_setup, GTK_UNIT_MM));
3081  ev_metadata_set_double (window->priv->metadata, "page-setup-margin-left",
3082  gtk_page_setup_get_left_margin (page_setup, GTK_UNIT_MM));
3083  ev_metadata_set_double (window->priv->metadata, "page-setup-margin-right",
3084  gtk_page_setup_get_right_margin (page_setup, GTK_UNIT_MM));
3085 }
3086 
3087 static void
3089  GtkPrintSettings *print_settings)
3090 {
3091  gint i;
3092 
3093  if (!window->priv->metadata)
3094  return;
3095 
3096  /* Load print setting that are specific to the document */
3097  for (i = 0; i < G_N_ELEMENTS (document_print_settings); i++) {
3098  gchar *value = NULL;
3099 
3101  document_print_settings[i], &value);
3102  gtk_print_settings_set (print_settings,
3103  document_print_settings[i], value);
3104  }
3105 }
3106 
3107 static void
3109  GtkPageSetup *page_setup)
3110 {
3111  gint int_value;
3112  gdouble double_value;
3113  GtkPaperSize *paper_size = gtk_page_setup_get_paper_size (page_setup);
3114 
3115  /* Load page setup options that are specific to the document */
3116  if (window->priv->metadata &&
3117  ev_metadata_get_int (window->priv->metadata, "page-setup-orientation", &int_value)) {
3118  gtk_page_setup_set_orientation (page_setup, int_value);
3119  } else {
3120  gtk_page_setup_set_orientation (page_setup, GTK_PAGE_ORIENTATION_PORTRAIT);
3121  }
3122 
3123  if (window->priv->metadata &&
3124  ev_metadata_get_double (window->priv->metadata, "page-setup-margin-top", &double_value)) {
3125  gtk_page_setup_set_top_margin (page_setup, double_value, GTK_UNIT_MM);
3126  } else {
3127  gtk_page_setup_set_top_margin (page_setup,
3128  gtk_paper_size_get_default_top_margin (paper_size, GTK_UNIT_MM),
3129  GTK_UNIT_MM);
3130  }
3131 
3132  if (window->priv->metadata &&
3133  ev_metadata_get_double (window->priv->metadata, "page-setup-margin-bottom", &double_value)) {
3134  gtk_page_setup_set_bottom_margin (page_setup, double_value, GTK_UNIT_MM);
3135  } else {
3136  gtk_page_setup_set_bottom_margin (page_setup,
3137  gtk_paper_size_get_default_bottom_margin (paper_size, GTK_UNIT_MM),
3138  GTK_UNIT_MM);
3139  }
3140 
3141  if (window->priv->metadata &&
3142  ev_metadata_get_double (window->priv->metadata, "page-setup-margin-left", &double_value)) {
3143  gtk_page_setup_set_left_margin (page_setup, double_value, GTK_UNIT_MM);
3144  } else {
3145  gtk_page_setup_set_left_margin (page_setup,
3146  gtk_paper_size_get_default_left_margin (paper_size, GTK_UNIT_MM),
3147  GTK_UNIT_MM);
3148  }
3149 
3150  if (window->priv->metadata &&
3151  ev_metadata_get_double (window->priv->metadata, "page-setup-margin-right", &double_value)) {
3152  gtk_page_setup_set_right_margin (page_setup, double_value, GTK_UNIT_MM);
3153  } else {
3154  gtk_page_setup_set_right_margin (page_setup,
3155  gtk_paper_size_get_default_right_margin (paper_size, GTK_UNIT_MM),
3156  GTK_UNIT_MM);
3157  }
3158 }
3159 
3160 static GtkPrintSettings *
3161 get_print_settings (GKeyFile *key_file)
3162 {
3163  GtkPrintSettings *print_settings;
3164 
3165  print_settings = g_key_file_has_group (key_file, EV_PRINT_SETTINGS_GROUP) ?
3166  gtk_print_settings_new_from_key_file (key_file, EV_PRINT_SETTINGS_GROUP, NULL) :
3167  gtk_print_settings_new ();
3168 
3169  return print_settings ? print_settings : gtk_print_settings_new ();
3170 }
3171 
3172 static GtkPageSetup *
3173 get_print_page_setup (GKeyFile *key_file)
3174 {
3175  GtkPageSetup *page_setup;
3176 
3177  page_setup = g_key_file_has_group (key_file, EV_PAGE_SETUP_GROUP) ?
3178  gtk_page_setup_new_from_key_file (key_file, EV_PAGE_SETUP_GROUP, NULL) :
3179  gtk_page_setup_new ();
3180 
3181  return page_setup ? page_setup : gtk_page_setup_new ();
3182 }
3183 
3184 static void
3186 {
3187  EvPrintOperation *op;
3188 
3189  if (!ev_window->priv->print_queue)
3190  return;
3191 
3192  while ((op = g_queue_peek_tail (ev_window->priv->print_queue))) {
3194  }
3195 }
3196 
3197 static void
3199  gint n_jobs)
3200 {
3201  gchar *text = NULL;
3202 
3203  if (!EV_IS_PROGRESS_MESSAGE_AREA (ev_window->priv->message_area) ||
3204  !ev_window->priv->print_queue)
3205  return;
3206 
3207  if (n_jobs == 0) {
3208  ev_window_set_message_area (ev_window, NULL);
3209  return;
3210  }
3211 
3212  if (n_jobs > 1) {
3213  text = g_strdup_printf (ngettext ("%d pending job in queue",
3214  "%d pending jobs in queue",
3215  n_jobs - 1), n_jobs - 1);
3216  }
3217 
3219  text);
3220  g_free (text);
3221 }
3222 
3223 static gboolean
3225 {
3226  gtk_widget_destroy (window);
3227 
3228  return FALSE;
3229 }
3230 
3231 static void
3233  GtkPrintOperationResult result,
3234  EvWindow *ev_window)
3235 {
3236  gint n_jobs;
3237 
3238  switch (result) {
3239  case GTK_PRINT_OPERATION_RESULT_APPLY: {
3240  GtkPrintSettings *print_settings;
3241 
3242  print_settings = ev_print_operation_get_print_settings (op);
3243  ev_window_save_print_settings (ev_window, print_settings);
3244 
3246  GtkPageSetup *page_setup;
3247 
3249  ev_window_save_print_page_setup (ev_window, page_setup);
3250  }
3251  }
3252 
3253  break;
3254  case GTK_PRINT_OPERATION_RESULT_ERROR: {
3255  GtkWidget *dialog;
3256  GError *error = NULL;
3257 
3258 
3259  ev_print_operation_get_error (op, &error);
3260 
3261  /* The message area is already used by
3262  * the printing progress, so it's better to
3263  * use a popup dialog in this case
3264  */
3265  dialog = gtk_message_dialog_new (GTK_WINDOW (ev_window),
3266  GTK_DIALOG_DESTROY_WITH_PARENT,
3267  GTK_MESSAGE_ERROR,
3268  GTK_BUTTONS_CLOSE,
3269  "%s", _("Failed to print document"));
3270  gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
3271  "%s", error->message);
3272  g_signal_connect (dialog, "response",
3273  G_CALLBACK (gtk_widget_destroy),
3274  NULL);
3275  gtk_widget_show (dialog);
3276 
3277  g_error_free (error);
3278  }
3279  break;
3280  case GTK_PRINT_OPERATION_RESULT_CANCEL:
3281  default:
3282  break;
3283  }
3284 
3285  g_queue_remove (ev_window->priv->print_queue, op);
3286  g_object_unref (op);
3287  n_jobs = g_queue_get_length (ev_window->priv->print_queue);
3288  ev_window_print_update_pending_jobs_message (ev_window, n_jobs);
3289 
3290  if (n_jobs == 0 && ev_window->priv->close_after_print)
3291  g_idle_add ((GSourceFunc)destroy_window,
3292  ev_window);
3293 }
3294 
3295 static void
3297  gint response,
3298  EvWindow *ev_window)
3299 {
3300  if (response == GTK_RESPONSE_CANCEL) {
3301  EvPrintOperation *op;
3302 
3303  op = g_queue_peek_tail (ev_window->priv->print_queue);
3305  } else {
3306  gtk_widget_hide (GTK_WIDGET (area));
3307  }
3308 }
3309 
3310 static void
3312  EvWindow *ev_window)
3313 {
3314  const gchar *status;
3315  gdouble fraction;
3316 
3317  status = ev_print_operation_get_status (op);
3318  fraction = ev_print_operation_get_progress (op);
3319 
3320  if (!ev_window->priv->message_area) {
3321  GtkWidget *area;
3322  const gchar *job_name;
3323  gchar *text;
3324 
3325  job_name = ev_print_operation_get_job_name (op);
3326  text = g_strdup_printf (_("Printing job “%s”"), job_name);
3327 
3328  area = ev_progress_message_area_new (GTK_STOCK_PRINT,
3329  text,
3330  GTK_STOCK_CLOSE,
3331  GTK_RESPONSE_CLOSE,
3332  GTK_STOCK_CANCEL,
3333  GTK_RESPONSE_CANCEL,
3334  NULL);
3336  g_signal_connect (area, "response",
3338  ev_window);
3339  gtk_widget_show (area);
3340  ev_window_set_message_area (ev_window, area);
3341  g_free (text);
3342  }
3343 
3345  status);
3347  fraction);
3348 }
3349 
3350 static void
3352  EvWindow *ev_window)
3353 {
3354  if (!ev_window->priv->print_queue)
3355  ev_window->priv->print_queue = g_queue_new ();
3356 
3357  g_queue_push_head (ev_window->priv->print_queue, op);
3359  g_queue_get_length (ev_window->priv->print_queue));
3360 }
3361 
3362 void
3364  gint first_page,
3365  gint last_page)
3366 {
3367  EvPrintOperation *op;
3368  GKeyFile *print_settings_file;
3369  GtkPrintSettings *print_settings;
3370  GtkPageSetup *print_page_setup;
3371  gint current_page;
3372  gint document_last_page;
3373  gboolean embed_page_setup;
3374  gchar *output_basename;
3375  gchar *unescaped_basename;
3376  const gchar *document_uri;
3377  gchar *dot;
3378 
3379  g_return_if_fail (EV_IS_WINDOW (ev_window));
3380  g_return_if_fail (ev_window->priv->document != NULL);
3381 
3382  if (!ev_window->priv->print_queue)
3383  ev_window->priv->print_queue = g_queue_new ();
3384 
3385  op = ev_print_operation_new (ev_window->priv->document);
3386  if (!op) {
3387  g_warning ("%s", "Printing is not supported for document\n");
3388  return;
3389  }
3390 
3391  g_signal_connect (op, "begin_print",
3393  (gpointer)ev_window);
3394  g_signal_connect (op, "status_changed",
3396  (gpointer)ev_window);
3397  g_signal_connect (op, "done",
3398  G_CALLBACK (ev_window_print_operation_done),
3399  (gpointer)ev_window);
3400 
3401  current_page = ev_document_model_get_page (ev_window->priv->model);
3402  document_last_page = ev_document_get_n_pages (ev_window->priv->document);
3403 
3404  print_settings_file = get_print_settings_file ();
3405 
3406  print_settings = get_print_settings (print_settings_file);
3407  ev_window_load_print_settings_from_metadata (ev_window, print_settings);
3408 
3409  print_page_setup = get_print_page_setup (print_settings_file);
3410  ev_window_load_print_page_setup_from_metadata (ev_window, print_page_setup);
3411 
3412  if (first_page != 1 || last_page != document_last_page) {
3413  GtkPageRange range;
3414 
3415  /* Ranges in GtkPrint are 0 - N */
3416  range.start = first_page - 1;
3417  range.end = last_page - 1;
3418 
3419  gtk_print_settings_set_print_pages (print_settings,
3420  GTK_PRINT_PAGES_RANGES);
3421  gtk_print_settings_set_page_ranges (print_settings,
3422  &range, 1);
3423  }
3424 
3425  document_uri = ev_document_get_uri (ev_window->priv->document);
3426  output_basename = g_path_get_basename (document_uri);
3427  dot = g_strrstr (output_basename, ".");
3428  if (dot)
3429  dot[0] = '\0';
3430 
3431  unescaped_basename = g_uri_unescape_string (output_basename, NULL);
3432  /* Set output basename for printing to file */
3433  gtk_print_settings_set (print_settings,
3434  GTK_PRINT_SETTINGS_OUTPUT_BASENAME,
3435  unescaped_basename);
3436  g_free (unescaped_basename);
3437  g_free (output_basename);
3438 
3439  ev_print_operation_set_job_name (op, gtk_window_get_title (GTK_WINDOW (ev_window)));
3440  ev_print_operation_set_current_page (op, current_page);
3441  ev_print_operation_set_print_settings (op, print_settings);
3442  ev_print_operation_set_default_page_setup (op, print_page_setup);
3443  embed_page_setup = ev_window->priv->lockdown_settings ?
3444  !g_settings_get_boolean (ev_window->priv->lockdown_settings,
3446  TRUE;
3447  ev_print_operation_set_embed_page_setup (op, embed_page_setup);
3448 
3449  g_object_unref (print_settings);
3450  g_object_unref (print_page_setup);
3451  g_key_file_free (print_settings_file);
3452 
3453  ev_print_operation_run (op, GTK_WINDOW (ev_window));
3454 }
3455 
3456 static void
3458 {
3459  ev_window_print_range (window, 1,
3461 }
3462 
3463 static void
3464 ev_window_cmd_file_print (GSimpleAction *action,
3465  GVariant *state,
3466  gpointer user_data)
3467 {
3468  EvWindow *ev_window = user_data;
3469 
3470  ev_window_print (ev_window);
3471 }
3472 
3473 static void
3474 ev_window_cmd_file_properties (GSimpleAction *action,
3475  GVariant *state,
3476  gpointer user_data)
3477 {
3478  EvWindow *ev_window = user_data;
3479 
3480  if (ev_window->priv->properties == NULL) {
3481  ev_window->priv->properties = ev_properties_dialog_new ();
3483  ev_window->priv->uri,
3484  ev_window->priv->document);
3485  g_object_add_weak_pointer (G_OBJECT (ev_window->priv->properties),
3486  (gpointer) &(ev_window->priv->properties));
3487  gtk_window_set_transient_for (GTK_WINDOW (ev_window->priv->properties),
3488  GTK_WINDOW (ev_window));
3489  }
3490 
3492  gtk_widget_show (ev_window->priv->properties);
3494 }
3495 
3496 static void
3498  gint response,
3499  EvWindow *ev_window)
3500 {
3501  gtk_widget_destroy (GTK_WIDGET (dialog));
3502 
3503  if (response == GTK_RESPONSE_YES)
3504  ev_window_reload_document (ev_window, NULL);
3505 }
3506 
3507 static void
3509  gint response,
3510  EvWindow *ev_window)
3511 {
3512  gtk_widget_destroy (GTK_WIDGET (dialog));
3513 
3514  switch (response) {
3515  case GTK_RESPONSE_YES:
3516  ev_window_save_a_copy (ev_window);
3517  break;
3518  case GTK_RESPONSE_NO:
3519  gtk_widget_destroy (GTK_WIDGET (ev_window));
3520  break;
3521  case GTK_RESPONSE_CANCEL:
3522  default:
3523  break;
3524  }
3525 }
3526 
3527 static gboolean
3529  EvWindowAction command)
3530 {
3531  EvDocument *document = ev_window->priv->document;
3532  GtkWidget *dialog;
3533  gchar *text, *markup;
3534  const gchar *secondary_text, *secondary_text_command;
3535 
3536  if (!document)
3537  return FALSE;
3538 
3539  if (EV_IS_DOCUMENT_FORMS (document) &&
3541  secondary_text = _("Document contains form fields that have been filled out. ");
3542  } else if (EV_IS_DOCUMENT_ANNOTATIONS (document) &&
3544  secondary_text = _("Document contains new or modified annotations. ");
3545  } else {
3546  return FALSE;
3547  }
3548 
3549  dialog = gtk_message_dialog_new (GTK_WINDOW (ev_window),
3550  GTK_DIALOG_MODAL,
3551  GTK_MESSAGE_QUESTION,
3552  GTK_BUTTONS_NONE,
3553  NULL);
3554 
3555  if (command == EV_WINDOW_ACTION_RELOAD) {
3556  text = g_markup_printf_escaped (_("Reload document “%s”?"),
3557  gtk_window_get_title (GTK_WINDOW (ev_window)));
3558  secondary_text_command = _("If you reload the document, changes will be permanently lost.");
3559  gtk_dialog_add_buttons (GTK_DIALOG (dialog),
3560  GTK_STOCK_NO,
3561  GTK_RESPONSE_NO,
3562  _("Reload"),
3563  GTK_RESPONSE_YES,
3564  NULL);
3565  g_signal_connect (dialog, "response",
3567  ev_window);
3568  } else {
3569  text = g_markup_printf_escaped (_("Save a copy of document “%s” before closing?"),
3570  gtk_window_get_title (GTK_WINDOW (ev_window)));
3571  secondary_text_command = _("If you don’t save a copy, changes will be permanently lost.");
3572  gtk_dialog_add_buttons (GTK_DIALOG (dialog),
3573  _("Close _without Saving"),
3574  GTK_RESPONSE_NO,
3575  GTK_STOCK_CANCEL,
3576  GTK_RESPONSE_CANCEL,
3577  _("Save a _Copy"),
3578  GTK_RESPONSE_YES,
3579  NULL);
3580  g_signal_connect (dialog, "response",
3582  ev_window);
3583 
3584  }
3585  markup = g_strdup_printf ("<b>%s</b>", text);
3586  g_free (text);
3587 
3588  gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog), markup);
3589  g_free (markup);
3590 
3591  gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
3592  "%s %s", secondary_text, secondary_text_command);
3593  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_YES);
3594  gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
3595  GTK_RESPONSE_YES,
3596  GTK_RESPONSE_NO,
3597  GTK_RESPONSE_CANCEL,
3598  -1);
3599 
3600  gtk_widget_show (dialog);
3601 
3602  return TRUE;
3603 }
3604 
3605 static void
3607  gint response,
3608  EvWindow *ev_window)
3609 {
3610  gtk_widget_destroy (GTK_WIDGET (dialog));
3611 
3612  switch (response) {
3613  case GTK_RESPONSE_YES:
3614  if (!ev_window->priv->print_queue ||
3615  g_queue_is_empty (ev_window->priv->print_queue))
3616  gtk_widget_destroy (GTK_WIDGET (ev_window));
3617  else
3618  ev_window->priv->close_after_print = TRUE;
3619  break;
3620  case GTK_RESPONSE_NO:
3621  ev_window->priv->close_after_print = TRUE;
3622  if (ev_window->priv->print_queue &&
3623  !g_queue_is_empty (ev_window->priv->print_queue)) {
3624  gtk_widget_set_sensitive (GTK_WIDGET (ev_window), FALSE);
3625  ev_window_print_cancel (ev_window);
3626  } else {
3627  gtk_widget_destroy (GTK_WIDGET (ev_window));
3628  }
3629  break;
3630  case GTK_RESPONSE_CANCEL:
3631  default:
3632  ev_window->priv->close_after_print = FALSE;
3633  }
3634 }
3635 
3636 static gboolean
3638 {
3639  GtkWidget *dialog;
3640  gchar *text, *markup;
3641  gint n_print_jobs;
3642 
3643  n_print_jobs = ev_window->priv->print_queue ?
3644  g_queue_get_length (ev_window->priv->print_queue) : 0;
3645 
3646  if (n_print_jobs == 0)
3647  return FALSE;
3648 
3649  dialog = gtk_message_dialog_new (GTK_WINDOW (ev_window),
3650  GTK_DIALOG_MODAL,
3651  GTK_MESSAGE_QUESTION,
3652  GTK_BUTTONS_NONE,
3653  NULL);
3654  if (n_print_jobs == 1) {
3655  EvPrintOperation *op;
3656  const gchar *job_name;
3657 
3658  op = g_queue_peek_tail (ev_window->priv->print_queue);
3659  job_name = ev_print_operation_get_job_name (op);
3660 
3661  text = g_strdup_printf (_("Wait until print job “%s” finishes before closing?"),
3662  job_name);
3663  } else {
3664  /* TRANS: the singular form is not really used as n_print_jobs > 1
3665  but some languages distinguish between different plurals forms,
3666  so the ngettext is needed. */
3667  text = g_strdup_printf (ngettext("There is %d print job active. "
3668  "Wait until print finishes before closing?",
3669  "There are %d print jobs active. "
3670  "Wait until print finishes before closing?",
3671  n_print_jobs),
3672  n_print_jobs);
3673  }
3674 
3675  markup = g_strdup_printf ("<b>%s</b>", text);
3676  g_free (text);
3677 
3678  gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog), markup);
3679  g_free (markup);
3680 
3681  gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s",
3682  _("If you close the window, pending print "
3683  "jobs will not be printed."));
3684 
3685  gtk_dialog_add_buttons (GTK_DIALOG (dialog),
3686  _("Cancel _print and Close"),
3687  GTK_RESPONSE_NO,
3688  GTK_STOCK_CANCEL,
3689  GTK_RESPONSE_CANCEL,
3690  _("Close _after Printing"),
3691  GTK_RESPONSE_YES,
3692  NULL);
3693  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_YES);
3694  gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
3695  GTK_RESPONSE_YES,
3696  GTK_RESPONSE_NO,
3697  GTK_RESPONSE_CANCEL,
3698  -1);
3699 
3700  g_signal_connect (dialog, "response",
3702  ev_window);
3703  gtk_widget_show (dialog);
3704 
3705  return TRUE;
3706 }
3707 
3708 static gboolean
3710 {
3711  if (EV_WINDOW_IS_PRESENTATION (ev_window)) {
3712  gint current_page;
3713 
3714  /* Save current page */
3715  current_page = ev_view_presentation_get_current_page (
3717  ev_document_model_set_page (ev_window->priv->model, current_page);
3718  }
3719 
3721  return FALSE;
3722 
3723  if (ev_window_check_print_queue (ev_window))
3724  return FALSE;
3725 
3726  return TRUE;
3727 }
3728 
3729 static void
3730 ev_window_cmd_file_close_window (GSimpleAction *action,
3731  GVariant *parameter,
3732  gpointer user_data)
3733 {
3734  EvWindow *ev_window = user_data;
3735 
3736  if (ev_window_close (ev_window))
3737  gtk_widget_destroy (GTK_WIDGET (ev_window));
3738 }
3739 
3740 static void
3741 ev_window_cmd_focus_page_selector (GSimpleAction *action,
3742  GVariant *parameter,
3743  gpointer user_data)
3744 {
3745  EvWindow *window = user_data;
3746  GtkWidget *page_selector;
3747  EvToolbar *toolbar;
3748 
3750  update_chrome_visibility (window);
3751 
3752  toolbar = window->priv->fs_toolbar ? EV_TOOLBAR (window->priv->fs_toolbar) : EV_TOOLBAR (window->priv->toolbar);
3753  page_selector = ev_toolbar_get_page_selector (toolbar);
3755 }
3756 
3757 static void
3758 ev_window_cmd_scroll_forward (GSimpleAction *action,
3759  GVariant *parameter,
3760  gpointer user_data)
3761 {
3762  EvWindow *window = user_data;
3763 
3764  g_signal_emit_by_name (window->priv->view, "scroll", GTK_SCROLL_PAGE_FORWARD, GTK_ORIENTATION_VERTICAL);
3765 }
3766 
3767 static void
3768 ev_window_cmd_scroll_backwards (GSimpleAction *action,
3769  GVariant *parameter,
3770  gpointer user_data)
3771 {
3772  EvWindow *window = user_data;
3773 
3774  g_signal_emit_by_name (window->priv->view, "scroll", GTK_SCROLL_PAGE_BACKWARD, GTK_ORIENTATION_VERTICAL);
3775 }
3776 
3777 static void
3778 ev_window_cmd_continuous (GSimpleAction *action,
3779  GVariant *state,
3780  gpointer user_data)
3781 {
3782  EvWindow *window = user_data;
3783 
3785  ev_document_model_set_continuous (window->priv->model, g_variant_get_boolean (state));
3786  g_simple_action_set_state (action, state);
3787 }
3788 
3789 static void
3790 ev_window_cmd_dual (GSimpleAction *action,
3791  GVariant *state,
3792  gpointer user_data)
3793 {
3794  EvWindow *window = user_data;
3795 
3797  ev_document_model_set_dual_page (window->priv->model, g_variant_get_boolean (state));
3798  g_simple_action_set_state (action, state);
3799 }
3800 
3801 static void
3802 ev_window_cmd_dual_odd_pages_left (GSimpleAction *action,
3803  GVariant *state,
3804  gpointer user_data)
3805 {
3806  EvWindow *window = user_data;
3807 
3809  g_variant_get_boolean (state));
3810  g_simple_action_set_state (action, state);
3811 }
3812 
3813 static void
3815  GVariant *state,
3816  gpointer user_data)
3817 {
3818  EvWindow *window = user_data;
3819  const gchar *mode;
3820 
3821  mode = g_variant_get_string (state, NULL);
3822 
3823  if (g_str_equal (mode, "fit-page"))
3825  else if (g_str_equal (mode, "fit-width"))
3827  else if (g_str_equal (mode, "automatic"))
3829  else if (g_str_equal (mode, "free"))
3831  else
3832  g_assert_not_reached ();
3833 
3834  g_simple_action_set_state (action, state);
3835 }
3836 
3837 static void
3838 ev_window_cmd_view_zoom (GSimpleAction *action,
3839  GVariant *parameter,
3840  gpointer user_data)
3841 {
3842  EvWindow *ev_window = user_data;
3843  gdouble zoom = g_variant_get_double (parameter);
3844 
3846  ev_document_model_set_scale (ev_window->priv->model,
3847  zoom * get_screen_dpi (ev_window) / 72.0);
3848 }
3849 
3850 static void
3851 ev_window_cmd_edit_select_all (GSimpleAction *action,
3852  GVariant *parameter,
3853  gpointer user_data)
3854 {
3855  EvWindow *ev_window = user_data;
3856 
3857  ev_view_select_all (EV_VIEW (ev_window->priv->view));
3858 }
3859 
3860 static void
3861 ev_window_cmd_toggle_find (GSimpleAction *action,
3862  GVariant *state,
3863  gpointer user_data)
3864 {
3865  EvWindow *ev_window = user_data;
3866 
3867  if (g_variant_get_boolean (state))
3868  ev_window_show_find_bar (ev_window, TRUE);
3869  else
3870  ev_window_close_find_bar (ev_window);
3871 
3872  g_simple_action_set_state (action, state);
3873 }
3874 
3875 static void
3876 ev_window_cmd_find (GSimpleAction *action,
3877  GVariant *parameter,
3878  gpointer user_data)
3879 {
3880  EvWindow *ev_window = user_data;
3881 
3882  ev_window_show_find_bar (ev_window, TRUE);
3883 }
3884 
3885 static void
3887 {
3888  gint page;
3889 
3890  page = ev_document_model_get_page (ev_window->priv->model);
3891  ev_view_find_restart (EV_VIEW (ev_window->priv->view), page);
3893 }
3894 
3895 static void
3897 {
3898  ev_view_find_previous (EV_VIEW (ev_window->priv->view));
3900 }
3901 
3902 static void
3904 {
3905  ev_view_find_next (EV_VIEW (ev_window->priv->view));
3907 }
3908 
3909 static gboolean
3911 {
3912  ev_window_find_next (ev_window);
3913  return FALSE;
3914 }
3915 
3916 static void
3917 ev_window_cmd_edit_find_next (GSimpleAction *action,
3918  GVariant *parameter,
3919  gpointer user_data)
3920 {
3921  EvWindow *ev_window = user_data;
3922  gboolean search_mode_enabled;
3923 
3924  if (EV_WINDOW_IS_PRESENTATION (ev_window))
3925  return;
3926 
3927  search_mode_enabled = gtk_search_bar_get_search_mode (GTK_SEARCH_BAR (ev_window->priv->search_bar));
3928  ev_window_show_find_bar (ev_window, FALSE);
3929 
3930  /* Use idle to make sure view allocation happens before find */
3931  if (!search_mode_enabled)
3932  g_idle_add ((GSourceFunc)find_next_idle_cb, ev_window);
3933  else
3934  ev_window_find_next (ev_window);
3935 }
3936 
3937 static gboolean
3939 {
3940  ev_window_find_previous (ev_window);
3941  return FALSE;
3942 }
3943 
3944 static void
3945 ev_window_cmd_edit_find_previous (GSimpleAction *action,
3946  GVariant *parameter,
3947  gpointer user_data)
3948 {
3949  EvWindow *ev_window = user_data;
3950  gboolean search_mode_enabled;
3951 
3952  if (EV_WINDOW_IS_PRESENTATION (ev_window))
3953  return;
3954 
3955  search_mode_enabled = gtk_search_bar_get_search_mode (GTK_SEARCH_BAR (ev_window->priv->search_bar));
3956  ev_window_show_find_bar (ev_window, FALSE);
3957 
3958  /* Use idle to make sure view allocation happens before find */
3959  if (!search_mode_enabled)
3960  g_idle_add ((GSourceFunc)find_previous_idle_cb, ev_window);
3961  else
3962  ev_window_find_previous (ev_window);
3963 }
3964 
3965 static void
3966 ev_window_cmd_edit_copy (GSimpleAction *action,
3967  GVariant *parameter,
3968  gpointer user_data)
3969 {
3970  EvWindow *ev_window = user_data;
3971 
3972  ev_view_copy (EV_VIEW (ev_window->priv->view));
3973 }
3974 
3975 static void
3977  GParamSpec *pspec,
3978  EvWindow *ev_window)
3979 {
3980  if (ev_window->priv->metadata && !ev_window_is_empty (ev_window))
3981  ev_metadata_set_int (ev_window->priv->metadata, "sidebar_size",
3982  gtk_paned_get_position (GTK_PANED (object)));
3983 }
3984 
3985 static void
3987 {
3988  GtkTreeModel *model;
3989  GtkWidget *page_selector;
3990 
3991  g_object_get (window->priv->sidebar_links,
3992  "model", &model,
3993  NULL);
3994 
3995  if (!model)
3996  return;
3997 
3998  page_selector = ev_toolbar_get_page_selector (EV_TOOLBAR (window->priv->toolbar));
4000  if (window->priv->fs_toolbar) {
4001  page_selector = ev_toolbar_get_page_selector (EV_TOOLBAR (window->priv->fs_toolbar));
4003  }
4004  g_object_unref (model);
4005 }
4006 
4007 static void
4009 {
4010  GAction *action;
4011  gboolean fullscreen;
4012 
4013  action = g_action_map_lookup_action (G_ACTION_MAP (window), "fullscreen");
4014  fullscreen = ev_document_model_get_fullscreen (window->priv->model);
4015  g_simple_action_set_state (G_SIMPLE_ACTION (action), g_variant_new_boolean (fullscreen));
4016 }
4017 
4018 static void
4020 {
4022  gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->fs_revealer), FALSE);
4023 }
4024 
4025 static gboolean
4027 {
4029 
4030  if (!gtk_revealer_get_reveal_child (GTK_REVEALER (window->priv->fs_revealer))) {
4031  window->priv->fs_timeout_id = 0;
4032  return FALSE;
4033  }
4034 
4035  return TRUE;
4036 }
4037 
4038 static void
4040 {
4041  if (window->priv->fs_timeout_id)
4042  g_source_remove (window->priv->fs_timeout_id);
4043  window->priv->fs_timeout_id = 0;
4044 }
4045 
4046 static void
4048 {
4049  window->priv->fs_timeout_id =
4050  g_timeout_add_seconds (FULLSCREEN_POPUP_TIMEOUT,
4051  (GSourceFunc)fullscreen_toolbar_timeout_cb, window);
4052 }
4053 
4054 static void
4056 {
4058  if (gtk_revealer_get_reveal_child (GTK_REVEALER (window->priv->fs_revealer)))
4059  return;
4060 
4061  gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->fs_revealer), TRUE);
4062  if (!window->priv->fs_pointer_on_toolbar)
4064 }
4065 
4066 static gboolean
4068  GdkEvent *event,
4069  EvWindow *window)
4070 {
4071  window->priv->fs_pointer_on_toolbar = TRUE;
4073 
4074  return FALSE;
4075 }
4076 
4077 static gboolean
4079  GdkEvent *event,
4080  EvWindow *window)
4081 {
4082  window->priv->fs_pointer_on_toolbar = FALSE;
4084 
4085  return FALSE;
4086 }
4087 
4088 static void
4090 {
4091  gboolean fullscreen_window = TRUE;
4092 
4094  return;
4095 
4096  if (EV_WINDOW_IS_PRESENTATION (window)) {
4098  fullscreen_window = FALSE;
4099  }
4100 
4101  window->priv->fs_overlay = gtk_overlay_new ();
4102  window->priv->fs_eventbox = gtk_event_box_new ();
4103  window->priv->fs_revealer = gtk_revealer_new ();
4104  g_signal_connect (window->priv->fs_eventbox, "enter-notify-event",
4106  window);
4107  g_signal_connect (window->priv->fs_eventbox, "leave-notify-event",
4109  window);
4110 
4111  gtk_widget_set_size_request (window->priv->fs_eventbox, -1, 1);
4112  gtk_widget_set_valign (window->priv->fs_eventbox, GTK_ALIGN_START);
4113  gtk_revealer_set_transition_type (GTK_REVEALER (window->priv->fs_revealer), GTK_REVEALER_TRANSITION_TYPE_SLIDE_UP);
4114  gtk_revealer_set_transition_duration (GTK_REVEALER (window->priv->fs_revealer), FULLSCREEN_TRANSITION_DURATION);
4115 
4116  g_object_ref (window->priv->main_box);
4117  gtk_container_remove (GTK_CONTAINER (window), window->priv->main_box);
4118  gtk_container_add (GTK_CONTAINER (window->priv->fs_overlay),
4119  window->priv->main_box);
4120  g_object_unref (window->priv->main_box);
4121 
4122  window->priv->fs_toolbar = ev_toolbar_new (window);
4125 
4127  g_signal_connect (ev_toolbar_get_page_selector (EV_TOOLBAR (window->priv->fs_toolbar)),
4128  "activate-link",
4129  G_CALLBACK (activate_link_cb),
4130  window);
4131  gtk_container_add (GTK_CONTAINER (window->priv->fs_revealer),
4132  window->priv->fs_toolbar);
4133  gtk_widget_show (window->priv->fs_toolbar);
4134 
4135  gtk_container_add (GTK_CONTAINER (window->priv->fs_eventbox),
4136  window->priv->fs_revealer);
4137  gtk_widget_show (window->priv->fs_revealer);
4138  gtk_overlay_add_overlay (GTK_OVERLAY (window->priv->fs_overlay),
4139  window->priv->fs_eventbox);
4140  gtk_widget_show (window->priv->fs_eventbox);
4141 
4142  gtk_container_add (GTK_CONTAINER (window), window->priv->fs_overlay);
4143  gtk_widget_show (window->priv->fs_overlay);
4144 
4147 
4149 
4150  if (fullscreen_window)
4151  gtk_window_fullscreen (GTK_WINDOW (window));
4152  gtk_widget_grab_focus (window->priv->view);
4153 
4154  if (window->priv->metadata && !ev_window_is_empty (window))
4155  ev_metadata_set_boolean (window->priv->metadata, "fullscreen", TRUE);
4156 }
4157 
4158 static void
4160  gboolean unfullscreen_window)
4161 {
4163  return;
4164 
4165  gtk_container_remove (GTK_CONTAINER (window->priv->fs_revealer),
4166  window->priv->fs_toolbar);
4167  window->priv->fs_toolbar = NULL;
4168  gtk_container_remove (GTK_CONTAINER (window->priv->fs_eventbox),
4169  window->priv->fs_revealer);
4170  gtk_container_remove (GTK_CONTAINER (window->priv->fs_overlay),
4171  window->priv->fs_eventbox);
4172 
4173  g_object_ref (window->priv->main_box);
4174  gtk_container_remove (GTK_CONTAINER (window->priv->fs_overlay),
4175  window->priv->main_box);
4176  gtk_container_remove (GTK_CONTAINER (window), window->priv->fs_overlay);
4177  window->priv->fs_overlay = NULL;
4178  gtk_container_add (GTK_CONTAINER (window), window->priv->main_box);
4179  g_object_unref (window->priv->main_box);
4180 
4182 
4185 
4186  if (unfullscreen_window)
4187  gtk_window_unfullscreen (GTK_WINDOW (window));
4188 
4189  if (window->priv->metadata && !ev_window_is_empty (window))
4190  ev_metadata_set_boolean (window->priv->metadata, "fullscreen", FALSE);
4191 }
4192 
4193 static void
4194 ev_window_cmd_view_fullscreen (GSimpleAction *action,
4195  GVariant *state,
4196  gpointer user_data)
4197 {
4198  EvWindow *window = user_data;
4199 
4200  if (g_variant_get_boolean (state)) {
4201  ev_window_run_fullscreen (window);
4202  } else {
4203  ev_window_stop_fullscreen (window, TRUE);
4204  }
4205 
4206  g_simple_action_set_state (action, state);
4207 }
4208 
4209 static void
4211 {
4212  EvWindowPrivate *priv = window->priv;
4213 
4214  if (priv->presentation_mode_inhibit_id != 0)
4215  return;
4216 
4218  gtk_application_inhibit (GTK_APPLICATION (g_application_get_default ()),
4219  GTK_WINDOW (window),
4220  GTK_APPLICATION_INHIBIT_IDLE,
4221  _("Running in presentation mode"));
4222 }
4223 
4224 
4225 static void
4227 {
4228  EvWindowPrivate *priv = window->priv;
4229 
4230  if (priv->presentation_mode_inhibit_id == 0)
4231  return;
4232 
4233  gtk_application_uninhibit (GTK_APPLICATION (g_application_get_default ()),
4235  priv->presentation_mode_inhibit_id = 0;
4236 }
4237 
4238 static void
4240 {
4241  GAction *action;
4242 
4243  action = g_action_map_lookup_action (G_ACTION_MAP (window), "presentation");
4244  g_simple_action_set_state (G_SIMPLE_ACTION (action),
4245  g_variant_new_boolean (EV_WINDOW_IS_PRESENTATION (window)));
4246 }
4247 
4248 static void
4250 {
4252 }
4253 
4254 static gboolean
4256 {
4258 
4259  return FALSE;
4260 }
4261 
4262 static gboolean
4264 {
4266 
4267  return FALSE;
4268 }
4269 
4270 static void
4272 {
4273  gboolean fullscreen_window = TRUE;
4274  guint current_page;
4275  guint rotation;
4276  gboolean inverted_colors;
4277 
4278  if (EV_WINDOW_IS_PRESENTATION (window))
4279  return;
4280 
4281  ev_window_close_find_bar (window);
4282 
4283  if (ev_document_model_get_fullscreen (window->priv->model)) {
4284  ev_window_stop_fullscreen (window, FALSE);
4285  fullscreen_window = FALSE;
4286  }
4287 
4288  current_page = ev_document_model_get_page (window->priv->model);
4289  rotation = ev_document_model_get_rotation (window->priv->model);
4290  inverted_colors = ev_document_model_get_inverted_colors (window->priv->model);
4292  current_page,
4293  rotation,
4294  inverted_colors);
4295  g_signal_connect_swapped (window->priv->presentation_view, "finished",
4297  window);
4298  g_signal_connect_swapped (window->priv->presentation_view, "external-link",
4299  G_CALLBACK (view_external_link_cb),
4300  window);
4301  g_signal_connect_swapped (window->priv->presentation_view, "focus-in-event",
4303  window);
4304  g_signal_connect_swapped (window->priv->presentation_view, "focus-out-event",
4306  window);
4307 
4308  gtk_box_pack_start (GTK_BOX (window->priv->main_box),
4309  window->priv->presentation_view,
4310  TRUE, TRUE, 0);
4311 
4312  gtk_widget_hide (window->priv->hpaned);
4314  update_chrome_visibility (window);
4315 
4316  gtk_widget_grab_focus (window->priv->presentation_view);
4317  if (fullscreen_window)
4318  gtk_window_fullscreen (GTK_WINDOW (window));
4319 
4320  gtk_widget_show (window->priv->presentation_view);
4321 
4323 
4324  if (window->priv->metadata && !ev_window_is_empty (window))
4325  ev_metadata_set_boolean (window->priv->metadata, "presentation", TRUE);
4326 }
4327 
4328 static void
4330  gboolean unfullscreen_window)
4331 {
4332  guint current_page;
4333  guint rotation;
4334 
4335  if (!EV_WINDOW_IS_PRESENTATION (window))
4336  return;
4337 
4339  ev_document_model_set_page (window->priv->model, current_page);
4341  ev_document_model_set_rotation (window->priv->model, rotation);
4342 
4343  gtk_container_remove (GTK_CONTAINER (window->priv->main_box),
4344  window->priv->presentation_view);
4345  window->priv->presentation_view = NULL;
4346 
4347  gtk_widget_show (window->priv->hpaned);
4349  update_chrome_visibility (window);
4350  if (unfullscreen_window)
4351  gtk_window_unfullscreen (GTK_WINDOW (window));
4352 
4353  gtk_widget_grab_focus (window->priv->view);
4354 
4356 
4357  if (window->priv->metadata && !ev_window_is_empty (window))
4358  ev_metadata_set_boolean (window->priv->metadata, "presentation", FALSE);
4359 }
4360 
4361 static void
4362 ev_window_cmd_view_presentation (GSimpleAction *action,
4363  GVariant *state,
4364  gpointer user_data)
4365 {
4366  EvWindow *window = user_data;
4367 
4368  if (g_variant_get_boolean (state)) {
4369  ev_window_run_presentation (window);
4370  }
4371  /* We don't exit presentation when action is toggled because it conflicts with some
4372  * remote controls. The behaviour is also consistent with libreoffice and other
4373  * presentation tools. See https://bugzilla.gnome.org/show_bug.cgi?id=556162
4374  */
4375 }
4376 
4377 static gboolean
4378 ev_window_state_event (GtkWidget *widget,
4379  GdkEventWindowState *event)
4380 {
4381  EvWindow *window = EV_WINDOW (widget);
4382 
4383  if (GTK_WIDGET_CLASS (ev_window_parent_class)->window_state_event) {
4384  GTK_WIDGET_CLASS (ev_window_parent_class)->window_state_event (widget, event);
4385  }
4386 
4387  if ((event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) == 0)
4388  return FALSE;
4389 
4390  if (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) {
4392  return FALSE;
4393 
4394  ev_window_run_fullscreen (window);
4395  } else {
4397  ev_window_stop_fullscreen (window, FALSE);
4398  else if (EV_WINDOW_IS_PRESENTATION (window))
4400  }
4401 
4402  return FALSE;
4403 }
4404 
4405 static void
4407  EvWindowPageMode page_mode)
4408 {
4409  GtkWidget *child = NULL;
4410  GtkWidget *real_child;
4411 
4412  if (window->priv->page_mode == page_mode)
4413  return;
4414 
4415  window->priv->page_mode = page_mode;
4416 
4417  switch (page_mode) {
4418  case PAGE_MODE_DOCUMENT:
4419  child = window->priv->view;
4420  break;
4421  case PAGE_MODE_PASSWORD:
4422  child = window->priv->password_view;
4423  break;
4424  default:
4425  g_assert_not_reached ();
4426  }
4427 
4428  real_child = gtk_bin_get_child (GTK_BIN (window->priv->scrolled_window));
4429  if (child != real_child) {
4430  gtk_container_remove (GTK_CONTAINER (window->priv->scrolled_window),
4431  real_child);
4432  gtk_container_add (GTK_CONTAINER (window->priv->scrolled_window),
4433  child);
4434  }
4436 }
4437 
4438 static void
4439 ev_window_cmd_edit_rotate_left (GSimpleAction *action,
4440  GVariant *parameter,
4441  gpointer user_data)
4442 {
4443  EvWindow *ev_window = user_data;
4444  gint rotation;
4445 
4446  if (EV_WINDOW_IS_PRESENTATION (ev_window)) {
4449  rotation - 90);
4450  } else {
4451  rotation = ev_document_model_get_rotation (ev_window->priv->model);
4452 
4453  ev_document_model_set_rotation (ev_window->priv->model, rotation - 90);
4454  }
4455 }
4456 
4457 static void
4458 ev_window_cmd_edit_rotate_right (GSimpleAction *action,
4459  GVariant *parameter,
4460  gpointer user_data)
4461 {
4462  EvWindow *ev_window = user_data;
4463  gint rotation;
4464 
4465  if (EV_WINDOW_IS_PRESENTATION (ev_window)) {
4468  rotation + 90);
4469  } else {
4470  rotation = ev_document_model_get_rotation (ev_window->priv->model);
4471 
4472  ev_document_model_set_rotation (ev_window->priv->model, rotation + 90);
4473  }
4474 }
4475 
4476 static void
4477 ev_window_cmd_view_inverted_colors (GSimpleAction *action,
4478  GVariant *state,
4479  gpointer user_data)
4480 {
4481  EvWindow *ev_window = user_data;
4482 
4484  g_variant_get_boolean (state));
4485  g_simple_action_set_state (action, state);
4486 }
4487 
4488 static void
4489 ev_window_cmd_edit_save_settings (GSimpleAction *action,
4490  GVariant *state,
4491  gpointer user_data)
4492 {
4493  EvWindow *ev_window = user_data;
4494  EvWindowPrivate *priv = ev_window->priv;
4495  EvDocumentModel *model = priv->model;
4496  GSettings *settings = priv->default_settings;
4497  EvSizingMode sizing_mode;
4498 
4499  g_settings_set_boolean (settings, "continuous",
4501  g_settings_set_boolean (settings, "dual-page",
4503  g_settings_set_boolean (settings, "dual-page-odd-left",
4505  g_settings_set_boolean (settings, "fullscreen",
4507  g_settings_set_boolean (settings, "inverted-colors",
4509  sizing_mode = ev_document_model_get_sizing_mode (model);
4510  g_settings_set_enum (settings, "sizing-mode", sizing_mode);
4511  if (sizing_mode == EV_SIZING_FREE) {
4512  gdouble zoom = ev_document_model_get_scale (model);
4513 
4514  zoom *= 72.0 / get_screen_dpi (ev_window);
4515  g_settings_set_double (settings, "zoom", zoom);
4516  }
4517  g_settings_set_boolean (settings, "show-sidebar",
4518  gtk_widget_get_visible (priv->sidebar));
4519  g_settings_set_int (settings, "sidebar-size",
4520  gtk_paned_get_position (GTK_PANED (priv->hpaned)));
4521  g_settings_set_string (settings, "sidebar-page",
4523  g_settings_apply (settings);
4524 }
4525 
4526 static void
4527 ev_window_cmd_view_zoom_in (GSimpleAction *action,
4528  GVariant *parameter,
4529  gpointer user_data)
4530 {
4531  EvWindow *ev_window = user_data;
4532 
4534  ev_view_zoom_in (EV_VIEW (ev_window->priv->view));
4535 }
4536 
4537 static void
4538 ev_window_cmd_view_zoom_out (GSimpleAction *action,
4539  GVariant *parameter,
4540  gpointer user_data)
4541 {
4542  EvWindow *ev_window = user_data;
4543 
4545  ev_view_zoom_out (EV_VIEW (ev_window->priv->view));
4546 }
4547 
4548 static void
4549 ev_window_cmd_go_back_history (GSimpleAction *action,
4550  GVariant *parameter,
4551  gpointer user_data)
4552 {
4553  EvWindow *ev_window = user_data;
4554 
4555  ev_history_go_back (ev_window->priv->history);
4556 }
4557 
4558 static void
4559 ev_window_cmd_go_forward_history (GSimpleAction *action,
4560  GVariant *parameter,
4561  gpointer user_data)
4562 {
4563  EvWindow *ev_window = user_data;
4564 
4565  ev_history_go_forward (ev_window->priv->history);
4566 }
4567 
4568 static void
4569 ev_window_cmd_go_previous_page (GSimpleAction *action,
4570  GVariant *parameter,
4571  gpointer user_data)
4572 {
4573  EvWindow *window = user_data;
4574 
4575  ev_view_previous_page (EV_VIEW (window->priv->view));
4576 }
4577 
4578 static void
4579 ev_window_cmd_go_next_page (GSimpleAction *action,
4580  GVariant *parameter,
4581  gpointer user_data)
4582 {
4583  EvWindow *window = user_data;
4584 
4585  ev_view_next_page (EV_VIEW (window->priv->view));
4586 }
4587 
4588 static void
4589 ev_window_cmd_go_first_page (GSimpleAction *action,
4590  GVariant *parameter,
4591  gpointer user_data)
4592 {
4593  EvWindow *window = user_data;
4594 
4595  ev_document_model_set_page (window->priv->model, 0);
4596 }
4597 
4598 static void
4599 ev_window_cmd_go_last_page (GSimpleAction *action,
4600  GVariant *parameter,
4601  gpointer user_data)
4602 {
4603  EvWindow *window = user_data;
4604 
4606  ev_document_get_n_pages (window->priv->document) - 1);
4607 }
4608 
4609 static void
4610 ev_window_cmd_go_forward (GSimpleAction *action,
4611  GVariant *parameter,
4612  gpointer user_data)
4613 {
4614  EvWindow *ev_window = user_data;
4615  int n_pages, current_page;
4616 
4617  n_pages = ev_document_get_n_pages (ev_window->priv->document);
4618  current_page = ev_document_model_get_page (ev_window->priv->model);
4619 
4620  if (current_page + 10 < n_pages) {
4621  ev_document_model_set_page (ev_window->priv->model, current_page + 10);
4622  }
4623 }
4624 
4625 static void
4626 ev_window_cmd_go_backwards (GSimpleAction *action,
4627  GVariant *parameter,
4628  gpointer user_data)
4629 {
4630  EvWindow *ev_window = user_data;
4631  int current_page;
4632 
4633  current_page = ev_document_model_get_page (ev_window->priv->model);
4634 
4635  if (current_page - 10 >= 0) {
4636  ev_document_model_set_page (ev_window->priv->model, current_page - 10);
4637  }
4638 }
4639 
4640 static gint
4642  EvBookmark *b)
4643 {
4644  if (a->page < b->page)
4645  return -1;
4646  if (a->page > b->page)
4647  return 1;
4648  return 0;
4649 }
4650 
4651 static void
4653 {
4654  GList *items, *it;
4655 
4656  g_menu_remove_all (window->priv->bookmarks_menu);
4657 
4658  items = g_list_sort (ev_bookmarks_get_bookmarks (window->priv->bookmarks),
4659  (GCompareFunc) compare_bookmarks);
4660 
4661  for (it = items; it; it = it->next) {
4662  EvBookmark *bookmark = it->data;
4663  GMenuItem *item;
4664 
4665  item = g_menu_item_new (bookmark->title, NULL);
4666  g_menu_item_set_action_and_target (item, "win.goto-bookmark", "u", bookmark->page);
4667  g_menu_append_item (window->priv->bookmarks_menu, item);
4668 
4669  g_object_unref (item);
4670  }
4671 
4672  g_list_free (items);
4673 }
4674 
4675 static void
4676 ev_window_cmd_bookmarks_add (GSimpleAction *action,
4677  GVariant *parameter,
4678  gpointer user_data)
4679 {
4680  EvWindow *window = user_data;
4681  EvBookmark bm;
4682  gchar *page_label;
4683 
4684  bm.page = ev_document_model_get_page (window->priv->model);
4685  page_label = ev_document_get_page_label (window->priv->document, bm.page);
4686  bm.title = g_strdup_printf (_("Page %s"), page_label);
4687  g_free (page_label);
4688 
4689  /* EvBookmarks takes ownership of bookmark */
4690  ev_bookmarks_add (window->priv->bookmarks, &bm);
4691 }
4692 
4693 static void
4695  GVariant *parameter,
4696  gpointer user_data)
4697 {
4698  EvWindow *window = user_data;
4699 
4700  ev_document_model_set_page (window->priv->model, g_variant_get_uint32 (parameter));
4701 }
4702 
4703 static void
4704 ev_window_cmd_view_reload (GSimpleAction *action,
4705  GVariant *parameter,
4706  gpointer user_data)
4707 {
4708  EvWindow *ev_window = user_data;
4709 
4711  return;
4712 
4713  ev_window_reload_document (ev_window, NULL);
4714 }
4715 
4716 static void
4717 ev_window_cmd_view_autoscroll (GSimpleAction *action,
4718  GVariant *parameter,
4719  gpointer user_data)
4720 {
4721  EvWindow *ev_window = user_data;
4722 
4723  ev_view_autoscroll_start (EV_VIEW (ev_window->priv->view));
4724 }
4725 
4726 static void
4727 ev_window_cmd_escape (GSimpleAction *action,
4728  GVariant *parameter,
4729  gpointer user_data)
4730 {
4731  EvWindow *window = user_data;
4733 
4734  if (gtk_search_bar_get_search_mode (GTK_SEARCH_BAR (window->priv->search_bar)))
4735  ev_window_close_find_bar (window);
4736  else if (ev_document_model_get_fullscreen (window->priv->model))
4737  ev_window_stop_fullscreen (window, TRUE);
4738  else if (EV_WINDOW_IS_PRESENTATION (window))
4740  else
4741  gtk_widget_grab_focus (window->priv->view);
4742 }
4743 
4744 static void
4746 {
4747  EvSizingMode mode;
4748  GEnumValue *enum_value;
4749 
4750  if (!window->priv->metadata || ev_window_is_empty (window))
4751  return;
4752 
4753  mode = ev_document_model_get_sizing_mode (window->priv->model);
4754  enum_value = g_enum_get_value (g_type_class_peek (EV_TYPE_SIZING_MODE), mode);
4755  ev_metadata_set_string (window->priv->metadata, "sizing_mode",
4756  enum_value->value_nick);
4757 }
4758 
4759 static void
4761  GParamSpec *pspec,
4762  EvWindow *ev_window)
4763 {
4764  ev_window_set_document (ev_window,
4766 }
4767 
4768 static void
4770  GParamSpec *pspec,
4771  EvWindow *ev_window)
4772 {
4773  EvSizingMode sizing_mode = ev_document_model_get_sizing_mode (model);
4774 
4775  g_object_set (ev_window->priv->scrolled_window,
4776  "hscrollbar-policy",
4777  sizing_mode == EV_SIZING_FREE ?
4778  GTK_POLICY_AUTOMATIC : GTK_POLICY_NEVER,
4779  "vscrollbar-policy", GTK_POLICY_AUTOMATIC,
4780  NULL);
4781 
4782  update_sizing_buttons (ev_window);
4783  save_sizing_mode (ev_window);
4784 }
4785 
4786 static void
4787 ev_window_zoom_changed_cb (EvDocumentModel *model, GParamSpec *pspec, EvWindow *ev_window)
4788 {
4790 
4791  if (!ev_window->priv->metadata)
4792  return;
4793 
4794  if (ev_document_model_get_sizing_mode (model) == EV_SIZING_FREE && !ev_window_is_empty (ev_window)) {
4795  gdouble zoom;
4796 
4797  zoom = ev_document_model_get_scale (model);
4798  zoom *= 72.0 / get_screen_dpi (ev_window);
4799  ev_metadata_set_double (ev_window->priv->metadata, "zoom", zoom);
4800  }
4801 }
4802 
4803 static void
4805  GParamSpec *pspec,
4806  EvWindow *ev_window)
4807 {
4808  gboolean continuous;
4809  GAction *action;
4810 
4811  continuous = ev_document_model_get_continuous (model);
4812 
4813  action = g_action_map_lookup_action (G_ACTION_MAP (ev_window), "continuous");
4814  g_simple_action_set_state (G_SIMPLE_ACTION (action), g_variant_new_boolean (continuous));
4815 
4816  if (ev_window->priv->metadata && !ev_window_is_empty (ev_window))
4817  ev_metadata_set_boolean (ev_window->priv->metadata, "continuous", continuous);
4818 }
4819 
4820 static void
4822  GParamSpec *pspec,
4823  EvWindow *window)
4824 {
4825  gint rotation = ev_document_model_get_rotation (model);
4826 
4827  if (window->priv->metadata && !ev_window_is_empty (window))
4828  ev_metadata_set_int (window->priv->metadata, "rotation",
4829  rotation);
4830 }
4831 
4832 static void
4834  GParamSpec *pspec,
4835  EvWindow *window)
4836 {
4837  gboolean inverted_colors = ev_document_model_get_inverted_colors (model);
4838  GAction *action;
4839 
4840  action = g_action_map_lookup_action (G_ACTION_MAP (window), "inverted-colors");
4841  g_simple_action_set_state (G_SIMPLE_ACTION (action),
4842  g_variant_new_boolean (inverted_colors));
4843 
4844  if (window->priv->metadata && !ev_window_is_empty (window))
4845  ev_metadata_set_boolean (window->priv->metadata, "inverted-colors",
4846  inverted_colors);
4847 }
4848 
4849 static void
4851  GParamSpec *pspec,
4852  EvWindow *ev_window)
4853 {
4854  gboolean dual_page;
4855  GAction *action;
4856 
4857  dual_page = ev_document_model_get_dual_page (model);
4858 
4859  action = g_action_map_lookup_action (G_ACTION_MAP (ev_window), "dual-page");
4860  g_simple_action_set_state (G_SIMPLE_ACTION (action), g_variant_new_boolean (dual_page));
4861 
4862  if (ev_window->priv->metadata && !ev_window_is_empty (ev_window))
4863  ev_metadata_set_boolean (ev_window->priv->metadata, "dual-page", dual_page);
4864 }
4865 
4866 static void
4868  GParamSpec *pspec,
4869  EvWindow *ev_window)
4870 {
4871  if (ev_window->priv->metadata && !ev_window_is_empty (ev_window))
4872  ev_metadata_set_boolean (ev_window->priv->metadata, "dual-page-odd-left",
4874 }
4875 
4876 static void
4877 ev_window_cmd_action_menu (GSimpleAction *action,
4878  GVariant *parameter,
4879  gpointer user_data)
4880 {
4881  EvWindow *ev_window = user_data;
4882  EvToolbar *toolbar;
4883 
4884  toolbar = ev_window->priv->fs_toolbar ? EV_TOOLBAR (ev_window->priv->fs_toolbar) : EV_TOOLBAR (ev_window->priv->toolbar);
4885  ev_toolbar_action_menu_popup (toolbar);
4886 }
4887 
4888 static void
4889 ev_window_view_cmd_toggle_sidebar (GSimpleAction *action,
4890  GVariant *state,
4891  gpointer user_data)
4892 {
4893  EvWindow *ev_window = user_data;
4894  gboolean show_side_pane;
4895 
4896  if (EV_WINDOW_IS_PRESENTATION (ev_window))
4897  return;
4898 
4899  show_side_pane = g_variant_get_boolean (state);
4900  g_simple_action_set_state (action, g_variant_new_boolean (show_side_pane));
4901 
4902  update_chrome_flag (ev_window, EV_CHROME_SIDEBAR, show_side_pane);
4903  update_chrome_visibility (ev_window);
4904 }
4905 
4906 static void
4908  GParamSpec *pspec,
4909  EvWindow *ev_window)
4910 {
4911  if (ev_window->priv->metadata && !ev_window_is_empty (ev_window)) {
4912  ev_metadata_set_string (ev_window->priv->metadata,
4913  "sidebar_page",
4915  }
4916 }
4917 
4918 static void
4920  GParamSpec *pspec,
4921  EvWindow *ev_window)
4922 {
4923  if (!EV_WINDOW_IS_PRESENTATION (ev_window)) {
4924  gboolean visible = gtk_widget_get_visible (GTK_WIDGET (ev_sidebar));
4925 
4926  g_action_group_change_action_state (G_ACTION_GROUP (ev_window), "show-side-pane",
4927  g_variant_new_boolean (visible));
4928 
4929  if (ev_window->priv->metadata)
4930  ev_metadata_set_boolean (ev_window->priv->metadata, "sidebar_visibility",
4931  visible);
4932  if (!visible)
4933  gtk_widget_grab_focus (ev_window->priv->view);
4934  }
4935 }
4936 
4937 static void
4939  EvLink *link)
4940 {
4941  gboolean show_external = FALSE;
4942  gboolean show_internal = FALSE;
4943  GAction *action;
4944 
4945  g_clear_object (&ev_window->priv->link);
4946  if (link) {
4947  EvLinkAction *ev_action;
4948 
4949  ev_window->priv->link = g_object_ref (link);
4950 
4951  ev_action = ev_link_get_action (link);
4952  if (ev_action) {
4953  switch (ev_link_action_get_action_type (ev_action)) {
4956  show_internal = TRUE;
4957  break;
4960  show_external = TRUE;
4961  break;
4962  default:
4963  break;
4964  }
4965  }
4966  }
4967 
4968  action = g_action_map_lookup_action (G_ACTION_MAP (ev_window), "open-link");
4969  g_simple_action_set_enabled (G_SIMPLE_ACTION (action), show_external);
4970 
4971  action = g_action_map_lookup_action (G_ACTION_MAP (ev_window), "copy-link-address");
4972  g_simple_action_set_enabled (G_SIMPLE_ACTION (action), show_external);
4973 
4974  action = g_action_map_lookup_action (G_ACTION_MAP (ev_window), "go-to-link");
4975  g_simple_action_set_enabled (G_SIMPLE_ACTION (action), show_internal);
4976 
4977  action = g_action_map_lookup_action (G_ACTION_MAP (ev_window), "open-link-new-window");
4978  g_simple_action_set_enabled (G_SIMPLE_ACTION (action), show_internal);
4979 }
4980 
4981 static void
4983  EvImage *image)
4984 {
4985  GAction *action;
4986  gboolean show_image = FALSE;
4987 
4988  g_clear_object (&ev_window->priv->image);
4989  if (image) {
4990  ev_window->priv->image = g_object_ref (image);
4991  show_image = TRUE;
4992  }
4993 
4994  action = g_action_map_lookup_action (G_ACTION_MAP (ev_window), "save-image");
4995  g_simple_action_set_enabled (G_SIMPLE_ACTION (action), show_image);
4996 
4997  action = g_action_map_lookup_action (G_ACTION_MAP (ev_window), "copy-image");
4998  g_simple_action_set_enabled (G_SIMPLE_ACTION (action), show_image);
4999 }
5000 
5001 static void
5003  EvAnnotation *annot)
5004 {
5005  GAction *action;
5006  gboolean show_annot_props = FALSE;
5007  gboolean show_attachment = FALSE;
5008  gboolean can_remove_annots = FALSE;
5009 
5010  g_clear_object (&ev_window->priv->annot);
5011  if (annot) {
5012  ev_window->priv->annot = g_object_ref (annot);
5013 
5014  show_annot_props = EV_IS_ANNOTATION_MARKUP (annot);
5015 
5016  if (EV_IS_ANNOTATION_ATTACHMENT (annot)) {
5017  EvAttachment *attachment;
5018 
5020  if (attachment) {
5021  show_attachment = TRUE;
5022 
5023  g_list_free_full (ev_window->priv->attach_list,
5024  g_object_unref);
5025  ev_window->priv->attach_list =
5026  g_list_prepend (ev_window->priv->attach_list,
5027  g_object_ref (attachment));
5028  }
5029  }
5030  }
5031 
5032  if (EV_IS_DOCUMENT_ANNOTATIONS (ev_window->priv->document))
5034 
5035  action = g_action_map_lookup_action (G_ACTION_MAP (ev_window), "annot-properties");
5036  g_simple_action_set_enabled (G_SIMPLE_ACTION (action), show_annot_props);
5037 
5038  action = g_action_map_lookup_action (G_ACTION_MAP (ev_window), "remove-annot");
5039  g_simple_action_set_enabled (G_SIMPLE_ACTION (action), annot != NULL && can_remove_annots);
5040 
5041  action = g_action_map_lookup_action (G_ACTION_MAP (ev_window), "open-attachment");
5042  g_simple_action_set_enabled (G_SIMPLE_ACTION (action), show_attachment);
5043 
5044  action = g_action_map_lookup_action (G_ACTION_MAP (ev_window), "save-attachment");
5045  g_simple_action_set_enabled (G_SIMPLE_ACTION (action), show_attachment);
5046 }
5047 
5048 static gboolean
5050  GList *items,
5051  EvWindow *ev_window)
5052 {
5053  GList *l;
5054  gboolean has_link = FALSE;
5055  gboolean has_image = FALSE;
5056  gboolean has_annot = FALSE;
5057 
5058  for (l = items; l; l = g_list_next (l)) {
5059  if (EV_IS_LINK (l->data)) {
5060  view_menu_link_popup (ev_window, EV_LINK (l->data));
5061  has_link = TRUE;
5062  } else if (EV_IS_IMAGE (l->data)) {
5063  view_menu_image_popup (ev_window, EV_IMAGE (l->data));
5064  has_image = TRUE;
5065  } else if (EV_IS_ANNOTATION (l->data)) {
5066  view_menu_annot_popup (ev_window, EV_ANNOTATION (l->data));
5067  has_annot = TRUE;
5068  }
5069  }
5070 
5071  if (!has_link)
5072  view_menu_link_popup (ev_window, NULL);
5073  if (!has_image)
5074  view_menu_image_popup (ev_window, NULL);
5075  if (!has_annot)
5076  view_menu_annot_popup (ev_window, NULL);
5077 
5078  if (!ev_window->priv->view_popup) {
5079  ev_window->priv->view_popup = gtk_menu_new_from_model (ev_window->priv->view_popup_menu);
5080  gtk_menu_attach_to_widget (GTK_MENU (ev_window->priv->view_popup),
5081  GTK_WIDGET (ev_window), NULL);
5082  }
5083 
5084  gtk_menu_popup (GTK_MENU (ev_window->priv->view_popup),
5085  NULL, NULL, NULL, NULL,
5086  3, gtk_get_current_event_time ());
5087  return TRUE;
5088 }
5089 
5090 static gboolean
5092  GList *attach_list,
5093  EvWindow *ev_window)
5094 {
5095  GAction *action;
5096 
5097  g_assert (attach_list != NULL);
5098 
5099  action = g_action_map_lookup_action (G_ACTION_MAP (ev_window), "open-attachment");
5100  g_simple_action_set_enabled (G_SIMPLE_ACTION (action), TRUE);
5101 
5102  action = g_action_map_lookup_action (G_ACTION_MAP (ev_window), "save-attachment");
5103  g_simple_action_set_enabled (G_SIMPLE_ACTION (action), TRUE);
5104 
5105  g_list_free_full (ev_window->priv->attach_list, g_object_unref);
5106  ev_window->priv->attach_list = attach_list;
5107 
5108  if (!ev_window->priv->attachment_popup) {
5109  ev_window->priv->attachment_popup = gtk_menu_new_from_model (ev_window->priv->attachment_popup_menu);
5110  gtk_menu_attach_to_widget (GTK_MENU (ev_window->priv->attachment_popup),
5111  GTK_WIDGET (ev_window), NULL);
5112  }
5113 
5114  gtk_menu_popup (GTK_MENU (ev_window->priv->attachment_popup),
5115  NULL, NULL, NULL, NULL,
5116  3, gtk_get_current_event_time ());
5117 
5118  return TRUE;
5119 }
5120 
5121 static void
5123  gint page,
5124  gint result,
5125  EvWindow *window)
5126 {
5127  ev_view_find_set_result (EV_VIEW (window->priv->view), page, result);
5128 }
5129 
5130 static void
5132  const char *uri,
5133  EvWindow *ev_window)
5134 {
5136  gtk_window_get_screen (GTK_WINDOW (ev_window)),
5137  NULL, 0, NULL, gtk_get_current_event_time ());
5138 }
5139 
5140 static void
5141 search_entry_stop_search_cb (GtkSearchEntry *entry,
5142  EvWindow *ev_window)
5143 {
5144  ev_window_close_find_bar (ev_window);
5145 }
5146 
5147 static void
5149  EvJobFind *job,
5150  EvWindow *ev_window)
5151 {
5152  if (!ev_window->priv->document || !EV_IS_DOCUMENT_FIND (ev_window->priv->document))
5153  return;
5154 
5155  ev_view_find_search_changed (EV_VIEW (ev_window->priv->view));
5156  ev_view_find_started (EV_VIEW (ev_window->priv->view), job);
5158 }
5159 
5160 static void
5162  gint page,
5163  EvWindow *ev_window)
5164 {
5167 }
5168 
5169 static void
5171  EvWindow *ev_window)
5172 {
5173 
5176 
5177  ev_view_find_search_changed (EV_VIEW (ev_window->priv->view));
5178  gtk_widget_queue_draw (GTK_WIDGET (ev_window->priv->view));
5179 }
5180 
5181 static void
5183  EvWindow *ev_window)
5184 {
5185  ev_window_find_previous (ev_window);
5186 }
5187 
5188 static void
5190  EvWindow *ev_window)
5191 {
5192  ev_window_find_next (ev_window);
5193 }
5194 
5195 static void
5196 search_bar_search_mode_enabled_changed (GtkSearchBar *search_bar,
5197  GParamSpec *param,
5198  EvWindow *ev_window)
5199 {
5200  gboolean enabled = gtk_search_bar_get_search_mode (search_bar);
5201 
5202  ev_view_find_set_highlight_search (EV_VIEW (ev_window->priv->view), enabled);
5204 
5205  if (!enabled) {
5206  /* Handle the case of search bar close button clicked */
5207  ev_window_close_find_bar (ev_window);
5208  }
5209 }
5210 
5211 static void
5213  gboolean restart)
5214 {
5215  if (gtk_widget_get_visible (ev_window->priv->find_sidebar)) {
5216  gtk_widget_grab_focus (ev_window->priv->search_box);
5217  return;
5218  }
5219 
5220  if (ev_window->priv->document == NULL || !EV_IS_DOCUMENT_FIND (ev_window->priv->document)) {
5221  g_error ("Find action should be insensitive since document doesn't support find");
5222  return;
5223  }
5224 
5225  if (EV_WINDOW_IS_PRESENTATION (ev_window))
5226  return;
5227 
5228  ev_history_freeze (ev_window->priv->history);
5229 
5230  g_object_ref (ev_window->priv->sidebar);
5231  gtk_container_remove (GTK_CONTAINER (ev_window->priv->hpaned), ev_window->priv->sidebar);
5232  gtk_paned_pack1 (GTK_PANED (ev_window->priv->hpaned),
5233  ev_window->priv->find_sidebar, FALSE, FALSE);
5234  gtk_widget_show (ev_window->priv->find_sidebar);
5235 
5236 
5237  gtk_search_bar_set_search_mode (GTK_SEARCH_BAR (ev_window->priv->search_bar), TRUE);
5238  gtk_widget_grab_focus (ev_window->priv->search_box);
5239  g_action_group_change_action_state (G_ACTION_GROUP (ev_window), "toggle-find", g_variant_new_boolean (TRUE));
5240 
5241  if (restart) {
5242  GtkSearchEntry *entry = ev_search_box_get_entry (EV_SEARCH_BOX (ev_window->priv->search_box));
5243  const char *search_string = gtk_entry_get_text (GTK_ENTRY (entry));
5244 
5245  if (search_string && search_string[0])
5246  ev_window_find_restart (ev_window);
5247  }
5248 }
5249 
5250 static void
5252 {
5253  if (!gtk_widget_get_visible (ev_window->priv->find_sidebar))
5254  return;
5255 
5256  g_object_ref (ev_window->priv->find_sidebar);
5257  gtk_container_remove (GTK_CONTAINER (ev_window->priv->hpaned),
5258  ev_window->priv->find_sidebar);
5259  gtk_paned_pack1 (GTK_PANED (ev_window->priv->hpaned),
5260  ev_window->priv->sidebar, FALSE, FALSE);
5261  gtk_widget_hide (ev_window->priv->find_sidebar);
5262 
5263  gtk_search_bar_set_search_mode (GTK_SEARCH_BAR (ev_window->priv->search_bar), FALSE);
5264  gtk_widget_grab_focus (ev_window->priv->view);
5265  g_action_group_change_action_state (G_ACTION_GROUP (ev_window), "toggle-find", g_variant_new_boolean (FALSE));
5266 
5267  ev_history_thaw (ev_window->priv->history);
5268 }
5269 
5270 static void
5271 ev_window_drag_data_received (GtkWidget *widget,
5272  GdkDragContext *context,
5273  gint x,
5274  gint y,
5275  GtkSelectionData *selection_data,
5276  guint info,
5277  guint time)
5278 
5279 {
5280  EvWindow *window = EV_WINDOW (widget);
5281  gchar **uris;
5282  gint i = 0;
5283  GSList *uri_list = NULL;
5284  GtkWidget *source;
5285 
5286  source = gtk_drag_get_source_widget (context);
5287  if (source && widget == gtk_widget_get_toplevel (source)) {
5288  gtk_drag_finish (context, FALSE, FALSE, time);
5289  return;
5290  }
5291 
5292  uris = gtk_selection_data_get_uris (selection_data);
5293  if (!uris) {
5294  gtk_drag_finish (context, FALSE, FALSE, time);
5295  return;
5296  }
5297 
5298  for (i = 0; uris[i]; i++) {
5299  uri_list = g_slist_prepend (uri_list, (gpointer) uris[i]);
5300  }
5301 
5303  gtk_window_get_screen (GTK_WINDOW (window)),
5304  0);
5305  gtk_drag_finish (context, TRUE, FALSE, time);
5306 
5307  g_strfreev (uris);
5308  g_slist_free (uri_list);
5309 }
5310 
5311 static void
5313  gboolean enabled)
5314 {
5315  GAction *action;
5316 
5317  if (window->priv->metadata)
5318  ev_metadata_set_boolean (window->priv->metadata, "caret-navigation", enabled);
5319 
5320  ev_view_set_caret_navigation_enabled (EV_VIEW (window->priv->view), enabled);
5321 
5322  action = g_action_map_lookup_action (G_ACTION_MAP (window), "caret-navigation");
5323  g_simple_action_set_state (G_SIMPLE_ACTION (action), g_variant_new_boolean (enabled));
5324 }
5325 
5326 static void
5328  gint response_id,
5329  EvWindow *window)
5330 {
5331  /* Turn the caret navigation mode on */
5332  if (response_id == GTK_RESPONSE_YES)
5334 
5335  /* Turn the confirmation dialog off if the user has requested not to show it again */
5336  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (window->priv->ask_caret_navigation_check))) {
5337  g_settings_set_boolean (ev_window_ensure_settings (window), "show-caret-navigation-message", FALSE);
5338  g_settings_apply (window->priv->settings);
5339  }
5340 
5341  window->priv->ask_caret_navigation_check = NULL;
5342  ev_window_set_message_area (window, NULL);
5343  gtk_widget_grab_focus (window->priv->view);
5344 }
5345 
5346 static void
5348  GVariant *state,
5349  gpointer user_data)
5350 {
5351  EvWindow *window = user_data;
5352  GtkWidget *message_area;
5353  GtkWidget *box;
5354  GtkWidget *hbox;
5355  gboolean enabled;
5356 
5357  /* Don't ask for user confirmation to turn the caret navigation off when it is active,
5358  * or to turn it on when the confirmation dialog is not to be shown per settings */
5359  enabled = ev_view_is_caret_navigation_enabled (EV_VIEW (window->priv->view));
5360  if (enabled || !g_settings_get_boolean (ev_window_ensure_settings (window), "show-caret-navigation-message")) {
5361  ev_window_set_caret_navigation_enabled (window, !enabled);
5362  return;
5363  }
5364 
5365  /* Ask for user confirmation to turn the caret navigation mode on */
5366  if (window->priv->message_area)
5367  return;
5368 
5369  message_area = ev_message_area_new (GTK_MESSAGE_QUESTION,
5370  _("Enable caret navigation?"),
5371  GTK_STOCK_NO, GTK_RESPONSE_NO,
5372  _("_Enable"), GTK_RESPONSE_YES,
5373  NULL);
5375  _("Pressing F7 turns the caret navigation on or off. "
5376  "This feature places a moveable cursor in text pages, "
5377  "allowing you to move around and select text with your keyboard. "
5378  "Do you want to enable the caret navigation?"));
5379 
5380  window->priv->ask_caret_navigation_check = gtk_check_button_new_with_label (_("Don’t show this message again"));
5381  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
5382  gtk_box_pack_start (GTK_BOX (hbox), window->priv->ask_caret_navigation_check,
5383  TRUE, TRUE, 0);
5384  gtk_widget_show_all (hbox);
5385 
5386  box = _ev_message_area_get_main_box (EV_MESSAGE_AREA (message_area));
5387  gtk_box_pack_start (GTK_BOX (box), hbox, TRUE, TRUE, 0);
5388 
5389  g_signal_connect (message_area, "response",
5391  window);
5392 
5393  gtk_widget_show (message_area);
5394  ev_window_set_message_area (window, message_area);
5395 }
5396 
5397 static void
5398 ev_window_cmd_toggle_edit_annots (GSimpleAction *action,
5399  GVariant *state,
5400  gpointer user_data)
5401 {
5402  EvWindow *ev_window = user_data;
5403 
5404  if (g_variant_get_boolean (state))
5405  gtk_widget_show (ev_window->priv->annots_toolbar);
5406  else
5407  gtk_widget_hide (ev_window->priv->annots_toolbar);
5408 
5409  g_simple_action_set_state (action, state);
5410 }
5411 
5412 static void
5413 ev_window_dispose (GObject *object)
5414 {
5415  EvWindow *window = EV_WINDOW (object);
5416  EvWindowPrivate *priv = window->priv;
5417  GObject *mpkeys = ev_application_get_media_keys (EV_APP);
5418 
5419  if (mpkeys) {
5420  g_signal_handlers_disconnect_by_func (mpkeys,
5422  window);
5423  }
5424 
5425 #ifdef ENABLE_DBUS
5426  if (priv->skeleton != NULL) {
5427  ev_window_emit_closed (window);
5428 
5429  g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (priv->skeleton));
5430  g_object_unref (priv->skeleton);
5431  priv->skeleton = NULL;
5432  g_free (priv->dbus_object_path);
5433  priv->dbus_object_path = NULL;
5434  }
5435 #endif /* ENABLE_DBUS */
5436 
5437  if (priv->bookmarks) {
5438  g_object_unref (priv->bookmarks);
5439  priv->bookmarks = NULL;
5440  }
5441 
5442  if (priv->metadata) {
5443  g_object_unref (priv->metadata);
5444  priv->metadata = NULL;
5445  }
5446 
5447  if (priv->setup_document_idle > 0) {
5448  g_source_remove (priv->setup_document_idle);
5449  priv->setup_document_idle = 0;
5450  }
5451 
5452  if (priv->loading_message_timeout) {
5453  g_source_remove (priv->loading_message_timeout);
5454  priv->loading_message_timeout = 0;
5455  }
5456 
5458 
5459  if (priv->monitor) {
5460  g_object_unref (priv->monitor);
5461  priv->monitor = NULL;
5462  }
5463 
5464  if (priv->title) {
5465  ev_window_title_free (priv->title);
5466  priv->title = NULL;
5467  }
5468 
5469  g_clear_object (&priv->bookmarks_menu);
5470  g_clear_object (&priv->view_popup_menu);
5471  g_clear_object (&priv->attachment_popup_menu);
5472 
5473  if (priv->recent_manager) {
5474  priv->recent_manager = NULL;
5475  }
5476 
5477  if (priv->settings) {
5478  g_object_unref (priv->settings);
5479  priv->settings = NULL;
5480  }
5481 
5482  if (priv->default_settings) {
5483  g_settings_apply (priv->default_settings);
5484  g_object_unref (priv->default_settings);
5485  priv->default_settings = NULL;
5486  }
5487 
5488  if (priv->lockdown_settings) {
5489  g_object_unref (priv->lockdown_settings);
5490  priv->lockdown_settings = NULL;
5491  }
5492 
5493  if (priv->model) {
5494  g_signal_handlers_disconnect_by_func (priv->model,
5496  window);
5497  g_object_unref (priv->model);
5498  priv->model = NULL;
5499  }
5500 
5501  if (priv->document) {
5502  g_object_unref (priv->document);
5503  priv->document = NULL;
5504  }
5505 
5506  if (priv->view) {
5507  g_object_unref (priv->view);
5508  priv->view = NULL;
5509  }
5510 
5511  if (priv->password_view) {
5512  g_object_unref (priv->password_view);
5513  priv->password_view = NULL;
5514  }
5515 
5516  if (priv->load_job) {
5517  ev_window_clear_load_job (window);
5518  }
5519 
5520  if (priv->reload_job) {
5521  ev_window_clear_reload_job (window);
5522  }
5523 
5524  if (priv->save_job) {
5525  ev_window_clear_save_job (window);
5526  }
5527 
5528  if (priv->local_uri) {
5529  ev_window_clear_local_uri (window);
5530  priv->local_uri = NULL;
5531  }
5532 
5534  if (priv->progress_cancellable) {
5535  g_object_unref (priv->progress_cancellable);
5536  priv->progress_cancellable = NULL;
5537  }
5538 
5539  ev_window_close_dialogs (window);
5540 
5541  if (priv->link) {
5542  g_object_unref (priv->link);
5543  priv->link = NULL;
5544  }
5545 
5546  if (priv->image) {
5547  g_object_unref (priv->image);
5548  priv->image = NULL;
5549  }
5550 
5551  if (priv->annot) {
5552  g_object_unref (priv->annot);
5553  priv->annot = NULL;
5554  }
5555 
5556  if (priv->attach_list) {
5557  g_list_foreach (priv->attach_list,
5558  (GFunc) g_object_unref,
5559  NULL);
5560  g_list_free (priv->attach_list);
5561  priv->attach_list = NULL;
5562  }
5563 
5564  if (priv->uri) {
5565  g_free (priv->uri);
5566  priv->uri = NULL;
5567  }
5568 
5569  if (priv->search_string) {
5570  g_free (priv->search_string);
5571  priv->search_string = NULL;
5572  }
5573 
5574  if (priv->dest) {
5575  g_object_unref (priv->dest);
5576  priv->dest = NULL;
5577  }
5578 
5579  if (priv->history) {
5580  g_object_unref (priv->history);
5581  priv->history = NULL;
5582  }
5583 
5584  if (priv->print_queue) {
5585  g_queue_free (priv->print_queue);
5586  priv->print_queue = NULL;
5587  }
5588 
5589  G_OBJECT_CLASS (ev_window_parent_class)->dispose (object);
5590 }
5591 
5592 /*
5593  * GtkWindow catches keybindings for the menu items _before_ passing them to
5594  * the focused widget. This is unfortunate and means that pressing Ctrl+a,
5595  * Ctrl+left or Ctrl+right in the search bar ends up selecting text in the EvView
5596  * or rotating it.
5597  * Here we override GtkWindow's handler to do the same things that it
5598  * does, but in the opposite order and then we chain up to the grand
5599  * parent handler, skipping gtk_window_key_press_event.
5600  */
5601 static gboolean
5602 ev_window_key_press_event (GtkWidget *widget,
5603  GdkEventKey *event)
5604 {
5605  static gpointer grand_parent_class = NULL;
5606  GtkWindow *window = GTK_WINDOW (widget);
5607 
5608  if (grand_parent_class == NULL)
5609  grand_parent_class = g_type_class_peek_parent (ev_window_parent_class);
5610 
5611  /* Handle focus widget key events */
5612  if (gtk_window_propagate_key_event (window, event))
5613  return TRUE;
5614 
5615  /* Handle mnemonics and accelerators */
5616  if (gtk_window_activate_key (window, event))
5617  return TRUE;
5618 
5619  /* Chain up, invokes binding set on window */
5620  return GTK_WIDGET_CLASS (grand_parent_class)->key_press_event (widget, event);
5621 }
5622 
5623 static gboolean
5624 ev_window_delete_event (GtkWidget *widget,
5625  GdkEventAny *event)
5626 {
5627  return !ev_window_close (EV_WINDOW (widget));
5628 }
5629 
5630 static void
5632 {
5633  GObjectClass *g_object_class = G_OBJECT_CLASS (ev_window_class);
5634  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (ev_window_class);
5635 
5636  g_object_class->dispose = ev_window_dispose;
5637 
5638  widget_class->delete_event = ev_window_delete_event;
5639  widget_class->key_press_event = ev_window_key_press_event;
5640  widget_class->window_state_event = ev_window_state_event;
5641  widget_class->drag_data_received = ev_window_drag_data_received;
5642 
5643  nautilus_sendto = g_find_program_in_path ("nautilus-sendto");
5644 
5645  g_type_class_add_private (g_object_class, sizeof (EvWindowPrivate));
5646 }
5647 
5648 static const GActionEntry actions[] = {
5649  { "open", ev_window_cmd_file_open },
5650  { "open-copy", ev_window_cmd_file_open_copy },
5651  { "save-copy", ev_window_cmd_save_as },
5652  { "send-to", ev_window_cmd_send_to },
5653  { "open-containing-folder", ev_window_cmd_open_containing_folder },
5654  { "print", ev_window_cmd_file_print },
5655  { "show-properties", ev_window_cmd_file_properties },
5656  { "copy", ev_window_cmd_edit_copy },
5657  { "select-all", ev_window_cmd_edit_select_all },
5658  { "save-settings", ev_window_cmd_edit_save_settings },
5659  { "go-previous-page", ev_window_cmd_go_previous_page },
5660  { "go-next-page", ev_window_cmd_go_next_page },
5661  { "go-first-page", ev_window_cmd_go_first_page },
5662  { "go-last-page", ev_window_cmd_go_last_page },
5663  { "go-forward", ev_window_cmd_go_forward },
5664  { "go-backwards", ev_window_cmd_go_backwards },
5665  { "go-back-history", ev_window_cmd_go_back_history },
5666  { "go-forward-history", ev_window_cmd_go_forward_history },
5667  { "find", ev_window_cmd_find },
5668  { "toggle-find", NULL, NULL, "false", ev_window_cmd_toggle_find },
5669  { "find-next", ev_window_cmd_edit_find_next },
5670  { "find-previous", ev_window_cmd_edit_find_previous },
5671  { "select-page", ev_window_cmd_focus_page_selector },
5672  { "continuous", NULL, NULL, "true", ev_window_cmd_continuous },
5673  { "dual-page", NULL, NULL, "false", ev_window_cmd_dual },
5674  { "dual-odd-left", NULL, NULL, "false", ev_window_cmd_dual_odd_pages_left },
5675  { "show-side-pane", NULL, NULL, "false", ev_window_view_cmd_toggle_sidebar },
5676  { "inverted-colors", NULL, NULL, "false", ev_window_cmd_view_inverted_colors },
5677  { "fullscreen", NULL, NULL, "false", ev_window_cmd_view_fullscreen },
5678  { "presentation", NULL, NULL, "false", ev_window_cmd_view_presentation },
5679  { "rotate-left", ev_window_cmd_edit_rotate_left },
5680  { "rotate-right", ev_window_cmd_edit_rotate_right },
5681  { "zoom-in", ev_window_cmd_view_zoom_in },
5682  { "zoom-out", ev_window_cmd_view_zoom_out },
5683  { "reload", ev_window_cmd_view_reload },
5684  { "auto-scroll", ev_window_cmd_view_autoscroll },
5685  { "add-bookmark", ev_window_cmd_bookmarks_add },
5686  { "goto-bookmark", ev_window_activate_goto_bookmark_action, "u" },
5687  { "close", ev_window_cmd_file_close_window },
5688  { "scroll-forward", ev_window_cmd_scroll_forward },
5689  { "scroll-backwards", ev_window_cmd_scroll_backwards },
5690  { "sizing-mode", NULL, "s", "'free'", ev_window_change_sizing_mode_action_state },
5691  { "zoom", ev_window_cmd_view_zoom, "d" },
5692  { "escape", ev_window_cmd_escape },
5693  { "open-menu", ev_window_cmd_action_menu },
5694  { "caret-navigation", NULL, NULL, "false", ev_window_cmd_view_toggle_caret_navigation },
5695  { "toggle-edit-annots", NULL, NULL, "false", ev_window_cmd_toggle_edit_annots },
5696  /* Popups specific items */
5697  { "open-link", ev_window_popup_cmd_open_link },
5698  { "open-link-new-window", ev_window_popup_cmd_open_link_new_window },
5699  { "go-to-link", ev_window_popup_cmd_open_link },
5700  { "copy-link-address", ev_window_popup_cmd_copy_link_address },
5701  { "save-image", ev_window_popup_cmd_save_image_as },
5702  { "copy-image", ev_window_popup_cmd_copy_image },
5703  { "open-attachment", ev_window_popup_cmd_open_attachment },
5704  { "save-attachment", ev_window_popup_cmd_save_attachment_as },
5705  { "annot-properties", ev_window_popup_cmd_annot_properties },
5706  { "remove-annot", ev_window_popup_cmd_remove_annotation }
5707 };
5708 
5709 static void
5711 {
5712  ev_view_handle_link (EV_VIEW (window->priv->view), link);
5713 }
5714 
5715 static void
5716 activate_link_cb (GObject *object, EvLink *link, EvWindow *window)
5717 {
5718  ev_view_handle_link (EV_VIEW (window->priv->view), link);
5719  gtk_widget_grab_focus (window->priv->view);
5720 }
5721 
5722 static void
5724  EvWindow *window)
5725 {
5726  ev_window_set_action_enabled (window, "go-back-history",
5727  ev_history_can_go_back (window->priv->history));
5728  ev_window_set_action_enabled (window, "go-forward-history",
5730 }
5731 
5732 static void
5734  EvWindow *window)
5735 {
5736  ev_view_reload (EV_VIEW (window->priv->view));
5737 }
5738 
5739 static void
5741  EvMapping *annot_mapping,
5742  EvWindow *window)
5743 {
5744  ev_view_focus_annotation (EV_VIEW (window->priv->view), annot_mapping);
5745 }
5746 
5747 static void
5749  EvAnnotationType annot_type)
5750 {
5751  ev_view_begin_add_annotation (EV_VIEW (window->priv->view), annot_type);
5752 }
5753 
5754 static void
5756  EvAnnotation *annot,
5757  EvWindow *window)
5758 {
5760  annot);
5762 }
5763 
5764 static void
5766  EvAnnotation *annot,
5767  EvWindow *window)
5768 {
5770 }
5771 
5772 static void
5774 {
5776 }
5777 
5778 static void
5780  GParamSpec *pspec,
5781  EvWindow *ev_window)
5782 {
5783  ev_window_update_links_model (ev_window);
5784 }
5785 
5786 static gboolean
5787 view_actions_focus_in_cb (GtkWidget *widget, GdkEventFocus *event, EvWindow *window)
5788 {
5789 #ifdef ENABLE_DBUS
5790  GObject *keys;
5791 
5793  if (keys)
5795 #endif /* ENABLE_DBUS */
5796 
5798  update_chrome_visibility (window);
5799 
5800  return FALSE;
5801 }
5802 
5803 static void
5804 sidebar_page_main_widget_update_cb (GObject *ev_sidebar_page,
5805  GParamSpec *pspec,
5806  EvWindow *ev_window)
5807 {
5808  GtkWidget *widget;
5809 
5810  g_object_get (ev_sidebar_page, "main_widget", &widget, NULL);
5811 
5812  if (widget != NULL) {
5813  g_signal_connect_object (widget, "focus_in_event",
5814  G_CALLBACK (view_actions_focus_in_cb),
5815  ev_window, 0);
5816  g_object_unref (widget);
5817  }
5818 }
5819 
5820 static gboolean
5821 window_state_event_cb (EvWindow *window, GdkEventWindowState *event, gpointer dummy)
5822 {
5823  if (!(event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) {
5824  gboolean maximized;
5825 
5826  maximized = event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED;
5827  if (window->priv->metadata && !ev_window_is_empty (window))
5828  ev_metadata_set_boolean (window->priv->metadata, "window_maximized", maximized);
5829  }
5830 
5831  return FALSE;
5832 }
5833 
5834 static gboolean
5835 window_configure_event_cb (EvWindow *window, GdkEventConfigure *event, gpointer dummy)
5836 {
5837  GdkWindowState state;
5838  gdouble document_width, document_height;
5839 
5840  if (!window->priv->metadata)
5841  return FALSE;
5842 
5843  state = gdk_window_get_state (gtk_widget_get_window (GTK_WIDGET (window)));
5844 
5845  if (!(state & GDK_WINDOW_STATE_FULLSCREEN)) {
5846  if (window->priv->document) {
5848  &document_width, &document_height);
5849  g_settings_set (window->priv->default_settings, "window-ratio", "(dd)",
5850  (double)event->width / document_width,
5851  (double)event->height / document_height);
5852 
5853  ev_metadata_set_int (window->priv->metadata, "window_x", event->x);
5854  ev_metadata_set_int (window->priv->metadata, "window_y", event->y);
5855  ev_metadata_set_int (window->priv->metadata, "window_width", event->width);
5856  ev_metadata_set_int (window->priv->metadata, "window_height", event->height);
5857  }
5858  }
5859 
5860  return FALSE;
5861 }
5862 
5863 static void
5865 {
5866  const char *filename = ev_link_action_get_filename (action);
5867  GAppInfo *app_info;
5868  GFile *file;
5869  GList file_list = {NULL};
5870  GdkAppLaunchContext *context;
5871  GdkScreen *screen;
5872  GError *error = NULL;
5873 
5874  if (filename == NULL)
5875  return;
5876 
5877  if (g_path_is_absolute (filename)) {
5878  file = g_file_new_for_path (filename);
5879  } else {
5880  GFile *base_file;
5881  gchar *dir;
5882 
5883  dir = g_path_get_dirname (window->priv->uri);
5884  base_file = g_file_new_for_uri (dir);
5885  g_free (dir);
5886 
5887  file = g_file_resolve_relative_path (base_file, filename);
5888  g_object_unref (base_file);
5889  }
5890 
5891  app_info = g_file_query_default_handler (file, NULL, &error);
5892  if (!app_info) {
5893  ev_window_error_message (window, error,
5894  "%s",
5895  _("Unable to launch external application."));
5896  g_object_unref (file);
5897  g_error_free (error);
5898 
5899  return;
5900  }
5901 
5902  screen = gtk_window_get_screen (GTK_WINDOW (window));
5903  context = gdk_display_get_app_launch_context (gdk_screen_get_display (screen));
5904  gdk_app_launch_context_set_screen (context, screen);
5905  gdk_app_launch_context_set_timestamp (context, gtk_get_current_event_time ());
5906 
5907  file_list.data = file;
5908  if (!g_app_info_launch (app_info, &file_list, G_APP_LAUNCH_CONTEXT (context), &error)) {
5909  ev_window_error_message (window, error,
5910  "%s",
5911  _("Unable to launch external application."));
5912  g_error_free (error);
5913  }
5914 
5915  g_object_unref (app_info);
5916  g_object_unref (file);
5917  /* FIXMEchpe: unref launch context? */
5918 
5919  /* According to the PDF spec filename can be an executable. I'm not sure
5920  allowing to launch executables is a good idea though. -- marco */
5921 }
5922 
5923 static void
5925 {
5926  const gchar *uri = ev_link_action_get_uri (action);
5927  GError *error = NULL;
5928  gboolean ret;
5929  GdkAppLaunchContext *context;
5930  GdkScreen *screen;
5931 
5932  screen = gtk_window_get_screen (GTK_WINDOW (window));
5933  context = gdk_display_get_app_launch_context (gdk_screen_get_display (screen));
5934  gdk_app_launch_context_set_screen (context, screen);
5935  gdk_app_launch_context_set_timestamp (context, gtk_get_current_event_time ());
5936 
5937  if (!g_strstr_len (uri, strlen (uri), "://") &&
5938  !g_str_has_prefix (uri, "mailto:")) {
5939  gchar *new_uri;
5940 
5941  /* Not a valid uri, assume http if it starts with www */
5942  if (g_str_has_prefix (uri, "www.")) {
5943  new_uri = g_strdup_printf ("http://%s", uri);
5944  } else {
5945  GFile *file, *parent;
5946 
5947  file = g_file_new_for_uri (window->priv->uri);
5948  parent = g_file_get_parent (file);
5949  g_object_unref (file);
5950  if (parent) {
5951  gchar *parent_uri = g_file_get_uri (parent);
5952 
5953  new_uri = g_build_filename (parent_uri, uri, NULL);
5954  g_free (parent_uri);
5955  g_object_unref (parent);
5956  } else {
5957  new_uri = g_strdup_printf ("file:///%s", uri);
5958  }
5959  }
5960  ret = g_app_info_launch_default_for_uri (new_uri, G_APP_LAUNCH_CONTEXT (context), &error);
5961  g_free (new_uri);
5962  } else {
5963  ret = g_app_info_launch_default_for_uri (uri, G_APP_LAUNCH_CONTEXT (context), &error);
5964  }
5965 
5966  if (ret == FALSE) {
5967  ev_window_error_message (window, error,
5968  "%s", _("Unable to open external link"));
5969  g_error_free (error);
5970  }
5971 
5972  /* FIXMEchpe: unref launch context? */
5973 }
5974 
5975 static void
5977 {
5978  gchar *uri;
5979  gchar *dir;
5980 
5981  dir = g_path_get_dirname (window->priv->uri);
5982 
5983  uri = g_build_filename (dir, ev_link_action_get_filename (action),
5984  NULL);
5985  g_free (dir);
5986 
5988  gtk_window_get_screen (GTK_WINDOW (window)),
5989  ev_link_action_get_dest (action),
5990  0,
5991  NULL,
5992  gtk_get_current_event_time ());
5993 
5994  g_free (uri);
5995 }
5996 
5997 static void
5999 {
6000  const gchar *name = ev_link_action_get_name (action);
6001 
6002  if (g_ascii_strcasecmp (name, "FirstPage") == 0) {
6003  g_action_group_activate_action (G_ACTION_GROUP (window), "go-first-page", NULL);
6004  } else if (g_ascii_strcasecmp (name, "PrevPage") == 0) {
6005  g_action_group_activate_action (G_ACTION_GROUP (window), "go-previous-page", NULL);
6006  } else if (g_ascii_strcasecmp (name, "NextPage") == 0) {
6007  g_action_group_activate_action (G_ACTION_GROUP (window), "go-next-page", NULL);
6008  } else if (g_ascii_strcasecmp (name, "LastPage") == 0) {
6009  g_action_group_activate_action (G_ACTION_GROUP (window), "go-last-page", NULL);
6010  } else if (g_ascii_strcasecmp (name, "GoToPage") == 0) {
6011  g_action_group_activate_action (G_ACTION_GROUP (window), "select-page", NULL);
6012  } else if (g_ascii_strcasecmp (name, "Find") == 0) {
6013  g_action_group_activate_action (G_ACTION_GROUP (window), "find", NULL);
6014  } else if (g_ascii_strcasecmp (name, "Close") == 0) {
6015  g_action_group_activate_action (G_ACTION_GROUP (window), "close", NULL);
6016  } else if (g_ascii_strcasecmp (name, "Print") == 0) {
6017  g_action_group_activate_action (G_ACTION_GROUP (window), "print", NULL);
6018  } else {
6019  g_warning ("Unimplemented named action: %s, please post a "
6020  "bug report in Evince bugzilla "
6021  "(http://bugzilla.gnome.org) with a testcase.",
6022  name);
6023  }
6024 }
6025 
6026 static void
6028 {
6029  switch (ev_link_action_get_action_type (action)) {
6031  EvLinkDest *dest;
6032 
6033  dest = ev_link_action_get_dest (action);
6034  if (!dest)
6035  return;
6036 
6037  ev_window_open_copy_at_dest (window, dest);
6038  }
6039  break;
6041  launch_external_uri (window, action);
6042  break;
6044  launch_action (window, action);
6045  break;
6047  open_remote_link (window, action);
6048  break;
6050  do_action_named (window, action);
6051  break;
6052  default:
6053  g_assert_not_reached ();
6054  }
6055 }
6056 
6057 static void
6058 ev_window_popup_cmd_open_link (GSimpleAction *action,
6059  GVariant *parameter,
6060  gpointer user_data)
6061 {
6062  EvWindow *window = user_data;
6063 
6064  ev_view_handle_link (EV_VIEW (window->priv->view), window->priv->link);
6065 }
6066 
6067 static void
6069  GVariant *parameter,
6070  gpointer user_data)
6071 {
6072  EvLinkAction *ev_action = NULL;
6073  EvLinkDest *dest;
6074  EvWindow *window = user_data;
6075 
6076  ev_action = ev_link_get_action (window->priv->link);
6077  if (!ev_action)
6078  return;
6079 
6080  dest = ev_link_action_get_dest (ev_action);
6081  if (!dest)
6082  return;
6083 
6084  ev_window_open_copy_at_dest (window, dest);
6085 }
6086 
6087 static void
6089  GVariant *parameter,
6090  gpointer user_data)
6091 {
6092  EvLinkAction *ev_action;
6093  EvWindow *window = user_data;
6094 
6095  ev_action = ev_link_get_action (window->priv->link);
6096  if (!ev_action)
6097  return;
6098 
6100  ev_action);
6101 }
6102 
6103 static GFile *
6105  GdkPixbufFormat *format)
6106 {
6107  GFile *target_file;
6108  gchar **extensions;
6109  gchar *uri_extension;
6110  gint i;
6111 
6112  extensions = gdk_pixbuf_format_get_extensions (format);
6113  for (i = 0; extensions[i]; i++) {
6114  if (g_str_has_suffix (uri, extensions[i])) {
6115  g_strfreev (extensions);
6116  return g_file_new_for_uri (uri);
6117  }
6118  }
6119 
6120  uri_extension = g_strconcat (uri, ".", extensions[0], NULL);
6121  target_file = g_file_new_for_uri (uri_extension);
6122  g_free (uri_extension);
6123  g_strfreev (extensions);
6124 
6125  return target_file;
6126 }
6127 
6128 static void
6130  gint response_id,
6131  EvWindow *ev_window)
6132 {
6133  GFile *target_file;
6134  gboolean is_native;
6135  GError *error = NULL;
6136  GdkPixbuf *pixbuf;
6137  gchar *uri;
6138  gchar *filename;
6139  gchar *file_format;
6140  GdkPixbufFormat *format;
6141  GtkFileFilter *filter;
6142 
6143  if (response_id != GTK_RESPONSE_OK) {
6144  gtk_widget_destroy (fc);
6145  return;
6146  }
6147 
6148  ev_window_file_chooser_save_folder (ev_window, GTK_FILE_CHOOSER (fc),
6149  G_USER_DIRECTORY_PICTURES);
6150 
6151  uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (fc));
6152  filter = gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (fc));
6153  format = g_object_get_data (G_OBJECT (filter), "pixbuf-format");
6154 
6155  if (format == NULL) {
6156  format = get_gdk_pixbuf_format_by_extension (uri);
6157  }
6158 
6159  if (format == NULL && g_strrstr (uri, ".") == NULL) {
6160  /* no extension found and no extension provided within uri */
6161  format = get_gdk_pixbuf_format_by_extension (".png");
6162  if (format == NULL) {
6163  /* no .png support, try .jpeg */
6164  format = get_gdk_pixbuf_format_by_extension (".jpeg");
6165  }
6166  }
6167 
6168  if (format == NULL) {
6169  ev_window_error_message (ev_window, NULL,
6170  "%s",
6171  _("Couldn’t find appropriate format to save image"));
6172  g_free (uri);
6173  gtk_widget_destroy (fc);
6174 
6175  return;
6176  }
6177 
6178  target_file = create_file_from_uri_for_format (uri, format);
6179  g_free (uri);
6180 
6181  is_native = g_file_is_native (target_file);
6182  if (is_native) {
6183  filename = g_file_get_path (target_file);
6184  } else {
6185  /* Create a temporary local file to save to */
6186  if (ev_mkstemp ("saveimage.XXXXXX", &filename, &error) == -1)
6187  goto has_error;
6188  }
6189 
6192  ev_window->priv->image);
6194 
6195  file_format = gdk_pixbuf_format_get_name (format);
6196  gdk_pixbuf_save (pixbuf, filename, file_format, &error, NULL);
6197  g_free (file_format);
6198  g_object_unref (pixbuf);
6199 
6200  has_error:
6201  if (error) {
6202  ev_window_error_message (ev_window, error,
6203  "%s", _("The image could not be saved."));
6204  g_error_free (error);
6205  g_free (filename);
6206  g_object_unref (target_file);
6207  gtk_widget_destroy (fc);
6208 
6209  return;
6210  }
6211 
6212  if (!is_native) {
6213  GFile *source_file;
6214 
6215  source_file = g_file_new_for_path (filename);
6216 
6218  source_file, target_file);
6219  g_object_unref (source_file);
6220  }
6221 
6222  g_free (filename);
6223  g_object_unref (target_file);
6224  gtk_widget_destroy (fc);
6225 }
6226 
6227 static void
6228 ev_window_popup_cmd_save_image_as (GSimpleAction *action,
6229  GVariant *parameter,
6230  gpointer user_data)
6231 {
6232  GtkWidget *fc;
6233  EvWindow *window = user_data;
6234 
6235  if (!window->priv->image)
6236  return;
6237 
6238  fc = gtk_file_chooser_dialog_new (_("Save Image"),
6239  GTK_WINDOW (window),
6240  GTK_FILE_CHOOSER_ACTION_SAVE,
6241  GTK_STOCK_CANCEL,
6242  GTK_RESPONSE_CANCEL,
6243  GTK_STOCK_SAVE, GTK_RESPONSE_OK,
6244  NULL);
6245 
6246  gtk_dialog_set_default_response (GTK_DIALOG (fc), GTK_RESPONSE_OK);
6247  gtk_dialog_set_alternative_button_order (GTK_DIALOG (fc),
6248  GTK_RESPONSE_OK,
6249  GTK_RESPONSE_CANCEL,
6250  -1);
6251 
6252  gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (fc), FALSE);
6253  gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (fc), TRUE);
6254 
6255  file_chooser_dialog_add_writable_pixbuf_formats (GTK_FILE_CHOOSER (fc));
6256 
6257  ev_window_file_chooser_restore_folder (window, GTK_FILE_CHOOSER (fc), NULL,
6258  G_USER_DIRECTORY_PICTURES);
6259 
6260  g_signal_connect (fc, "response",
6261  G_CALLBACK (image_save_dialog_response_cb),
6262  window);
6263 
6264  gtk_widget_show (fc);
6265 }
6266 
6267 static void
6268 ev_window_popup_cmd_copy_image (GSimpleAction *action,
6269  GVariant *parameter,
6270  gpointer user_data)
6271 {
6272  GtkClipboard *clipboard;
6273  GdkPixbuf *pixbuf;
6274  EvWindow *window = user_data;
6275 
6276  if (!window->priv->image)
6277  return;
6278 
6279  clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window),
6280  GDK_SELECTION_CLIPBOARD);
6283  window->priv->image);
6285 
6286  gtk_clipboard_set_image (clipboard, pixbuf);
6287  g_object_unref (pixbuf);
6288 }
6289 
6290 static void
6292  GVariant *parameter,
6293  gpointer user_data)
6294 {
6295  EvWindow *window = user_data;
6296  const gchar *author;
6297  GdkRGBA rgba;
6298  gdouble opacity;
6299  gboolean popup_is_open;
6301  EvAnnotation *annot = window->priv->annot;
6303 
6304  if (!annot)
6305  return;
6306 
6308  gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (window));
6309  if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_APPLY) {
6310  gtk_widget_destroy (GTK_WIDGET (dialog));
6311 
6312  return;
6313  }
6314 
6315  /* Set annotations changes */
6318  mask |= EV_ANNOTATIONS_SAVE_LABEL;
6319 
6321  if (ev_annotation_set_rgba (annot, &rgba))
6322  mask |= EV_ANNOTATIONS_SAVE_COLOR;
6323 
6327 
6328  popup_is_open = ev_annotation_properties_dialog_get_popup_is_open (dialog);
6329  if (ev_annotation_markup_set_popup_is_open (EV_ANNOTATION_MARKUP (annot), popup_is_open))
6331 
6332  if (EV_IS_ANNOTATION_TEXT (annot)) {
6333  EvAnnotationTextIcon icon;
6334 
6336  if (ev_annotation_text_set_icon (EV_ANNOTATION_TEXT (annot), icon))
6338  }
6339 
6340  if (EV_IS_ANNOTATION_TEXT_MARKUP (annot)) {
6341  EvAnnotationTextMarkupType markup_type;
6342 
6346  }
6347 
6348  if (mask != EV_ANNOTATIONS_SAVE_NONE) {
6351  window->priv->annot,
6352  mask);
6354 
6355  /* FIXME: update annot region only */
6356  ev_view_reload (EV_VIEW (window->priv->view));
6357  }
6358 
6359  gtk_widget_destroy (GTK_WIDGET (dialog));
6360 }
6361 
6362 static void
6364  GVariant *parameter,
6365  gpointer user_data)
6366 {
6367  EvWindow *window = user_data;
6368 
6370  window->priv->annot);
6371 }
6372 
6373 static void
6375  GVariant *parameter,
6376  gpointer user_data)
6377 {
6378  GList *l;
6379  GdkScreen *screen;
6380  EvWindow *window = user_data;
6381 
6382  if (!window->priv->attach_list)
6383  return;
6384 
6385  screen = gtk_window_get_screen (GTK_WINDOW (window));
6386 
6387  for (l = window->priv->attach_list; l && l->data; l = g_list_next (l)) {
6388  EvAttachment *attachment;
6389  GError *error = NULL;
6390 
6391  attachment = (EvAttachment *) l->data;
6392 
6393  ev_attachment_open (attachment, screen, gtk_get_current_event_time (), &error);
6394 
6395  if (error) {
6396  ev_window_error_message (window, error,
6397  "%s", _("Unable to open attachment"));
6398  g_error_free (error);
6399  }
6400  }
6401 }
6402 
6403 static void
6405  gint response_id,
6406  EvWindow *ev_window)
6407 {
6408  GFile *target_file;
6409  gchar *uri;
6410  GList *l;
6411  GtkFileChooserAction fc_action;
6412  gboolean is_dir;
6413  gboolean is_native;
6414 
6415  if (response_id != GTK_RESPONSE_OK) {
6416  gtk_widget_destroy (fc);
6417  return;
6418  }
6419 
6420  ev_window_file_chooser_save_folder (ev_window, GTK_FILE_CHOOSER (fc),
6421  G_USER_DIRECTORY_DOCUMENTS);
6422 
6423  uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (fc));
6424  target_file = g_file_new_for_uri (uri);
6425  g_object_get (G_OBJECT (fc), "action", &fc_action, NULL);
6426  is_dir = (fc_action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
6427  is_native = g_file_is_native (target_file);
6428 
6429  for (l = ev_window->priv->attach_list; l && l->data; l = g_list_next (l)) {
6430  EvAttachment *attachment;
6431  GFile *save_to = NULL;
6432  GError *error = NULL;
6433 
6434  attachment = (EvAttachment *) l->data;
6435 
6436  if (is_native) {
6437  if (is_dir) {
6438  save_to = g_file_get_child (target_file,
6439  /* FIXMEchpe: file name encoding! */
6440  ev_attachment_get_name (attachment));
6441  } else {
6442  save_to = g_object_ref (target_file);
6443  }
6444  } else {
6445  save_to = ev_mkstemp_file ("saveattachment.XXXXXX", &error);
6446  }
6447 
6448  if (save_to)
6449  ev_attachment_save (attachment, save_to, &error);
6450 
6451  if (error) {
6452  ev_window_error_message (ev_window, error,
6453  "%s", _("The attachment could not be saved."));
6454  g_error_free (error);
6455  g_object_unref (save_to);
6456 
6457  continue;
6458  }
6459 
6460  if (!is_native) {
6461  GFile *dest_file;
6462 
6463  if (is_dir) {
6464  dest_file = g_file_get_child (target_file,
6465  ev_attachment_get_name (attachment));
6466  } else {
6467  dest_file = g_object_ref (target_file);
6468  }
6469 
6471  save_to, dest_file);
6472 
6473  g_object_unref (dest_file);
6474  }
6475 
6476  g_object_unref (save_to);
6477  }
6478 
6479  g_free (uri);
6480  g_object_unref (target_file);
6481 
6482  gtk_widget_destroy (fc);
6483 }
6484 
6485 static void
6487  GVariant *parameter,
6488  gpointer user_data)
6489 {
6490  GtkWidget *fc;
6491  EvAttachment *attachment = NULL;
6492  EvWindow *window = user_data;
6493 
6494  if (!window->priv->attach_list)
6495  return;
6496 
6497  if (g_list_length (window->priv->attach_list) == 1)
6498  attachment = (EvAttachment *) window->priv->attach_list->data;
6499 
6500  fc = gtk_file_chooser_dialog_new (
6501  _("Save Attachment"),
6502  GTK_WINDOW (window),
6503  attachment ? GTK_FILE_CHOOSER_ACTION_SAVE : GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
6504  GTK_STOCK_CANCEL,
6505  GTK_RESPONSE_CANCEL,
6506  GTK_STOCK_SAVE, GTK_RESPONSE_OK,
6507  NULL);
6508 
6509  gtk_dialog_set_default_response (GTK_DIALOG (fc), GTK_RESPONSE_OK);
6510  gtk_dialog_set_alternative_button_order (GTK_DIALOG (fc),
6511  GTK_RESPONSE_OK,
6512  GTK_RESPONSE_CANCEL,
6513  -1);
6514 
6515  gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (fc), TRUE);
6516  gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (fc), FALSE);
6517 
6518  if (attachment)
6519  gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (fc),
6520  ev_attachment_get_name (attachment));
6521 
6522  ev_window_file_chooser_restore_folder (window, GTK_FILE_CHOOSER (fc), NULL,
6523  G_USER_DIRECTORY_DOCUMENTS);
6524 
6525  g_signal_connect (fc, "response",
6527  window);
6528 
6529  gtk_widget_show (fc);
6530 }
6531 
6532 static void
6534  const gchar *key,
6535  gpointer user_data)
6536 {
6537  if (!gtk_window_is_active (GTK_WINDOW (window)))
6538  return;
6539 
6540  /* Note how Previous/Next only go to the
6541  * next/previous page despite their icon telling you
6542  * they should go to the beginning/end.
6543  *
6544  * There's very few keyboards with FFW/RWD though,
6545  * so we stick the most useful keybinding on the most
6546  * often seen keys
6547  */
6548  if (strcmp (key, "Play") == 0) {
6549  ev_window_run_presentation (window);
6550  } else if (strcmp (key, "Previous") == 0) {
6551  if (EV_WINDOW_IS_PRESENTATION (window))
6553  else
6554  g_action_group_activate_action (G_ACTION_GROUP (window), "go-previous-page", NULL);
6555  } else if (strcmp (key, "Next") == 0) {
6556  if (EV_WINDOW_IS_PRESENTATION (window))
6558  else
6559  g_action_group_activate_action (G_ACTION_GROUP (window), "go-next-page", NULL);
6560  } else if (strcmp (key, "FastForward") == 0) {
6561  g_action_group_activate_action (G_ACTION_GROUP (window), "go-last-page", NULL);
6562  } else if (strcmp (key, "Rewind") == 0) {
6563  g_action_group_activate_action (G_ACTION_GROUP (window), "go-first-page", NULL);
6564  }
6565 }
6566 
6567 #ifdef ENABLE_DBUS
6568 static void
6569 ev_window_sync_source (EvWindow *window,
6570  EvSourceLink *link)
6571 {
6572  guint32 timestamp;
6573  gchar *uri_input;
6574  GFile *input_gfile;
6575 
6576  if (window->priv->skeleton == NULL)
6577  return;
6578 
6579  timestamp = gtk_get_current_event_time ();
6580  if (g_path_is_absolute (link->filename)) {
6581  input_gfile = g_file_new_for_path (link->filename);
6582  } else {
6583  GFile *gfile, *parent_gfile;
6584 
6585  gfile = g_file_new_for_uri (window->priv->uri);
6586  parent_gfile = g_file_get_parent (gfile);
6587 
6588  /* parent_gfile should never be NULL */
6589  if (parent_gfile == NULL) {
6590  g_printerr ("Document URI is '/'\n");
6591  return;
6592  }
6593 
6594  input_gfile = g_file_get_child (parent_gfile, link->filename);
6595  g_object_unref (parent_gfile);
6596  g_object_unref (gfile);
6597  }
6598 
6599  uri_input = g_file_get_uri (input_gfile);
6600  g_object_unref (input_gfile);
6601 
6602  ev_evince_window_emit_sync_source (window->priv->skeleton,
6603  uri_input,
6604  g_variant_new ("(ii)", link->line, link->col),
6605  timestamp);
6606  g_free (uri_input);
6607 }
6608 
6609 static void
6610 ev_window_emit_closed (EvWindow *window)
6611 {
6612  if (window->priv->skeleton == NULL)
6613  return;
6614 
6615  ev_evince_window_emit_closed (window->priv->skeleton);
6616 
6617  /* If this is the last window call g_dbus_connection_flush_sync()
6618  * to make sure the signal is emitted.
6619  */
6621  g_dbus_connection_flush_sync (g_application_get_dbus_connection (g_application_get_default ()), NULL, NULL);
6622 }
6623 
6624 static void
6625 ev_window_emit_doc_loaded (EvWindow *window)
6626 {
6627  if (window->priv->skeleton == NULL)
6628  return;
6629 
6630  ev_evince_window_emit_document_loaded (window->priv->skeleton, window->priv->uri);
6631 }
6632 
6633 static gboolean
6634 handle_sync_view_cb (EvEvinceWindow *object,
6635  GDBusMethodInvocation *invocation,
6636  const gchar *source_file,
6637  GVariant *source_point,
6638  guint timestamp,
6639  EvWindow *window)
6640 {
6641  if (window->priv->document && ev_document_has_synctex (window->priv->document)) {
6642  EvSourceLink link;
6643 
6644  link.filename = (char *) source_file;
6645  g_variant_get (source_point, "(ii)", &link.line, &link.col);
6646  ev_view_highlight_forward_search (EV_VIEW (window->priv->view), &link);
6647  gtk_window_present_with_time (GTK_WINDOW (window), timestamp);
6648  }
6649 
6650  ev_evince_window_complete_sync_view (object, invocation);
6651 
6652  return TRUE;
6653 }
6654 #endif /* ENABLE_DBUS */
6655 
6656 static gboolean
6657 _gtk_css_provider_load_from_resource (GtkCssProvider *provider,
6658  const char *resource_path,
6659  GError **error)
6660 {
6661  GBytes *data;
6662  gboolean retval;
6663 
6664  data = g_resources_lookup_data (resource_path, 0, error);
6665  if (!data)
6666  return FALSE;
6667 
6668  retval = gtk_css_provider_load_from_data (provider,
6669  g_bytes_get_data (data, NULL),
6670  g_bytes_get_size (data),
6671  error);
6672  g_bytes_unref (data);
6673 
6674  return retval;
6675 }
6676 
6677 static void
6679 {
6680  static gsize initialization_value = 0;
6681 
6682  if (g_once_init_enter (&initialization_value)) {
6683  GtkCssProvider *css_provider;
6684  GError *error = NULL;
6685 
6686  css_provider = gtk_css_provider_new ();
6688  "/org/gnome/evince/ui/evince.css",
6689  &error);
6690  g_assert_no_error (error);
6691  gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
6692  GTK_STYLE_PROVIDER (css_provider),
6693  GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
6694  g_object_unref (css_provider);
6695 
6696  g_once_init_leave (&initialization_value, 1);
6697  }
6698 }
6699 
6700 static void
6702 {
6703  GtkBuilder *builder;
6704  GError *error = NULL;
6705  GtkWidget *sidebar_widget;
6706  GtkWidget *overlay;
6707  GtkWidget *searchbar_revealer;
6708  GObject *mpkeys;
6709  guint page_cache_mb;
6710  gboolean allow_links_change_zoom;
6711  GtkEntry *search_entry;
6712 #ifdef ENABLE_DBUS
6713  GDBusConnection *connection;
6714  static gint window_id = 0;
6715 #endif
6716  GAppInfo *app_info;
6717 
6718  g_signal_connect (ev_window, "configure_event",
6719  G_CALLBACK (window_configure_event_cb), NULL);
6720  g_signal_connect (ev_window, "window_state_event",
6721  G_CALLBACK (window_state_event_cb), NULL);
6722 
6723  ev_window->priv = EV_WINDOW_GET_PRIVATE (ev_window);
6724 
6725 #ifdef ENABLE_DBUS
6726  connection = g_application_get_dbus_connection (g_application_get_default ());
6727  if (connection) {
6728  EvEvinceWindow *skeleton;
6729 
6730  ev_window->priv->dbus_object_path = g_strdup_printf (EV_WINDOW_DBUS_OBJECT_PATH, window_id++);
6731 
6732  skeleton = ev_evince_window_skeleton_new ();
6733  if (g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (skeleton),
6734  connection,
6735  ev_window->priv->dbus_object_path,
6736  &error)) {
6737  ev_window->priv->skeleton = skeleton;
6738  g_signal_connect (skeleton, "handle-sync-view",
6739  G_CALLBACK (handle_sync_view_cb),
6740  ev_window);
6741  } else {
6742  g_printerr ("Failed to register bus object %s: %s\n",
6743  ev_window->priv->dbus_object_path, error->message);
6744  g_error_free (error);
6745  g_free (ev_window->priv->dbus_object_path);
6746  ev_window->priv->dbus_object_path = NULL;
6747  error = NULL;
6748 
6749  g_object_unref (skeleton);
6750  ev_window->priv->skeleton = NULL;
6751  }
6752  }
6753 #endif /* ENABLE_DBUS */
6754 
6755  ev_window->priv->model = ev_document_model_new ();
6756 
6757  ev_window->priv->page_mode = PAGE_MODE_DOCUMENT;
6758  ev_window->priv->chrome = EV_CHROME_NORMAL;
6759  ev_window->priv->presentation_mode_inhibit_id = 0;
6760 
6761  ev_window->priv->history = ev_history_new (ev_window->priv->model);
6762  g_signal_connect (ev_window->priv->history, "activate-link",
6763  G_CALLBACK (activate_link_cb),
6764  ev_window);
6765  g_signal_connect (ev_window->priv->history, "changed",
6766  G_CALLBACK (history_changed_cb),
6767  ev_window);
6768 
6769  ev_window->priv->bookmarks_menu = g_menu_new ();
6770 
6771  app_info = g_app_info_get_default_for_uri_scheme ("mailto");
6772  ev_window->priv->has_mailto_handler = app_info != NULL;
6773  g_clear_object (&app_info);
6774 
6775  ev_window->priv->main_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
6776  gtk_container_add (GTK_CONTAINER (ev_window), ev_window->priv->main_box);
6777  gtk_widget_show (ev_window->priv->main_box);
6778 
6779  g_action_map_add_action_entries (G_ACTION_MAP (ev_window),
6780  actions, G_N_ELEMENTS (actions),
6781  ev_window);
6782 
6783  ev_window_init_css ();
6784 
6785  ev_window->priv->recent_manager = gtk_recent_manager_get_default ();
6786 
6787  ev_window->priv->toolbar = ev_toolbar_new (ev_window);
6788  gtk_widget_set_no_show_all (ev_window->priv->toolbar, TRUE);
6789  gtk_header_bar_set_show_close_button (GTK_HEADER_BAR (ev_window->priv->toolbar), TRUE);
6790  gtk_window_set_titlebar (GTK_WINDOW (ev_window), ev_window->priv->toolbar);
6791  gtk_widget_show (ev_window->priv->toolbar);
6792 
6793  /* Window title */
6794  ev_window->priv->title = ev_window_title_new (ev_window);
6795 
6796  g_signal_connect (ev_toolbar_get_page_selector (EV_TOOLBAR (ev_window->priv->toolbar)),
6797  "activate-link",
6798  G_CALLBACK (activate_link_cb),
6799  ev_window);
6800 
6801  /* Annotations toolbar */
6803  g_signal_connect_swapped (ev_window->priv->annots_toolbar,
6804  "begin-add-annot",
6805  G_CALLBACK (ev_window_begin_add_annot),
6806  ev_window);
6807  g_signal_connect_swapped (ev_window->priv->annots_toolbar,
6808  "cancel-add-annot",
6809  G_CALLBACK (ev_window_cancel_add_annot),
6810  ev_window);
6811  gtk_box_pack_start (GTK_BOX (ev_window->priv->main_box),
6812  ev_window->priv->annots_toolbar, FALSE, TRUE, 0);
6813 
6814  /* Search Bar */
6815  ev_window->priv->search_bar = gtk_search_bar_new ();
6816  gtk_search_bar_set_show_close_button (GTK_SEARCH_BAR (ev_window->priv->search_bar), TRUE);
6817 
6818  ev_window->priv->search_box = ev_search_box_new (ev_window->priv->model);
6819  search_entry = GTK_ENTRY (ev_search_box_get_entry (EV_SEARCH_BOX (ev_window->priv->search_box)));
6820  gtk_entry_set_width_chars (search_entry, 32);
6821  gtk_entry_set_max_length (search_entry, 512);
6822  gtk_container_add (GTK_CONTAINER (ev_window->priv->search_bar),
6823  ev_window->priv->search_box);
6824  gtk_widget_show (ev_window->priv->search_box);
6825 
6826  /* Wrap search bar in a revealer.
6827  * Workaround for the gtk+ bug: https://bugzilla.gnome.org/show_bug.cgi?id=724096
6828  */
6829  searchbar_revealer = gtk_revealer_new ();
6830  g_object_bind_property (G_OBJECT (searchbar_revealer), "reveal-child",
6831  G_OBJECT (ev_window->priv->search_bar), "search-mode-enabled",
6832  G_BINDING_BIDIRECTIONAL);
6833  gtk_container_add (GTK_CONTAINER (searchbar_revealer), ev_window->priv->search_bar);
6834  gtk_widget_show (GTK_WIDGET (searchbar_revealer));
6835 
6836  /* We don't use gtk_search_bar_connect_entry, because it clears the entry when the
6837  * search is closed, but we want to keep the current search.
6838  */
6839  gtk_box_pack_start (GTK_BOX (ev_window->priv->main_box),
6840  searchbar_revealer, FALSE, TRUE, 0);
6841  gtk_widget_show (ev_window->priv->search_bar);
6842 
6843  /* Add the main area */
6844  ev_window->priv->hpaned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
6845  g_signal_connect (ev_window->priv->hpaned,
6846  "notify::position",
6848  ev_window);
6849 
6850  gtk_paned_set_position (GTK_PANED (ev_window->priv->hpaned), SIDEBAR_DEFAULT_SIZE);
6851  gtk_box_pack_start (GTK_BOX (ev_window->priv->main_box), ev_window->priv->hpaned,
6852  TRUE, TRUE, 0);
6853  gtk_widget_show (ev_window->priv->hpaned);
6854 
6855  ev_window->priv->sidebar = ev_sidebar_new ();
6857  ev_window->priv->model);
6858  gtk_paned_pack1 (GTK_PANED (ev_window->priv->hpaned),
6859  ev_window->priv->sidebar, FALSE, FALSE);
6860  gtk_widget_show (ev_window->priv->sidebar);
6861 
6862  /* Stub sidebar, for now */
6863 
6864  sidebar_widget = ev_sidebar_thumbnails_new ();
6865  ev_window->priv->sidebar_thumbs = sidebar_widget;
6866  g_signal_connect (sidebar_widget,
6867  "notify::main-widget",
6869  ev_window);
6870  sidebar_page_main_widget_update_cb (G_OBJECT (sidebar_widget), NULL, ev_window);
6871  gtk_widget_show (sidebar_widget);
6872  ev_sidebar_add_page (EV_SIDEBAR (ev_window->priv->sidebar),
6873  sidebar_widget);
6874 
6875  sidebar_widget = ev_sidebar_links_new ();
6876  ev_window->priv->sidebar_links = sidebar_widget;
6877  g_signal_connect (sidebar_widget,
6878  "notify::model",
6879  G_CALLBACK (sidebar_widget_model_set),
6880  ev_window);
6881  g_signal_connect (sidebar_widget,
6882  "link_activated",
6883  G_CALLBACK (sidebar_links_link_activated_cb),
6884  ev_window);
6885  sidebar_page_main_widget_update_cb (G_OBJECT (sidebar_widget), NULL, ev_window);
6886  gtk_widget_show (sidebar_widget);
6887  ev_sidebar_add_page (EV_SIDEBAR (ev_window->priv->sidebar),
6888  sidebar_widget);
6889 
6890  sidebar_widget = ev_sidebar_attachments_new ();
6891  ev_window->priv->sidebar_attachments = sidebar_widget;
6892  g_signal_connect_object (sidebar_widget,
6893  "popup",
6894  G_CALLBACK (attachment_bar_menu_popup_cb),
6895  ev_window, 0);
6896  gtk_widget_show (sidebar_widget);
6897  ev_sidebar_add_page (EV_SIDEBAR (ev_window->priv->sidebar),
6898  sidebar_widget);
6899 
6900  sidebar_widget = ev_sidebar_layers_new ();
6901  ev_window->priv->sidebar_layers = sidebar_widget;
6902  g_signal_connect (sidebar_widget,
6903  "layers_visibility_changed",
6904  G_CALLBACK (sidebar_layers_visibility_changed),
6905  ev_window);
6906  gtk_widget_show (sidebar_widget);
6907  ev_sidebar_add_page (EV_SIDEBAR (ev_window->priv->sidebar),
6908  sidebar_widget);
6909 
6910  sidebar_widget = ev_sidebar_annotations_new ();
6911  ev_window->priv->sidebar_annots = sidebar_widget;
6912  g_signal_connect (sidebar_widget,
6913  "annot_activated",
6914  G_CALLBACK (sidebar_annots_annot_activated_cb),
6915  ev_window);
6916  gtk_widget_show (sidebar_widget);
6917  ev_sidebar_add_page (EV_SIDEBAR (ev_window->priv->sidebar),
6918  sidebar_widget);
6919 
6920  sidebar_widget = ev_sidebar_bookmarks_new ();
6921  ev_window->priv->sidebar_bookmarks = sidebar_widget;
6922  gtk_widget_show (sidebar_widget);
6923  ev_sidebar_add_page (EV_SIDEBAR (ev_window->priv->sidebar),
6924  sidebar_widget);
6925 
6926  ev_window->priv->view_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
6927 
6928  overlay = gtk_overlay_new ();
6929  ev_window->priv->scrolled_window = gtk_scrolled_window_new (NULL, NULL);
6930  gtk_container_add (GTK_CONTAINER (overlay), ev_window->priv->scrolled_window);
6931  gtk_widget_show (ev_window->priv->scrolled_window);
6932 
6933  ev_window->priv->loading_message = ev_loading_message_new ();
6934  gtk_widget_set_name (ev_window->priv->loading_message, "ev-loading-message");
6935  gtk_widget_set_halign (ev_window->priv->loading_message, GTK_ALIGN_END);
6936  gtk_widget_set_valign (ev_window->priv->loading_message, GTK_ALIGN_START);
6937  gtk_widget_set_no_show_all (ev_window->priv->loading_message, TRUE);
6938  gtk_overlay_add_overlay (GTK_OVERLAY (overlay), ev_window->priv->loading_message);
6939 
6940  gtk_box_pack_start (GTK_BOX (ev_window->priv->view_box),
6941  overlay,
6942  TRUE, TRUE, 0);
6943  gtk_widget_show (overlay);
6944 
6945  gtk_paned_add2 (GTK_PANED (ev_window->priv->hpaned),
6946  ev_window->priv->view_box);
6947  gtk_widget_show (ev_window->priv->view_box);
6948 
6949  ev_window->priv->view = ev_view_new ();
6950  page_cache_mb = g_settings_get_uint (ev_window_ensure_settings (ev_window),
6953  page_cache_mb * 1024 * 1024);
6954  allow_links_change_zoom = g_settings_get_boolean (ev_window_ensure_settings (ev_window),
6957  allow_links_change_zoom);
6958  ev_view_set_model (EV_VIEW (ev_window->priv->view), ev_window->priv->model);
6959 
6960  ev_window->priv->password_view = ev_password_view_new (GTK_WINDOW (ev_window));
6961  g_signal_connect_swapped (ev_window->priv->password_view,
6962  "unlock",
6963  G_CALLBACK (ev_window_password_view_unlock),
6964  ev_window);
6965  g_signal_connect_object (ev_window->priv->view, "focus_in_event",
6966  G_CALLBACK (view_actions_focus_in_cb),
6967  ev_window, 0);
6968  g_signal_connect_swapped (ev_window->priv->view, "external-link",
6969  G_CALLBACK (view_external_link_cb),
6970  ev_window);
6971  g_signal_connect_object (ev_window->priv->view, "handle-link",
6972  G_CALLBACK (view_handle_link_cb),
6973  ev_window, 0);
6974  g_signal_connect_object (ev_window->priv->view, "popup",
6975  G_CALLBACK (view_menu_popup_cb),
6976  ev_window, 0);
6977  g_signal_connect_object (ev_window->priv->view, "selection-changed",
6978  G_CALLBACK (view_selection_changed_cb),
6979  ev_window, 0);
6980  g_signal_connect_object (ev_window->priv->view, "annot-added",
6981  G_CALLBACK (view_annot_added),
6982  ev_window, 0);
6983  g_signal_connect_object (ev_window->priv->view, "annot-removed",
6984  G_CALLBACK (view_annot_removed),
6985  ev_window, 0);
6986  g_signal_connect_object (ev_window->priv->view, "layers-changed",
6987  G_CALLBACK (view_layers_changed_cb),
6988  ev_window, 0);
6989  g_signal_connect_object (ev_window->priv->view, "notify::is-loading",
6990  G_CALLBACK (view_is_loading_changed_cb),
6991  ev_window, 0);
6992  g_signal_connect_object (ev_window->priv->view, "cursor-moved",
6993  G_CALLBACK (view_caret_cursor_moved_cb),
6994  ev_window, 0);
6995 #ifdef ENABLE_DBUS
6996  g_signal_connect_swapped (ev_window->priv->view, "sync-source",
6997  G_CALLBACK (ev_window_sync_source),
6998  ev_window);
6999 #endif
7000  gtk_widget_show (ev_window->priv->view);
7001  gtk_widget_show (ev_window->priv->password_view);
7002 
7003  /* Find results sidebar */
7004  ev_window->priv->find_sidebar = ev_find_sidebar_new ();
7005  g_signal_connect (ev_window->priv->find_sidebar,
7006  "result-activated",
7007  G_CALLBACK (find_sidebar_result_activated_cb),
7008  ev_window);
7009 
7010  /* We own a ref on these widgets, as we can swap them in and out */
7011  g_object_ref (ev_window->priv->view);
7012  g_object_ref (ev_window->priv->password_view);
7013 
7014  gtk_container_add (GTK_CONTAINER (ev_window->priv->scrolled_window),
7015  ev_window->priv->view);
7016 
7017  /* Connect to model signals */
7018  g_signal_connect_swapped (ev_window->priv->model,
7019  "page-changed",
7020  G_CALLBACK (ev_window_page_changed_cb),
7021  ev_window);
7022  g_signal_connect (ev_window->priv->model,
7023  "notify::document",
7024  G_CALLBACK (ev_window_document_changed_cb),
7025  ev_window);
7026  g_signal_connect (ev_window->priv->model,
7027  "notify::scale",
7028  G_CALLBACK (ev_window_zoom_changed_cb),
7029  ev_window);
7030  g_signal_connect (ev_window->priv->model,
7031  "notify::sizing-mode",
7032  G_CALLBACK (ev_window_sizing_mode_changed_cb),
7033  ev_window);
7034  g_signal_connect (ev_window->priv->model,
7035  "notify::rotation",
7036  G_CALLBACK (ev_window_rotation_changed_cb),
7037  ev_window);
7038  g_signal_connect (ev_window->priv->model,
7039  "notify::continuous",
7040  G_CALLBACK (ev_window_continuous_changed_cb),
7041  ev_window);
7042  g_signal_connect (ev_window->priv->model,
7043  "notify::dual-page",
7044  G_CALLBACK (ev_window_dual_mode_changed_cb),
7045  ev_window);
7046  g_signal_connect (ev_window->priv->model,
7047  "notify::dual-odd-left",
7049  ev_window);
7050  g_signal_connect (ev_window->priv->model,
7051  "notify::inverted-colors",
7053  ev_window);
7054 
7055  /* Connect sidebar signals */
7056  g_signal_connect (ev_window->priv->sidebar,
7057  "notify::visible",
7059  ev_window);
7060  g_signal_connect (ev_window->priv->sidebar,
7061  "notify::current-page",
7063  ev_window);
7064 
7065  /* Connect to find bar signals */
7066  g_signal_connect (ev_window->priv->search_box,
7067  "started",
7068  G_CALLBACK (search_started_cb),
7069  ev_window);
7070  g_signal_connect (ev_window->priv->search_box,
7071  "updated",
7072  G_CALLBACK (search_updated_cb),
7073  ev_window);
7074  g_signal_connect (ev_window->priv->search_box,
7075  "cleared",
7076  G_CALLBACK (search_cleared_cb),
7077  ev_window);
7078  g_signal_connect (ev_window->priv->search_box,
7079  "previous",
7080  G_CALLBACK (search_previous_cb),
7081  ev_window);
7082  g_signal_connect (ev_window->priv->search_box,
7083  "next",
7084  G_CALLBACK (search_next_cb),
7085  ev_window);
7086  g_signal_connect (search_entry,
7087  "stop-search",
7088  G_CALLBACK (search_entry_stop_search_cb),
7089  ev_window);
7090  g_signal_connect (ev_window->priv->search_bar,
7091  "notify::search-mode-enabled",
7093  ev_window);
7094 
7095  /* Popups */
7096  builder = gtk_builder_new_from_resource ("/org/gnome/evince/gtk/menus.ui");
7097  ev_window->priv->view_popup_menu = g_object_ref (G_MENU_MODEL (gtk_builder_get_object (builder, "view-popup-menu")));
7098  ev_window->priv->attachment_popup_menu = g_object_ref (G_MENU_MODEL (gtk_builder_get_object (builder, "attachments-popup")));
7099  g_object_unref (builder);
7100 
7101  /* Media player keys */
7103  if (mpkeys) {
7104  g_signal_connect_swapped (mpkeys, "key_pressed",
7106  ev_window);
7107  }
7108 
7109  /* Give focus to the document view */
7110  gtk_widget_grab_focus (ev_window->priv->view);
7111 
7112  ev_window->priv->default_settings = g_settings_new (GS_SCHEMA_NAME".Default");
7113  g_settings_delay (ev_window->priv->default_settings);
7114  ev_window_setup_default (ev_window);
7115 
7116  gtk_window_set_default_size (GTK_WINDOW (ev_window), 600, 600);
7117 
7118  ev_window_sizing_mode_changed_cb (ev_window->priv->model, NULL, ev_window);
7120 
7121  /* Drag and Drop */
7122  gtk_drag_dest_set (GTK_WIDGET (ev_window),
7123  GTK_DEST_DEFAULT_ALL,
7124  NULL, 0,
7125  GDK_ACTION_COPY);
7126  gtk_drag_dest_add_uri_targets (GTK_WIDGET (ev_window));
7127 }
7128 
7136 GtkWidget *
7138 {
7139  GtkWidget *ev_window;
7140 
7141  ev_window = GTK_WIDGET (g_object_new (EV_TYPE_WINDOW,
7142  "type", GTK_WINDOW_TOPLEVEL,
7143  "application", g_application_get_default (),
7144  "show-menubar", FALSE,
7145  NULL));
7146 
7147  return ev_window;
7148 }
7149 
7150 const gchar *
7152 {
7153 #ifdef ENABLE_DBUS
7154  return ev_window->priv->dbus_object_path;
7155 #else
7156  return NULL;
7157 #endif
7158 }
7159 
7160 GMenuModel *
7162 {
7163  g_return_val_if_fail (EV_WINDOW (ev_window), NULL);
7164 
7165  return G_MENU_MODEL (ev_window->priv->bookmarks_menu);
7166 }
7167 
7168 EvHistory *
7170 {
7171  g_return_val_if_fail (EV_WINDOW (ev_window), NULL);
7172 
7173  return ev_window->priv->history;
7174 }
7175 
7178 {
7179  g_return_val_if_fail (EV_WINDOW (ev_window), NULL);
7180 
7181  return ev_window->priv->model;
7182 }
7183 
7184 GtkWidget *
7186 {
7187  g_return_val_if_fail (EV_WINDOW (ev_window), NULL);
7188 
7189  return ev_window->priv->toolbar;
7190 }
7191 
7192 void
7194 {
7195  g_return_if_fail (EV_WINDOW (ev_window));
7196 
7197  gtk_widget_grab_focus (ev_window->priv->view);
7198 }