]> www.fi.muni.cz Git - evince.git/blobdiff - shell/ev-window.c
Fixed wrong translation.
[evince.git] / shell / ev-window.c
index cb7f71bb61959b32f23ff6a5d5ef6716b2b678bb..d3787180f9bc97e37053a16d11de230e94cc059e 100644 (file)
@@ -87,9 +87,9 @@
 #include <glib/gstdio.h>
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
-#include <gnome.h>
 #include <libgnomevfs/gnome-vfs-utils.h>
 #include <libgnomevfs/gnome-vfs-async-ops.h>
+#include <libgnomevfs/gnome-vfs-ops.h>
 #include <gconf/gconf-client.h>
 
 #include <errno.h>
@@ -158,6 +158,7 @@ struct _EvWindowPrivate {
 
        /* Preview mode */
        GtkWidget *preview_toolbar;
+       gchar     *print_settings_file;
 
        /* Popup view */
        GtkWidget *view_popup;
@@ -191,6 +192,7 @@ struct _EvWindowPrivate {
 
 #ifdef WITH_GTK_PRINT
        EvJob            *print_job;
+       gboolean          print_preview;
        GtkPrintJob      *gtk_print_job;
        GtkPrinter       *printer;
        GtkPrintSettings *print_settings;
@@ -209,7 +211,7 @@ struct _EvWindowPrivate {
 #define GCONF_LOCKDOWN_SAVE         "/desktop/gnome/lockdown/disable_save_to_disk"
 #define GCONF_LOCKDOWN_PRINT        "/desktop/gnome/lockdown/disable_printing"
 
-#define PRESENTATION_TIMEOUT 5 * 1000
+#define PRESENTATION_TIMEOUT 5
 
 #define SIDEBAR_DEFAULT_SIZE    132
 #define LINKS_SIDEBAR_ID "links"
@@ -271,20 +273,6 @@ static void        view_handle_link_cb                     (EvView *view,
 
 G_DEFINE_TYPE (EvWindow, ev_window, GTK_TYPE_WINDOW)
 
-static gdouble
-ev_window_get_screen_dpi (EvWindow *ev_window)
-{
-       GdkScreen *screen;
-       gdouble    xdpi, ydpi;
-
-       screen = gtk_window_get_screen (GTK_WINDOW (ev_window));
-
-       xdpi = 25.4 * gdk_screen_get_width (screen) / gdk_screen_get_width_mm (screen);
-       ydpi = 25.4 * gdk_screen_get_height (screen) / gdk_screen_get_height_mm (screen);
-       
-       return (xdpi + ydpi) / 2.0;
-}
-
 static void
 ev_window_set_action_sensitive (EvWindow   *ev_window,
                                const char *name,
@@ -392,7 +380,8 @@ ev_window_setup_action_sensitivity (EvWindow *ev_window)
        /* Toolbar-specific actions: */
        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,  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);
 }
@@ -454,7 +443,7 @@ ev_window_update_actions (EvWindow *ev_window)
                                                      ZOOM_CONTROL_ACTION);
 
                real_zoom = ev_view_get_zoom (EV_VIEW (ev_window->priv->view));
-               real_zoom *= 72.0 / ev_window_get_screen_dpi (ev_window);
+               real_zoom *= 72.0 / get_screen_dpi (GTK_WINDOW (ev_window));
                zoom = ephy_zoom_get_nearest_zoom_level (real_zoom);
 
                ephy_zoom_action_set_zoom_level (EPHY_ZOOM_ACTION (action), zoom);
@@ -517,7 +506,7 @@ update_chrome_visibility (EvWindow *window)
        fullscreen_toolbar = ((priv->chrome & EV_CHROME_FULLSCREEN_TOOLBAR) != 0 || 
                              (priv->chrome & EV_CHROME_RAISE_TOOLBAR) != 0) && fullscreen;
        findbar = (priv->chrome & EV_CHROME_FINDBAR) != 0;
-       sidebar = (priv->chrome & EV_CHROME_SIDEBAR) != 0 && !fullscreen_mode;
+       sidebar = (priv->chrome & EV_CHROME_SIDEBAR) != 0 && !presentation;
        preview_toolbar = (priv->chrome& EV_CHROME_PREVIEW_TOOLBAR);
 
        set_widget_visibility (priv->menubar, menubar); 
@@ -709,6 +698,9 @@ ev_window_add_history (EvWindow *window, gint page, EvLink *link)
        EvLinkAction *action;
        EvLinkDest *dest;
        
+       if (window->priv->history == NULL)
+               return;
+       
        if (link) {
                action = g_object_ref (ev_link_get_action (link));
                dest = ev_link_action_get_dest (action);
@@ -981,7 +973,7 @@ setup_view_from_metadata (EvWindow *window)
                gdouble zoom_value;
 
                zoom_value = g_value_get_double (&zoom);
-               zoom_value *= ev_window_get_screen_dpi (window) / 72.0;
+               zoom_value *= get_screen_dpi (GTK_WINDOW (window)) / 72.0;
                ev_view_set_zoom (view, zoom_value, FALSE);
                g_value_unset (&zoom);
        }
@@ -1087,7 +1079,7 @@ ev_window_setup_document (EvWindow *ev_window)
                                        0, 0, 1.0,
                                        &page_width, &page_height);
                scale = (gdouble)128 / (gdouble)page_width;
-               
+
                rc = ev_render_context_new (0, 0, scale);
                ev_window->priv->thumbnail_job = ev_job_thumbnail_new (document, rc);
                g_signal_connect (ev_window->priv->thumbnail_job, "finished",
@@ -1230,19 +1222,23 @@ ev_window_clear_load_job (EvWindow *ev_window)
 static void
 ev_window_clear_local_uri (EvWindow *ev_window)
 {
-    char *filename;
-    
     if (ev_window->priv->local_uri) {
-           filename = g_filename_from_uri (ev_window->priv->local_uri, NULL, NULL);
-           if (filename != NULL) {
-                   g_unlink (filename);
-                   g_free (filename);
-           }
+           ev_tmp_uri_unlink (ev_window->priv->local_uri);
            g_free (ev_window->priv->local_uri);
            ev_window->priv->local_uri = NULL;
     }
 }
 
+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)
 {
@@ -1402,9 +1398,9 @@ ev_window_close_dialogs (EvWindow *ev_window)
 }
 
 static gint
-xfer_update_progress_callback (GnomeVFSAsyncHandle      *handle,
-                              GnomeVFSXferProgressInfo *info,
-                              EvWindow                 *ev_window)
+open_xfer_update_progress_callback (GnomeVFSAsyncHandle      *handle,
+                                   GnomeVFSXferProgressInfo *info,
+                                   EvWindow                 *ev_window)
 {
        switch (info->status) {
                case GNOME_VFS_XFER_PROGRESS_STATUS_OK:
@@ -1429,7 +1425,8 @@ ev_window_open_uri (EvWindow       *ev_window,
                    const char     *uri,
                    EvLinkDest     *dest,
                    EvWindowRunMode mode,
-                   gboolean        unlink_temp_file)
+                   gboolean        unlink_temp_file,
+                   const gchar    *print_settings)
 {
        GnomeVFSURI *source_uri;
        GnomeVFSURI *target_uri;
@@ -1437,10 +1434,16 @@ 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;
+       }
+
        if (ev_window->priv->uri)
                g_free (ev_window->priv->uri);
        ev_window->priv->uri = g_strdup (uri);
@@ -1481,7 +1484,8 @@ ev_window_open_uri (EvWindow       *ev_window,
                                      GNOME_VFS_XFER_ERROR_MODE_ABORT,
                                      GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE,
                                      GNOME_VFS_PRIORITY_DEFAULT,
-                                     (GnomeVFSAsyncXferProgressCallback)xfer_update_progress_callback,
+                                     (GnomeVFSAsyncXferProgressCallback)
+                                     open_xfer_update_progress_callback,
                                      ev_window,
                                      NULL, NULL); 
                
@@ -1502,6 +1506,8 @@ file_open_dialog_response_cb (GtkWidget *chooser,
                              gint       response_id,
                              EvWindow  *ev_window)
 {
+       gchar *uri;
+
        if (response_id == GTK_RESPONSE_OK) {
                GSList *uris;
 
@@ -1514,8 +1520,10 @@ file_open_dialog_response_cb (GtkWidget *chooser,
                g_slist_foreach (uris, (GFunc)g_free, NULL);    
                g_slist_free (uris);
        }
-       ev_application_set_chooser_uri (EV_APP, 
-                                       gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (chooser)));
+
+       uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (chooser));
+       ev_application_set_chooser_uri (EV_APP, uri);
+       g_free (uri);
 
        gtk_widget_destroy (chooser);
 }
@@ -1542,9 +1550,9 @@ ev_window_cmd_file_open (GtkAction *action, EvWindow *window)
        } else if (window->priv->uri != NULL) {
                gtk_file_chooser_set_uri (GTK_FILE_CHOOSER (chooser),
                                          window->priv->uri);
-       }
-       else {
+       } else {
                char *folder;
+               
                folder = xdg_user_dir_lookup ("DOCUMENTS");
                gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (chooser),
                                                     folder);
@@ -1637,6 +1645,7 @@ ev_window_cmd_file_open_copy_at_dest (EvWindow *window, EvLinkDest *dest)
                                         dest,
                                         0,
                                         TRUE,
+                                        NULL,
                                         GDK_CURRENT_TIME);
        g_free (symlink_uri);
 }
@@ -1671,7 +1680,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, FALSE,
+                                        NULL, 0, FALSE, NULL, 
                                         GDK_CURRENT_TIME);
 }
 #else
@@ -1689,7 +1698,7 @@ ev_window_cmd_recent_file_activate (GtkAction *action,
 
        ev_application_open_uri_at_dest (EV_APP, uri,
                                         gtk_window_get_screen (GTK_WINDOW (ev_window)),
-                                        NULL, 0, FALSE,
+                                        NULL, 0, FALSE, NULL,
                                         GDK_CURRENT_TIME);
        
        g_free (uri);
@@ -1872,28 +1881,107 @@ ev_window_setup_recent (EvWindow *ev_window)
 #endif /* HAVE_GTK_RECENT */
 }
 
+static gint
+save_xfer_update_progress_callback (GnomeVFSAsyncHandle      *handle,
+                                   GnomeVFSXferProgressInfo *info,
+                                   GnomeVFSURI              *tmp_uri)
+{
+       switch (info->status) {
+               case GNOME_VFS_XFER_PROGRESS_STATUS_OK:
+                       if (info->phase == GNOME_VFS_XFER_PHASE_COMPLETED) {
+                               gchar *uri;
+
+                               uri = gnome_vfs_uri_to_string (tmp_uri, 0);
+                               ev_tmp_uri_unlink (uri);
+                               g_free (uri);
+                               gnome_vfs_uri_unref (tmp_uri);
+                       }
+                       return 1;
+               case GNOME_VFS_XFER_PROGRESS_STATUS_VFSERROR:
+                       if (info->vfs_status != GNOME_VFS_OK) {
+                               GtkWidget *dialog;
+                               gchar     *uri;
+
+                               dialog = gtk_message_dialog_new (NULL,
+                                                                GTK_DIALOG_DESTROY_WITH_PARENT,
+                                                                GTK_MESSAGE_ERROR,
+                                                                GTK_BUTTONS_CLOSE,
+                                                                _("The file could not be saved as ā€œ%sā€."),
+                                                                info->target_name);
+                               gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+                                                                         gnome_vfs_result_to_string (info->vfs_status));
+
+                               g_signal_connect (dialog, "response",
+                                                 G_CALLBACK (gtk_widget_destroy),
+                                                 NULL);
+                               gtk_widget_show (dialog);
+
+                               uri = gnome_vfs_uri_to_string (tmp_uri, 0);
+                               ev_tmp_uri_unlink (uri);
+                               g_free (uri);
+                               gnome_vfs_uri_unref (tmp_uri);
+                       }
+                       return 1;
+               case GNOME_VFS_XFER_PROGRESS_STATUS_OVERWRITE:
+               case GNOME_VFS_XFER_PROGRESS_STATUS_DUPLICATE:
+                       return 1;
+               default:
+                       g_assert_not_reached ();
+       }
+
+       return 0;
+}
+
+static void
+ev_window_save_remote (EvWindow    *ev_window,
+                      GnomeVFSURI *src,
+                      GnomeVFSURI *dst)
+{
+       GnomeVFSAsyncHandle *handle;
+       GList               *slist = NULL;
+       GList               *tlist = NULL;
+       
+       slist = g_list_prepend (slist, src);
+       tlist = g_list_prepend (tlist, dst);
+       gnome_vfs_async_xfer (&handle, slist, tlist,
+                             GNOME_VFS_XFER_DEFAULT | GNOME_VFS_XFER_FOLLOW_LINKS,
+                             GNOME_VFS_XFER_ERROR_MODE_ABORT,
+                             GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE,
+                             GNOME_VFS_PRIORITY_DEFAULT,
+                             (GnomeVFSAsyncXferProgressCallback)
+                             save_xfer_update_progress_callback,
+                             gnome_vfs_uri_ref (src),
+                             NULL, NULL);
+       g_list_free (slist);
+       g_list_free (tlist);
+}
+
 static void
 file_save_dialog_response_cb (GtkWidget *fc,
                              gint       response_id,
                              EvWindow  *ev_window)
 {
-       const gchar *uri_unc;
-       gint         fd;
-       gchar       *filename;
-       gchar       *tmp_filename;
-       GError      *error = NULL;
+       gchar  *uri;
+       gchar  *local_uri;
+       gint    fd;
+       gchar  *filename;
+       gchar  *tmp_filename;
+       GError *error = NULL;
 
        if (response_id != GTK_RESPONSE_OK) {
                gtk_widget_destroy (fc);
                return;
        }
-       
 
-       filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (fc));
+       uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (fc));
+
+       filename = ev_tmp_filename ("saveacopy");
        tmp_filename = g_strdup_printf ("%s.XXXXXX", filename);
+       g_free (filename);
        
        fd = g_mkstemp (tmp_filename);
        if (fd == -1) {
+               gchar *msg;
                gchar *display_name;
                gint   save_errno = errno;
                
@@ -1904,74 +1992,95 @@ file_save_dialog_response_cb (GtkWidget *fc,
                             _("Failed to create file ā€œ%sā€: %s"),
                             display_name, g_strerror (save_errno));
                g_free (display_name);
-       } else {
-               gchar *uri;
-               
-               uri = g_filename_to_uri (tmp_filename, NULL, NULL);
-               
-               ev_document_doc_mutex_lock ();
-               ev_document_save (ev_window->priv->document, uri, &error);
-               ev_document_doc_mutex_unlock ();
-               
+
+               msg = g_strdup_printf (_("The file could not be saved as ā€œ%sā€."), uri);
+               ev_window_error_dialog (GTK_WINDOW (ev_window), msg, error);
+
+               g_free (tmp_filename);
                g_free (uri);
-               close (fd);
+               g_free (msg);
+               g_error_free (error);
+               gtk_widget_destroy (fc);
+               
+               return;
        }
 
+       /* Save document to temp filename */
+       local_uri = g_filename_to_uri (tmp_filename, NULL, NULL);
+       
+       ev_document_doc_mutex_lock ();
+       ev_document_save (ev_window->priv->document, local_uri, &error);
+       ev_document_doc_mutex_unlock ();
+       
+       close (fd);
+
        if (!error) {
-               uri_unc = g_object_get_data (G_OBJECT (ev_window->priv->document),
-                                            "uri-uncompressed");
-               if (uri_unc) {
-                       EvCompressionType ctype;
-                       gchar            *uri_comp;
-                       gchar            *uri;
+               /* If original document was compressed,
+                * compress it again before saving
+                */
+               if (g_object_get_data (G_OBJECT (ev_window->priv->document),
+                                      "uri-uncompressed")) {
+                       EvCompressionType ctype = EV_COMPRESSION_NONE;
                        const gchar      *ext;
+                       gchar            *uri_comp;
 
-                       ctype = EV_COMPRESSION_NONE;
-                       
                        ext = g_strrstr (ev_window->priv->uri, ".gz");
                        if (ext && g_ascii_strcasecmp (ext, ".gz") == 0)
                                ctype = EV_COMPRESSION_GZIP;
-                       
+
                        ext = g_strrstr (ev_window->priv->uri, ".bz2");
                        if (ext && g_ascii_strcasecmp (ext, ".bz2") == 0)
                                ctype = EV_COMPRESSION_BZIP2;
                        
-                       uri = g_filename_to_uri (tmp_filename, NULL, NULL);
-                       uri_comp = ev_file_compress (uri, ctype, &error);
-                       g_free (uri);
-                       g_unlink (tmp_filename);
-                       g_free (tmp_filename);
-
+                       uri_comp = ev_file_compress (local_uri, ctype, &error);
+                       g_free (local_uri);
+                       ev_tmp_filename_unlink (tmp_filename);
+                       
                        if (!uri_comp || error) {
-                               tmp_filename = NULL;
+                               local_uri = NULL;
                        } else {
-                               tmp_filename = g_filename_from_uri (uri_comp,
-                                                                   NULL, NULL);
+                               local_uri = uri_comp;
                        }
-                       
-                       g_free (uri_comp);
                }
        }
 
-       if (tmp_filename && g_rename (tmp_filename, filename) == -1) {
-               g_unlink (tmp_filename);
-       }
-       
+       g_free (tmp_filename);
+
        if (error) {
                gchar *msg;
-               gchar *uri;
-               
-               uri = g_filename_to_uri (filename, NULL, NULL);
+
                msg = g_strdup_printf (_("The file could not be saved as ā€œ%sā€."), uri);
                ev_window_error_dialog (GTK_WINDOW (ev_window), msg, error);
-               g_free (msg);
                g_free (uri);
+               g_free (msg);
                g_error_free (error);
+               g_free (local_uri);
+               gtk_widget_destroy (fc);
+
+               return;
        }
-       
-       g_free (tmp_filename);
-       g_free (filename);
 
+       if (local_uri) {
+               GnomeVFSURI *target_uri;
+
+               target_uri = gnome_vfs_uri_new (uri);
+               if (gnome_vfs_uri_is_local (target_uri)) {
+                       /* If target uri is local, just rename local_uri */
+                       if (gnome_vfs_move (local_uri, uri, TRUE) != GNOME_VFS_OK)
+                               ev_tmp_uri_unlink (local_uri);
+               } else {
+                       GnomeVFSURI *source_uri;
+
+                       source_uri = gnome_vfs_uri_new (local_uri);
+                       ev_window_save_remote (ev_window, source_uri, target_uri);
+                       gnome_vfs_uri_unref (source_uri);
+               }
+
+               gnome_vfs_uri_unref (target_uri);
+               g_free (local_uri);
+       }
+
+       g_free (uri);
        gtk_widget_destroy (fc);
 }
 
@@ -1993,7 +2102,8 @@ 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_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER (fc), TRUE);    
+       gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (fc), FALSE);
+       gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (fc), TRUE);   
        file_name = gnome_vfs_format_uri_for_display (ev_window->priv->uri);
        base_name = g_path_get_basename (file_name);
         folder = xdg_user_dir_lookup ("DOCUMENTS");
@@ -2052,6 +2162,11 @@ ev_window_clear_print_job (EvWindow *window)
                g_object_unref (window->priv->print_job);
                window->priv->print_job = NULL;
        }
+
+       if (window->priv->gtk_print_job) {
+               g_object_unref (window->priv->gtk_print_job);
+               window->priv->gtk_print_job = NULL;
+       }
 }
 
 static void
@@ -2074,6 +2189,10 @@ ev_window_print_finished (GtkPrintJob *print_job,
 
                gtk_dialog_run (GTK_DIALOG (dialog));
                gtk_widget_destroy (dialog);
+       } else {
+               /* If printed successfully, save print settings */
+               ev_application_set_print_settings (EV_APP,
+                                                  window->priv->print_settings);
        }
 }
 
@@ -2081,13 +2200,9 @@ static void
 ev_window_print_send (EvWindow    *window,
                      const gchar *filename)
 {
-       GtkPrintJob *job;
        GtkPrintSettings *settings;
-       GError      *error = NULL;
+       EvFileExporterCapabilities capabilities;
        
-       if (window->priv->gtk_print_job)
-               g_object_unref (window->priv->gtk_print_job);
-
        /* Some printers take into account some print settings,
         * and others don't. However we have exported the document
         * to a ps or pdf file according to such print settings. So,
@@ -2095,32 +2210,70 @@ ev_window_print_send (EvWindow    *window,
         * settings set to default values. 
         */
        settings = gtk_print_settings_copy (window->priv->print_settings);
-       gtk_print_settings_set_n_copies (settings, 1);
+       capabilities = ev_file_exporter_get_capabilities (EV_FILE_EXPORTER (window->priv->document));
+
        gtk_print_settings_set_page_ranges (settings, NULL, 0);
-       gtk_print_settings_set_page_set (settings, GTK_PAGE_SET_ALL);
        gtk_print_settings_set_print_pages (settings, GTK_PRINT_PAGES_ALL);
-       gtk_print_settings_set_scale (settings, 1.0);
-       gtk_print_settings_set_collate (settings, FALSE);
-       gtk_print_settings_set_reverse (settings, FALSE);
-       
-       job = gtk_print_job_new ("evince-print",
-                                window->priv->printer,
-                                settings,
-                                window->priv->print_page_setup);
-
-       g_object_unref (settings);
-       
-       window->priv->gtk_print_job = job;
+       if (capabilities & EV_FILE_EXPORTER_CAN_COPIES)
+               gtk_print_settings_set_n_copies (settings, 1);
+       if (capabilities & EV_FILE_EXPORTER_CAN_PAGE_SET)
+               gtk_print_settings_set_page_set (settings, GTK_PAGE_SET_ALL);
+       if (capabilities & EV_FILE_EXPORTER_CAN_SCALE)
+               gtk_print_settings_set_scale (settings, 1.0);
+       if (capabilities & EV_FILE_EXPORTER_CAN_COLLATE)
+               gtk_print_settings_set_collate (settings, FALSE);
+       if (capabilities & EV_FILE_EXPORTER_CAN_REVERSE)
+               gtk_print_settings_set_reverse (settings, FALSE);
+       if (capabilities & EV_FILE_EXPORTER_CAN_NUMBER_UP)
+               gtk_print_settings_set_number_up (settings, 1);
+       
+       if (window->priv->print_preview) {
+               gchar *uri;
+               gchar *print_settings_file = NULL;
 
-       if (gtk_print_job_set_source_file (job, filename, &error)) {
-               gtk_print_job_send (job,
-                                   (GtkPrintJobCompleteFunc)ev_window_print_finished,
-                                   window, NULL);
+               ev_application_set_print_settings (EV_APP,
+                                                  window->priv->print_settings);
+               
+#if GTK_CHECK_VERSION (2, 11, 0)
+               print_settings_file = ev_tmp_filename ("print-settings");
+               gtk_print_settings_to_file (settings, print_settings_file, NULL);
+#endif
+               uri = g_filename_to_uri (filename, NULL, NULL);
+               ev_application_open_uri_at_dest (EV_APP,
+                                                uri, 
+                                                gtk_window_get_screen (GTK_WINDOW (window)),
+                                                NULL,
+                                                EV_WINDOW_MODE_PREVIEW,
+                                                TRUE,
+                                                print_settings_file,
+                                                GDK_CURRENT_TIME);
+               g_free (print_settings_file);
+               g_free (uri);
        } else {
-               ev_window_clear_print_job (window);
-               g_warning (error->message);
-               g_error_free (error);
+               GtkPrintJob *job;
+               GError      *error = NULL;
+       
+               job = gtk_print_job_new ("evince-print",
+                                        window->priv->printer,
+                                        settings,
+                                        window->priv->print_page_setup);
+
+               if (window->priv->gtk_print_job)
+                       g_object_unref (window->priv->gtk_print_job);
+               window->priv->gtk_print_job = job;
+
+               if (gtk_print_job_set_source_file (job, filename, &error)) {
+                       gtk_print_job_send (job,
+                                           (GtkPrintJobCompleteFunc)ev_window_print_finished,
+                                           window, NULL);
+               } else {
+                       ev_window_clear_print_job (window);
+                       g_warning (error->message);
+                       g_error_free (error);
+               }
        }
+
+       g_object_unref (settings);
 }
 
 static void
@@ -2147,6 +2300,7 @@ ev_window_print_dialog_response_cb (GtkDialog *dialog,
        EvPrintPageSet page_set;
        gint           n_ranges = 0;
        gint           copies;
+       gint           pages_per_sheet;
        gboolean       collate;
        gboolean       reverse;
        gdouble        scale;
@@ -2156,13 +2310,15 @@ ev_window_print_dialog_response_cb (GtkDialog *dialog,
        GtkPrintPages  print_pages;
        const gchar   *file_format;
        
-       if (response != GTK_RESPONSE_OK) {
+       if (response == GTK_RESPONSE_CANCEL) {
                gtk_widget_destroy (GTK_WIDGET (dialog));
                window->priv->print_dialog = NULL;
 
                return FALSE;
        }
 
+       window->priv->print_preview = (response == GTK_RESPONSE_APPLY);
+
        if (window->priv->printer)
                g_object_unref (window->priv->printer);
        if (window->priv->print_settings)
@@ -2236,6 +2392,8 @@ ev_window_print_dialog_response_cb (GtkDialog *dialog,
                height *= scale;
        }
 
+       pages_per_sheet = gtk_print_settings_get_number_up (window->priv->print_settings);
+       
        copies = gtk_print_settings_get_n_copies (window->priv->print_settings);
        collate = gtk_print_settings_get_collate (window->priv->print_settings);
        reverse = gtk_print_settings_get_reverse (window->priv->print_settings);
@@ -2245,6 +2403,7 @@ ev_window_print_dialog_response_cb (GtkDialog *dialog,
                                                    width, height,
                                                    ranges, n_ranges,
                                                    page_set,
+                                                   pages_per_sheet,
                                                    copies, collate,
                                                    reverse);
        
@@ -2281,8 +2440,10 @@ ev_window_print_range (EvWindow *ev_window, int first_page, int last_page)
        current_page = ev_page_cache_get_current_page (page_cache);
        document_last_page = ev_page_cache_get_n_pages (page_cache);
 
-       if (!ev_window->priv->print_settings)
-               ev_window->priv->print_settings = gtk_print_settings_new ();
+       if (!ev_window->priv->print_settings) {
+               ev_window->priv->print_settings = g_object_ref (
+                       ev_application_get_print_settings (EV_APP));
+       }
 
        if (first_page != 1 || last_page != document_last_page) {
                GtkPageRange range;
@@ -2300,19 +2461,8 @@ ev_window_print_range (EvWindow *ev_window, int first_page, int last_page)
        dialog = gtk_print_unix_dialog_new (_("Print"), GTK_WINDOW (ev_window));
        ev_window->priv->print_dialog = dialog;
        
-       capabilities = GTK_PRINT_CAPABILITY_PAGE_SET |
-               GTK_PRINT_CAPABILITY_COPIES |
-               GTK_PRINT_CAPABILITY_COLLATE |
-               GTK_PRINT_CAPABILITY_REVERSE |
-               GTK_PRINT_CAPABILITY_SCALE |
-               GTK_PRINT_CAPABILITY_GENERATE_PS;
-       
-       if (EV_IS_FILE_EXPORTER (ev_window->priv->document) &&
-           ev_file_exporter_format_supported (EV_FILE_EXPORTER (ev_window->priv->document),
-                                              EV_FILE_FORMAT_PDF)) {
-               capabilities |= GTK_PRINT_CAPABILITY_GENERATE_PDF;
-       }
-       
+       capabilities = GTK_PRINT_CAPABILITY_PREVIEW |
+               ev_file_exporter_get_capabilities (EV_FILE_EXPORTER (ev_window->priv->document));
        gtk_print_unix_dialog_set_manual_capabilities (GTK_PRINT_UNIX_DIALOG (dialog),
                                                       capabilities);
 
@@ -2756,9 +2906,16 @@ presentation_set_timeout (EvWindow *window)
        if (window->priv->presentation_timeout_id > 0) {
                g_source_remove (window->priv->presentation_timeout_id);
        }
-       
+
+#if GLIB_CHECK_VERSION (2, 13, 0)
+       window->priv->presentation_timeout_id =
+               g_timeout_add_seconds (PRESENTATION_TIMEOUT,
+                                      (GSourceFunc)presentation_timeout_cb, window);
+#else
        window->priv->presentation_timeout_id = 
-           g_timeout_add (PRESENTATION_TIMEOUT, (GSourceFunc)presentation_timeout_cb, window);
+           g_timeout_add (PRESENTATION_TIMEOUT * 1000,
+                          (GSourceFunc)presentation_timeout_cb, window);
+#endif 
 
        ev_view_show_cursor (EV_VIEW (window->priv->view));
 }
@@ -2878,7 +3035,7 @@ ev_window_cmd_view_presentation (GtkAction *action, EvWindow *window)
 {
        gboolean presentation;
 
-        g_return_if_fail (EV_IS_WINDOW (window));
+       g_return_if_fail (EV_IS_WINDOW (window));
        ev_window_stop_fullscreen (window);
 
        presentation = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
@@ -2892,6 +3049,8 @@ ev_window_cmd_view_presentation (GtkAction *action, EvWindow *window)
 static void
 ev_window_run_preview (EvWindow *window)
 {
+       GtkAction *action;
+       
        if (!window->priv->preview_toolbar) {
                window->priv->preview_toolbar =
                        gtk_ui_manager_get_widget (window->priv->ui_manager,
@@ -2911,6 +3070,14 @@ ev_window_run_preview (EvWindow *window)
        update_chrome_flag (window, EV_CHROME_SIDEBAR, FALSE);
 
        update_chrome_flag (window, EV_CHROME_PREVIEW_TOOLBAR, TRUE);
+       
+       action = gtk_action_group_get_action (window->priv->action_group,
+                                             "PreviewPrint");
+#if GTK_CHECK_VERSION (2, 11, 0)
+       gtk_action_set_visible (action, TRUE);
+#else
+       gtk_action_set_visible (action, FALSE);
+#endif
 
        update_chrome_visibility (window);
 }
@@ -2927,22 +3094,8 @@ ev_window_screen_changed (GtkWidget *widget,
        if (screen == old_screen)
                return;
 
-#ifdef HAVE_GTK_RECENT
-       if (old_screen) {
-               g_signal_handlers_disconnect_by_func (
-                       gtk_recent_manager_get_for_screen (old_screen),
-                       G_CALLBACK (ev_window_setup_recent), window);
-       }
-
-       priv->recent_manager = gtk_recent_manager_get_for_screen (screen);
-       g_signal_connect_swapped (priv->recent_manager,
-                                 "changed",
-                                 G_CALLBACK (ev_window_setup_recent),
-                                 window);
-#endif
-       
-       ev_view_set_screen_dpi (EV_VIEW (window->priv->view),
-                               ev_window_get_screen_dpi (window));
+       ev_view_set_screen_dpi (EV_VIEW (priv->view),
+                               get_screen_dpi (GTK_WINDOW (window)));
        
        if (GTK_WIDGET_CLASS (ev_window_parent_class)->screen_changed) {
                GTK_WIDGET_CLASS (ev_window_parent_class)->screen_changed (widget, old_screen);
@@ -3125,7 +3278,7 @@ ev_window_cmd_view_reload (GtkAction *action, EvWindow *ev_window)
        gchar *uri;
 
        uri = g_strdup (ev_window->priv->uri);
-       ev_window_open_uri (ev_window, uri, NULL, 0, FALSE);
+       ev_window_open_uri (ev_window, uri, NULL, 0, FALSE, NULL);
        g_free (uri);
 }
 
@@ -3133,15 +3286,47 @@ 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;
 
-       g_return_if_fail (EV_IS_WINDOW (ev_window));
+       int i;
 
-       gnome_help_display ("evince.xml", NULL, &error);
+       const char * const * langs = g_get_language_names ();
 
-       if(error != NULL) {
+       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;
+               }
+       }
+
+       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 (error->message);
                g_error_free (error);
        }
+       g_free (command);
 }
 
 static void
@@ -3157,6 +3342,139 @@ ev_window_cmd_start_presentation (GtkAction *action, EvWindow *window)
        ev_window_run_presentation (window);
 }
 
+#ifdef WITH_GTK_PRINT
+static void ev_window_do_preview_print (EvWindow *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) {
+               GtkWidget *dialog;
+
+               dialog = gtk_message_dialog_new (GTK_WINDOW (window),
+                                                GTK_DIALOG_MODAL,
+                                                GTK_MESSAGE_ERROR,
+                                                GTK_BUTTONS_OK,
+                                                _("Failed to print document"));
+               gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+                                                         error->message);
+
+               gtk_dialog_run (GTK_DIALOG (dialog));
+               gtk_widget_destroy (dialog);
+       }
+
+       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 ("evince-print",
+                                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 (error->message);
+               g_error_free (error);
+       }
+
+       g_free (filename);
+
+       gtk_widget_hide (GTK_WIDGET (window));
+}
+
+#endif /* WITH_GTK_PRINT */
+
+static void
+ev_window_cmd_preview_print (GtkAction *action, EvWindow *window)
+{
+#ifdef WITH_GTK_PRINT
+       EvWindowPrivate *priv = window->priv;
+       GtkPrintSettings *print_settings = NULL;
+#if GTK_CHECK_VERSION (2, 11, 0)
+       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 (error->message);
+                               g_error_free (error);
+                               print_settings = NULL;
+                       }
+               }
+       }
+#endif /* GTK 2.11.0 */
+       
+       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);
+#endif /* WITH_GTK_PRINT */
+}
+
 static void
 ev_window_cmd_escape (GtkAction *action, EvWindow *window)
 {
@@ -3189,38 +3507,6 @@ ev_window_cmd_escape (GtkAction *action, EvWindow *window)
        }
 }
 
-static void
-update_view_size (EvView *view, EvWindow *window)
-{
-       int width, height;
-       GtkRequisition vsb_requisition;
-       GtkRequisition hsb_requisition;
-       int scrollbar_spacing;
-
-       /* Calculate the width available for the */
-       width = window->priv->scrolled_window->allocation.width;
-       height = window->priv->scrolled_window->allocation.height;
-
-       if (gtk_scrolled_window_get_shadow_type (GTK_SCROLLED_WINDOW (window->priv->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 (window->priv->scrolled_window)->vscrollbar,
-                                &vsb_requisition);
-       gtk_widget_size_request (GTK_SCROLLED_WINDOW (window->priv->scrolled_window)->hscrollbar,
-                                &hsb_requisition);
-       gtk_widget_style_get (window->priv->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
 save_sizing_mode (EvWindow *window)
 {
@@ -3248,10 +3534,11 @@ ev_window_sizing_mode_changed_cb (EvView *view, GParamSpec *pspec,
 
        scrolled_window = ev_window->priv->scrolled_window;
 
-       g_signal_handlers_disconnect_by_func (ev_window->priv->view, update_view_size, ev_window);
+       g_signal_handlers_disconnect_by_func (ev_window->priv->view, ev_view_update_view_size, scrolled_window);
 
        if (sizing_mode != EV_SIZING_FREE)
-               update_view_size (NULL, ev_window);
+               ev_view_update_view_size (EV_VIEW (ev_window->priv->view),
+                                         GTK_SCROLLED_WINDOW (scrolled_window));
 
        switch (sizing_mode) {
                case EV_SIZING_BEST_FIT:
@@ -3260,8 +3547,8 @@ ev_window_sizing_mode_changed_cb (EvView *view, GParamSpec *pspec,
                                      "vscrollbar-policy", GTK_POLICY_AUTOMATIC,
                                      NULL);
                        g_signal_connect (ev_window->priv->view, "zoom_invalid",
-                                         G_CALLBACK (update_view_size),
-                                         ev_window);
+                                         G_CALLBACK (ev_view_update_view_size),
+                                         scrolled_window);
                        break;
                case EV_SIZING_FIT_WIDTH:
                        g_object_set (G_OBJECT (scrolled_window),
@@ -3269,8 +3556,8 @@ ev_window_sizing_mode_changed_cb (EvView *view, GParamSpec *pspec,
                                      "vscrollbar-policy", GTK_POLICY_AUTOMATIC,
                                      NULL);
                        g_signal_connect (ev_window->priv->view, "zoom_invalid",
-                                         G_CALLBACK (update_view_size),
-                                         ev_window);
+                                         G_CALLBACK (ev_view_update_view_size),
+                                         scrolled_window);
                        break;
                case EV_SIZING_FREE:
                        g_object_set (G_OBJECT (scrolled_window),
@@ -3293,7 +3580,7 @@ ev_window_zoom_changed_cb (EvView *view, GParamSpec *pspec, EvWindow *ev_window)
                gdouble zoom;
 
                zoom = ev_view_get_zoom (view);
-               zoom *= 72.0 / ev_window_get_screen_dpi (ev_window);
+               zoom *= 72.0 / get_screen_dpi (GTK_WINDOW(ev_window));
                ev_metadata_manager_set_double (ev_window->priv->uri, "zoom", zoom);
        }
 }
@@ -3480,6 +3767,9 @@ ev_window_view_toolbar_cb (GtkAction *action, EvWindow *ev_window)
 static void
 ev_window_view_sidebar_cb (GtkAction *action, EvWindow *ev_window)
 {
+       if (ev_view_get_presentation (EV_VIEW (ev_window->priv->view)))
+               return;
+           
        update_chrome_flag (ev_window, EV_CHROME_SIDEBAR,
                            gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
 }
@@ -3520,9 +3810,7 @@ ev_window_sidebar_visibility_changed_cb (EvSidebar  *ev_sidebar,
 
        action = gtk_action_group_get_action (ev_window->priv->action_group, "ViewSidebar");
 
-       if (!ev_view_get_presentation (view) && 
-           !ev_view_get_fullscreen (view)) {
-
+       if (!ev_view_get_presentation (view)) {
                gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
                                              GTK_WIDGET_VISIBLE (ev_sidebar));
 
@@ -3758,7 +4046,7 @@ zoom_control_changed_cb (EphyZoomAction *action,
        
        if (mode == EV_SIZING_FREE) {
                ev_view_set_zoom (EV_VIEW (ev_window->priv->view),
-                                 zoom * ev_window_get_screen_dpi (ev_window) / 72.0,
+                                 zoom * get_screen_dpi (GTK_WINDOW (ev_window)) / 72.0,
                                  FALSE);
        }
 }
@@ -3931,6 +4219,11 @@ 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;
@@ -4044,6 +4337,9 @@ 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", "",
@@ -4105,10 +4401,10 @@ static const GtkToggleActionEntry toggle_entries[] = {
         { "ViewDual", EV_STOCK_VIEW_DUAL, N_("_Dual"), NULL,
          N_("Show two pages at once"),
          G_CALLBACK (ev_window_cmd_dual), FALSE },
-        { "ViewFullscreen", NULL, N_("_Fullscreen"), "F11",
+        { "ViewFullscreen", GTK_STOCK_FULLSCREEN, N_("_Fullscreen"), "F11",
           N_("Expand the window to fill the screen"),
           G_CALLBACK (ev_window_cmd_view_fullscreen) },
-        { "ViewPresentation", NULL, N_("_Presentation"), "F5",
+        { "ViewPresentation", EV_STOCK_RUN_PRESENTATION, N_("_Presentation"), "F5",
           N_("Run document as a presentation"),
           G_CALLBACK (ev_window_cmd_view_presentation) },
         { "ViewBestFit", EV_STOCK_ZOOM_PAGE, N_("_Best Fit"), NULL,
@@ -4173,6 +4469,7 @@ register_custom_actions (EvWindow *window, GtkActionGroup *group)
                               "name", PAGE_SELECTOR_ACTION,
                               "label", _("Page"),
                               "tooltip", _("Select Page"),
+                              "icon_name", "text-x-generic",
                               "visible_overflown", FALSE,
                               NULL);
        g_signal_connect (action, "activate_link",
@@ -4183,7 +4480,7 @@ register_custom_actions (EvWindow *window, GtkActionGroup *group)
        action = g_object_new (EPHY_TYPE_ZOOM_ACTION,
                               "name", ZOOM_CONTROL_ACTION,
                               "label", _("Zoom"),
-                              "stock_id", GTK_STOCK_ZOOM_IN,
+                              "stock_id", EV_STOCK_ZOOM,
                               "tooltip", _("Adjust the zoom level"),
                               "zoom", 1.0,
                               NULL);
@@ -4454,6 +4751,7 @@ open_remote_link (EvWindow *window, EvLinkAction *action)
                                         ev_link_action_get_dest (action),
                                         0,
                                         FALSE,
+                                        NULL,
                                         GDK_CURRENT_TIME);
 
        g_free (uri);
@@ -4563,9 +4861,11 @@ image_save_dialog_response_cb (GtkWidget *fc,
                               gint       response_id,
                               EvWindow  *ev_window)
 {
-       gchar  *uri;
-       gchar  *filename;
-       GError *error = NULL;
+       GnomeVFSURI *target_uri;
+       gchar       *uri;
+       gchar       *filename;
+       gboolean     is_local;
+       GError      *error = NULL;
        
        if (response_id != GTK_RESPONSE_OK) {
                gtk_widget_destroy (fc);
@@ -4573,7 +4873,15 @@ image_save_dialog_response_cb (GtkWidget *fc,
        }
 
        uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (fc));
-       filename = g_filename_from_uri (uri, NULL, NULL);
+       target_uri = gnome_vfs_uri_new (uri);
+       is_local = gnome_vfs_uri_is_local (target_uri);
+       
+       if (is_local) {
+               filename = g_filename_from_uri (uri, NULL, NULL);
+       } else {
+               filename = ev_tmp_filename ("saveimage");
+       }
+       
        g_free (uri);
        
        /* FIXME: allow saving in other image formats than png */
@@ -4585,10 +4893,26 @@ image_save_dialog_response_cb (GtkWidget *fc,
                                        _("The image could not be saved."),
                                        error);
                g_error_free (error);
+               g_free (filename);
+               gnome_vfs_uri_unref (target_uri);
+               gtk_widget_destroy (fc);
+
+               return;
        }
 
-       g_free (filename);
+       if (!is_local) {
+               GnomeVFSURI *source_uri;
+               gchar       *local_uri;
 
+               local_uri = g_filename_to_uri (filename, NULL, NULL);
+               source_uri = gnome_vfs_uri_new (local_uri);
+               g_free (local_uri);
+               ev_window_save_remote (ev_window, source_uri, target_uri);
+               gnome_vfs_uri_unref (source_uri);
+       }
+       
+       g_free (filename);
+       gnome_vfs_uri_unref (target_uri);
        gtk_widget_destroy (fc);
 }
 
@@ -4610,6 +4934,7 @@ ev_view_popup_cmd_save_image_as (GtkAction *action, EvWindow *window)
                                          NULL);
 
        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 ();
@@ -4668,10 +4993,12 @@ attachment_save_dialog_response_cb (GtkWidget *fc,
                                    gint       response_id,
                                    EvWindow  *ev_window)
 {
+       GnomeVFSURI          *target_uri;
        gchar                *uri;
        GList                *l;
        GtkFileChooserAction  fc_action;
        gboolean              is_dir;
+       gboolean              is_local;
        
        if (response_id != GTK_RESPONSE_OK) {
                gtk_widget_destroy (fc);
@@ -4679,9 +5006,10 @@ attachment_save_dialog_response_cb (GtkWidget *fc,
        }
 
        uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (fc));
-       
+       target_uri = gnome_vfs_uri_new (uri);
        g_object_get (G_OBJECT (fc), "action", &fc_action, NULL);
        is_dir = (fc_action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
+       is_local = gnome_vfs_uri_is_local (target_uri);
        
        for (l = ev_window->priv->attach_list; l && l->data; l = g_list_next (l)) {
                EvAttachment *attachment;
@@ -4690,26 +5018,57 @@ attachment_save_dialog_response_cb (GtkWidget *fc,
                
                attachment = (EvAttachment *) l->data;
 
-               if (is_dir) {
-                       filename = g_strjoin ("/", uri,
-                                             ev_attachment_get_name (attachment),
-                                             NULL);
+               if (is_local) {
+                       if (is_dir) {
+                               filename = g_strjoin ("/", uri,
+                                                     ev_attachment_get_name (attachment),
+                                                     NULL);
+                       } else {
+                               filename = g_strdup (uri);
+                       }
                } else {
-                       filename = g_strdup (uri);
+                       filename = ev_tmp_filename ("saveattachment");
                }
-               
+
                ev_attachment_save (attachment, filename, &error);
-               g_free (filename);
                
                if (error) {
                        ev_window_error_dialog (GTK_WINDOW (ev_window),
                                                _("The attachment could not be saved."),
                                                error);
                        g_error_free (error);
+                       g_free (filename);
+
+                       continue;
                }
+
+               if (!is_local) {
+                       GnomeVFSURI *src_uri;
+                       GnomeVFSURI *dest_uri;
+                       gchar       *local_uri;
+
+                       if (is_dir) {
+                               const gchar *name = ev_attachment_get_name (attachment);
+
+                               dest_uri = gnome_vfs_uri_append_file_name (target_uri,
+                                                                          name);
+                       } else {
+                               dest_uri = gnome_vfs_uri_ref (target_uri);
+                       }
+                       
+                       local_uri = g_filename_to_uri (filename, NULL, NULL);
+                       src_uri = gnome_vfs_uri_new (local_uri);
+                       g_free (local_uri);
+                       ev_window_save_remote (ev_window, src_uri, dest_uri);
+                       gnome_vfs_uri_unref (src_uri);
+                       gnome_vfs_uri_unref (dest_uri);
+               }
+
+               g_free (filename);
        }
 
        g_free (uri);
+       gnome_vfs_uri_unref (target_uri);
 
        gtk_widget_destroy (fc);
 }
@@ -4737,6 +5096,7 @@ ev_attachment_popup_cmd_save_attachment_as (GtkAction *action, EvWindow *window)
 
        gtk_dialog_set_default_response (GTK_DIALOG (fc), GTK_RESPONSE_OK);
        gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (fc), TRUE);
+       gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (fc), FALSE);
 
        if (attachment)
                gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (fc),
@@ -4818,8 +5178,13 @@ ev_window_init (EvWindow *ev_window)
        }
        
 #ifdef HAVE_GTK_RECENT
+#if GTK_CHECK_VERSION(2,11,4)
+       ev_window->priv->recent_manager = gtk_recent_manager_get_default ();
+#else
+       /* It's fine to just use the one of the default screen here */
        ev_window->priv->recent_manager = gtk_recent_manager_get_for_screen (
-               gtk_widget_get_screen (GTK_WIDGET (ev_window)));
+               gdk_screen_get_default ());
+#endif
        ev_window->priv->recent_action_group = NULL;
        ev_window->priv->recent_ui_id = 0;
        g_signal_connect_swapped (ev_window->priv->recent_manager,
@@ -4869,6 +5234,17 @@ ev_window_init (EvWindow *ev_window)
 
        /* Stub sidebar, for now */
 
+       sidebar_widget = ev_sidebar_thumbnails_new ();
+       ev_window->priv->sidebar_thumbs = sidebar_widget;
+       g_signal_connect (sidebar_widget,
+                         "notify::main-widget",
+                         G_CALLBACK (sidebar_page_main_widget_update_cb),
+                         ev_window);
+       sidebar_page_main_widget_update_cb (G_OBJECT (sidebar_widget), NULL, ev_window);
+       gtk_widget_show (sidebar_widget);
+       ev_sidebar_add_page (EV_SIDEBAR (ev_window->priv->sidebar),
+                            sidebar_widget);
+
        sidebar_widget = ev_sidebar_links_new ();
        ev_window->priv->sidebar_links = sidebar_widget;
        g_signal_connect (sidebar_widget,
@@ -4894,17 +5270,6 @@ ev_window_init (EvWindow *ev_window)
        ev_sidebar_add_page (EV_SIDEBAR (ev_window->priv->sidebar),
                             sidebar_widget);
 
-       sidebar_widget = ev_sidebar_thumbnails_new ();
-       ev_window->priv->sidebar_thumbs = sidebar_widget;
-       g_signal_connect (sidebar_widget,
-                         "notify::main-widget",
-                         G_CALLBACK (sidebar_page_main_widget_update_cb),
-                         ev_window);
-       sidebar_page_main_widget_update_cb (G_OBJECT (sidebar_widget), NULL, ev_window);
-       gtk_widget_show (sidebar_widget);
-       ev_sidebar_add_page (EV_SIDEBAR (ev_window->priv->sidebar),
-                            sidebar_widget);
-
        ev_window->priv->scrolled_window =
                GTK_WIDGET (g_object_new (GTK_TYPE_SCROLLED_WINDOW,
                                          "shadow-type", GTK_SHADOW_IN,
@@ -4916,7 +5281,7 @@ ev_window_init (EvWindow *ev_window)
 
        ev_window->priv->view = ev_view_new ();
        ev_view_set_screen_dpi (EV_VIEW (ev_window->priv->view),
-                               ev_window_get_screen_dpi (ev_window));
+                               get_screen_dpi (GTK_WINDOW (ev_window)));
        ev_window->priv->password_view = ev_password_view_new ();
        g_signal_connect_swapped (ev_window->priv->password_view,
                                  "unlock",