X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=blobdiff_plain;f=shell%2Fev-window.c;h=078cb9c29bb0f4dd3fea5b3e98e047530c8ea139;hb=8c149ccd2a3cced2cd0a676ad6f7b8d33fd98404;hp=697eb737f5605a4b5a673c32c42ba956c1c29aad;hpb=5c07c67fba670090d1110c80745881f92c3f12a9;p=evince.git diff --git a/shell/ev-window.c b/shell/ev-window.c index 697eb737..078cb9c2 100644 --- a/shell/ev-window.c +++ b/shell/ev-window.c @@ -5,7 +5,7 @@ * Copyright (C) 2004 Martin Kretzschmar * Copyright (C) 2004 Red Hat, Inc. * Copyright (C) 2000, 2001, 2002, 2003, 2004 Marco Pesenti Gritti - * Copyright (C) 2003, 2004, 2005 Christian Persch + * Copyright © 2003, 2004, 2005, 2009 Christian Persch * * Author: * Martin Kretzschmar @@ -38,12 +38,10 @@ #include #include #include -#if GTK_CHECK_VERSION (2, 14, 0) -#include -#else -#include -#endif + +#ifdef WITH_GCONF #include +#endif #include "egg-editable-toolbar.h" #include "egg-toolbar-editor.h" @@ -61,6 +59,7 @@ #include "ev-document-images.h" #include "ev-document-links.h" #include "ev-document-thumbnails.h" +#include "ev-document-type-builtins.h" #include "ev-file-exporter.h" #include "ev-file-helpers.h" #include "ev-file-monitor.h" @@ -70,7 +69,6 @@ #include "ev-jobs.h" #include "ev-message-area.h" #include "ev-metadata-manager.h" -#include "ev-mount-operation.h" #include "ev-navigation-action.h" #include "ev-open-recent-action.h" #include "ev-page-action.h" @@ -86,6 +84,7 @@ #include "ev-utils.h" #include "ev-keyring.h" #include "ev-view.h" +#include "ev-view-type-builtins.h" #include "ev-window.h" #include "ev-window-title.h" #include "ev-print-operation.h" @@ -111,10 +110,15 @@ typedef enum { EV_CHROME_RAISE_TOOLBAR = 1 << 3, EV_CHROME_FULLSCREEN_TOOLBAR = 1 << 4, EV_CHROME_SIDEBAR = 1 << 5, - EV_CHROME_PREVIEW_TOOLBAR = 1 << 6, EV_CHROME_NORMAL = EV_CHROME_MENUBAR | EV_CHROME_TOOLBAR | EV_CHROME_SIDEBAR } EvChrome; +typedef enum { + EV_SAVE_DOCUMENT, + EV_SAVE_ATTACHMENT, + EV_SAVE_IMAGE +} EvSaveType; + struct _EvWindowPrivate { /* UI */ EvChrome chrome; @@ -135,6 +139,14 @@ struct _EvWindowPrivate { GtkWidget *sidebar_attachments; GtkWidget *sidebar_layers; + /* Menubar accels */ + guint menubar_accel_keyval; + GdkModifierType menubar_accel_modifier; + + /* Progress Messages */ + guint progress_idle; + GCancellable *progress_cancellable; + /* Dialogs */ GtkWidget *properties; GtkWidget *print_dialog; @@ -154,10 +166,6 @@ struct _EvWindowPrivate { /* Presentation mode */ guint presentation_timeout_id; - /* Preview mode */ - GtkWidget *preview_toolbar; - gchar *print_settings_file; - /* Popup view */ GtkWidget *view_popup; EvLink *link; @@ -171,8 +179,6 @@ struct _EvWindowPrivate { char *uri; glong uri_mtime; char *local_uri; - EvLinkDest *dest; - gboolean unlink_temp_file; gboolean in_reload; EvFileMonitor *monitor; guint setup_document_idle; @@ -183,6 +189,11 @@ struct _EvWindowPrivate { EvWindowPageMode page_mode; EvWindowTitle *title; + /* Load params */ + EvLinkDest *dest; + gchar *search_string; + EvWindowRunMode window_mode; + EvJob *load_job; EvJob *reload_job; EvJob *thumbnail_job; @@ -191,10 +202,9 @@ struct _EvWindowPrivate { /* Printing */ GQueue *print_queue; - GtkPrinter *printer; GtkPrintSettings *print_settings; GtkPageSetup *print_page_setup; - + gboolean close_after_print; }; #define EV_WINDOW_GET_PRIVATE(object) \ @@ -224,7 +234,8 @@ static const gchar *document_print_settings[] = { GTK_PRINT_SETTINGS_SCALE, GTK_PRINT_SETTINGS_PRINT_PAGES, GTK_PRINT_SETTINGS_PAGE_RANGES, - GTK_PRINT_SETTINGS_PAGE_SET + GTK_PRINT_SETTINGS_PAGE_SET, + GTK_PRINT_SETTINGS_OUTPUT_URI }; static void ev_window_update_actions (EvWindow *ev_window); @@ -235,7 +246,8 @@ static void ev_window_set_page_mode (EvWindow *windo EvWindowPageMode page_mode); static void ev_window_load_job_cb (EvJob *job, gpointer data); -static void ev_window_reload_document (EvWindow *window); +static void ev_window_reload_document (EvWindow *window, + EvLinkDest *dest); static void ev_window_reload_job_cb (EvJob *job, EvWindow *window); static void ev_window_set_icon_from_thumbnail (EvJobThumbnail *job, @@ -260,7 +272,6 @@ static void ev_window_stop_presentation (EvWindow *windo gboolean unfullscreen_window); static void ev_window_cmd_view_presentation (GtkAction *action, EvWindow *window); -static void ev_window_run_preview (EvWindow *window); static void ev_view_popup_cmd_open_link (GtkAction *action, EvWindow *window); static void ev_view_popup_cmd_open_link_new_window (GtkAction *action, @@ -288,12 +299,12 @@ static void ev_window_cmd_edit_find (GtkAction *actio static void find_bar_search_changed_cb (EggFindBar *find_bar, GParamSpec *param, EvWindow *ev_window); -static void ev_window_do_preview_print (EvWindow *window); static void ev_window_load_file_remote (EvWindow *ev_window, GFile *source_file); static void ev_window_media_player_key_pressed (EvWindow *window, const gchar *key, gpointer user_data); +static void ev_window_save_print_page_setup (EvWindow *window); G_DEFINE_TYPE (EvWindow, ev_window, GTK_TYPE_WINDOW) @@ -322,16 +333,17 @@ ev_window_setup_action_sensitivity (EvWindow *ev_window) gboolean can_get_text = FALSE; gboolean has_pages = FALSE; gboolean can_find = FALSE; - +#ifdef WITH_GCONF GConfClient *client; +#endif if (document) { has_document = TRUE; - info = ev_page_cache_get_info (ev_window->priv->page_cache); + info = ev_document_get_info (document); } if (has_document && ev_window->priv->page_cache) { - has_pages = ev_page_cache_get_n_pages (ev_window->priv->page_cache) > 0; + has_pages = ev_document_get_n_pages (document) > 0; } if (!info || info->fields_mask == 0) { @@ -346,19 +358,21 @@ ev_window_setup_action_sensitivity (EvWindow *ev_window) can_find = TRUE; } +#ifdef WITH_GCONF client = gconf_client_get_default (); override_restrictions = gconf_client_get_bool (client, GCONF_OVERRIDE_RESTRICTIONS, NULL); +#endif if (!override_restrictions && info && info->fields_mask & EV_DOCUMENT_INFO_PERMISSIONS) { ok_to_print = (info->permissions & EV_DOCUMENT_PERMISSIONS_OK_TO_PRINT); ok_to_copy = (info->permissions & EV_DOCUMENT_PERMISSIONS_OK_TO_COPY); } - if (has_document && !EV_IS_FILE_EXPORTER(document)) + if (has_document && !ev_print_operation_exists_for_document(document)) ok_to_print = FALSE; - +#ifdef WITH_GCONF if (gconf_client_get_bool (client, GCONF_LOCKDOWN_SAVE, NULL)) { ok_to_copy = FALSE; } @@ -368,11 +382,12 @@ ev_window_setup_action_sensitivity (EvWindow *ev_window) } g_object_unref (client); +#endif /* File menu */ ev_window_set_action_sensitive (ev_window, "FileOpenCopy", has_document); ev_window_set_action_sensitive (ev_window, "FileSaveAs", has_document && ok_to_copy); - ev_window_set_action_sensitive (ev_window, "FilePrintSetup", has_pages && ok_to_print); + ev_window_set_action_sensitive (ev_window, "FilePageSetup", has_pages && ok_to_print); ev_window_set_action_sensitive (ev_window, "FilePrint", has_pages && ok_to_print); ev_window_set_action_sensitive (ev_window, "FileProperties", has_document && has_properties); @@ -395,7 +410,6 @@ ev_window_setup_action_sensitivity (EvWindow *ev_window) ev_window_set_action_sensitive (ev_window, PAGE_SELECTOR_ACTION, has_pages); ev_window_set_action_sensitive (ev_window, ZOOM_CONTROL_ACTION, has_pages); ev_window_set_action_sensitive (ev_window, NAVIGATION_ACTION, FALSE); - ev_window_set_action_sensitive (ev_window, "PreviewPrint", has_pages && ok_to_print); ev_window_update_actions (ev_window); } @@ -411,7 +425,7 @@ ev_window_update_actions (EvWindow *ev_window) if (ev_window->priv->document && ev_window->priv->page_cache) { page = ev_page_cache_get_current_page (ev_window->priv->page_cache); - n_pages = ev_page_cache_get_n_pages (ev_window->priv->page_cache); + n_pages = ev_document_get_n_pages (ev_window->priv->document); has_pages = n_pages > 0; } @@ -425,6 +439,8 @@ ev_window_update_actions (EvWindow *ev_window) has_pages && can_find_in_page); ev_window_set_action_sensitive (ev_window, "EditFindPrevious", has_pages && can_find_in_page); + ev_window_set_action_sensitive (ev_window, "F3", + has_pages && can_find_in_page); presentation_mode = ev_view_get_presentation (view); @@ -512,7 +528,6 @@ update_chrome_visibility (EvWindow *window) EvWindowPrivate *priv = window->priv; gboolean menubar, toolbar, findbar, fullscreen_toolbar, sidebar; gboolean fullscreen_mode, presentation, fullscreen; - gboolean preview_toolbar; presentation = ev_view_get_presentation (EV_VIEW (priv->view)); fullscreen = ev_view_get_fullscreen (EV_VIEW (priv->view)); @@ -525,18 +540,13 @@ update_chrome_visibility (EvWindow *window) (priv->chrome & EV_CHROME_RAISE_TOOLBAR) != 0) && fullscreen; findbar = (priv->chrome & EV_CHROME_FINDBAR) != 0; sidebar = (priv->chrome & EV_CHROME_SIDEBAR) != 0 && !presentation; - preview_toolbar = (priv->chrome& EV_CHROME_PREVIEW_TOOLBAR); set_widget_visibility (priv->menubar, menubar); set_widget_visibility (priv->toolbar, toolbar); set_widget_visibility (priv->find_bar, findbar); set_widget_visibility (priv->sidebar, sidebar); - if (priv->preview_toolbar) - set_widget_visibility (priv->preview_toolbar, preview_toolbar); - ev_window_set_action_sensitive (window, "EditToolbar", toolbar); - gtk_widget_set_sensitive (priv->menubar, menubar); if (priv->fullscreen_toolbar != NULL) { set_widget_visibility (priv->fullscreen_toolbar, fullscreen_toolbar); @@ -792,7 +802,7 @@ ev_window_add_history (EvWindow *window, gint page, EvLink *link) } else { dest = ev_link_dest_new_page (page); action = ev_link_action_new_dest (dest); - page_label = ev_page_cache_get_page_label (window->priv->page_cache, page); + page_label = ev_document_get_page_label (window->priv->document, page); } if (!page_label) @@ -863,29 +873,6 @@ update_document_mode (EvWindow *window, EvDocumentMode mode) } } -static void -setup_document_from_metadata (EvWindow *window) -{ - char *uri = window->priv->uri; - GValue page = { 0, }; - gint n_pages; - gint new_page; - - /* View the previously shown page, but make sure to not open a document on - * the last page, since closing it on the last page most likely means the - * user was finished reading the document. In that case, reopening should - * show the first page. */ - if (uri && ev_metadata_manager_get (uri, "page", &page, TRUE)) { - n_pages = ev_page_cache_get_n_pages (window->priv->page_cache); - new_page = CLAMP (g_value_get_int (&page), 0, n_pages - 1); - if (!window->priv->in_reload && new_page == n_pages - 1) - new_page = 0; - ev_page_cache_set_current_page (window->priv->page_cache, - new_page); - g_value_unset (&page); - } -} - static void setup_chrome_from_metadata (EvWindow *window) { @@ -901,17 +888,18 @@ setup_chrome_from_metadata (EvWindow *window) } static void -setup_sidebar_from_metadata (EvWindow *window, EvDocument *document) +setup_sidebar_from_metadata (EvWindow *window) { - char *uri = window->priv->uri; - GtkWidget *sidebar = window->priv->sidebar; - GtkWidget *links = window->priv->sidebar_links; - GtkWidget *thumbs = window->priv->sidebar_thumbs; - GtkWidget *attachments = window->priv->sidebar_attachments; - GtkWidget *layers = window->priv->sidebar_layers; - GValue sidebar_size = { 0, }; - GValue sidebar_page = { 0, }; - GValue sidebar_visibility = { 0, }; + gchar *uri = window->priv->uri; + EvDocument *document = window->priv->document; + GtkWidget *sidebar = window->priv->sidebar; + GtkWidget *links = window->priv->sidebar_links; + GtkWidget *thumbs = window->priv->sidebar_thumbs; + GtkWidget *attachments = window->priv->sidebar_attachments; + GtkWidget *layers = window->priv->sidebar_layers; + GValue sidebar_size = { 0, }; + GValue sidebar_page = { 0, }; + GValue sidebar_visibility = { 0, }; if (ev_metadata_manager_get (uri, "sidebar_size", &sidebar_size, FALSE)) { gtk_paned_set_position (GTK_PANED (window->priv->hpaned), @@ -952,13 +940,73 @@ setup_sidebar_from_metadata (EvWindow *window, EvDocument *document) } static void -setup_size_from_metadata (EvWindow *window) +setup_document_from_metadata (EvWindow *window) { - char *uri = window->priv->uri; + gchar *uri = window->priv->uri; + GValue page = { 0, }; GValue width = { 0, }; GValue height = { 0, }; GValue width_ratio = { 0, }; GValue height_ratio = { 0, }; + + /* View the previously shown page, but make sure to not open a document on + * the last page, since closing it on the last page most likely means the + * user was finished reading the document. In that case, reopening should + * show the first page. */ + if (uri && ev_metadata_manager_get (uri, "page", &page, TRUE)) { + gint n_pages; + gint new_page; + + n_pages = ev_document_get_n_pages (window->priv->document); + new_page = CLAMP (g_value_get_int (&page), 0, n_pages - 1); + ev_page_cache_set_current_page (window->priv->page_cache, + new_page); + g_value_unset (&page); + } + + setup_sidebar_from_metadata (window); + + if (ev_metadata_manager_get (uri, "window_width", &width, TRUE) && + ev_metadata_manager_get (uri, "window_height", &height, TRUE)) + return; /* size was already set in setup_size_from_metadata */ + + if (ev_metadata_manager_get (uri, "window_width_ratio", &width_ratio, FALSE) && + ev_metadata_manager_get (uri, "window_height_ratio", &height_ratio, FALSE)) { + gdouble document_width; + gdouble document_height; + GdkScreen *screen; + gint request_width; + gint request_height; + + ev_document_get_max_page_size (window->priv->document, + &document_width, &document_height); + + request_width = (gint)(g_value_get_double (&width_ratio) * document_width + 0.5); + request_height = (gint)(g_value_get_double (&height_ratio) * document_height + 0.5); + + screen = gtk_window_get_screen (GTK_WINDOW (window)); + + if (screen) { + request_width = MIN (request_width, gdk_screen_get_width (screen)); + request_height = MIN (request_width, gdk_screen_get_height (screen)); + } + + if (request_width > 0 && request_height > 0) { + gtk_window_resize (GTK_WINDOW (window), + request_width, + request_height); + } + g_value_unset (&width_ratio); + g_value_unset (&height_ratio); + } +} + +static void +setup_size_from_metadata (EvWindow *window) +{ + char *uri = window->priv->uri; + GValue width = { 0, }; + GValue height = { 0, }; GValue maximized = { 0, }; GValue x = { 0, }; GValue y = { 0, }; @@ -989,43 +1037,6 @@ setup_size_from_metadata (EvWindow *window) g_value_get_int (&height)); g_value_unset (&width); g_value_unset (&height); - return; - } - - if (window->priv->page_cache && - ev_metadata_manager_get (uri, "window_width_ratio", &width_ratio, FALSE) && - ev_metadata_manager_get (uri, "window_height_ratio", &height_ratio, FALSE)) { - - gint document_width; - gint document_height; - - GdkScreen *screen; - - gint request_width; - gint request_height; - - ev_page_cache_get_max_width (window->priv->page_cache, - 0, 1.0, - &document_width); - ev_page_cache_get_max_height (window->priv->page_cache, - 0, 1.0, - &document_height); - - request_width = g_value_get_double (&width_ratio) * document_width; - request_height = g_value_get_double (&height_ratio) * document_height; - - screen = gtk_window_get_screen (GTK_WINDOW (window)); - - if (screen) { - request_width = MIN (request_width, gdk_screen_get_width (screen)); - request_height = MIN (request_width, gdk_screen_get_height (screen)); - } - - gtk_window_resize (GTK_WINDOW (window), - request_width, - request_height); - g_value_unset (&width_ratio); - g_value_unset (&height_ratio); } } @@ -1033,7 +1044,7 @@ static void setup_view_from_metadata (EvWindow *window) { EvView *view = EV_VIEW (window->priv->view); - char *uri = window->priv->uri; + gchar *uri = window->priv->uri; GEnumValue *enum_value; GValue sizing_mode = { 0, }; GValue zoom = { 0, }; @@ -1042,22 +1053,11 @@ setup_view_from_metadata (EvWindow *window) GValue presentation = { 0, }; GValue fullscreen = { 0, }; GValue rotation = { 0, }; - GValue maximized = { 0, }; - - /* Maximized */ - if (ev_metadata_manager_get (uri, "window_maximized", &maximized, FALSE)) { - if (g_value_get_boolean (&maximized)) { - gtk_window_maximize (GTK_WINDOW (window)); - } else { - gtk_window_unmaximize (GTK_WINDOW (window)); - } - g_value_unset (&maximized); - } /* Sizing mode */ if (ev_metadata_manager_get (uri, "sizing_mode", &sizing_mode, FALSE)) { enum_value = g_enum_get_value_by_nick - (EV_SIZING_MODE_CLASS, g_value_get_string (&sizing_mode)); + (g_type_class_peek (EV_TYPE_SIZING_MODE), g_value_get_string (&sizing_mode)); g_value_unset (&sizing_mode); ev_view_set_sizing_mode (view, enum_value->value); } @@ -1152,22 +1152,21 @@ ev_window_set_icon_from_thumbnail (EvJobThumbnail *job, static void ev_window_refresh_window_thumbnail (EvWindow *ev_window, int rotation) { - gint page_width, page_height; + gdouble page_width; gdouble scale; EvDocument *document = ev_window->priv->document; - + if (!EV_IS_DOCUMENT_THUMBNAILS (document) || - ev_page_cache_get_n_pages (ev_window->priv->page_cache) <= 0) { + ev_document_get_n_pages (document) <= 0 || + !ev_document_check_dimensions (document)) { return; } - + ev_window_clear_thumbnail_job (ev_window); - - ev_page_cache_get_size (ev_window->priv->page_cache, - 0, 0, 1.0, - &page_width, &page_height); - scale = (gdouble)128 / (gdouble)page_width; - + + ev_document_get_page_size (document, 0, &page_width, NULL); + scale = 128. / page_width; + ev_window->priv->thumbnail_job = ev_job_thumbnail_new (document, 0, rotation, scale); g_signal_connect (ev_window->priv->thumbnail_job, "finished", G_CALLBACK (ev_window_set_icon_from_thumbnail), @@ -1209,9 +1208,11 @@ ev_window_setup_document (EvWindow *ev_window) ev_window->priv->document); } - info = ev_page_cache_get_info (ev_window->priv->page_cache); + info = ev_document_get_info (document); update_document_mode (ev_window, info->mode); + gtk_widget_grab_focus (ev_window->priv->view); + return FALSE; } @@ -1232,19 +1233,31 @@ ev_window_set_document (EvWindow *ev_window, EvDocument *document) g_signal_connect (ev_window->priv->page_cache, "history-changed", G_CALLBACK (history_changed_cb), ev_window); - setup_size_from_metadata (ev_window); - setup_sidebar_from_metadata (ev_window, document); - setup_document_from_metadata (ev_window); + if (ev_window->priv->in_reload && ev_window->priv->dest) { + gint page; - if (ev_page_cache_get_n_pages (ev_window->priv->page_cache) > 0) { - ev_view_set_document (view, document); - } else { + /* Restart the current page */ + page = CLAMP (ev_link_dest_get_page (ev_window->priv->dest), + 0, + ev_document_get_n_pages (document) - 1); + ev_page_cache_set_current_page (ev_window->priv->page_cache, page); + g_object_unref (ev_window->priv->dest); + ev_window->priv->dest = NULL; + } + + if (ev_document_get_n_pages (document) <= 0) { ev_window_warning_message (ev_window, "%s", _("The document contains no pages")); + } else if (!ev_document_check_dimensions (document)) { + ev_window_warning_message (ev_window, "%s", + _("The document contains only empty pages")); + } else { + ev_view_set_document (view, document); } if (ev_window->priv->setup_document_idle > 0) g_source_remove (ev_window->priv->setup_document_idle); + ev_window->priv->setup_document_idle = g_idle_add ((GSourceFunc)ev_window_setup_document, ev_window); } @@ -1252,7 +1265,7 @@ static void ev_window_document_changed (EvWindow *ev_window, gpointer user_data) { - ev_window_reload_document (ev_window); + ev_window_reload_document (ev_window, NULL); } static void @@ -1304,17 +1317,7 @@ ev_window_clear_local_uri (EvWindow *ev_window) } static void -ev_window_clear_print_settings_file (EvWindow *ev_window) -{ - if (ev_window->priv->print_settings_file) { - g_unlink (ev_window->priv->print_settings_file); - g_free (ev_window->priv->print_settings_file); - ev_window->priv->print_settings_file = NULL; - } -} - -static void -ev_window_clear_temp_file (EvWindow *ev_window) +ev_window_clear_temp_symlink (EvWindow *ev_window) { GFile *file, *tempdir; @@ -1322,16 +1325,45 @@ ev_window_clear_temp_file (EvWindow *ev_window) return; file = g_file_new_for_uri (ev_window->priv->uri); - tempdir = g_file_new_for_path (g_get_tmp_dir ()); + tempdir = g_file_new_for_path (ev_tmp_dir ()); if (g_file_has_prefix (file, tempdir)) { - g_file_delete (file, NULL, NULL); + GFileInfo *file_info; + GError *error = NULL; + + file_info = g_file_query_info (file, + G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK, + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, + NULL, &error); + if (file_info) { + if (g_file_info_get_is_symlink (file_info)) + g_file_delete (file, NULL, NULL); + g_object_unref (file_info); + } else { + g_warning ("Error deleting temp symlink: %s\n", error->message); + g_error_free (error); + } } g_object_unref (file); g_object_unref (tempdir); } +static void +ev_window_handle_link (EvWindow *ev_window, + EvLinkDest *dest) +{ + if (dest) { + EvLink *link; + EvLinkAction *link_action; + + link_action = ev_link_action_new_dest (dest); + link = ev_link_new (NULL, link_action); + ev_view_handle_link (EV_VIEW (ev_window->priv->view), link); + g_object_unref (link); + } +} + /* This callback will executed when load job will be finished. * * Since the flow of the error dialog is very confusing, we assume that both @@ -1355,14 +1387,11 @@ ev_window_load_job_cb (EvJob *job, /* Success! */ if (!ev_job_is_failed (job)) { ev_window_set_document (ev_window, document); - - if (job_load->mode != EV_WINDOW_MODE_PREVIEW) { - setup_view_from_metadata (ev_window); - } - if (!ev_window->priv->unlink_temp_file) { - ev_window_add_recent (ev_window, ev_window->priv->uri); - } + setup_document_from_metadata (ev_window); + setup_view_from_metadata (ev_window); + + ev_window_add_recent (ev_window, ev_window->priv->uri); ev_window_title_set_type (ev_window->priv->title, EV_WINDOW_TITLE_DOCUMENT); @@ -1376,39 +1405,36 @@ ev_window_load_job_cb (EvJob *job, flags); } - if (job_load->dest) { - EvLink *link; - EvLinkAction *link_action; - - link_action = ev_link_action_new_dest (g_object_ref (job_load->dest)); - link = ev_link_new (NULL, link_action); - ev_view_handle_link (EV_VIEW (ev_window->priv->view), link); - g_object_unref (link); - } + ev_window_handle_link (ev_window, ev_window->priv->dest); + /* Already unrefed by ev_link_action + * FIXME: link action should inc dest ref counting + * or not unref it at all + */ + ev_window->priv->dest = NULL; - switch (job_load->mode) { + switch (ev_window->priv->window_mode) { case EV_WINDOW_MODE_FULLSCREEN: ev_window_run_fullscreen (ev_window); break; case EV_WINDOW_MODE_PRESENTATION: ev_window_run_presentation (ev_window); break; - case EV_WINDOW_MODE_PREVIEW: - ev_window_run_preview (ev_window); - break; default: break; } - if (job_load->search_string && EV_IS_DOCUMENT_FIND (document)) { + if (ev_window->priv->search_string && EV_IS_DOCUMENT_FIND (document)) { ev_window_cmd_edit_find (NULL, ev_window); egg_find_bar_set_search_string (EGG_FIND_BAR (ev_window->priv->find_bar), - job_load->search_string); + ev_window->priv->search_string); } + g_free (ev_window->priv->search_string); + ev_window->priv->search_string = NULL; + /* Create a monitor for the document */ ev_window->priv->monitor = ev_file_monitor_new (ev_window->priv->uri); - g_signal_connect_swapped (G_OBJECT (ev_window->priv->monitor), "changed", + g_signal_connect_swapped (ev_window->priv->monitor, "changed", G_CALLBACK (ev_window_document_changed), ev_window); @@ -1416,8 +1442,7 @@ ev_window_load_job_cb (EvJob *job, return; } - if (job->error->domain == EV_DOCUMENT_ERROR && - job->error->code == EV_DOCUMENT_ERROR_ENCRYPTED) { + if (g_error_matches (job->error, EV_DOCUMENT_ERROR, EV_DOCUMENT_ERROR_ENCRYPTED)) { gchar *password; setup_view_from_metadata (ev_window); @@ -1464,15 +1489,24 @@ ev_window_reload_job_cb (EvJob *job, EvWindow *ev_window) { GtkWidget *widget; + EvLinkDest *dest = NULL; if (ev_job_is_failed (job)) { ev_window_clear_reload_job (ev_window); ev_window->priv->in_reload = FALSE; + g_object_unref (ev_window->priv->dest); + ev_window->priv->dest = NULL; + return; } - + + if (ev_window->priv->dest) { + dest = g_object_ref (ev_window->priv->dest); + } ev_window_set_document (ev_window, job->document); + ev_window_handle_link (ev_window, dest); + /* Restart the search after reloading */ widget = gtk_window_get_focus (GTK_WINDOW (ev_window)); if (widget && gtk_widget_get_ancestor (widget, EGG_TYPE_FIND_BAR)) { @@ -1517,6 +1551,86 @@ ev_window_close_dialogs (EvWindow *ev_window) ev_window->priv->properties = NULL; } +static void +ev_window_clear_progress_idle (EvWindow *ev_window) +{ + if (ev_window->priv->progress_idle > 0) + g_source_remove (ev_window->priv->progress_idle); + ev_window->priv->progress_idle = 0; +} + +static void +reset_progress_idle (EvWindow *ev_window) +{ + ev_window->priv->progress_idle = 0; +} + +static void +ev_window_show_progress_message (EvWindow *ev_window, + guint interval, + GSourceFunc function) +{ + if (ev_window->priv->progress_idle > 0) + g_source_remove (ev_window->priv->progress_idle); + ev_window->priv->progress_idle = + g_timeout_add_seconds_full (G_PRIORITY_DEFAULT, + interval, function, + ev_window, + (GDestroyNotify)reset_progress_idle); +} + +static void +ev_window_reset_progress_cancellable (EvWindow *ev_window) +{ + if (ev_window->priv->progress_cancellable) + g_cancellable_reset (ev_window->priv->progress_cancellable); + else + ev_window->priv->progress_cancellable = g_cancellable_new (); +} + +static void +ev_window_progress_response_cb (EvProgressMessageArea *area, + gint response, + EvWindow *ev_window) +{ + if (response == GTK_RESPONSE_CANCEL) + g_cancellable_cancel (ev_window->priv->progress_cancellable); + ev_window_set_message_area (ev_window, NULL); +} + +static gboolean +show_loading_progress (EvWindow *ev_window) +{ + GtkWidget *area; + gchar *text; + gchar *display_name; + + if (ev_window->priv->message_area) + return FALSE; + + display_name = escape_uri_for_display (ev_window->priv->uri); + text = g_strdup_printf (_("Loading document from “%s”"), + display_name); + + area = ev_progress_message_area_new (GTK_STOCK_OPEN, + text, + GTK_STOCK_CLOSE, + GTK_RESPONSE_CLOSE, + GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL, + NULL); + g_signal_connect (area, "response", + G_CALLBACK (ev_window_progress_response_cb), + ev_window); + gtk_widget_show (area); + ev_window_set_message_area (ev_window, area); + + g_free (text); + g_free (display_name); + + return FALSE; +} + static void ev_window_load_remote_failed (EvWindow *ev_window, GError *error) @@ -1580,6 +1694,8 @@ window_open_file_copy_ready_cb (GFile *source, EvWindow *ev_window) { GError *error = NULL; + + ev_window_clear_progress_idle (ev_window); g_file_copy_finish (source, async_result, &error); if (!error) { @@ -1593,17 +1709,24 @@ window_open_file_copy_ready_cb (GFile *source, return; } - if (error->domain == G_IO_ERROR && - error->code == G_IO_ERROR_NOT_MOUNTED) { + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_MOUNTED)) { GMountOperation *operation; - operation = ev_mount_operation_new (GTK_WINDOW (ev_window)); + operation = gtk_mount_operation_new (GTK_WINDOW (ev_window)); g_file_mount_enclosing_volume (source, G_MOUNT_MOUNT_NONE, operation, NULL, (GAsyncReadyCallback)mount_volume_ready_cb, ev_window); g_object_unref (operation); + } else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + ev_window_clear_load_job (ev_window); + ev_window_clear_local_uri (ev_window); + g_free (ev_window->priv->uri); + ev_window->priv->uri = NULL; + g_object_unref (source); + + ev_view_set_loading (EV_VIEW (ev_window->priv->view), FALSE); } else { ev_window_load_remote_failed (ev_window, error); g_object_unref (source); @@ -1613,8 +1736,31 @@ window_open_file_copy_ready_cb (GFile *source, } static void -ev_window_load_file_remote (EvWindow *ev_window, - GFile *source_file) +window_open_file_copy_progress_cb (goffset n_bytes, + goffset total_bytes, + EvWindow *ev_window) +{ + gchar *status; + gdouble fraction; + + if (!ev_window->priv->message_area) + return; + + fraction = n_bytes / (gdouble)total_bytes; + status = g_strdup_printf (_("Downloading document (%d%%)"), + (gint)(fraction * 100)); + + ev_progress_message_area_set_status (EV_PROGRESS_MESSAGE_AREA (ev_window->priv->message_area), + status); + ev_progress_message_area_set_fraction (EV_PROGRESS_MESSAGE_AREA (ev_window->priv->message_area), + fraction); + + g_free (status); +} + +static void +ev_window_load_file_remote (EvWindow *ev_window, + GFile *source_file) { GFile *target_file; @@ -1633,14 +1779,21 @@ ev_window_load_file_remote (EvWindow *ev_window, g_free (base_name); g_free (tmp_name); } + + ev_window_reset_progress_cancellable (ev_window); target_file = g_file_new_for_uri (ev_window->priv->local_uri); g_file_copy_async (source_file, target_file, - 0, G_PRIORITY_DEFAULT, NULL, - NULL, NULL, /* no progress callback */ - (GAsyncReadyCallback) window_open_file_copy_ready_cb, + 0, G_PRIORITY_DEFAULT, + ev_window->priv->progress_cancellable, + (GFileProgressCallback)window_open_file_copy_progress_cb, + ev_window, + (GAsyncReadyCallback)window_open_file_copy_ready_cb, ev_window); g_object_unref (target_file); + + ev_window_show_progress_message (ev_window, 1, + (GSourceFunc)show_loading_progress); } void @@ -1648,9 +1801,7 @@ ev_window_open_uri (EvWindow *ev_window, const char *uri, EvLinkDest *dest, EvWindowRunMode mode, - const gchar *search_string, - gboolean unlink_temp_file, - const gchar *print_settings) + const gchar *search_string) { GFile *source_file; @@ -1658,7 +1809,7 @@ ev_window_open_uri (EvWindow *ev_window, if (ev_window->priv->uri && g_ascii_strcasecmp (ev_window->priv->uri, uri) == 0) { - ev_window_reload_document (ev_window); + ev_window_reload_document (ev_window, dest); return; } @@ -1670,23 +1821,26 @@ ev_window_open_uri (EvWindow *ev_window, ev_window_close_dialogs (ev_window); ev_window_clear_load_job (ev_window); ev_window_clear_local_uri (ev_window); - ev_window_clear_print_settings_file (ev_window); ev_view_set_loading (EV_VIEW (ev_window->priv->view), TRUE); - ev_window->priv->unlink_temp_file = unlink_temp_file; - - if (mode == EV_WINDOW_MODE_PREVIEW) { - ev_window->priv->print_settings_file = print_settings ? - g_strdup (print_settings) : NULL; - } + ev_window->priv->window_mode = mode; if (ev_window->priv->uri) g_free (ev_window->priv->uri); ev_window->priv->uri = g_strdup (uri); + if (ev_window->priv->search_string) + g_free (ev_window->priv->search_string); + ev_window->priv->search_string = search_string ? + g_strdup (search_string) : NULL; + + if (ev_window->priv->dest) + g_object_unref (ev_window->priv->dest); + ev_window->priv->dest = dest ? g_object_ref (dest) : NULL; + setup_size_from_metadata (ev_window); - - ev_window->priv->load_job = ev_job_load_new (uri, dest, mode, search_string); + + ev_window->priv->load_job = ev_job_load_new (uri); g_signal_connect (ev_window->priv->load_job, "finished", G_CALLBACK (ev_window_load_job_cb), @@ -1707,23 +1861,86 @@ ev_window_reload_local (EvWindow *ev_window) const gchar *uri; uri = ev_window->priv->local_uri ? ev_window->priv->local_uri : ev_window->priv->uri; - ev_window->priv->reload_job = ev_job_load_new (uri, NULL, 0, NULL); + ev_window->priv->reload_job = ev_job_load_new (uri); g_signal_connect (ev_window->priv->reload_job, "finished", G_CALLBACK (ev_window_reload_job_cb), ev_window); ev_job_scheduler_push_job (ev_window->priv->reload_job, EV_JOB_PRIORITY_NONE); } +static gboolean +show_reloading_progress (EvWindow *ev_window) +{ + GtkWidget *area; + gchar *text; + + if (ev_window->priv->message_area) + return FALSE; + + text = g_strdup_printf (_("Reloading document from %s"), + ev_window->priv->uri); + area = ev_progress_message_area_new (GTK_STOCK_REFRESH, + text, + GTK_STOCK_CLOSE, + GTK_RESPONSE_CLOSE, + GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL, + NULL); + g_signal_connect (area, "response", + G_CALLBACK (ev_window_progress_response_cb), + ev_window); + gtk_widget_show (area); + ev_window_set_message_area (ev_window, area); + g_free (text); + + return FALSE; +} + static void reload_remote_copy_ready_cb (GFile *remote, GAsyncResult *async_result, EvWindow *ev_window) { - g_file_copy_finish (remote, async_result, NULL); - ev_window_reload_local (ev_window); + GError *error = NULL; + + ev_window_clear_progress_idle (ev_window); + + g_file_copy_finish (remote, async_result, &error); + if (error) { + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + ev_window_error_message (ev_window, error, + "%s", _("Failed to reload document.")); + g_error_free (error); + } else { + ev_window_reload_local (ev_window); + } + g_object_unref (remote); } +static void +reload_remote_copy_progress_cb (goffset n_bytes, + goffset total_bytes, + EvWindow *ev_window) +{ + gchar *status; + gdouble fraction; + + if (!ev_window->priv->message_area) + return; + + fraction = n_bytes / (gdouble)total_bytes; + status = g_strdup_printf (_("Downloading document (%d%%)"), + (gint)(fraction * 100)); + + ev_progress_message_area_set_status (EV_PROGRESS_MESSAGE_AREA (ev_window->priv->message_area), + status); + ev_progress_message_area_set_fraction (EV_PROGRESS_MESSAGE_AREA (ev_window->priv->message_area), + fraction); + + g_free (status); +} + static void query_remote_uri_mtime_cb (GFile *remote, GAsyncResult *async_result, @@ -1748,14 +1965,21 @@ query_remote_uri_mtime_cb (GFile *remote, /* Remote file has changed */ ev_window->priv->uri_mtime = mtime.tv_sec; + + ev_window_reset_progress_cancellable (ev_window); + target_file = g_file_new_for_uri (ev_window->priv->local_uri); g_file_copy_async (remote, target_file, G_FILE_COPY_OVERWRITE, - G_PRIORITY_DEFAULT, NULL, - NULL, NULL, /* no progress callback */ - (GAsyncReadyCallback) reload_remote_copy_ready_cb, + G_PRIORITY_DEFAULT, + ev_window->priv->progress_cancellable, + (GFileProgressCallback)reload_remote_copy_progress_cb, + ev_window, + (GAsyncReadyCallback)reload_remote_copy_ready_cb, ev_window); g_object_unref (target_file); + ev_window_show_progress_message (ev_window, 1, + (GSourceFunc)show_reloading_progress); } else { g_object_unref (remote); ev_window_reload_local (ev_window); @@ -1780,11 +2004,22 @@ ev_window_reload_remote (EvWindow *ev_window) } static void -ev_window_reload_document (EvWindow *ev_window) +ev_window_reload_document (EvWindow *ev_window, + EvLinkDest *dest) { + gint page; + + ev_window_clear_reload_job (ev_window); ev_window->priv->in_reload = TRUE; + page = ev_page_cache_get_current_page (ev_window->priv->page_cache); + + if (ev_window->priv->dest) + g_object_unref (ev_window->priv->dest); + /* FIXME: save the scroll position too (xyz dest) */ + ev_window->priv->dest = dest ? g_object_ref (dest) : ev_link_dest_new_page (page); + if (ev_window->priv->local_uri) { ev_window_reload_remote (ev_window); } else { @@ -1797,24 +2032,25 @@ file_open_dialog_response_cb (GtkWidget *chooser, gint response_id, EvWindow *ev_window) { - gchar *uri; - if (response_id == GTK_RESPONSE_OK) { GSList *uris; + gchar *uri; uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (chooser)); ev_application_open_uri_list (EV_APP, uris, gtk_window_get_screen (GTK_WINDOW (ev_window)), GDK_CURRENT_TIME); - - g_slist_foreach (uris, (GFunc)g_free, NULL); + + g_slist_foreach (uris, (GFunc)g_free, NULL); g_slist_free (uris); - } - uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (chooser)); - ev_application_set_chooser_uri (EV_APP, uri); - g_free (uri); + uri = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (chooser)); + ev_application_set_filechooser_uri (EV_APP, + GTK_FILE_CHOOSER_ACTION_OPEN, + uri); + g_free (uri); + } gtk_widget_destroy (chooser); } @@ -1822,7 +2058,9 @@ file_open_dialog_response_cb (GtkWidget *chooser, static void ev_window_cmd_file_open (GtkAction *action, EvWindow *window) { - GtkWidget *chooser; + GtkWidget *chooser; + const gchar *default_uri; + gchar *parent_uri = NULL; chooser = gtk_file_chooser_dialog_new (_("Open Document"), GTK_WINDOW (window), @@ -1835,12 +2073,23 @@ ev_window_cmd_file_open (GtkAction *action, EvWindow *window) ev_document_factory_add_filters (chooser, NULL); gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (chooser), TRUE); gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (chooser), FALSE); - if (ev_application_get_chooser_uri (EV_APP) != NULL) { - gtk_file_chooser_set_uri (GTK_FILE_CHOOSER (chooser), - ev_application_get_chooser_uri (EV_APP)); - } else if (window->priv->uri != NULL) { - gtk_file_chooser_set_uri (GTK_FILE_CHOOSER (chooser), - window->priv->uri); + + default_uri = ev_application_get_filechooser_uri (EV_APP, GTK_FILE_CHOOSER_ACTION_OPEN); + if (!default_uri && window->priv->uri) { + GFile *file, *parent; + + file = g_file_new_for_uri (window->priv->uri); + parent = g_file_get_parent (file); + if (parent) { + parent_uri = g_file_get_uri (parent); + default_uri = parent_uri; + g_object_unref (parent); + } + g_object_unref (file); + } + + if (default_uri) { + gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (chooser), default_uri); } else { const gchar *folder; @@ -1848,7 +2097,8 @@ ev_window_cmd_file_open (GtkAction *action, EvWindow *window) gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (chooser), folder ? folder : g_get_home_dir ()); } - + g_free (parent_uri); + g_signal_connect (chooser, "response", G_CALLBACK (file_open_dialog_response_cb), window); @@ -1859,10 +2109,11 @@ ev_window_cmd_file_open (GtkAction *action, EvWindow *window) static gchar * ev_window_create_tmp_symlink (const gchar *filename, GError **error) { - gchar *tmp_filename = NULL; - gchar *name; - gint res; - guint i = 0; + gchar *tmp_filename = NULL; + gchar *name; + guint i = 0; + GError *link_error = NULL; + GFile *tmp_file = NULL; name = g_path_get_basename (filename); @@ -1871,29 +2122,32 @@ ev_window_create_tmp_symlink (const gchar *filename, GError **error) if (tmp_filename) g_free (tmp_filename); + if (tmp_file) + g_object_unref (tmp_file); + g_clear_error (&link_error); basename = g_strdup_printf ("%s-%d", name, i++); tmp_filename = g_build_filename (ev_tmp_dir (), basename, NULL); g_free (basename); - } while ((res = symlink (filename, tmp_filename)) != 0 && errno == EEXIST); - - g_free (name); + tmp_file = g_file_new_for_path (tmp_filename); + } while (!g_file_make_symbolic_link (tmp_file, filename, NULL, &link_error) && + g_error_matches (link_error, G_IO_ERROR, G_IO_ERROR_EXISTS)); - if (res != 0 && errno != EEXIST) { - if (error) { - *error = g_error_new (G_FILE_ERROR, - g_file_error_from_errno (errno), - _("Couldn't create symlink “%s”: %s"), - tmp_filename, strerror (errno)); - } + g_free (name); + g_object_unref (tmp_file); + if (link_error) { + g_propagate_prefixed_error (error, + link_error, + _("Couldn't create symlink “%s”: "), + tmp_filename); g_free (tmp_filename); - + return NULL; } - + return tmp_filename; } @@ -1933,8 +2187,6 @@ ev_window_cmd_file_open_copy_at_dest (EvWindow *window, EvLinkDest *dest) dest, 0, NULL, - TRUE, - NULL, GDK_CURRENT_TIME); g_free (symlink_uri); } @@ -1968,8 +2220,7 @@ ev_window_cmd_recent_file_activate (GtkAction *action, ev_application_open_uri_at_dest (EV_APP, uri, gtk_window_get_screen (GTK_WINDOW (window)), - NULL, 0, NULL, FALSE, NULL, - GDK_CURRENT_TIME); + NULL, 0, NULL, GDK_CURRENT_TIME); } static void @@ -1979,8 +2230,7 @@ ev_window_open_recent_action_item_activated (EvOpenRecentAction *action, { ev_application_open_uri_at_dest (EV_APP, uri, gtk_window_get_screen (GTK_WINDOW (window)), - NULL, 0, NULL, FALSE, NULL, - GDK_CURRENT_TIME); + NULL, 0, NULL, GDK_CURRENT_TIME); } static void @@ -2109,7 +2359,7 @@ ev_window_setup_recent (EvWindow *ev_window) gtk_recent_info_ref (info), (GDestroyNotify) gtk_recent_info_unref); - g_signal_connect (G_OBJECT (action), "activate", + g_signal_connect (action, "activate", G_CALLBACK (ev_window_cmd_recent_file_activate), (gpointer) ev_window); @@ -2135,42 +2385,149 @@ ev_window_setup_recent (EvWindow *ev_window) g_list_free (items); } +static gboolean +show_saving_progress (GFile *dst) +{ + EvWindow *ev_window; + GtkWidget *area; + gchar *text; + gchar *uri; + EvSaveType save_type; + + ev_window = EV_WINDOW (g_object_get_data (G_OBJECT (dst), "ev-window")); + ev_window->priv->progress_idle = 0; + + if (ev_window->priv->message_area) + return FALSE; + + save_type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dst), "save-type")); + uri = g_file_get_uri (dst); + switch (save_type) { + case EV_SAVE_DOCUMENT: + text = g_strdup_printf (_("Saving document to %s"), uri); + break; + case EV_SAVE_ATTACHMENT: + text = g_strdup_printf (_("Saving attachment to %s"), uri); + break; + case EV_SAVE_IMAGE: + text = g_strdup_printf (_("Saving image to %s"), uri); + break; + default: + g_assert_not_reached (); + } + g_free (uri); + area = ev_progress_message_area_new (GTK_STOCK_SAVE, + text, + GTK_STOCK_CLOSE, + GTK_RESPONSE_CLOSE, + GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL, + NULL); + g_signal_connect (area, "response", + G_CALLBACK (ev_window_progress_response_cb), + ev_window); + gtk_widget_show (area); + ev_window_set_message_area (ev_window, area); + g_free (text); + + return FALSE; +} + static void window_save_file_copy_ready_cb (GFile *src, GAsyncResult *async_result, GFile *dst) { - EvWindow *window; - gchar *name; - GError *error = NULL; + EvWindow *ev_window; + GError *error = NULL; + ev_window = EV_WINDOW (g_object_get_data (G_OBJECT (dst), "ev-window")); + ev_window_clear_progress_idle (ev_window); + if (g_file_copy_finish (src, async_result, &error)) { ev_tmp_file_unlink (src); return; } - window = EV_WINDOW (g_object_get_data (G_OBJECT (dst), "ev-window")); - name = g_file_get_basename (dst); - ev_window_error_message (window, error, - _("The file could not be saved as “%s”."), - name); + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + gchar *name; + + name = g_file_get_basename (dst); + ev_window_error_message (ev_window, error, + _("The file could not be saved as “%s”."), + name); + g_free (name); + } ev_tmp_file_unlink (src); - g_free (name); g_error_free (error); } static void -ev_window_save_remote (EvWindow *ev_window, - GFile *src, - GFile *dst) +window_save_file_copy_progress_cb (goffset n_bytes, + goffset total_bytes, + GFile *dst) +{ + EvWindow *ev_window; + EvSaveType save_type; + gchar *status; + gdouble fraction; + + ev_window = EV_WINDOW (g_object_get_data (G_OBJECT (dst), "ev-window")); + + if (!ev_window->priv->message_area) + return; + + fraction = n_bytes / (gdouble)total_bytes; + save_type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dst), "save-type")); + + switch (save_type) { + case EV_SAVE_DOCUMENT: + status = g_strdup_printf (_("Uploading document (%d%%)"), + (gint)(fraction * 100)); + break; + case EV_SAVE_ATTACHMENT: + status = g_strdup_printf (_("Uploading attachment (%d%%)"), + (gint)(fraction * 100)); + break; + case EV_SAVE_IMAGE: + status = g_strdup_printf (_("Uploading image (%d%%)"), + (gint)(fraction * 100)); + break; + default: + g_assert_not_reached (); + } + + ev_progress_message_area_set_status (EV_PROGRESS_MESSAGE_AREA (ev_window->priv->message_area), + status); + ev_progress_message_area_set_fraction (EV_PROGRESS_MESSAGE_AREA (ev_window->priv->message_area), + fraction); + + g_free (status); +} + +static void +ev_window_save_remote (EvWindow *ev_window, + EvSaveType save_type, + GFile *src, + GFile *dst) { + ev_window_reset_progress_cancellable (ev_window); g_object_set_data (G_OBJECT (dst), "ev-window", ev_window); + g_object_set_data (G_OBJECT (dst), "save-type", GINT_TO_POINTER (save_type)); g_file_copy_async (src, dst, G_FILE_COPY_OVERWRITE, - G_PRIORITY_DEFAULT, NULL, - NULL, NULL, /* no progress callback */ - (GAsyncReadyCallback) window_save_file_copy_ready_cb, - dst); + G_PRIORITY_DEFAULT, + ev_window->priv->progress_cancellable, + (GFileProgressCallback)window_save_file_copy_progress_cb, + dst, + (GAsyncReadyCallback)window_save_file_copy_ready_cb, + dst); + ev_window->priv->progress_idle = + g_timeout_add_seconds_full (G_PRIORITY_DEFAULT, + 1, + (GSourceFunc)show_saving_progress, + dst, + NULL); } static void @@ -2207,14 +2564,32 @@ file_save_dialog_response_cb (GtkWidget *fc, EvWindow *ev_window) { gchar *uri; - + GFile *file, *parent; + if (response_id != GTK_RESPONSE_OK) { gtk_widget_destroy (fc); return; } - + uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (fc)); - + file = g_file_new_for_uri (uri); + parent = g_file_get_parent (file); + g_object_unref (file); + if (parent) { + gchar *folder_uri; + + folder_uri = g_file_get_uri (parent); + ev_application_set_filechooser_uri (EV_APP, + GTK_FILE_CHOOSER_ACTION_SAVE, + folder_uri); + g_free (folder_uri); + g_object_unref (parent); + } + + /* FIXME: remote copy should be done here rather than in the save job, + * so that we can track progress and cancel the operation + */ + ev_window_clear_save_job (ev_window); ev_window->priv->save_job = ev_job_save_new (ev_window->priv->document, uri, ev_window->priv->uri); @@ -2234,7 +2609,7 @@ ev_window_cmd_save_as (GtkAction *action, EvWindow *ev_window) GtkWidget *fc; gchar *base_name; GFile *file; - const gchar *folder; + const gchar *default_uri; fc = gtk_file_chooser_dialog_new ( _("Save a Copy"), @@ -2245,20 +2620,31 @@ ev_window_cmd_save_as (GtkAction *action, EvWindow *ev_window) ev_document_factory_add_filters (fc, ev_window->priv->document); gtk_dialog_set_default_response (GTK_DIALOG (fc), GTK_RESPONSE_OK); + gtk_dialog_set_alternative_button_order (GTK_DIALOG (fc), + GTK_RESPONSE_OK, + GTK_RESPONSE_CANCEL, + -1); gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (fc), FALSE); gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (fc), TRUE); file = g_file_new_for_uri (ev_window->priv->uri); base_name = g_file_get_basename (file); gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (fc), base_name); - - folder = g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS); - gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (fc), - folder ? folder : g_get_home_dir ()); - + + default_uri = ev_application_get_filechooser_uri (EV_APP, GTK_FILE_CHOOSER_ACTION_SAVE); + if (default_uri) { + gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (fc), default_uri); + } else { + const gchar *folder; + + folder = g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS); + gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (fc), + folder ? folder : g_get_home_dir ()); + } + g_object_unref (file); g_free (base_name); - + g_signal_connect (fc, "response", G_CALLBACK (file_save_dialog_response_cb), ev_window); @@ -2266,30 +2652,6 @@ ev_window_cmd_save_as (GtkAction *action, EvWindow *ev_window) gtk_widget_show (fc); } -static void -ev_window_print_page_setup_done_cb (GtkPageSetup *page_setup, - EvWindow *window) -{ - /* Dialog was canceled */ - if (!page_setup) - return; - - if (window->priv->print_page_setup) - g_object_unref (window->priv->print_page_setup); - window->priv->print_page_setup = g_object_ref (page_setup); -} - -static void -ev_window_cmd_file_print_setup (GtkAction *action, EvWindow *ev_window) -{ - gtk_print_run_page_setup_dialog_async ( - GTK_WINDOW (ev_window), - ev_window->priv->print_page_setup, - ev_window->priv->print_settings, - (GtkPageSetupDoneFunc) ev_window_print_page_setup_done_cb, - ev_window); -} - static void ev_window_load_print_settings_from_metadata (EvWindow *window) { @@ -2311,32 +2673,153 @@ ev_window_load_print_settings_from_metadata (EvWindow *window) } static void -ev_window_save_print_settings (EvWindow *window) +ev_window_save_print_settings (EvWindow *window) +{ + gchar *uri = window->priv->uri; + gint i; + + /* Save print settings that are specific to the document */ + for (i = 0; i < G_N_ELEMENTS (document_print_settings); i++) { + const gchar *value; + + value = gtk_print_settings_get (window->priv->print_settings, + document_print_settings[i]); + ev_metadata_manager_set_string (uri, document_print_settings[i], value); + } +} + +static void +ev_window_save_print_page_setup (EvWindow *window) +{ + gchar *uri = window->priv->uri; + GtkPageSetup *page_setup = window->priv->print_page_setup; + + /* Save page setup options that are specific to the document */ + ev_metadata_manager_set_int (uri, "page-setup-orientation", + gtk_page_setup_get_orientation (page_setup)); + ev_metadata_manager_set_double (uri, "page-setup-margin-top", + gtk_page_setup_get_top_margin (page_setup, GTK_UNIT_MM)); + ev_metadata_manager_set_double (uri, "page-setup-margin-bottom", + gtk_page_setup_get_bottom_margin (page_setup, GTK_UNIT_MM)); + ev_metadata_manager_set_double (uri, "page-setup-margin-left", + gtk_page_setup_get_left_margin (page_setup, GTK_UNIT_MM)); + ev_metadata_manager_set_double (uri, "page-setup-margin-right", + gtk_page_setup_get_right_margin (page_setup, GTK_UNIT_MM)); +} + +static void +ev_window_load_print_page_setup_from_metadata (EvWindow *window) +{ + gchar *uri = window->priv->uri; + GtkPageSetup *page_setup = window->priv->print_page_setup; + GtkPaperSize *paper_size; + GValue value = { 0, }; + + paper_size = gtk_page_setup_get_paper_size (page_setup); + + /* Load page setup options that are specific to the document */ + if (ev_metadata_manager_get (uri, "page-setup-orientation", &value, TRUE)) { + gtk_page_setup_set_orientation (page_setup, g_value_get_int (&value)); + g_value_unset (&value); + } else { + gtk_page_setup_set_orientation (page_setup, GTK_PAGE_ORIENTATION_PORTRAIT); + } + + if (ev_metadata_manager_get (uri, "page-setup-margin-top", &value, TRUE)) { + gtk_page_setup_set_top_margin (page_setup, g_value_get_double (&value), GTK_UNIT_MM); + g_value_unset (&value); + } else { + gtk_page_setup_set_top_margin (page_setup, + gtk_paper_size_get_default_top_margin (paper_size, GTK_UNIT_MM), + GTK_UNIT_MM); + } + + if (ev_metadata_manager_get (uri, "page-setup-margin-bottom", &value, TRUE)) { + gtk_page_setup_set_bottom_margin (page_setup, g_value_get_double (&value), GTK_UNIT_MM); + g_value_unset (&value); + } else { + gtk_page_setup_set_bottom_margin (page_setup, + gtk_paper_size_get_default_bottom_margin (paper_size, GTK_UNIT_MM), + GTK_UNIT_MM); + } + + if (ev_metadata_manager_get (uri, "page-setup-margin-left", &value, TRUE)) { + gtk_page_setup_set_left_margin (page_setup, g_value_get_double (&value), GTK_UNIT_MM); + g_value_unset (&value); + } else { + gtk_page_setup_set_left_margin (page_setup, + gtk_paper_size_get_default_left_margin (paper_size, GTK_UNIT_MM), + GTK_UNIT_MM); + } + + if (ev_metadata_manager_get (uri, "page-setup-margin-right", &value, TRUE)) { + gtk_page_setup_set_right_margin (page_setup, g_value_get_double (&value), GTK_UNIT_MM); + g_value_unset (&value); + } else { + gtk_page_setup_set_right_margin (page_setup, + gtk_paper_size_get_default_right_margin (paper_size, GTK_UNIT_MM), + GTK_UNIT_MM); + } +} + +static void +ev_window_print_page_setup_done_cb (GtkPageSetup *page_setup, + EvWindow *window) +{ + /* Dialog was canceled */ + if (!page_setup) + return; + + if (window->priv->print_page_setup != page_setup) { + if (window->priv->print_page_setup) + g_object_unref (window->priv->print_page_setup); + window->priv->print_page_setup = g_object_ref (page_setup); + } + + ev_application_set_page_setup (EV_APP, page_setup); + ev_window_save_print_page_setup (window); +} + +static void +ev_window_cmd_file_print_setup (GtkAction *action, EvWindow *ev_window) +{ + if (!ev_window->priv->print_page_setup) { + ev_window->priv->print_page_setup = gtk_page_setup_copy ( + ev_application_get_page_setup (EV_APP)); + ev_window_load_print_page_setup_from_metadata (ev_window); + } + + gtk_print_run_page_setup_dialog_async ( + GTK_WINDOW (ev_window), + ev_window->priv->print_page_setup, + ev_window->priv->print_settings, + (GtkPageSetupDoneFunc) ev_window_print_page_setup_done_cb, + ev_window); +} + +static void +ev_window_print_cancel (EvWindow *ev_window) { - gchar *uri = window->priv->uri; - gint i; + EvPrintOperation *op; - /* Save print settings that are specific to the document */ - for (i = 0; i < G_N_ELEMENTS (document_print_settings); i++) { - const gchar *value; + if (!ev_window->priv->print_queue) + return; - value = gtk_print_settings_get (window->priv->print_settings, - document_print_settings[i]); - ev_metadata_manager_set_string (uri, document_print_settings[i], value); + while ((op = g_queue_peek_tail (ev_window->priv->print_queue))) { + ev_print_operation_cancel (op); } } static void -ev_window_print_update_pending_jobs_message (EvWindow *ev_window) +ev_window_print_update_pending_jobs_message (EvWindow *ev_window, + gint n_jobs) { - gint n_jobs; gchar *text = NULL; if (!EV_IS_PROGRESS_MESSAGE_AREA (ev_window->priv->message_area) || !ev_window->priv->print_queue) return; - n_jobs = g_queue_get_length (ev_window->priv->print_queue); if (n_jobs == 0) { ev_window_set_message_area (ev_window, NULL); return; @@ -2353,11 +2836,21 @@ ev_window_print_update_pending_jobs_message (EvWindow *ev_window) g_free (text); } +static gboolean +destroy_window (GtkWidget *window) +{ + gtk_widget_destroy (window); + + return FALSE; +} + static void ev_window_print_operation_done (EvPrintOperation *op, GtkPrintOperationResult result, EvWindow *ev_window) { + gint n_jobs; + switch (result) { case GTK_PRINT_OPERATION_RESULT_APPLY: { GtkPrintSettings *print_settings; @@ -2407,7 +2900,12 @@ ev_window_print_operation_done (EvPrintOperation *op, g_queue_remove (ev_window->priv->print_queue, op); g_object_unref (op); - ev_window_print_update_pending_jobs_message (ev_window); + n_jobs = g_queue_get_length (ev_window->priv->print_queue); + ev_window_print_update_pending_jobs_message (ev_window, n_jobs); + + if (n_jobs == 0 && ev_window->priv->close_after_print) + g_idle_add ((GSourceFunc)destroy_window, + ev_window); } static void @@ -2450,7 +2948,7 @@ ev_window_print_operation_status_changed (EvPrintOperation *op, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL); - ev_window_print_update_pending_jobs_message (ev_window); + ev_window_print_update_pending_jobs_message (ev_window, 1); g_signal_connect (area, "response", G_CALLBACK (ev_window_print_progress_response_cb), ev_window); @@ -2475,7 +2973,8 @@ ev_window_print_operation_begin_print (EvPrintOperation *op, ev_window->priv->print_queue = g_queue_new (); g_queue_push_head (ev_window->priv->print_queue, op); - ev_window_print_update_pending_jobs_message (ev_window); + ev_window_print_update_pending_jobs_message (ev_window, + g_queue_get_length (ev_window->priv->print_queue)); if (ev_window->priv->print_settings) g_object_unref (ev_window->priv->print_settings); @@ -2500,19 +2999,24 @@ ev_window_print_range (EvWindow *ev_window, ev_window->priv->print_queue = g_queue_new (); op = ev_print_operation_new (ev_window->priv->document); - g_signal_connect (G_OBJECT (op), "begin_print", + if (!op) { + g_warning ("%s", "Printing is not supported for document\n"); + return; + } + + g_signal_connect (op, "begin_print", G_CALLBACK (ev_window_print_operation_begin_print), (gpointer)ev_window); - g_signal_connect (G_OBJECT (op), "status_changed", + g_signal_connect (op, "status_changed", G_CALLBACK (ev_window_print_operation_status_changed), (gpointer)ev_window); - g_signal_connect (G_OBJECT (op), "done", + g_signal_connect (op, "done", G_CALLBACK (ev_window_print_operation_done), (gpointer)ev_window); page_cache = ev_page_cache_get (ev_window->priv->document); current_page = ev_page_cache_get_current_page (page_cache); - document_last_page = ev_page_cache_get_n_pages (page_cache); + document_last_page = ev_document_get_n_pages (ev_window->priv->document); if (!ev_window->priv->print_settings) { ev_window->priv->print_settings = gtk_print_settings_copy ( @@ -2520,6 +3024,12 @@ ev_window_print_range (EvWindow *ev_window, ev_window_load_print_settings_from_metadata (ev_window); } + if (!ev_window->priv->print_page_setup) { + ev_window->priv->print_page_setup = gtk_page_setup_copy ( + ev_application_get_page_setup (EV_APP)); + ev_window_load_print_page_setup_from_metadata (ev_window); + } + if (first_page != 1 || last_page != document_last_page) { GtkPageRange range; @@ -2536,8 +3046,7 @@ ev_window_print_range (EvWindow *ev_window, ev_print_operation_set_job_name (op, gtk_window_get_title (GTK_WINDOW (ev_window))); ev_print_operation_set_current_page (op, current_page); ev_print_operation_set_print_settings (op, ev_window->priv->print_settings); - if (ev_window->priv->print_page_setup) - ev_print_operation_set_default_page_setup (op, ev_window->priv->print_page_setup); + ev_print_operation_set_default_page_setup (op, ev_window->priv->print_page_setup); ev_print_operation_run (op, GTK_WINDOW (ev_window)); } @@ -2545,13 +3054,8 @@ ev_window_print_range (EvWindow *ev_window, static void ev_window_print (EvWindow *window) { - EvPageCache *page_cache; - gint last_page; - - page_cache = ev_page_cache_get (window->priv->document); - last_page = ev_page_cache_get_n_pages (page_cache); - - ev_window_print_range (window, 1, last_page); + ev_window_print_range (window, 1, + ev_document_get_n_pages (window->priv->document)); } static void @@ -2578,13 +3082,102 @@ ev_window_cmd_file_properties (GtkAction *action, EvWindow *ev_window) gtk_widget_show (ev_window->priv->properties); ev_document_fc_mutex_unlock (); } - + +static void +print_jobs_confirmation_dialog_response (GtkDialog *dialog, + gint response, + EvWindow *ev_window) +{ + gtk_widget_destroy (GTK_WIDGET (dialog)); + + switch (response) { + case GTK_RESPONSE_YES: + if (!ev_window->priv->print_queue || + g_queue_is_empty (ev_window->priv->print_queue)) + gtk_widget_destroy (GTK_WIDGET (ev_window)); + else + ev_window->priv->close_after_print = TRUE; + break; + case GTK_RESPONSE_NO: + ev_window->priv->close_after_print = TRUE; + if (ev_window->priv->print_queue && + !g_queue_is_empty (ev_window->priv->print_queue)) { + gtk_widget_set_sensitive (GTK_WIDGET (ev_window), FALSE); + ev_window_print_cancel (ev_window); + } else { + gtk_widget_destroy (GTK_WIDGET (ev_window)); + } + break; + case GTK_RESPONSE_CANCEL: + default: + ev_window->priv->close_after_print = FALSE; + } +} + static void ev_window_cmd_file_close_window (GtkAction *action, EvWindow *ev_window) { - g_return_if_fail (EV_IS_WINDOW (ev_window)); + GtkWidget *dialog; + gchar *text, *markup; + gint n_print_jobs; + + n_print_jobs = ev_window->priv->print_queue ? + g_queue_get_length (ev_window->priv->print_queue) : 0; + + if (n_print_jobs == 0) { + gtk_widget_destroy (GTK_WIDGET (ev_window)); + return; + } + + dialog = gtk_message_dialog_new (GTK_WINDOW (ev_window), + GTK_DIALOG_MODAL, + GTK_MESSAGE_QUESTION, + GTK_BUTTONS_NONE, + NULL); + if (n_print_jobs == 1) { + EvPrintOperation *op; + const gchar *job_name; + + op = g_queue_peek_tail (ev_window->priv->print_queue); + job_name = ev_print_operation_get_job_name (op); + + text = g_strdup_printf (_("Wait until print job “%s” finishes before closing?"), + job_name); + } else { + text = g_strdup_printf (_("There are %d print jobs active. " + "Wait until print finishes before closing?"), + n_print_jobs); + } - gtk_widget_destroy (GTK_WIDGET (ev_window)); + markup = g_strdup_printf ("%s", text); + g_free (text); + + gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog), markup); + g_free (markup); + + gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", + _("If you close the window, pending print " + "jobs will not be printed.")); + + gtk_dialog_add_buttons (GTK_DIALOG (dialog), + _("Cancel _print and Close"), + GTK_RESPONSE_NO, + GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL, + _("Close _after Printing"), + GTK_RESPONSE_YES, + NULL); + gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_YES); + gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog), + GTK_RESPONSE_YES, + GTK_RESPONSE_NO, + GTK_RESPONSE_CANCEL, + -1); + + g_signal_connect (dialog, "response", + G_CALLBACK (print_jobs_confirmation_dialog_response), + ev_window); + gtk_widget_show (dialog); } static void @@ -3037,35 +3630,32 @@ ev_window_cmd_view_presentation (GtkAction *action, EvWindow *window) } static void -ev_window_run_preview (EvWindow *window) +ev_window_setup_gtk_settings (EvWindow *window) { - GtkAction *action; - - if (!window->priv->preview_toolbar) { - window->priv->preview_toolbar = - gtk_ui_manager_get_widget (window->priv->ui_manager, - "/PreviewToolbar"); + GtkSettings *settings; + GdkScreen *screen; + gchar *menubar_accel_accel; - gtk_box_pack_start (GTK_BOX (window->priv->main_box), - window->priv->preview_toolbar, - FALSE, FALSE, 0); - gtk_box_reorder_child (GTK_BOX (window->priv->main_box), - window->priv->preview_toolbar, 1); - } - - ev_view_set_continuous (EV_VIEW (window->priv->view), FALSE); - - update_chrome_flag (window, EV_CHROME_TOOLBAR, FALSE); - update_chrome_flag (window, EV_CHROME_MENUBAR, FALSE); - update_chrome_flag (window, EV_CHROME_SIDEBAR, FALSE); + screen = gtk_window_get_screen (GTK_WINDOW (window)); + settings = gtk_settings_get_for_screen (screen); - update_chrome_flag (window, EV_CHROME_PREVIEW_TOOLBAR, TRUE); - - action = gtk_action_group_get_action (window->priv->action_group, - "PreviewPrint"); - gtk_action_set_visible (action, TRUE); + g_object_get (settings, + "gtk-menu-bar-accel", &menubar_accel_accel, + NULL); + if (menubar_accel_accel != NULL && menubar_accel_accel[0] != '\0') { + gtk_accelerator_parse (menubar_accel_accel, + &window->priv->menubar_accel_keyval, + &window->priv->menubar_accel_modifier); + if (window->priv->menubar_accel_keyval == 0) { + g_warning ("Failed to parse menu bar accelerator '%s'\n", + menubar_accel_accel); + } + } else { + window->priv->menubar_accel_keyval = 0; + window->priv->menubar_accel_modifier = 0; + } - update_chrome_visibility (window); + g_free (menubar_accel_accel); } static void @@ -3080,6 +3670,7 @@ ev_window_screen_changed (GtkWidget *widget, if (screen == old_screen) return; + ev_window_setup_gtk_settings (window); ev_view_set_screen_dpi (EV_VIEW (priv->view), get_screen_dpi (GTK_WINDOW (window))); @@ -3252,12 +3843,10 @@ ev_window_cmd_go_first_page (GtkAction *action, EvWindow *ev_window) static void ev_window_cmd_go_last_page (GtkAction *action, EvWindow *ev_window) { - int n_pages; - g_return_if_fail (EV_IS_WINDOW (ev_window)); - n_pages = ev_page_cache_get_n_pages (ev_window->priv->page_cache); - ev_page_cache_set_current_page (ev_window->priv->page_cache, n_pages - 1); + ev_page_cache_set_current_page (ev_window->priv->page_cache, + ev_document_get_n_pages (ev_window->priv->document) - 1); } static void @@ -3267,7 +3856,7 @@ ev_window_cmd_go_forward (GtkAction *action, EvWindow *ev_window) g_return_if_fail (EV_IS_WINDOW (ev_window)); - n_pages = ev_page_cache_get_n_pages (ev_window->priv->page_cache); + n_pages = ev_document_get_n_pages (ev_window->priv->document); current_page = ev_page_cache_get_current_page (ev_window->priv->page_cache); if (current_page + 10 < n_pages) @@ -3290,7 +3879,7 @@ ev_window_cmd_go_backward (GtkAction *action, EvWindow *ev_window) static void ev_window_cmd_view_reload (GtkAction *action, EvWindow *ev_window) { - ev_window_reload_document (ev_window); + ev_window_reload_document (ev_window, NULL); } static void @@ -3299,7 +3888,6 @@ ev_window_cmd_view_autoscroll (GtkAction *action, EvWindow *ev_window) ev_view_autoscroll_start (EV_VIEW (ev_window->priv->view)); } -#if GTK_CHECK_VERSION (2, 14, 0) static void ev_window_cmd_help_contents (GtkAction *action, EvWindow *ev_window) { @@ -3315,56 +3903,6 @@ ev_window_cmd_help_contents (GtkAction *action, EvWindow *ev_window) g_error_free (error); } } -#else /* !GTK_CHECK_VERSION (2, 14, 0) */ -static void -ev_window_cmd_help_contents (GtkAction *action, EvWindow *ev_window) -{ - GError *error = NULL; - GdkScreen *screen; - char *command; - const char *lang; - char *uri = NULL; - - int i; - - const char * const * langs = g_get_language_names (); - - for (i = 0; langs[i]; i++) { - lang = langs[i]; - if (strchr (lang, '.')) { - continue; - } - - uri = g_build_filename(GNOMEDATADIR, - "/gnome/help/" PACKAGE, - lang, - "/evince.xml", - NULL); - - if (g_file_test (uri, G_FILE_TEST_EXISTS)) { - break; - } - g_free (uri); - uri = NULL; - } - - if (uri == NULL) { - g_warning ("Cannot find help"); - return; - } - - command = g_strconcat ("gnome-help ghelp://", uri, NULL); - g_free (uri); - - screen = gtk_widget_get_screen (GTK_WIDGET (ev_window)); - gdk_spawn_command_line_on_screen (screen, command, &error); - if (error != NULL) { - g_warning ("%s", error->message); - g_error_free (error); - } - g_free (command); -} -#endif /* GTK_CHECK_VERSION (2, 14, 0) */ static void ev_window_cmd_leave_fullscreen (GtkAction *action, EvWindow *window) @@ -3378,120 +3916,6 @@ ev_window_cmd_start_presentation (GtkAction *action, EvWindow *window) ev_window_run_presentation (window); } -static gboolean -ev_window_enumerate_printer_cb (GtkPrinter *printer, - EvWindow *window) -{ - EvWindowPrivate *priv = window->priv; - const gchar *printer_name; - - printer_name = gtk_print_settings_get_printer (priv->print_settings); - if ((printer_name - && strcmp (printer_name, gtk_printer_get_name (printer)) == 0) || - (!printer_name && gtk_printer_is_default (printer))) { - if (priv->printer) - g_object_unref (priv->printer); - priv->printer = g_object_ref (printer); - - /* Now that we have the printer, we'll start the print */ - ev_window_do_preview_print (window); - - return TRUE; /* we're done */ - } - - return FALSE; /* continue the enumeration */ -} - -static void -ev_window_preview_print_finished (GtkPrintJob *print_job, - EvWindow *window, - GError *error) -{ - if (error) { - ev_window_error_message (window, error, - "%s", _("Failed to print document")); - } - - g_object_unref (print_job); - gtk_widget_destroy (GTK_WIDGET (window)); -} - -static void -ev_window_do_preview_print (EvWindow *window) -{ - EvWindowPrivate *priv = window->priv; - GtkPageSetup *page_setup; - GtkPrintJob *job; - gchar *filename; - GError *error = NULL; - - g_assert (priv->print_settings != NULL); - g_assert (priv->printer != NULL); - - page_setup = gtk_page_setup_new (); - - job = gtk_print_job_new (gtk_window_get_title (GTK_WINDOW (window)), - priv->printer, - priv->print_settings, - page_setup); - - g_object_unref (priv->print_settings); - priv->print_settings = NULL; - g_object_unref (priv->printer); - priv->printer = NULL; - g_object_unref (page_setup); - - filename = g_filename_from_uri (priv->local_uri ? - priv->local_uri : priv->uri, - NULL, NULL); - - if (gtk_print_job_set_source_file (job, filename, &error)) { - gtk_print_job_send (job, - (GtkPrintJobCompleteFunc)ev_window_preview_print_finished, - window, NULL); - } else { - g_warning ("%s", error->message); - g_error_free (error); - } - - g_free (filename); - - gtk_widget_hide (GTK_WIDGET (window)); -} - -static void -ev_window_cmd_preview_print (GtkAction *action, EvWindow *window) -{ - EvWindowPrivate *priv = window->priv; - GtkPrintSettings *print_settings = NULL; - const gchar *print_settings_file = priv->print_settings_file; - - if (print_settings_file) { - if (g_file_test (print_settings_file, G_FILE_TEST_IS_REGULAR)) { - GError *error = NULL; - - print_settings = gtk_print_settings_new_from_file (print_settings_file, - &error); - - if (error) { - g_warning ("%s", error->message); - g_error_free (error); - print_settings = NULL; - } - } - } - - if (!print_settings) - print_settings = gtk_print_settings_new (); - - if (priv->print_settings) - g_object_unref (priv->print_settings); - priv->print_settings = print_settings; - - gtk_enumerate_printers ((GtkPrinterFunc) ev_window_enumerate_printer_cb, - window, NULL, FALSE); -} - static void ev_window_cmd_escape (GtkAction *action, EvWindow *window) { @@ -3534,58 +3958,66 @@ save_sizing_mode (EvWindow *window) GEnumValue *enum_value; mode = ev_view_get_sizing_mode (EV_VIEW (window->priv->view)); - enum_value = g_enum_get_value (EV_SIZING_MODE_CLASS, mode); + enum_value = g_enum_get_value (g_type_class_peek (EV_TYPE_SIZING_MODE), mode); if (!ev_window_is_empty (window)) ev_metadata_manager_set_string (window->priv->uri, "sizing_mode", enum_value->value_nick); } +static void +ev_window_set_view_size (EvWindow *window) +{ + gint width, height; + GtkRequisition vsb_requisition; + GtkRequisition hsb_requisition; + gint scrollbar_spacing; + GtkWidget *scrolled_window = window->priv->scrolled_window; + + if (!window->priv->view) + return; + + /* Calculate the width available for the content */ + width = scrolled_window->allocation.width; + height = scrolled_window->allocation.height; + + if (gtk_scrolled_window_get_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window)) == GTK_SHADOW_IN) { + width -= 2 * window->priv->view->style->xthickness; + height -= 2 * window->priv->view->style->ythickness; + } + + gtk_widget_size_request (GTK_SCROLLED_WINDOW (scrolled_window)->vscrollbar, + &vsb_requisition); + gtk_widget_size_request (GTK_SCROLLED_WINDOW (scrolled_window)->hscrollbar, + &hsb_requisition); + gtk_widget_style_get (scrolled_window, + "scrollbar_spacing", + &scrollbar_spacing, + NULL); + + ev_view_set_zoom_for_size (EV_VIEW (window->priv->view), + MAX (1, width), + MAX (1, height), + vsb_requisition.width + scrollbar_spacing, + hsb_requisition.height + scrollbar_spacing); +} + static void ev_window_sizing_mode_changed_cb (EvView *view, GParamSpec *pspec, EvWindow *ev_window) { - GtkWidget *scrolled_window; EvSizingMode sizing_mode; g_object_get (ev_window->priv->view, "sizing-mode", &sizing_mode, NULL); - scrolled_window = ev_window->priv->scrolled_window; - - g_signal_handlers_disconnect_by_func (ev_window->priv->view, ev_view_update_view_size, scrolled_window); - - if (sizing_mode != EV_SIZING_FREE) - ev_view_update_view_size (EV_VIEW (ev_window->priv->view), - GTK_SCROLLED_WINDOW (scrolled_window)); - - switch (sizing_mode) { - case EV_SIZING_BEST_FIT: - g_object_set (G_OBJECT (scrolled_window), - "hscrollbar-policy", GTK_POLICY_NEVER, - "vscrollbar-policy", GTK_POLICY_AUTOMATIC, - NULL); - g_signal_connect (ev_window->priv->view, "zoom_invalid", - G_CALLBACK (ev_view_update_view_size), - scrolled_window); - break; - case EV_SIZING_FIT_WIDTH: - g_object_set (G_OBJECT (scrolled_window), - "hscrollbar-policy", GTK_POLICY_NEVER, - "vscrollbar-policy", GTK_POLICY_AUTOMATIC, - NULL); - g_signal_connect (ev_window->priv->view, "zoom_invalid", - G_CALLBACK (ev_view_update_view_size), - scrolled_window); - break; - case EV_SIZING_FREE: - g_object_set (G_OBJECT (scrolled_window), - "hscrollbar-policy", GTK_POLICY_AUTOMATIC, - "vscrollbar-policy", GTK_POLICY_AUTOMATIC, - NULL); - break; - } + g_object_set (ev_window->priv->scrolled_window, + "hscrollbar-policy", + sizing_mode == EV_SIZING_FREE ? + GTK_POLICY_AUTOMATIC : GTK_POLICY_NEVER, + "vscrollbar-policy", GTK_POLICY_AUTOMATIC, + NULL); update_sizing_buttons (ev_window); save_sizing_mode (ev_window); @@ -3716,6 +4148,7 @@ ev_window_cmd_help_about (GtkAction *action, EvWindow *ev_window) "Bryan Clark ", "Carlos Garcia Campos ", "Wouter Bolsterlee ", + "Christian Persch ", NULL }; @@ -3760,7 +4193,7 @@ ev_window_cmd_help_about (GtkAction *action, EvWindow *ev_window) "name", _("Evince"), "version", VERSION, "copyright", - _("\xc2\xa9 1996-2007 The Evince authors"), + _("© 1996–2009 The Evince authors"), "license", license_trans, "website", "http://www.gnome.org/projects/evince", "comments", comments, @@ -4084,7 +4517,7 @@ find_bar_search_changed_cb (EggFindBar *find_bar, if (search_string && search_string[0]) { ev_window->priv->find_job = ev_job_find_new (ev_window->priv->document, ev_page_cache_get_current_page (ev_window->priv->page_cache), - ev_page_cache_get_n_pages (ev_window->priv->page_cache), + ev_document_get_n_pages (ev_window->priv->document), search_string, case_sensitive); g_signal_connect (ev_window->priv->find_job, "finished", @@ -4148,7 +4581,7 @@ zoom_control_changed_cb (EphyZoomAction *action, } else { mode = EV_SIZING_FREE; } - + ev_view_set_sizing_mode (EV_VIEW (ev_window->priv->view), mode); if (mode == EV_SIZING_FREE) { @@ -4158,6 +4591,47 @@ zoom_control_changed_cb (EphyZoomAction *action, } } +static void +ev_window_drag_data_received (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *selection_data, + guint info, + guint time) + +{ + EvWindow *window = EV_WINDOW (widget); + gchar **uris; + gint i = 0; + GSList *uri_list = NULL; + GtkWidget *source; + + source = gtk_drag_get_source_widget (context); + if (source && widget == gtk_widget_get_toplevel (source)) { + gtk_drag_finish (context, FALSE, FALSE, time); + return; + } + + uris = gtk_selection_data_get_uris (selection_data); + if (!uris) { + gtk_drag_finish (context, FALSE, FALSE, time); + return; + } + + for (i = 0; uris[i]; i++) { + uri_list = g_slist_prepend (uri_list, (gpointer) uris[i]); + } + + ev_application_open_uri_list (EV_APP, uri_list, + gtk_window_get_screen (GTK_WINDOW (window)), + 0); + gtk_drag_finish (context, TRUE, FALSE, time); + + g_strfreev (uris); + g_slist_free (uri_list); +} + static void ev_window_finalize (GObject *object) { @@ -4279,12 +4753,13 @@ ev_window_dispose (GObject *object) priv->local_uri = NULL; } - ev_window_close_dialogs (window); - - if (window->priv->printer) { - g_object_unref (window->priv->printer); - window->priv->printer = NULL; + ev_window_clear_progress_idle (window); + if (priv->progress_cancellable) { + g_object_unref (priv->progress_cancellable); + priv->progress_cancellable = NULL; } + + ev_window_close_dialogs (window); if (window->priv->print_settings) { g_object_unref (window->priv->print_settings); @@ -4323,12 +4798,17 @@ ev_window_dispose (GObject *object) } if (priv->uri) { - if (priv->unlink_temp_file) - ev_window_clear_temp_file (window); + /* Delete the uri if it's a temp symlink (open a copy) */ + ev_window_clear_temp_symlink (window); g_free (priv->uri); priv->uri = NULL; } + if (priv->search_string) { + g_free (priv->search_string); + priv->search_string = NULL; + } + if (priv->dest) { g_object_unref (priv->dest); priv->dest = NULL; @@ -4339,11 +4819,6 @@ ev_window_dispose (GObject *object) priv->history = NULL; } - if (priv->print_settings_file) { - ev_window_clear_print_settings_file (window); - priv->print_settings_file = NULL; - } - if (priv->presentation_timeout_id > 0) { g_source_remove (priv->presentation_timeout_id); priv->presentation_timeout_id = 0; @@ -4357,6 +4832,64 @@ ev_window_dispose (GObject *object) G_OBJECT_CLASS (ev_window_parent_class)->dispose (object); } +static void +menubar_deactivate_cb (GtkWidget *menubar, + EvWindow *window) +{ + g_signal_handlers_disconnect_by_func (menubar, + G_CALLBACK (menubar_deactivate_cb), + window); + + gtk_menu_shell_deselect (GTK_MENU_SHELL (menubar)); + + update_chrome_visibility (window); +} + +static gboolean +ev_window_key_press_event (GtkWidget *widget, + GdkEventKey *event) +{ + EvWindow *ev_window = EV_WINDOW (widget); + EvWindowPrivate *priv = ev_window->priv; + gboolean handled = FALSE; + + /* Propagate the event to the view first + * It's needed to be able to type in + * annot popups windows + */ + if (priv->view) { + g_object_ref (priv->view); + if (GTK_WIDGET_IS_SENSITIVE (priv->view)) + handled = gtk_widget_event (priv->view, (GdkEvent*) event); + g_object_unref (priv->view); + } + + if (!handled && !ev_view_get_presentation (EV_VIEW (priv->view))) { + guint modifier = event->state & gtk_accelerator_get_default_mod_mask (); + + if (priv->menubar_accel_keyval != 0 && + event->keyval == priv->menubar_accel_keyval && + modifier == priv->menubar_accel_modifier) { + if (!GTK_WIDGET_VISIBLE (priv->menubar)) { + g_signal_connect (priv->menubar, "deactivate", + G_CALLBACK (menubar_deactivate_cb), + ev_window); + + gtk_widget_show (priv->menubar); + gtk_menu_shell_select_first (GTK_MENU_SHELL (priv->menubar), + FALSE); + + handled = TRUE; + } + } + } + + if (!handled) + handled = GTK_WIDGET_CLASS (ev_window_parent_class)->key_press_event (widget, event); + + return handled; +} + static void ev_window_class_init (EvWindowClass *ev_window_class) { @@ -4366,8 +4899,10 @@ ev_window_class_init (EvWindowClass *ev_window_class) g_object_class->dispose = ev_window_dispose; g_object_class->finalize = ev_window_finalize; + widget_class->key_press_event = ev_window_key_press_event; widget_class->screen_changed = ev_window_screen_changed; widget_class->window_state_event = ev_window_state_event; + widget_class->drag_data_received = ev_window_drag_data_received; g_type_class_add_private (g_object_class, sizeof (EvWindowPrivate)); } @@ -4390,7 +4925,7 @@ static const GtkActionEntry entries[] = { { "FileSaveAs", GTK_STOCK_SAVE_AS, N_("_Save a Copy..."), "S", N_("Save a copy of the current document"), G_CALLBACK (ev_window_cmd_save_as) }, - { "FilePrintSetup", NULL, N_("Print Set_up..."), NULL, + { "FilePageSetup", GTK_STOCK_PAGE_SETUP, N_("Page Set_up..."), NULL, N_("Setup the page settings for printing"), G_CALLBACK (ev_window_cmd_file_print_setup) }, { "FilePrint", GTK_STOCK_PRINT, N_("_Print..."), "P", @@ -4415,9 +4950,9 @@ static const GtkActionEntry entries[] = { G_CALLBACK (ev_window_cmd_edit_find_previous) }, { "EditToolbar", NULL, N_("T_oolbar"), NULL, NULL, G_CALLBACK (ev_window_cmd_edit_toolbar) }, - { "EditRotateLeft", EV_STOCK_ROTATE_LEFT, N_("Rotate _Left"), "Left", NULL, + { "EditRotateLeft", EV_STOCK_ROTATE_LEFT, N_("Rotate _Left"), "Left", NULL, G_CALLBACK (ev_window_cmd_edit_rotate_left) }, - { "EditRotateRight", EV_STOCK_ROTATE_RIGHT, N_("Rotate _Right"), "Right", NULL, + { "EditRotateRight", EV_STOCK_ROTATE_RIGHT, N_("Rotate _Right"), "Right", NULL, G_CALLBACK (ev_window_cmd_edit_rotate_right) }, /* View menu */ @@ -4462,15 +4997,14 @@ static const GtkActionEntry entries[] = { { "StartPresentation", EV_STOCK_RUN_PRESENTATION, N_("Start Presentation"), NULL, N_("Start a presentation"), G_CALLBACK (ev_window_cmd_start_presentation) }, - { "PreviewPrint", GTK_STOCK_PRINT, N_("Print"), NULL, - N_("Print this document"), - G_CALLBACK (ev_window_cmd_preview_print) }, /* Accellerators */ { "Escape", NULL, "", "Escape", "", G_CALLBACK (ev_window_cmd_escape) }, { "Slash", GTK_STOCK_FIND, NULL, "slash", NULL, G_CALLBACK (ev_window_cmd_edit_find) }, + { "F3", NULL, "", "F3", NULL, + G_CALLBACK (ev_window_cmd_edit_find_next) }, { "PageDown", NULL, "", "Page_Down", NULL, G_CALLBACK (ev_window_cmd_scroll_forward) }, { "PageUp", NULL, "", "Page_Up", NULL, @@ -4787,30 +5321,23 @@ window_configure_event_cb (EvWindow *window, GdkEventConfigure *event, gpointer { char *uri = window->priv->uri; GdkWindowState state; - int x, y, width, height, document_width, document_height; + gdouble document_width, document_height; state = gdk_window_get_state (GTK_WIDGET (window)->window); if (!(state & GDK_WINDOW_STATE_FULLSCREEN)) { - gtk_window_get_position (GTK_WINDOW (window), &x, &y); - gtk_window_get_size (GTK_WINDOW (window), &width, &height); - - if (!ev_window_is_empty (window) && window->priv->page_cache) { - ev_page_cache_get_max_width (window->priv->page_cache, - 0, 1.0, - &document_width); - ev_page_cache_get_max_height (window->priv->page_cache, - 0, 1.0, - &document_height); - ev_metadata_manager_set_double (uri, "window_width_ratio", - (double)width / document_width); - ev_metadata_manager_set_double (uri, "window_height_ratio", - (double)height / document_height); - - ev_metadata_manager_set_int (uri, "window_x", x); - ev_metadata_manager_set_int (uri, "window_y", y); - ev_metadata_manager_set_int (uri, "window_width", width); - ev_metadata_manager_set_int (uri, "window_height", height); + if (!ev_window_is_empty (window) && window->priv->document) { + ev_document_get_max_page_size (window->priv->document, + &document_width, &document_height); + ev_metadata_manager_set_double (uri, "window_width_ratio", + (double)event->width / document_width); + ev_metadata_manager_set_double (uri, "window_height_ratio", + (double)event->height / document_height); + + ev_metadata_manager_set_int (uri, "window_x", event->x); + ev_metadata_manager_set_int (uri, "window_y", event->y); + ev_metadata_manager_set_int (uri, "window_width", event->width); + ev_metadata_manager_set_int (uri, "window_height", event->height); } } @@ -4824,7 +5351,7 @@ launch_action (EvWindow *window, EvLinkAction *action) GAppInfo *app_info; GFile *file; GList file_list = {NULL}; - GAppLaunchContext *context = NULL; + GAppLaunchContext *context; GError *error = NULL; if (filename == NULL) @@ -4855,12 +5382,10 @@ launch_action (EvWindow *window, EvLinkAction *action) return; } -#if GTK_CHECK_VERSION (2, 14, 0) context = G_APP_LAUNCH_CONTEXT (gdk_app_launch_context_new ()); gdk_app_launch_context_set_screen (GDK_APP_LAUNCH_CONTEXT (context), gtk_window_get_screen (GTK_WINDOW (window))); gdk_app_launch_context_set_timestamp (GDK_APP_LAUNCH_CONTEXT (context), GDK_CURRENT_TIME); -#endif file_list.data = file; if (!g_app_info_launch (app_info, &file_list, context, &error)) { @@ -4883,17 +5408,13 @@ launch_external_uri (EvWindow *window, EvLinkAction *action) const gchar *uri = ev_link_action_get_uri (action); GError *error = NULL; gboolean ret; -#if GTK_CHECK_VERSION (2, 14, 0) - GAppLaunchContext *context = NULL; -#endif + GAppLaunchContext *context; -#if GTK_CHECK_VERSION (2, 14, 0) context = G_APP_LAUNCH_CONTEXT (gdk_app_launch_context_new ()); gdk_app_launch_context_set_screen (GDK_APP_LAUNCH_CONTEXT (context), gtk_window_get_screen (GTK_WINDOW (window))); gdk_app_launch_context_set_timestamp (GDK_APP_LAUNCH_CONTEXT (context), GDK_CURRENT_TIME); -#endif if (!g_strstr_len (uri, strlen (uri), "://") && !g_str_has_prefix (uri, "mailto:")) { @@ -4931,8 +5452,6 @@ open_remote_link (EvWindow *window, EvLinkAction *action) ev_link_action_get_dest (action), 0, NULL, - FALSE, - NULL, GDK_CURRENT_TIME); g_free (uri); @@ -4957,6 +5476,8 @@ do_action_named (EvWindow *window, EvLinkAction *action) ev_window_cmd_edit_find (NULL, window); } else if (g_ascii_strcasecmp (name, "Close") == 0) { ev_window_cmd_file_close_window (NULL, window); + } else if (g_ascii_strcasecmp (name, "Print") == 0) { + ev_window_cmd_file_print (NULL, window); } else { g_warning ("Unimplemented named action: %s, please post a " "bug report in Evince bugzilla " @@ -5062,6 +5583,15 @@ image_save_dialog_response_cb (GtkWidget *fc, format = get_gdk_pixbuf_format_by_extension (uri); } + if (format == NULL && g_strrstr (uri, ".") == NULL) { + /* no extension found and no extension provided within uri */ + format = get_gdk_pixbuf_format_by_extension (".png"); + if (format == NULL) { + /* no .png support, try .jpeg */ + format = get_gdk_pixbuf_format_by_extension (".jpeg"); + } + } + if (format == NULL) { ev_window_error_message (ev_window, NULL, "%s", @@ -5116,9 +5646,10 @@ image_save_dialog_response_cb (GtkWidget *fc, if (!is_native) { GFile *source_file; - source_file = g_file_new_for_uri (filename); + source_file = g_file_new_for_path (filename); - ev_window_save_remote (ev_window, source_file, target_file); + ev_window_save_remote (ev_window, EV_SAVE_IMAGE, + source_file, target_file); g_object_unref (source_file); } @@ -5144,6 +5675,11 @@ ev_view_popup_cmd_save_image_as (GtkAction *action, EvWindow *window) NULL); gtk_dialog_set_default_response (GTK_DIALOG (fc), GTK_RESPONSE_OK); + gtk_dialog_set_alternative_button_order (GTK_DIALOG (fc), + GTK_RESPONSE_OK, + GTK_RESPONSE_CANCEL, + -1); + gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (fc), FALSE); gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (fc), TRUE); @@ -5265,7 +5801,8 @@ attachment_save_dialog_response_cb (GtkWidget *fc, dest_file = g_object_ref (target_file); } - ev_window_save_remote (ev_window, save_to, dest_file); + ev_window_save_remote (ev_window, EV_SAVE_ATTACHMENT, + save_to, dest_file); g_object_unref (dest_file); } @@ -5301,6 +5838,11 @@ ev_attachment_popup_cmd_save_attachment_as (GtkAction *action, EvWindow *window) NULL); gtk_dialog_set_default_response (GTK_DIALOG (fc), GTK_RESPONSE_OK); + gtk_dialog_set_alternative_button_order (GTK_DIALOG (fc), + GTK_RESPONSE_OK, + GTK_RESPONSE_CANCEL, + -1); + gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (fc), TRUE); gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (fc), FALSE); @@ -5352,6 +5894,7 @@ ev_window_init (EvWindow *ev_window) GError *error = NULL; GtkWidget *sidebar_widget; GObject *mpkeys; + gchar *ui_path; g_signal_connect (ev_window, "configure_event", G_CALLBACK (window_configure_event_cb), NULL); @@ -5406,12 +5949,15 @@ ev_window_init (EvWindow *ev_window) gtk_ui_manager_insert_action_group (ev_window->priv->ui_manager, action_group, 0); - if (!gtk_ui_manager_add_ui_from_file (ev_window->priv->ui_manager, - DATADIR"/evince-ui.xml", - &error)) { + ui_path = g_build_filename (ev_application_get_data_dir (EV_APP), + "evince-ui.xml", NULL); + if (!gtk_ui_manager_add_ui_from_file ( + ev_window->priv->ui_manager, ui_path, &error)) + { g_warning ("building menus failed: %s", error->message); g_error_free (error); } + g_free (ui_path); ev_window->priv->recent_manager = gtk_recent_manager_get_default (); ev_window->priv->recent_action_group = NULL; @@ -5541,7 +6087,9 @@ ev_window_init (EvWindow *ev_window) g_signal_connect_object (ev_window->priv->view, "handle-link", G_CALLBACK (view_handle_link_cb), ev_window, 0); - + g_signal_connect_swapped (ev_window->priv->view, "zoom_invalid", + G_CALLBACK (ev_window_set_view_size), + ev_window); g_signal_connect_object (ev_window->priv->view, "popup", G_CALLBACK (view_menu_popup_cb), @@ -5643,13 +6191,15 @@ ev_window_init (EvWindow *ev_window) G_CALLBACK (ev_window_media_player_key_pressed), ev_window); } - + /* Give focus to the document view */ gtk_widget_grab_focus (ev_window->priv->view); /* Set it user interface params */ ev_window_setup_recent (ev_window); + ev_window_setup_gtk_settings (ev_window); + setup_chrome_from_metadata (ev_window); set_chrome_actions (ev_window); update_chrome_visibility (ev_window); @@ -5657,10 +6207,17 @@ ev_window_init (EvWindow *ev_window) gtk_window_set_default_size (GTK_WINDOW (ev_window), 600, 600); setup_view_from_metadata (ev_window); - setup_sidebar_from_metadata (ev_window, NULL); + setup_sidebar_from_metadata (ev_window); ev_window_sizing_mode_changed_cb (EV_VIEW (ev_window->priv->view), NULL, ev_window); ev_window_setup_action_sensitivity (ev_window); + + /* Drag and Drop */ + gtk_drag_dest_set (GTK_WIDGET (ev_window), + GTK_DEST_DEFAULT_ALL, + NULL, 0, + GDK_ACTION_COPY); + gtk_drag_dest_add_uri_targets (GTK_WIDGET (ev_window)); } /**