]> www.fi.muni.cz Git - evince.git/blobdiff - shell/ev-window.c
Move ev_page_cache_check_dimensions() to EvDocument
[evince.git] / shell / ev-window.c
index 41d9357fc0271670c02bae2695098be6cdfde94a..078cb9c29bb0f4dd3fea5b3e98e047530c8ea139 100644 (file)
@@ -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 <martink@gnome.org>
@@ -38,7 +38,6 @@
 #include <glib/gi18n.h>
 #include <gio/gio.h>
 #include <gtk/gtk.h>
-#include <gtk/gtkunixprint.h>
 
 #ifdef WITH_GCONF
 #include <gconf/gconf-client.h>
@@ -140,6 +139,10 @@ 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;
@@ -199,7 +202,6 @@ struct _EvWindowPrivate {
 
        /* Printing */
        GQueue           *print_queue;
-       GtkPrinter       *printer;
        GtkPrintSettings *print_settings;
        GtkPageSetup     *print_page_setup;
        gboolean          close_after_print;
@@ -244,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,
@@ -336,11 +339,11 @@ ev_window_setup_action_sensitivity (EvWindow *ev_window)
 
        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) {
@@ -366,7 +369,7 @@ ev_window_setup_action_sensitivity (EvWindow *ev_window)
                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
@@ -384,7 +387,7 @@ ev_window_setup_action_sensitivity (EvWindow *ev_window)
        /* 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);
 
@@ -422,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;
        }
 
@@ -544,7 +547,6 @@ update_chrome_visibility (EvWindow *window)
        set_widget_visibility (priv->sidebar, sidebar);
        
        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);
@@ -800,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)
@@ -955,7 +957,7 @@ setup_document_from_metadata (EvWindow *window)
                gint n_pages;
                gint new_page;
                
-               n_pages = ev_page_cache_get_n_pages (window->priv->page_cache);
+               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);
@@ -970,21 +972,17 @@ setup_document_from_metadata (EvWindow *window)
 
        if (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;
+               gdouble    document_width;
+               gdouble    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;
+               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));
                
@@ -992,10 +990,12 @@ setup_document_from_metadata (EvWindow *window)
                        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);
+               
+               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);
        }
@@ -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;
 }
 
@@ -1238,21 +1239,25 @@ ev_window_set_document (EvWindow *ev_window, EvDocument *document)
                /* Restart the current page */
                page = CLAMP (ev_link_dest_get_page (ev_window->priv->dest),
                              0,
-                             ev_page_cache_get_n_pages (ev_window->priv->page_cache) - 1);
+                             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_page_cache_get_n_pages (ev_window->priv->page_cache) > 0) {
-               ev_view_set_document (view, document);
-       } else {
+       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);
 }
 
@@ -1260,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
@@ -1344,6 +1349,21 @@ ev_window_clear_temp_symlink (EvWindow *ev_window)
        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
@@ -1385,21 +1405,12 @@ ev_window_load_job_cb (EvJob *job,
                                                  flags);
                }
 
-               if (ev_window->priv->dest) {
-                       EvLink *link;
-                       EvLinkAction *link_action;
-       
-                       link_action = ev_link_action_new_dest (ev_window->priv->dest);
-                       link = ev_link_new (NULL, link_action);
-                       ev_view_handle_link (EV_VIEW (ev_window->priv->view), link);
-                       g_object_unref (link);
-
-                       /* 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;
-               }
+               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 (ev_window->priv->window_mode) {
                        case EV_WINDOW_MODE_FULLSCREEN:
@@ -1478,6 +1489,7 @@ 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);
@@ -1487,9 +1499,14 @@ ev_window_reload_job_cb (EvJob    *job,
                
                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)) {
@@ -1586,12 +1603,15 @@ show_loading_progress (EvWindow *ev_window)
 {
        GtkWidget *area;
        gchar     *text;
+       gchar     *display_name;
        
        if (ev_window->priv->message_area)
                return FALSE;
-       
-       text = g_strdup_printf (_("Loading document from %s"),
-                               ev_window->priv->uri);
+
+       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,
@@ -1604,7 +1624,9 @@ show_loading_progress (EvWindow *ev_window)
                          ev_window);
        gtk_widget_show (area);
        ev_window_set_message_area (ev_window, area);
+
        g_free (text);
+       g_free (display_name);
 
        return FALSE;
 }
@@ -1787,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;
        }
 
@@ -1982,7 +2004,8 @@ 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;
 
@@ -1995,7 +2018,7 @@ ev_window_reload_document (EvWindow *ev_window)
        if (ev_window->priv->dest)
                g_object_unref (ev_window->priv->dest);
        /* FIXME: save the scroll position too (xyz dest) */
-       ev_window->priv->dest = ev_link_dest_new_page (page);
+       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);
@@ -2009,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);
 }
@@ -2034,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),
@@ -2047,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;
 
@@ -2060,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);
@@ -2526,17 +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);
@@ -2556,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"),
@@ -2577,14 +2630,21 @@ ev_window_cmd_save_as (GtkAction *action, EvWindow *ev_window)
        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);
@@ -2939,6 +2999,11 @@ ev_window_print_range (EvWindow *ev_window,
                ev_window->priv->print_queue = g_queue_new ();
 
        op = ev_print_operation_new (ev_window->priv->document);
+       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);
@@ -2951,7 +3016,7 @@ ev_window_print_range (EvWindow *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 (
@@ -2959,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;
 
@@ -2975,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));
 }
@@ -2984,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
@@ -3564,6 +3629,35 @@ ev_window_cmd_view_presentation (GtkAction *action, EvWindow *window)
        }
 }
 
+static void
+ev_window_setup_gtk_settings (EvWindow *window)
+{
+       GtkSettings *settings;
+       GdkScreen   *screen;
+       gchar       *menubar_accel_accel;
+
+       screen = gtk_window_get_screen (GTK_WINDOW (window));
+       settings = gtk_settings_get_for_screen (screen);
+
+       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;
+       }
+
+       g_free (menubar_accel_accel);
+}
+
 static void
 ev_window_screen_changed (GtkWidget *widget,
                          GdkScreen *old_screen)
@@ -3576,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)));
        
@@ -3748,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
@@ -3763,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)
@@ -3786,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
@@ -4055,6 +4148,7 @@ ev_window_cmd_help_about (GtkAction *action, EvWindow *ev_window)
                "Bryan Clark <clarkbw@gnome.org>",
                "Carlos Garcia Campos <carlosgc@gnome.org>",
                "Wouter Bolsterlee <wbolster@gnome.org>",
+                "Christian Persch <chpe" "\100" "gnome.org>",
                NULL
        };
 
@@ -4099,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,
@@ -4423,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",
@@ -4507,10 +4601,17 @@ ev_window_drag_data_received (GtkWidget        *widget,
                              guint             time)
 
 {
-       EvWindow *window = EV_WINDOW (widget);
-       gchar   **uris;
-       gint      i = 0;
-       GSList   *uri_list = NULL;
+       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) {
@@ -4660,11 +4761,6 @@ ev_window_dispose (GObject *object)
        
        ev_window_close_dialogs (window);
 
-       if (window->priv->printer) {
-               g_object_unref (window->priv->printer);
-               window->priv->printer = NULL;
-       }
-
        if (window->priv->print_settings) {
                g_object_unref (window->priv->print_settings);
                window->priv->print_settings = NULL;
@@ -4736,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)
 {
@@ -4745,6 +4899,7 @@ 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;
@@ -4770,7 +4925,7 @@ static const GtkActionEntry entries[] = {
                { "FileSaveAs", GTK_STOCK_SAVE_AS, N_("_Save a Copy..."), "<control>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..."), "<control>P",
@@ -5166,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);
                }
        }
 
@@ -5328,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 "
@@ -5433,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",
@@ -5735,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);
@@ -5789,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;
@@ -6028,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);