]> www.fi.muni.cz Git - evince.git/blobdiff - shell/ev-window.c
Implement "split" effect.
[evince.git] / shell / ev-window.c
index 96200fce702d20a7cca4ba83ce054fde43b93952..a9d7bdc063777277d585383881c6cdd02c227560 100644 (file)
@@ -32,6 +32,7 @@
 #include "ev-window-title.h"
 #include "ev-navigation-action.h"
 #include "ev-page-action.h"
+#include "ev-open-recent-action.h"
 #include "ev-sidebar.h"
 #include "ev-sidebar-links.h"
 #include "ev-sidebar-attachments.h"
 #include <string.h>
 #include <unistd.h>
 
+#include "ev-message-area.h"
+
+#include "eggfileformatchooser.h"
+
 #if !GLIB_CHECK_VERSION (2, 13, 3)
 char *xdg_user_dir_lookup (char *type);
 #endif
@@ -118,10 +123,12 @@ struct _EvWindowPrivate {
        GtkWidget *menubar;
        GtkWidget *toolbar;
        GtkWidget *hpaned;
+       GtkWidget *view_box;
        GtkWidget *sidebar;
        GtkWidget *find_bar;
        GtkWidget *scrolled_window;
        GtkWidget *view;
+       GtkWidget *message_area;
        GtkWidget *password_view;
        GtkWidget *sidebar_thumbs;
        GtkWidget *sidebar_links;
@@ -210,6 +217,19 @@ struct _EvWindowPrivate {
 #define THUMBNAILS_SIDEBAR_ID "thumbnails"
 #define ATTACHMENTS_SIDEBAR_ID "attachments"
 
+#ifdef WITH_GTK_PRINT
+static const gchar *document_print_settings[] = {
+       GTK_PRINT_SETTINGS_N_COPIES,
+       GTK_PRINT_SETTINGS_COLLATE,
+       GTK_PRINT_SETTINGS_REVERSE,
+       GTK_PRINT_SETTINGS_NUMBER_UP,
+       GTK_PRINT_SETTINGS_SCALE,
+       GTK_PRINT_SETTINGS_PRINT_PAGES,
+       GTK_PRINT_SETTINGS_PAGE_RANGES,
+       GTK_PRINT_SETTINGS_PAGE_SET
+};
+#endif /* WITH_GTK_PRINT */
+
 static void    ev_window_update_actions                (EvWindow         *ev_window);
 static void     ev_window_sidebar_visibility_changed_cb (EvSidebar        *ev_sidebar,
                                                         GParamSpec       *pspec,
@@ -264,6 +284,8 @@ static void ev_window_cmd_view_page_width           (GtkAction        *action,
 static void    view_handle_link_cb                     (EvView           *view, 
                                                         EvLink           *link, 
                                                         EvWindow         *window);
+static void     ev_window_cmd_edit_find                 (GtkAction        *action,
+                                                        EvWindow         *ev_window);
 static void     find_bar_search_changed_cb              (EggFindBar       *find_bar,
                                                         GParamSpec       *param,
                                                         EvWindow         *ev_window);
@@ -373,6 +395,7 @@ ev_window_setup_action_sensitivity (EvWindow *ev_window)
        ev_window_set_action_sensitive (ev_window, "ViewBestFit", has_pages);
        ev_window_set_action_sensitive (ev_window, "ViewPageWidth", has_pages);
        ev_window_set_action_sensitive (ev_window, "ViewReload", has_pages);
+       ev_window_set_action_sensitive (ev_window, "ViewAutoscroll", has_pages);
 
        /* Toolbar-specific actions: */
        ev_window_set_action_sensitive (ev_window, PAGE_SELECTOR_ACTION, has_pages);
@@ -608,29 +631,55 @@ ev_window_is_empty (const EvWindow *ev_window)
 }
 
 static void
-ev_window_error_dialog_response_cb (GtkWidget *dialog,
-                                  gint       response_id,
-                                  EvWindow  *ev_window)
+ev_window_set_message_area (EvWindow  *window,
+                           GtkWidget *area)
 {
-       gtk_widget_destroy (dialog);
+       if (window->priv->message_area == area)
+               return;
+
+       if (window->priv->message_area)
+               gtk_widget_destroy (window->priv->message_area);
+       window->priv->message_area = area;
+
+       if (!area)
+               return;
+
+       gtk_box_pack_start (GTK_BOX (window->priv->view_box),
+                           window->priv->message_area,
+                           FALSE, FALSE, 0);
+       gtk_box_reorder_child (GTK_BOX (window->priv->view_box),
+                              window->priv->message_area, 0);
+       g_object_add_weak_pointer (G_OBJECT (window->priv->message_area),
+                                  (gpointer) &(window->priv->message_area));
 }
 
 static void
-ev_window_error_dialog (GtkWindow *window, const gchar *msg, GError *error)
+ev_window_error_message_response_cb (EvMessageArea *area,
+                                    gint           response_id,
+                                    EvWindow      *window)
 {
-       GtkWidget *dialog;
+       ev_window_set_message_area (window, NULL);
+}
 
-       dialog = gtk_message_dialog_new (GTK_WINDOW (window),
-                                        GTK_DIALOG_DESTROY_WITH_PARENT,
-                                        GTK_MESSAGE_ERROR,
-                                        GTK_BUTTONS_CLOSE,
-                                        msg);
-       gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
-                                                 "%s", error->message);
-       g_signal_connect (dialog, "response",
-                         G_CALLBACK (ev_window_error_dialog_response_cb),
-                          window);
-       gtk_widget_show (dialog);
+static void
+ev_window_error_message (GtkWindow *window, const gchar *msg, GError *error)
+{
+       GtkWidget *area;
+
+       if (EV_WINDOW (window)->priv->message_area)
+               return;
+
+       area = ev_message_area_new (GTK_MESSAGE_ERROR,
+                                   msg,
+                                   GTK_STOCK_CLOSE,
+                                   GTK_RESPONSE_CANCEL,
+                                   NULL);
+       ev_message_area_set_secondary_text (EV_MESSAGE_AREA (area), error->message);
+       g_signal_connect (area, "response",
+                         G_CALLBACK (ev_window_error_message_response_cb),
+                         window);
+       gtk_widget_show (area);
+       ev_window_set_message_area (EV_WINDOW (window), area);
 }
 
 static void
@@ -1133,6 +1182,8 @@ ev_window_set_document (EvWindow *ev_window, EvDocument *document)
        if (ev_window->priv->document)
                g_object_unref (ev_window->priv->document);
        ev_window->priv->document = g_object_ref (document);
+
+       ev_window_set_message_area (ev_window, NULL);
        
        ev_window->priv->page_cache = ev_page_cache_get (ev_window->priv->document);
        g_signal_connect (ev_window->priv->page_cache, "page-changed",
@@ -1341,6 +1392,10 @@ ev_window_load_job_cb  (EvJobLoad *job,
                                find_bar_search_changed_cb (EGG_FIND_BAR (ev_window->priv->find_bar),
                                                            NULL, ev_window);
                        }
+               } else if (job->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->search_string);
                }
 
                ev_window_clear_load_job (ev_window);
@@ -1364,9 +1419,9 @@ ev_window_load_job_cb  (EvJobLoad *job,
                
                ev_window_popup_password_dialog (ev_window);
        } else {
-               ev_window_error_dialog (GTK_WINDOW (ev_window), 
-                                       _("Unable to open document"),
-                                       job->error);
+               ev_window_error_message (GTK_WINDOW (ev_window), 
+                                        _("Unable to open document"),
+                                        job->error);
                ev_window_clear_load_job (ev_window);
                ev_window->priv->in_reload = FALSE;
        }       
@@ -1447,11 +1502,17 @@ 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)
 {
        GnomeVFSURI *source_uri;
        GnomeVFSURI *target_uri;
+
+       if (ev_window->priv->uri &&
+           g_ascii_strcasecmp (ev_window->priv->uri, uri) == 0) {
+               ev_window->priv->in_reload = TRUE;
+       }
        
        ev_window_close_dialogs (ev_window);
        ev_window_clear_load_job (ev_window);
@@ -1472,7 +1533,7 @@ ev_window_open_uri (EvWindow       *ev_window,
 
        setup_size_from_metadata (ev_window);
        
-       ev_window->priv->load_job = ev_job_load_new (uri, dest, mode);
+       ev_window->priv->load_job = ev_job_load_new (uri, dest, mode, search_string);
        g_signal_connect (ev_window->priv->load_job,
                          "finished",
                          G_CALLBACK (ev_window_load_job_cb),
@@ -1653,9 +1714,9 @@ ev_window_cmd_file_open_copy_at_dest (EvWindow *window, EvLinkDest *dest)
        new_filename = ev_window_create_tmp_symlink (old_filename, &error);
 
        if (error) {
-               ev_window_error_dialog (GTK_WINDOW (window),
-                                       _("Cannot open a copy."),
-                                       error);
+               ev_window_error_message (GTK_WINDOW (window),
+                                        _("Cannot open a copy."),
+                                        error);
 
                g_error_free (error);
                g_free (old_filename);
@@ -1674,6 +1735,7 @@ ev_window_cmd_file_open_copy_at_dest (EvWindow *window, EvLinkDest *dest)
                                         gtk_window_get_screen (GTK_WINDOW (window)),
                                         dest,
                                         0,
+                                        NULL, 
                                         TRUE,
                                         NULL,
                                         GDK_CURRENT_TIME);
@@ -1696,8 +1758,8 @@ ev_window_cmd_file_open_copy (GtkAction *action, EvWindow *window)
 }
 
 static void
-ev_window_cmd_recent_file_activate (GtkAction     *action,
-                                   EvWindow      *window)
+ev_window_cmd_recent_file_activate (GtkAction *action,
+                                   EvWindow  *window)
 {
        GtkRecentInfo *info;
        const gchar   *uri;
@@ -1709,7 +1771,18 @@ 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, FALSE, NULL, 
+                                        NULL, 0, NULL, FALSE, NULL, 
+                                        GDK_CURRENT_TIME);
+}
+
+static void
+ev_window_open_recent_action_item_activated (EvOpenRecentAction *action,
+                                            const gchar        *uri,
+                                            EvWindow           *window)
+{
+       ev_application_open_uri_at_dest (EV_APP, uri,
+                                        gtk_window_get_screen (GTK_WINDOW (window)),
+                                        NULL, 0, NULL, FALSE, NULL, 
                                         GDK_CURRENT_TIME);
 }
 
@@ -1960,7 +2033,7 @@ ev_window_save_job_cb (EvJobSave *job,
                gchar *msg;
                
                msg = g_strdup_printf (_("The file could not be saved as ā€œ%sā€."), job->uri);
-               ev_window_error_dialog (GTK_WINDOW (window), msg, job->error);
+               ev_window_error_message (GTK_WINDOW (window), msg, job->error);
                g_free (msg);
        }
 
@@ -2092,6 +2165,40 @@ ev_window_clear_print_job (EvWindow *window)
        }
 }
 
+static void
+ev_window_load_print_settings_from_metadata (EvWindow *window)
+{
+       gchar *uri = window->priv->uri;
+       gint   i;
+       
+       /* Load print setting that are specific to the document */
+       for (i = 0; i < G_N_ELEMENTS (document_print_settings); i++) {
+               GValue   value = { 0, };
+               gboolean success;
+
+               success = ev_metadata_manager_get (uri, document_print_settings[i], &value, TRUE);
+               gtk_print_settings_set (window->priv->print_settings,
+                                       document_print_settings[i],
+                                       success ? g_value_get_string (&value) : NULL);
+       }
+}
+
+static void
+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_print_finished (GtkPrintJob *print_job,
                          EvWindow    *window,
@@ -2116,6 +2223,7 @@ ev_window_print_finished (GtkPrintJob *print_job,
                /* If printed successfully, save print settings */
                ev_application_set_print_settings (EV_APP,
                                                   window->priv->print_settings);
+               ev_window_save_print_settings (window);
        }
 }
 
@@ -2169,6 +2277,7 @@ ev_window_print_send (EvWindow    *window,
                                                 gtk_window_get_screen (GTK_WINDOW (window)),
                                                 NULL,
                                                 EV_WINDOW_MODE_PREVIEW,
+                                                NULL, 
                                                 TRUE,
                                                 print_settings_file,
                                                 GDK_CURRENT_TIME);
@@ -2376,8 +2485,9 @@ ev_window_print_range (EvWindow *ev_window, int first_page, int last_page)
        document_last_page = ev_page_cache_get_n_pages (page_cache);
 
        if (!ev_window->priv->print_settings) {
-               ev_window->priv->print_settings = g_object_ref (
+               ev_window->priv->print_settings = gtk_print_settings_copy (
                        ev_application_get_print_settings (EV_APP));
+               ev_window_load_print_settings_from_metadata (ev_window);
        }
 
        if (first_page != 1 || last_page != document_last_page) {
@@ -2755,6 +2865,27 @@ fullscreen_toolbar_setup_item_properties (GtkUIManager *ui_manager)
        g_object_set (item, "is-important", TRUE, NULL);
 }
 
+static void
+fullscreen_toolbar_remove_shadow (GtkWidget *toolbar)
+{
+       static gboolean done = FALSE;
+
+       if (!done) {
+               gtk_rc_parse_string (
+                       "\n"
+                       "   style \"fullscreen-toolbar-style\"\n"
+                       "   {\n"
+                       "      GtkToolbar::shadow-type=GTK_SHADOW_NONE\n"
+                       "   }\n"
+                       "\n"
+                       "    widget \"*.fullscreen-toolbar\" style \"fullscreen-toolbar-style\"\n"
+                       "\n");
+               done = TRUE;
+       }
+       
+       gtk_widget_set_name (toolbar, "fullscreen-toolbar");
+}
+
 static void
 ev_window_run_fullscreen (EvWindow *window)
 {
@@ -2765,6 +2896,7 @@ ev_window_run_fullscreen (EvWindow *window)
 
                gtk_toolbar_set_style (GTK_TOOLBAR (window->priv->fullscreen_toolbar),
                                       GTK_TOOLBAR_BOTH_HORIZ);
+               fullscreen_toolbar_remove_shadow (window->priv->fullscreen_toolbar);
                fullscreen_toolbar_setup_item_properties (window->priv->ui_manager);
 
                gtk_box_pack_start (GTK_BOX (window->priv->main_box),
@@ -3224,13 +3356,17 @@ ev_window_cmd_view_reload (GtkAction *action, EvWindow *ev_window)
 {
        gchar *uri;
 
-       ev_window->priv->in_reload = TRUE;
-       
        uri = g_strdup (ev_window->priv->uri);
-       ev_window_open_uri (ev_window, uri, NULL, 0, FALSE, NULL);
+       ev_window_open_uri (ev_window, uri, NULL, 0, NULL, FALSE, NULL);
        g_free (uri);
 }
 
+static void
+ev_window_cmd_view_autoscroll (GtkAction *action, EvWindow *ev_window)
+{
+       ev_view_autoscroll (EV_VIEW (ev_window->priv->view));
+}
+
 static void
 ev_window_cmd_help_contents (GtkAction *action, EvWindow *ev_window)
 {
@@ -4272,6 +4408,9 @@ static const GtkActionEntry entries[] = {
           N_("Reload the document"),
           G_CALLBACK (ev_window_cmd_view_reload) },
 
+       { "ViewAutoscroll", GTK_STOCK_MEDIA_PLAY, N_("Auto_scroll"), NULL, NULL,
+         G_CALLBACK (ev_window_cmd_view_autoscroll) },
+
         /* Go menu */
         { "GoPreviousPage", GTK_STOCK_GO_BACK, N_("_Previous Page"), "<control>Page_Up",
           N_("Go to the previous page"),
@@ -4464,6 +4603,20 @@ register_custom_actions (EvWindow *window, GtkActionGroup *group)
                          G_CALLBACK (navigation_action_activate_link_cb), window);
        gtk_action_group_add_action (group, action);
        g_object_unref (action);
+
+       action = g_object_new (EV_TYPE_OPEN_RECENT_ACTION,
+                              "name", "FileOpenRecent",
+                              "label", _("_Open..."),
+                              "tooltip", _("Open an existing document"),
+                              "stock_id", GTK_STOCK_OPEN,
+                              NULL);
+       g_signal_connect (action, "activate",
+                         G_CALLBACK (ev_window_cmd_file_open), window);
+       g_signal_connect (action, "item_activated",
+                         G_CALLBACK (ev_window_open_recent_action_item_activated),
+                         window);
+       gtk_action_group_add_action (group, action);
+       g_object_unref (action);
 }
 
 static void
@@ -4711,6 +4864,7 @@ open_remote_link (EvWindow *window, EvLinkAction *action)
                                         gtk_window_get_screen (GTK_WINDOW (window)),
                                         ev_link_action_get_dest (action),
                                         0,
+                                        NULL, 
                                         FALSE,
                                         NULL,
                                         GDK_CURRENT_TIME);
@@ -4822,37 +4976,48 @@ image_save_dialog_response_cb (GtkWidget *fc,
                               gint       response_id,
                               EvWindow  *ev_window)
 {
+       GtkWidget   *format_chooser;
        GnomeVFSURI *target_uri;
        gchar       *uri;
+       gchar       *uri_extension;
        gchar       *filename;
+       gchar       *file_format;
        gboolean     is_local;
        GError      *error = NULL;
+       guint        format;
        
        if (response_id != GTK_RESPONSE_OK) {
                gtk_widget_destroy (fc);
                return;
        }
 
+       format_chooser = gtk_file_chooser_get_extra_widget (GTK_FILE_CHOOSER (fc));
+       
        uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (fc));
-       target_uri = gnome_vfs_uri_new (uri);
+       format = egg_file_format_chooser_get_format (EGG_FILE_FORMAT_CHOOSER (format_chooser), uri);
+       uri_extension = egg_file_format_chooser_append_extension (EGG_FILE_FORMAT_CHOOSER (format_chooser),
+                                                                 uri, format);
+       file_format = (char *)egg_file_format_chooser_get_format_data (EGG_FILE_FORMAT_CHOOSER (format_chooser),
+                                                                      format);
+       target_uri = gnome_vfs_uri_new (uri_extension);
        is_local = gnome_vfs_uri_is_local (target_uri);
        
        if (is_local) {
-               filename = g_filename_from_uri (uri, NULL, NULL);
+               filename = g_filename_from_uri (uri_extension, NULL, NULL);
        } else {
                filename = ev_tmp_filename ("saveimage");
        }
        
        g_free (uri);
+       g_free (uri_extension);
        
-       /* FIXME: allow saving in other image formats than png */
        gdk_pixbuf_save (ev_image_get_pixbuf (ev_window->priv->image),
-                        filename, "png", &error, NULL);
+                        filename, file_format, &error, NULL);
        
        if (error) {
-               ev_window_error_dialog (GTK_WINDOW (ev_window),
-                                       _("The image could not be saved."),
-                                       error);
+               ev_window_error_message (GTK_WINDOW (ev_window),
+                                        _("The image could not be saved."),
+                                        error);
                g_error_free (error);
                g_free (filename);
                gnome_vfs_uri_unref (target_uri);
@@ -4880,7 +5045,7 @@ image_save_dialog_response_cb (GtkWidget *fc,
 static void
 ev_view_popup_cmd_save_image_as (GtkAction *action, EvWindow *window)
 {
-       GtkWidget     *fc;
+       GtkWidget     *fc, *format_chooser;
        GtkFileFilter *filter;
 
        if (!window->priv->image)
@@ -4897,11 +5062,12 @@ ev_view_popup_cmd_save_image_as (GtkAction *action, EvWindow *window)
        gtk_dialog_set_default_response (GTK_DIALOG (fc), GTK_RESPONSE_OK);
        gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (fc), FALSE);
        gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (fc), TRUE);
-
-       filter = gtk_file_filter_new ();
-       gtk_file_filter_set_name (filter, _("Images"));
-       gtk_file_filter_add_pixbuf_formats (filter);
-       gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fc), filter);
+       
+       format_chooser = egg_file_format_chooser_new ();
+       egg_file_format_chooser_add_pixbuf_formats (EGG_FILE_FORMAT_CHOOSER (format_chooser),
+                                                   0, NULL);
+       
+       gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (fc), format_chooser);
 
        g_signal_connect (fc, "response",
                          G_CALLBACK (image_save_dialog_response_cb),
@@ -4941,9 +5107,9 @@ ev_attachment_popup_cmd_open_attachment (GtkAction *action, EvWindow *window)
                ev_attachment_open (attachment, &error);
 
                if (error) {
-                       ev_window_error_dialog (GTK_WINDOW (window),
-                                               _("Unable to open attachment"),
-                                               error);
+                       ev_window_error_message (GTK_WINDOW (window),
+                                                _("Unable to open attachment"),
+                                                error);
                        g_error_free (error);
                }
        }
@@ -4994,9 +5160,9 @@ attachment_save_dialog_response_cb (GtkWidget *fc,
                ev_attachment_save (attachment, filename, &error);
                
                if (error) {
-                       ev_window_error_dialog (GTK_WINDOW (ev_window),
-                                               _("The attachment could not be saved."),
-                                               error);
+                       ev_window_error_message (GTK_WINDOW (ev_window),
+                                                _("The attachment could not be saved."),
+                                                error);
                        g_error_free (error);
                        g_free (filename);
 
@@ -5151,7 +5317,7 @@ ev_window_init (EvWindow *ev_window)
                                  "changed",
                                  G_CALLBACK (ev_window_setup_recent),
                                  ev_window);
-       
+
        ev_window->priv->menubar =
                 gtk_ui_manager_get_widget (ev_window->priv->ui_manager,
                                            "/MainMenu");
@@ -5159,7 +5325,6 @@ ev_window_init (EvWindow *ev_window)
                            ev_window->priv->menubar,
                            FALSE, FALSE, 0);
 
-
        ev_window->priv->toolbar = GTK_WIDGET 
          (g_object_new (EGG_TYPE_EDITABLE_TOOLBAR,
                         "ui-manager", ev_window->priv->ui_manager,
@@ -5229,14 +5394,19 @@ ev_window_init (EvWindow *ev_window)
        ev_sidebar_add_page (EV_SIDEBAR (ev_window->priv->sidebar),
                             sidebar_widget);
 
+       ev_window->priv->view_box = gtk_vbox_new (FALSE, 0);
        ev_window->priv->scrolled_window =
                GTK_WIDGET (g_object_new (GTK_TYPE_SCROLLED_WINDOW,
                                          "shadow-type", GTK_SHADOW_IN,
                                          NULL));
+       gtk_box_pack_start (GTK_BOX (ev_window->priv->view_box),
+                           ev_window->priv->scrolled_window,
+                           TRUE, TRUE, 0);
        gtk_widget_show (ev_window->priv->scrolled_window);
 
        gtk_paned_add2 (GTK_PANED (ev_window->priv->hpaned),
-                       ev_window->priv->scrolled_window);
+                       ev_window->priv->view_box);
+       gtk_widget_show (ev_window->priv->view_box);
 
        ev_window->priv->view = ev_view_new ();
        ev_view_set_screen_dpi (EV_VIEW (ev_window->priv->view),