+static void
+ev_window_clear_thumbnail_job (EvWindow *ev_window)
+{
+ if (ev_window->priv->thumbnail_job != NULL) {
+ if (!ev_job_is_finished (ev_window->priv->thumbnail_job))
+ ev_job_cancel (ev_window->priv->thumbnail_job);
+
+ g_signal_handlers_disconnect_by_func (ev_window->priv->thumbnail_job,
+ ev_window_set_icon_from_thumbnail,
+ ev_window);
+ g_object_unref (ev_window->priv->thumbnail_job);
+ ev_window->priv->thumbnail_job = NULL;
+ }
+}
+
+static void
+ev_window_set_icon_from_thumbnail (EvJobThumbnail *job,
+ EvWindow *ev_window)
+{
+ if (job->thumbnail) {
+ gtk_window_set_icon (GTK_WINDOW (ev_window),
+ job->thumbnail);
+ }
+
+ ev_window_clear_thumbnail_job (ev_window);
+}
+
+static void
+ev_window_refresh_window_thumbnail (EvWindow *ev_window, int rotation)
+{
+ gint page_width, page_height;
+ 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) {
+ 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_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),
+ ev_window);
+ ev_job_scheduler_push_job (ev_window->priv->thumbnail_job, EV_JOB_PRIORITY_NONE);
+}
+
+static gboolean
+ev_window_setup_document (EvWindow *ev_window)
+{
+ const EvDocumentInfo *info;
+ EvDocument *document = ev_window->priv->document;
+ EvSidebar *sidebar = EV_SIDEBAR (ev_window->priv->sidebar);
+ GtkAction *action;
+
+ ev_window->priv->setup_document_idle = 0;
+
+ ev_window_refresh_window_thumbnail (ev_window, 0);
+
+ ev_window_set_page_mode (ev_window, PAGE_MODE_DOCUMENT);
+ ev_window_title_set_document (ev_window->priv->title, document);
+ ev_window_title_set_uri (ev_window->priv->title, ev_window->priv->uri);
+
+ ev_sidebar_set_document (sidebar, document);
+
+ action = gtk_action_group_get_action (ev_window->priv->action_group, PAGE_SELECTOR_ACTION);
+ ev_page_action_set_document (EV_PAGE_ACTION (action), document);
+ ev_window_setup_action_sensitivity (ev_window);
+
+ if (ev_window->priv->history)
+ g_object_unref (ev_window->priv->history);
+ ev_window->priv->history = ev_history_new ();
+ action = gtk_action_group_get_action (ev_window->priv->action_group, NAVIGATION_ACTION);
+ ev_navigation_action_set_history (EV_NAVIGATION_ACTION (action), ev_window->priv->history);
+
+ if (ev_window->priv->properties) {
+ ev_properties_dialog_set_document (EV_PROPERTIES_DIALOG (ev_window->priv->properties),
+ ev_window->priv->document);
+ }
+
+ info = ev_page_cache_get_info (ev_window->priv->page_cache);
+ update_document_mode (ev_window, info->mode);
+
+ return FALSE;
+}
+
+static void
+ev_window_set_document (EvWindow *ev_window, EvDocument *document)
+{
+ EvView *view = EV_VIEW (ev_window->priv->view);
+
+ if (ev_window->priv->document)
+ g_object_unref (ev_window->priv->document);
+ ev_window->priv->document = g_object_ref (document);
+
+ ev_window_set_message_area (ev_window, NULL);
+
+ ev_window->priv->page_cache = ev_page_cache_get (ev_window->priv->document);
+ g_signal_connect (ev_window->priv->page_cache, "page-changed",
+ G_CALLBACK (page_changed_cb), ev_window);
+ g_signal_connect (ev_window->priv->page_cache, "history-changed",
+ G_CALLBACK (history_changed_cb), ev_window);
+
+ setup_size_from_metadata (ev_window);
+ setup_sidebar_from_metadata (ev_window, document);
+ setup_document_from_metadata (ev_window);
+
+ if (ev_page_cache_get_n_pages (ev_window->priv->page_cache) > 0) {
+ ev_view_set_document (view, document);
+ } else {
+ ev_window_warning_message (GTK_WINDOW (ev_window),
+ _("The document contains no pages"));
+ }
+
+ 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);
+}
+
+static void
+ev_window_document_changed (EvWindow *ev_window,
+ gpointer user_data)
+{
+ ev_window_reload_document (ev_window);
+}
+
+static void
+password_dialog_response (GtkWidget *password_dialog,
+ gint response_id,
+ EvWindow *ev_window)
+{
+ if (response_id == GTK_RESPONSE_OK) {
+ ev_job_load_set_password (EV_JOB_LOAD (ev_window->priv->load_job),
+ ev_password_dialog_get_password (EV_PASSWORD_DIALOG (password_dialog)));
+
+ ev_password_dialog_save_password (EV_PASSWORD_DIALOG (password_dialog));
+
+ ev_window_title_set_type (ev_window->priv->title, EV_WINDOW_TITLE_DOCUMENT);
+ ev_job_scheduler_push_job (ev_window->priv->load_job, EV_JOB_PRIORITY_NONE);
+
+ gtk_widget_destroy (password_dialog);
+
+ return;
+ }
+
+ gtk_widget_set_sensitive (ev_window->priv->password_view, TRUE);
+ gtk_widget_destroy (password_dialog);
+}
+
+/* Called either by ev_window_load_job_cb or by the "unlock" callback on the
+ * password_view page. It assumes that ev_window->priv->password_* has been set
+ * correctly. These are cleared by password_dialog_response() */
+
+static void
+ev_window_popup_password_dialog (EvWindow *ev_window)
+{
+ g_assert (ev_window->priv->load_job);
+
+ gtk_widget_set_sensitive (ev_window->priv->password_view, FALSE);
+
+ ev_window_title_set_uri (ev_window->priv->title, ev_window->priv->uri);
+ ev_window_title_set_type (ev_window->priv->title, EV_WINDOW_TITLE_PASSWORD);
+
+ if (ev_window->priv->password_dialog == NULL) {
+ ev_window->priv->password_dialog =
+ g_object_new (EV_TYPE_PASSWORD_DIALOG, "uri", ev_window->priv->uri, NULL);
+ gtk_window_set_transient_for (GTK_WINDOW (ev_window->priv->password_dialog), GTK_WINDOW (ev_window));
+
+ g_object_add_weak_pointer (G_OBJECT (ev_window->priv->password_dialog),
+ (gpointer) &(ev_window->priv->password_dialog));
+ g_signal_connect (ev_window->priv->password_dialog,
+ "response",
+ G_CALLBACK (password_dialog_response),
+ ev_window);
+ gtk_widget_show (ev_window->priv->password_dialog);
+ } else {
+ ev_password_dialog_set_bad_pass (EV_PASSWORD_DIALOG (ev_window->priv->password_dialog));
+ }
+}
+
+static void
+ev_window_clear_load_job (EvWindow *ev_window)
+{
+ if (ev_window->priv->load_job != NULL) {
+ if (!ev_job_is_finished (ev_window->priv->load_job))
+ ev_job_cancel (ev_window->priv->load_job);
+
+ g_signal_handlers_disconnect_by_func (ev_window->priv->load_job, ev_window_load_job_cb, ev_window);
+ g_object_unref (ev_window->priv->load_job);
+ ev_window->priv->load_job = NULL;
+ }
+}
+
+static void
+ev_window_clear_reload_job (EvWindow *ev_window)
+{
+ if (ev_window->priv->reload_job != NULL) {
+ if (!ev_job_is_finished (ev_window->priv->reload_job))
+ ev_job_cancel (ev_window->priv->reload_job);
+
+ g_signal_handlers_disconnect_by_func (ev_window->priv->reload_job, ev_window_reload_job_cb, ev_window);
+ g_object_unref (ev_window->priv->reload_job);
+ ev_window->priv->reload_job = NULL;
+ }
+}
+
+static void
+ev_window_clear_local_uri (EvWindow *ev_window)
+{
+ if (ev_window->priv->local_uri) {
+ 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)
+{
+ GFile *file, *tempdir;
+
+ if (!ev_window->priv->uri)
+ return;
+
+ file = g_file_new_for_uri (ev_window->priv->uri);
+ tempdir = g_file_new_for_path (g_get_tmp_dir ());
+
+ if (g_file_has_prefix (file, tempdir)) {
+ g_file_delete (file, NULL, NULL);
+ }
+
+ g_object_unref (file);
+ g_object_unref (tempdir);
+}
+
+/* This callback will executed when load job will be finished.
+ *
+ * Since the flow of the error dialog is very confusing, we assume that both
+ * document and uri will go away after this function is called, and thus we need
+ * to ref/dup them. Additionally, it needs to clear
+ * ev_window->priv->password_{uri,document}, and thus people who call this
+ * function should _not_ necessarily expect those to exist after being
+ * called. */
+static void
+ev_window_load_job_cb (EvJob *job,
+ gpointer data)
+{
+ EvWindow *ev_window = EV_WINDOW (data);
+ EvDocument *document = EV_JOB (job)->document;
+ EvJobLoad *job_load = EV_JOB_LOAD (job);
+
+ g_assert (job_load->uri);
+
+ ev_view_set_loading (EV_VIEW (ev_window->priv->view), FALSE);
+
+ /* Success! */
+ if (!ev_job_is_failed (job)) {
+ ev_window_set_document (ev_window, document);
+
+ if (job_load->mode != EV_WINDOW_MODE_PREVIEW) {
+ setup_view_from_metadata (ev_window);
+ }
+
+ if (!ev_window->priv->unlink_temp_file) {
+ ev_window_add_recent (ev_window, ev_window->priv->uri);
+ }
+
+ if (job_load->dest) {
+ EvLink *link;
+ EvLinkAction *link_action;
+
+ link_action = ev_link_action_new_dest (g_object_ref (job_load->dest));
+ link = ev_link_new (NULL, link_action);
+ ev_view_handle_link (EV_VIEW (ev_window->priv->view), link);
+ g_object_unref (link);
+ }
+
+ switch (job_load->mode) {
+ case EV_WINDOW_MODE_FULLSCREEN:
+ ev_window_run_fullscreen (ev_window);
+ break;
+ case EV_WINDOW_MODE_PRESENTATION:
+ ev_window_run_presentation (ev_window);
+ break;
+ case EV_WINDOW_MODE_PREVIEW:
+ ev_window_run_preview (ev_window);
+ break;
+ default:
+ break;
+ }
+
+ if (job_load->search_string && EV_IS_DOCUMENT_FIND (document)) {
+ ev_window_cmd_edit_find (NULL, ev_window);
+ egg_find_bar_set_search_string (EGG_FIND_BAR (ev_window->priv->find_bar),
+ job_load->search_string);
+ }
+
+ /* Create a monitor for the document */
+ ev_window->priv->monitor = ev_file_monitor_new (job_load->uri);
+ g_signal_connect_swapped (G_OBJECT (ev_window->priv->monitor), "changed",
+ G_CALLBACK (ev_window_document_changed),
+ ev_window);
+
+ ev_window_clear_load_job (ev_window);
+ return;
+ }
+
+ if (job->error->domain == EV_DOCUMENT_ERROR &&
+ job->error->code == EV_DOCUMENT_ERROR_ENCRYPTED) {
+ GFile *file;
+ gchar *base_name;
+
+ setup_view_from_metadata (ev_window);
+
+ file = g_file_new_for_uri (job_load->uri);
+ base_name = g_file_get_basename (file);
+ ev_password_view_set_file_name (EV_PASSWORD_VIEW (ev_window->priv->password_view),
+ base_name);
+ g_object_unref (file);
+ 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_message (GTK_WINDOW (ev_window),
+ _("Unable to open document"),
+ job->error);
+ ev_window_clear_load_job (ev_window);
+ }
+}
+
+static void
+ev_window_reload_job_cb (EvJob *job,
+ EvWindow *ev_window)
+{
+ GtkWidget *widget;
+
+ if (ev_job_is_failed (job)) {
+ ev_window_clear_reload_job (ev_window);
+ ev_window->priv->in_reload = FALSE;
+ return;
+ }
+
+ ev_window_set_document (ev_window, job->document);
+
+ /* 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)) {
+ find_bar_search_changed_cb (EGG_FIND_BAR (ev_window->priv->find_bar),
+ NULL, ev_window);
+ }
+
+ ev_window_clear_reload_job (ev_window);
+ ev_window->priv->in_reload = FALSE;
+}
+
+/**
+ * ev_window_get_uri:
+ * @ev_window: The instance of the #EvWindow.
+ *
+ * It returns the uri of the document showed in the #EvWindow.
+ *
+ * Returns: the uri of the document showed in the #EvWindow.
+ */
+const char *
+ev_window_get_uri (EvWindow *ev_window)
+{
+ return ev_window->priv->uri;
+}
+
+/**
+ * ev_window_close_dialogs:
+ * @ev_window: The window where dialogs will be closed.
+ *
+ * It looks for password, print and properties dialogs and closes them and
+ * frees them from memory. If there is any print job it does free it too.
+ */
+static void
+ev_window_close_dialogs (EvWindow *ev_window)