+static void
+ev_window_load_job_cb (EvJobLoad *job,
+ gpointer data)
+{
+ EvWindow *ev_window = EV_WINDOW (data);
+ EvDocument *document = EV_JOB (job)->document;
+
+ g_assert (job->uri);
+
+ ev_view_set_loading (EV_VIEW (ev_window->priv->view), FALSE);
+
+ /* Success! */
+ if (job->error == NULL) {
+ ev_window_set_document (ev_window, document);
+
+ if (job->mode != EV_WINDOW_MODE_PREVIEW) {
+ setup_view_from_metadata (ev_window);
+ }
+
+ if (!ev_window->priv->unlink_temp_file) {
+ ev_window_add_recent (ev_window, ev_window->priv->uri);
+ }
+
+ if (job->dest) {
+ EvLink *link;
+ EvLinkAction *link_action;
+
+ link_action = ev_link_action_new_dest (g_object_ref (job->dest));
+ link = ev_link_new (NULL, link_action);
+ ev_view_handle_link (EV_VIEW (ev_window->priv->view), link);
+ g_object_unref (link);
+ }
+
+ switch (job->mode) {
+ case EV_WINDOW_MODE_FULLSCREEN:
+ ev_window_run_fullscreen (ev_window);
+ break;
+ case EV_WINDOW_MODE_PRESENTATION:
+ ev_window_run_presentation (ev_window);
+ break;
+ case EV_WINDOW_MODE_PREVIEW:
+ ev_window_run_preview (ev_window);
+ break;
+ default:
+ break;
+ }
+
+ ev_window_clear_load_job (ev_window);
+ return;
+ }
+
+ if (job->error->domain == EV_DOCUMENT_ERROR &&
+ job->error->code == EV_DOCUMENT_ERROR_ENCRYPTED) {
+ gchar *base_name, *file_name;
+
+ setup_view_from_metadata (ev_window);
+
+ file_name = gnome_vfs_format_uri_for_display (job->uri);
+ base_name = g_path_get_basename (file_name);
+ ev_password_view_set_file_name (EV_PASSWORD_VIEW (ev_window->priv->password_view),
+ base_name);
+ g_free (file_name);
+ g_free (base_name);
+ ev_window_set_page_mode (ev_window, PAGE_MODE_PASSWORD);
+
+ ev_window_popup_password_dialog (ev_window);
+ } else {
+ ev_window_error_dialog (GTK_WINDOW (ev_window),
+ _("Unable to open document"),
+ job->error);
+ ev_window_clear_load_job (ev_window);
+ }
+
+ return;
+}
+
+const char *
+ev_window_get_uri (EvWindow *ev_window)
+{
+ return ev_window->priv->uri;
+}
+
+static void
+ev_window_close_dialogs (EvWindow *ev_window)
+{
+ if (ev_window->priv->password_dialog)
+ gtk_widget_destroy (ev_window->priv->password_dialog);
+ ev_window->priv->password_dialog = NULL;
+
+#ifdef WITH_PRINT
+ if (ev_window->priv->print_dialog)
+ gtk_widget_destroy (ev_window->priv->print_dialog);
+ ev_window->priv->print_dialog = NULL;
+#endif
+
+#ifdef WITH_GNOME_PRINT
+ if (ev_window->priv->print_job)
+ g_object_unref (ev_window->priv->print_job);
+ ev_window->priv->print_job = NULL;
+#endif
+
+ if (ev_window->priv->properties)
+ gtk_widget_destroy (ev_window->priv->properties);
+ ev_window->priv->properties = NULL;
+}
+
+static gint
+xfer_update_progress_callback (GnomeVFSAsyncHandle *handle,
+ GnomeVFSXferProgressInfo *info,
+ EvWindow *ev_window)
+{
+ switch (info->status) {
+ case GNOME_VFS_XFER_PROGRESS_STATUS_OK:
+ if (info->phase == GNOME_VFS_XFER_PHASE_COMPLETED) {
+ ev_job_queue_add_job (ev_window->priv->load_job, EV_JOB_PRIORITY_HIGH);
+ }
+
+ return 1;
+ case GNOME_VFS_XFER_PROGRESS_STATUS_VFSERROR:
+ case GNOME_VFS_XFER_PROGRESS_STATUS_OVERWRITE:
+ case GNOME_VFS_XFER_PROGRESS_STATUS_DUPLICATE:
+ return 1;
+ default:
+ g_assert_not_reached ();
+ }
+
+ return 0;
+}
+
+void
+ev_window_open_uri (EvWindow *ev_window,
+ const char *uri,
+ EvLinkDest *dest,
+ EvWindowRunMode mode,
+ gboolean unlink_temp_file)
+{
+ GnomeVFSURI *source_uri;
+ GnomeVFSURI *target_uri;
+
+ ev_window_close_dialogs (ev_window);
+ ev_window_clear_load_job (ev_window);
+ ev_window_clear_local_uri (ev_window);
+ ev_view_set_loading (EV_VIEW (ev_window->priv->view), TRUE);
+
+ ev_window->priv->unlink_temp_file = unlink_temp_file;
+
+ if (ev_window->priv->uri)
+ g_free (ev_window->priv->uri);
+ ev_window->priv->uri = g_strdup (uri);
+
+ setup_size_from_metadata (ev_window);
+
+ ev_window->priv->load_job = ev_job_load_new (uri, dest, mode);
+ g_signal_connect (ev_window->priv->load_job,
+ "finished",
+ G_CALLBACK (ev_window_load_job_cb),
+ ev_window);
+
+ source_uri = gnome_vfs_uri_new (uri);
+ if (!gnome_vfs_uri_is_local (source_uri) && !ev_window->priv->local_uri) {
+ GnomeVFSAsyncHandle *handle;
+ GList *slist = NULL;
+ GList *tlist = NULL;
+ char *tmp_name;
+ char *base_name;
+
+ /* We'd like to keep extension of source uri since
+ * it helps to resolve some mime types, say cbz */
+
+ tmp_name = ev_tmp_filename (NULL);
+ base_name = gnome_vfs_uri_extract_short_name (source_uri);
+ ev_window->priv->local_uri = g_strconcat ("file:", tmp_name, "-", base_name, NULL);
+ ev_job_load_set_uri (EV_JOB_LOAD (ev_window->priv->load_job),
+ ev_window->priv->local_uri);
+ g_free (base_name);
+ g_free (tmp_name);
+
+ target_uri = gnome_vfs_uri_new (ev_window->priv->local_uri);
+
+ slist = g_list_prepend (slist, source_uri);
+ tlist = g_list_prepend (tlist, target_uri);
+ 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)xfer_update_progress_callback,
+ ev_window,
+ NULL, NULL);
+
+ g_list_free (slist);
+ g_list_free (tlist);
+ gnome_vfs_uri_unref (target_uri);
+ gnome_vfs_uri_unref (source_uri);
+
+ return;
+ }
+
+ gnome_vfs_uri_unref (source_uri);
+ ev_job_queue_add_job (ev_window->priv->load_job, EV_JOB_PRIORITY_HIGH);
+}
+
+static void
+file_open_dialog_response_cb (GtkWidget *chooser,
+ gint response_id,
+ EvWindow *ev_window)
+{
+ if (response_id == GTK_RESPONSE_OK) {
+ GSList *uris;
+
+ 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_free (uris);
+ }
+ ev_application_set_chooser_uri (EV_APP,
+ gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (chooser)));
+
+ gtk_widget_destroy (chooser);
+}
+
+static void
+ev_window_cmd_file_open (GtkAction *action, EvWindow *window)
+{
+ GtkWidget *chooser;
+
+ chooser = gtk_file_chooser_dialog_new (_("Open Document"),
+ GTK_WINDOW (window),
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OPEN, GTK_RESPONSE_OK,
+ NULL);
+
+ 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);
+ }
+ else {
+ char *folder;
+ folder = xdg_user_dir_lookup ("DOCUMENTS");
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (chooser),
+ folder);
+ free (folder);
+ }
+
+ g_signal_connect (chooser, "response",
+ G_CALLBACK (file_open_dialog_response_cb),
+ window);
+
+ gtk_widget_show (chooser);
+}
+
+static gchar *
+ev_window_create_tmp_symlink (const gchar *filename, GError **error)
+{
+ gchar *tmp_filename = NULL;
+ gchar *name;
+ gint res;
+ guint i = 0;
+
+ name = g_path_get_basename (filename);
+
+ do {
+ gchar *basename;
+
+ if (tmp_filename)
+ g_free (tmp_filename);
+
+ basename = g_strdup_printf ("%s-%d", name, i++);
+ tmp_filename = g_build_filename (ev_tmp_dir (),
+ basename, NULL);
+
+ g_free (basename);
+ } while ((res = symlink (filename, tmp_filename)) != 0 && errno == EEXIST);
+
+ g_free (name);
+
+ if (res != 0 && errno != EEXIST) {
+ if (error) {
+ *error = g_error_new (G_FILE_ERROR,
+ g_file_error_from_errno (errno),
+ _("Couldn't create symlink “%s”: %s"),
+ tmp_filename, strerror (errno));
+ }
+
+ g_free (tmp_filename);
+
+ return NULL;
+ }
+
+ return tmp_filename;
+}
+
+static void
+ev_window_cmd_file_open_copy_at_dest (EvWindow *window, EvLinkDest *dest)
+{
+ GError *error = NULL;
+ gchar *symlink_uri;
+ gchar *old_filename;
+ gchar *new_filename;
+ const gchar *uri_unc;
+
+ uri_unc = g_object_get_data (G_OBJECT (window->priv->document),
+ "uri-uncompressed");
+ old_filename = g_filename_from_uri (uri_unc ? uri_unc : window->priv->uri,
+ NULL, NULL);
+ new_filename = ev_window_create_tmp_symlink (old_filename, &error);
+
+ if (error) {
+ ev_window_error_dialog (GTK_WINDOW (window),
+ _("Cannot open a copy."),
+ error);
+
+ g_error_free (error);
+ g_free (old_filename);
+ g_free (new_filename);
+
+ return;
+ }
+
+ g_free (old_filename);
+
+ symlink_uri = g_filename_to_uri (new_filename, NULL, NULL);
+ g_free (new_filename);
+
+ ev_application_open_uri_at_dest (EV_APP,
+ symlink_uri,
+ gtk_window_get_screen (GTK_WINDOW (window)),
+ dest,
+ 0,
+ TRUE,
+ GDK_CURRENT_TIME);
+ g_free (symlink_uri);
+}
+
+static void
+ev_window_cmd_file_open_copy (GtkAction *action, EvWindow *window)
+{
+ EvPageCache *page_cache;
+ EvLinkDest *dest;
+ gint current_page;
+
+ page_cache = ev_page_cache_get (window->priv->document);
+ current_page = ev_page_cache_get_current_page (page_cache);
+
+ dest = ev_link_dest_new_page (current_page);
+ ev_window_cmd_file_open_copy_at_dest (window, dest);
+ g_object_unref (dest);
+}
+
+#ifdef HAVE_GTK_RECENT
+static void
+ev_window_cmd_recent_file_activate (GtkAction *action,
+ EvWindow *window)
+{
+ GtkRecentInfo *info;
+ const gchar *uri;
+
+ info = g_object_get_data (G_OBJECT (action), "gtk-recent-info");
+ g_assert (info != NULL);
+
+ uri = gtk_recent_info_get_uri (info);
+
+ ev_application_open_uri_at_dest (EV_APP, uri,
+ gtk_window_get_screen (GTK_WINDOW (window)),
+ NULL, 0, FALSE,
+ GDK_CURRENT_TIME);
+}
+#else
+static void
+ev_window_cmd_recent_file_activate (GtkAction *action,
+ EvWindow *ev_window)
+{
+ char *uri;
+ EggRecentItem *item;
+
+ item = egg_recent_view_uimanager_get_item (ev_window->priv->recent_view,
+ action);
+
+ uri = egg_recent_item_get_uri (item);
+
+ ev_application_open_uri (EV_APP, uri, NULL,
+ GDK_CURRENT_TIME, NULL);
+
+ g_free (uri);
+}
+#endif /* HAVE_GTK_RECENT */
+
+static void
+ev_window_add_recent (EvWindow *window, const char *filename)
+{
+#ifdef HAVE_GTK_RECENT
+ gtk_recent_manager_add_item (window->priv->recent_manager, filename);
+#else
+ EggRecentItem *item;
+
+ item = egg_recent_item_new_from_uri (filename);
+ egg_recent_item_add_group (item, "Evince");
+ egg_recent_model_add_full (ev_application_get_recent_model (EV_APP), item);
+#endif /* HAVE_GTK_RECENT */
+}
+
+#ifdef HAVE_GTK_RECENT
+static gint
+compare_recent_items (GtkRecentInfo *a, GtkRecentInfo *b)
+{
+ gboolean has_ev_a, has_ev_b;
+ const gchar *evince = g_get_application_name ();
+
+ has_ev_a = gtk_recent_info_has_application (a, evince);
+ has_ev_b = gtk_recent_info_has_application (b, evince);
+
+ if (has_ev_a && has_ev_b) {
+ time_t time_a, time_b;
+
+ time_a = gtk_recent_info_get_modified (a);
+ time_b = gtk_recent_info_get_modified (b);
+
+ return (time_b - time_a);
+ } else if (has_ev_a) {
+ return -1;
+ } else if (has_ev_b) {
+ return 1;
+ }
+
+ return 0;
+}
+#endif /* HAVE_GTK_RECENT */
+
+/*
+ * Doubles underscore to avoid spurious menu accels.
+ */
+static gchar *
+ev_window_get_recent_file_label (gint index, const gchar *filename)
+{
+ GString *str;
+ gint length;
+ const gchar *p;
+ const gchar *end;
+
+ g_return_val_if_fail (filename != NULL, NULL);
+
+ length = strlen (filename);
+ str = g_string_sized_new (length + 10);
+ g_string_printf (str, "_%d. ", index);
+
+ p = filename;
+ end = filename + length;
+
+ while (p != end) {
+ const gchar *next;
+ next = g_utf8_next_char (p);
+
+ switch (*p) {
+ case '_':
+ g_string_append (str, "__");
+ break;
+ default:
+ g_string_append_len (str, p, next - p);
+ break;
+ }
+
+ p = next;
+ }
+
+ return g_string_free (str, FALSE);
+}
+
+static void
+ev_window_setup_recent (EvWindow *ev_window)
+{
+#ifdef HAVE_GTK_RECENT
+ GList *items, *l;
+ guint n_items = 0;
+ const gchar *evince = g_get_application_name ();
+ static guint i = 0;
+
+ if (ev_window->priv->recent_ui_id > 0) {
+ gtk_ui_manager_remove_ui (ev_window->priv->ui_manager,
+ ev_window->priv->recent_ui_id);
+ gtk_ui_manager_ensure_update (ev_window->priv->ui_manager);
+ }
+ ev_window->priv->recent_ui_id = gtk_ui_manager_new_merge_id (ev_window->priv->ui_manager);
+
+ if (ev_window->priv->recent_action_group) {
+ gtk_ui_manager_remove_action_group (ev_window->priv->ui_manager,
+ ev_window->priv->recent_action_group);
+ g_object_unref (ev_window->priv->recent_action_group);
+ }
+ ev_window->priv->recent_action_group = gtk_action_group_new ("RecentFilesActions");
+ gtk_ui_manager_insert_action_group (ev_window->priv->ui_manager,
+ ev_window->priv->recent_action_group, 0);
+
+ items = gtk_recent_manager_get_items (ev_window->priv->recent_manager);
+ items = g_list_sort (items, (GCompareFunc) compare_recent_items);
+
+ for (l = items; l && l->data; l = g_list_next (l)) {
+ GtkRecentInfo *info;
+ GtkAction *action;
+ gchar *action_name;
+ gchar *label;
+
+ info = (GtkRecentInfo *) l->data;
+
+ if (!gtk_recent_info_has_application (info, evince) ||
+ (gtk_recent_info_is_local (info) && !gtk_recent_info_exists (info)))
+ continue;
+
+ action_name = g_strdup_printf ("RecentFile%u", i++);
+ label = ev_window_get_recent_file_label (
+ n_items + 1, gtk_recent_info_get_display_name (info));
+
+ action = g_object_new (GTK_TYPE_ACTION,
+ "name", action_name,
+ "label", label,
+ NULL);
+
+ g_object_set_data_full (G_OBJECT (action),
+ "gtk-recent-info",
+ gtk_recent_info_ref (info),
+ (GDestroyNotify) gtk_recent_info_unref);
+
+ g_signal_connect (G_OBJECT (action), "activate",
+ G_CALLBACK (ev_window_cmd_recent_file_activate),
+ (gpointer) ev_window);
+
+ gtk_action_group_add_action (ev_window->priv->recent_action_group,
+ action);
+ g_object_unref (action);
+
+ gtk_ui_manager_add_ui (ev_window->priv->ui_manager,
+ ev_window->priv->recent_ui_id,
+ "/MainMenu/FileMenu/RecentFilesMenu",
+ label,
+ action_name,
+ GTK_UI_MANAGER_MENUITEM,
+ FALSE);
+ g_free (action_name);
+ g_free (label);
+
+ if (++n_items == 5)
+ break;
+ }
+
+ g_list_foreach (items, (GFunc) gtk_recent_info_unref, NULL);
+ g_list_free (items);
+#else /* HAVE_GTK_RECENT */
+ ev_window->priv->recent_view = egg_recent_view_uimanager_new (ev_window->priv->ui_manager,
+ "/MainMenu/FileMenu/RecentFilesMenu",
+ G_CALLBACK (ev_window_cmd_recent_file_activate),
+ ev_window);
+
+ egg_recent_view_uimanager_show_icons (EGG_RECENT_VIEW_UIMANAGER (ev_window->priv->recent_view), FALSE);
+
+ egg_recent_view_set_model (EGG_RECENT_VIEW (ev_window->priv->recent_view),
+ ev_application_get_recent_model (EV_APP));
+
+ egg_recent_view_uimanager_set_trailing_sep (ev_window->priv->recent_view, TRUE);
+
+ g_signal_connect (ev_window->priv->recent_view, "activate",
+ G_CALLBACK (ev_window_cmd_recent_file_activate), ev_window);
+#endif /* HAVE_GTK_RECENT */
+}
+
+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;
+
+ if (response_id != GTK_RESPONSE_OK) {
+ gtk_widget_destroy (fc);
+ return;
+ }
+
+
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (fc));
+ tmp_filename = g_strdup_printf ("%s.XXXXXX", filename);
+
+ fd = g_mkstemp (tmp_filename);
+ if (fd == -1) {
+ gchar *display_name;
+ gint save_errno = errno;
+
+ display_name = g_filename_display_name (tmp_filename);
+ g_set_error (&error,
+ G_FILE_ERROR,
+ g_file_error_from_errno (save_errno),
+ _("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 ();
+
+ g_free (uri);
+ 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;
+ const gchar *ext;
+
+ 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);
+
+ if (!uri_comp || error) {
+ tmp_filename = NULL;
+ } else {
+ tmp_filename = g_filename_from_uri (uri_comp,
+ NULL, NULL);
+ }
+
+ g_free (uri_comp);
+ }
+ }
+
+ if (tmp_filename && g_rename (tmp_filename, filename) == -1) {
+ g_unlink (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_error_free (error);
+ }
+
+ g_free (tmp_filename);
+ g_free (filename);
+
+ gtk_widget_destroy (fc);
+}
+
+static void
+ev_window_cmd_save_as (GtkAction *action, EvWindow *ev_window)
+{
+ GtkWidget *fc;
+ gchar *base_name;
+ gchar *file_name;
+ gchar *folder;
+
+ fc = gtk_file_chooser_dialog_new (
+ _("Save a Copy"),
+ GTK_WINDOW (ev_window), GTK_FILE_CHOOSER_ACTION_SAVE,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_SAVE, GTK_RESPONSE_OK,
+ NULL);
+
+ 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);
+ 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");
+ gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (fc), base_name);
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (fc), folder);
+ g_free (file_name);
+ g_free (base_name);
+ free (folder);
+
+ g_signal_connect (fc, "response",
+ G_CALLBACK (file_save_dialog_response_cb),
+ ev_window);
+
+ gtk_widget_show (fc);
+}
+
+#ifdef WITH_GTK_PRINT
+static void
+ev_window_print_page_setup_done_cb (GtkPageSetup *page_setup,
+ EvWindow *window)
+{
+ /* Dialog was canceled */
+ if (!page_setup)
+ return;
+
+ if (window->priv->print_page_setup)
+ g_object_unref (window->priv->print_page_setup);
+ window->priv->print_page_setup = g_object_ref (page_setup);
+}
+#endif /* WITH_GTK_PRINT */
+
+static void
+ev_window_cmd_file_print_setup (GtkAction *action, EvWindow *ev_window)
+{
+#ifdef WITH_GTK_PRINT
+ gtk_print_run_page_setup_dialog_async (
+ GTK_WINDOW (ev_window),
+ ev_window->priv->print_page_setup,
+ ev_window->priv->print_settings,
+ (GtkPageSetupDoneFunc) ev_window_print_page_setup_done_cb,
+ ev_window);
+#endif /* WITH_GTK_PRINT */
+}
+
+#ifdef WITH_GTK_PRINT
+static void
+ev_window_clear_print_job (EvWindow *window)
+{
+ if (window->priv->print_job) {
+ if (!window->priv->print_job->finished)
+ ev_job_queue_remove_job (window->priv->print_job);
+
+ g_signal_handlers_disconnect_by_func (window->priv->print_job,
+ ev_window_print_job_cb,
+ 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
+ev_window_print_finished (GtkPrintJob *print_job,
+ EvWindow *window,
+ GError *error)
+{
+ ev_window_clear_print_job (window);
+
+ 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);
+ }
+}
+
+static void
+ev_window_print_send (EvWindow *window,
+ const gchar *filename)
+{
+ GtkPrintJob *job;
+ GtkPrintSettings *settings;
+ GError *error = NULL;
+
+ 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,
+ * we want to send the exported file to printer with those
+ * settings set to default values.
+ */
+ settings = gtk_print_settings_copy (window->priv->print_settings);
+ gtk_print_settings_set_n_copies (settings, 1);
+ 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 (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);
+ }
+}
+
+static void
+ev_window_print_job_cb (EvJobPrint *job,
+ EvWindow *window)
+{
+ if (job->error) {
+ g_warning (job->error->message);
+ ev_window_clear_print_job (window);
+ return;
+ }
+
+ g_assert (job->temp_file != NULL);
+
+ ev_window_print_send (window, job->temp_file);
+}
+