]> www.fi.muni.cz Git - evince.git/blobdiff - shell/ev-sidebar-links.c
[dualscreen] fix crash on ctrl+w and fix control window closing
[evince.git] / shell / ev-sidebar-links.c
index 5d3469543e12bb49030165b8c7a76a6208c60c50..28a4fddc66d2db03e7e5cbb19b000bde20dabbdc 100644 (file)
@@ -17,7 +17,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
 #ifdef HAVE_CONFIG_H
 #endif
 
 #include <string.h>
+
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
 
-#include "ev-sidebar-page.h"
-#include "ev-sidebar-links.h"
-#include "ev-job-queue.h"
 #include "ev-document-links.h"
+#include "ev-job-scheduler.h"
+#include "ev-sidebar-links.h"
+#include "ev-sidebar-page.h"
 #include "ev-window.h"
 
 struct _EvSidebarLinksPrivate {
@@ -45,7 +46,7 @@ struct _EvSidebarLinksPrivate {
        EvJob *job;
        GtkTreeModel *model;
        EvDocument *document;
-       EvPageCache *page_cache;
+       EvDocumentModel *doc_model;
 };
 
 enum {
@@ -59,18 +60,20 @@ enum {
        N_SIGNALS
 };
 
-static void update_page_callback                       (EvPageCache       *page_cache,
-                                                        gint               current_page,
-                                                        EvSidebarLinks    *sidebar_links);
+static void update_page_callback                       (EvSidebarLinks    *sidebar_links,
+                                                        gint               old_page,
+                                                        gint               current_page);
 static void row_activated_callback                     (GtkTreeView *treeview,
                                                         GtkTreePath *arg1,
                                                         GtkTreeViewColumn *arg2,
                                                         gpointer user_data);
+static void ev_sidebar_links_set_links_model            (EvSidebarLinks *links,
+                                                        GtkTreeModel   *model);
 static void job_finished_callback                      (EvJobLinks     *job,
                                                         EvSidebarLinks *sidebar_links);
-static void ev_sidebar_links_page_iface_init           (EvSidebarPageIface *iface);
-static void ev_sidebar_links_set_document                      (EvSidebarPage  *sidebar_page,
-                                                        EvDocument     *document);
+static void ev_sidebar_links_set_current_page           (EvSidebarLinks *sidebar_links,
+                                                        gint            current_page);
+static void ev_sidebar_links_page_iface_init           (EvSidebarPageInterface *iface);
 static gboolean ev_sidebar_links_support_document      (EvSidebarPage  *sidebar_page,
                                                         EvDocument     *document);
 static const gchar* ev_sidebar_links_get_label                 (EvSidebarPage *sidebar_page);
@@ -94,18 +97,12 @@ ev_sidebar_links_set_property (GObject      *object,
                               const GValue *value,
                               GParamSpec   *pspec)
 {
-       EvSidebarLinks *ev_sidebar_links;
-       GtkTreeModel *model;
-  
-       ev_sidebar_links = EV_SIDEBAR_LINKS (object);
+       EvSidebarLinks *ev_sidebar_links = EV_SIDEBAR_LINKS (object);
 
        switch (prop_id)
        {
        case PROP_MODEL:
-               model = ev_sidebar_links->priv->model;
-               ev_sidebar_links->priv->model = GTK_TREE_MODEL (g_value_dup_object (value));
-               if (model)
-                       g_object_unref (model);
+               ev_sidebar_links_set_links_model (ev_sidebar_links, g_value_get_object (value));
                break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -145,7 +142,7 @@ ev_sidebar_links_dispose (GObject *object)
        if (sidebar->priv->job) {
                g_signal_handlers_disconnect_by_func (sidebar->priv->job,
                                                      job_finished_callback, sidebar);
-               ev_job_queue_remove_job (sidebar->priv->job);                                                 
+               ev_job_cancel (sidebar->priv->job);                                                   
                g_object_unref (sidebar->priv->job);
                sidebar->priv->job = NULL;
        }
@@ -158,7 +155,7 @@ ev_sidebar_links_dispose (GObject *object)
        if (sidebar->priv->document) {
                g_object_unref (sidebar->priv->document);
                sidebar->priv->document = NULL;
-               sidebar->priv->page_cache = NULL;
+               sidebar->priv->doc_model = NULL;
        }
 
        G_OBJECT_CLASS (ev_sidebar_links_parent_class)->dispose (object);
@@ -174,9 +171,8 @@ ev_sidebar_links_map (GtkWidget *widget)
        GTK_WIDGET_CLASS (ev_sidebar_links_parent_class)->map (widget);
 
        if (links->priv->model) {
-               update_page_callback (links->priv->page_cache,
-                                     ev_page_cache_get_current_page (links->priv->page_cache),
-                                     links);
+               ev_sidebar_links_set_current_page (links,
+                                                  ev_document_model_get_page (links->priv->doc_model));
        }
 }
 
@@ -238,10 +234,10 @@ selection_changed_callback (GtkTreeSelection   *selection,
                if (link == NULL)
                        return;
 
-               g_signal_handler_block (ev_sidebar_links->priv->page_cache,
+               g_signal_handler_block (ev_sidebar_links->priv->doc_model,
                                        ev_sidebar_links->priv->page_changed_id);
                g_signal_emit (ev_sidebar_links, signals[LINK_ACTIVATED], 0, link);
-               g_signal_handler_unblock (ev_sidebar_links->priv->page_cache,
+               g_signal_handler_unblock (ev_sidebar_links->priv->doc_model,
                                          ev_sidebar_links->priv->page_changed_id);
 
                g_object_unref (link);
@@ -263,7 +259,7 @@ create_loading_model (void)
                                                     G_TYPE_STRING);
 
        gtk_list_store_append (GTK_LIST_STORE (retval), &iter);
-       markup = g_strdup_printf ("<span size=\"larger\" style=\"italic\">%s</span>", _("Loading..."));
+       markup = g_strdup_printf ("<span size=\"larger\" style=\"italic\">%s</span>", _("Loading…"));
        gtk_list_store_set (GTK_LIST_STORE (retval), &iter,
                            EV_DOCUMENT_LINKS_COLUMN_MARKUP, markup,
                            EV_DOCUMENT_LINKS_COLUMN_EXPAND, FALSE,
@@ -288,6 +284,7 @@ print_section_cb (GtkWidget *menuitem, EvSidebarLinks *sidebar)
        if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
                EvLink *link;
                int first_page, last_page = -1;
+               EvDocumentLinks *document_links;
 
                gtk_tree_model_get (model, &iter,
                                    EV_DOCUMENT_LINKS_COLUMN_LINK, &link,
@@ -296,7 +293,9 @@ print_section_cb (GtkWidget *menuitem, EvSidebarLinks *sidebar)
                if (!link)
                        return;
 
-               first_page = ev_link_get_page (link);
+               document_links = EV_DOCUMENT_LINKS (sidebar->priv->document);
+
+               first_page = ev_document_links_get_link_page (document_links, link);
                if (first_page == -1) {
                        g_object_unref (link);
                        return;
@@ -311,22 +310,19 @@ print_section_cb (GtkWidget *menuitem, EvSidebarLinks *sidebar)
                                            -1);
 
                        if (link) {
-                               last_page = ev_link_get_page (link);
+                               last_page = ev_document_links_get_link_page (document_links, link);;
                                g_object_unref (link);
                        }
                } else {
-                       last_page = ev_page_cache_get_n_pages (sidebar->priv->page_cache);
+                       last_page = ev_document_get_n_pages (sidebar->priv->document);
                }
 
                if (last_page == -1)
-                       last_page = ev_page_cache_get_n_pages (sidebar->priv->page_cache);
+                       last_page = ev_document_get_n_pages (sidebar->priv->document);
        
                window = gtk_widget_get_toplevel (GTK_WIDGET (sidebar));
                if (EV_IS_WINDOW (window)) {
-#ifdef WITH_PRINT
-                       ev_window_print_range (EV_WINDOW (window),
-                                              first_page, last_page);
-#endif
+                       ev_window_print_range (EV_WINDOW (window), first_page, last_page);
                }
        }
 }
@@ -339,7 +335,7 @@ build_popup_menu (EvSidebarLinks *sidebar)
 
        menu = gtk_menu_new ();
        item = gtk_image_menu_item_new_from_stock (GTK_STOCK_PRINT, NULL);
-       gtk_label_set_label (GTK_LABEL (GTK_BIN (item)->child), _("Print..."));
+       gtk_label_set_label (GTK_LABEL (gtk_bin_get_child (GTK_BIN (item))), _("Print…"));
        gtk_widget_show (item);
        gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
        g_signal_connect (item, "activate",
@@ -439,13 +435,16 @@ ev_sidebar_links_construct (EvSidebarLinks *ev_sidebar_links)
        gtk_tree_view_column_set_attributes (GTK_TREE_VIEW_COLUMN (column), renderer,
                                             "text", EV_DOCUMENT_LINKS_COLUMN_PAGE_LABEL,
                                             NULL);
-       g_object_set (G_OBJECT (renderer), "style", PANGO_STYLE_ITALIC, NULL);
+       g_object_set (G_OBJECT (renderer),
+                      "style", PANGO_STYLE_ITALIC,
+                      "xalign", 1.0,
+                      NULL);
 
-       g_signal_connect (GTK_TREE_VIEW (priv->tree_view),
+       g_signal_connect (priv->tree_view,
                          "button_press_event",
                          G_CALLBACK (button_press_cb),
                          ev_sidebar_links);
-       g_signal_connect (GTK_TREE_VIEW (priv->tree_view),
+       g_signal_connect (priv->tree_view,
                          "popup_menu",
                          G_CALLBACK (popup_menu_cb),
                          ev_sidebar_links);
@@ -459,40 +458,6 @@ ev_sidebar_links_init (EvSidebarLinks *ev_sidebar_links)
        ev_sidebar_links_construct (ev_sidebar_links);
 }
 
-static gboolean
-fill_page_labels (GtkTreeModel *tree_model,
-                  GtkTreePath *path,
-                  GtkTreeIter *iter,
-                 EvSidebarLinks    *sidebar_links)
-{
-       EvLink *link;
-       gint page;
-       gchar *page_label;
-
-       gtk_tree_model_get (tree_model, iter,
-                           EV_DOCUMENT_LINKS_COLUMN_LINK, &link,
-                           -1);
-
-       if (!link)
-               return FALSE;
-
-       page = ev_link_get_page (link);
-
-       if (page < 0) 
-               return FALSE;
-       
-       page_label = ev_page_cache_get_page_label (sidebar_links->priv->page_cache,
-                                                  page);
-       gtk_tree_store_set (GTK_TREE_STORE (tree_model), iter,
-                           EV_DOCUMENT_LINKS_COLUMN_PAGE_LABEL, page_label, 
-                           -1);
-
-       g_free (page_label);
-
-       g_object_unref (link);
-       return FALSE;
-}
-
 /* Public Functions */
 
 GtkWidget *
@@ -521,11 +486,12 @@ update_page_callback_foreach (GtkTreeModel *model,
        if (link) {
                int current_page;
                int dest_page;
+               EvDocumentLinks *document_links = EV_DOCUMENT_LINKS (sidebar_links->priv->document);
 
-               dest_page = ev_link_get_page (link);
+               dest_page = ev_document_links_get_link_page (document_links, link);
                g_object_unref (link);
                
-               current_page = ev_page_cache_get_current_page (sidebar_links->priv->page_cache);
+               current_page = ev_document_model_get_page (sidebar_links->priv->doc_model);
                         
                if (dest_page == current_page) {
                        gtk_tree_view_expand_to_path (GTK_TREE_VIEW (sidebar_links->priv->tree_view),
@@ -541,16 +507,15 @@ update_page_callback_foreach (GtkTreeModel *model,
 }
 
 static void
-update_page_callback (EvPageCache    *page_cache,
-                     gint            current_page,
-                     EvSidebarLinks *sidebar_links)
+ev_sidebar_links_set_current_page (EvSidebarLinks *sidebar_links,
+                                  gint            current_page)
 {
        GtkTreeSelection *selection;
        GtkTreeModel *model;
        GtkTreeIter iter;
 
        /* Widget is not currently visible */
-       if (!GTK_WIDGET_MAPPED (sidebar_links))
+       if (!gtk_widget_get_mapped (GTK_WIDGET (sidebar_links)))
                return;
        
        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (sidebar_links->priv->tree_view));
@@ -563,8 +528,9 @@ update_page_callback (EvPageCache    *page_cache,
                                    -1);
                if (link) {
                        gint dest_page;
+                       EvDocumentLinks *document_links = EV_DOCUMENT_LINKS (sidebar_links->priv->document);
 
-                       dest_page = ev_link_get_page (link);
+                       dest_page = ev_document_links_get_link_page (document_links, link);
                        g_object_unref (link);
                        
                        if (dest_page == current_page)
@@ -588,12 +554,20 @@ update_page_callback (EvPageCache    *page_cache,
        g_signal_handler_unblock (sidebar_links->priv->tree_view, sidebar_links->priv->row_activated_id);
 }
 
+static void
+update_page_callback (EvSidebarLinks *sidebar_links,
+                     gint            old_page,
+                     gint            new_page)
+{
+       ev_sidebar_links_set_current_page (sidebar_links, new_page);
+}
+
 static void 
 row_activated_callback (GtkTreeView       *treeview,
                        GtkTreePath       *arg1,
                        GtkTreeViewColumn *arg2,
                        gpointer           user_data)
-{      
+{
        if (gtk_tree_view_row_expanded (GTK_TREE_VIEW (treeview), arg1)) {
                gtk_tree_view_collapse_row (GTK_TREE_VIEW (treeview), arg1);
        } else {
@@ -624,20 +598,31 @@ expand_open_links (GtkTreeView *tree_view, GtkTreeModel *model, GtkTreeIter *par
                } while (gtk_tree_model_iter_next (model, &iter));
        }
 }
-       
+
+static void
+ev_sidebar_links_set_links_model (EvSidebarLinks *sidebar_links,
+                                 GtkTreeModel   *model)
+{
+       EvSidebarLinksPrivate *priv = sidebar_links->priv;
+
+       if (priv->model == model)
+               return;
+
+       if (priv->model)
+               g_object_unref (priv->model);
+       priv->model = g_object_ref (model);
+
+       g_object_notify (G_OBJECT (sidebar_links), "model");
+}
+
 static void
 job_finished_callback (EvJobLinks     *job,
                       EvSidebarLinks *sidebar_links)
 {
-       EvSidebarLinksPrivate *priv;
+       EvSidebarLinksPrivate *priv = sidebar_links->priv;
        GtkTreeSelection *selection;
 
-       priv = sidebar_links->priv;
-       
-       priv->model = job->model;
-       g_object_notify (G_OBJECT (sidebar_links), "model");
-       
-       gtk_tree_model_foreach (priv->model, (GtkTreeModelForeachFunc)fill_page_labels, sidebar_links);
+       ev_sidebar_links_set_links_model (sidebar_links, job->model);
 
        gtk_tree_view_set_model (GTK_TREE_VIEW (priv->tree_view), job->model);
        
@@ -648,33 +633,41 @@ job_finished_callback (EvJobLinks     *job,
 
        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree_view));
        gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
-       priv->selection_id = g_signal_connect (selection, "changed",
-                                              G_CALLBACK (selection_changed_callback),
-                                              sidebar_links);
-       priv->page_changed_id = g_signal_connect (priv->page_cache, "page-changed",
-                                                 G_CALLBACK (update_page_callback),
-                                                 sidebar_links);
-       priv->row_activated_id = g_signal_connect (G_OBJECT (priv->tree_view), "row-activated",
-                                                   G_CALLBACK (row_activated_callback), sidebar_links);
-       update_page_callback (priv->page_cache,
-                             ev_page_cache_get_current_page (priv->page_cache),
-                             sidebar_links);
+       
+       if (priv->selection_id <= 0) {
+               priv->selection_id =
+                       g_signal_connect (selection, "changed",
+                                         G_CALLBACK (selection_changed_callback),
+                                         sidebar_links);
+       }
+       priv->page_changed_id =
+               g_signal_connect_swapped (priv->doc_model, "page-changed",
+                                         G_CALLBACK (update_page_callback),
+                                         sidebar_links);
+       if (priv->row_activated_id <= 0) {
+               priv->row_activated_id =
+                       g_signal_connect (priv->tree_view, "row-activated",
+                                         G_CALLBACK (row_activated_callback),
+                                         sidebar_links);
+       }
 
+       ev_sidebar_links_set_current_page (sidebar_links,
+                                          ev_document_model_get_page (priv->doc_model));
 }
 
 static void
-ev_sidebar_links_set_document (EvSidebarPage  *sidebar_page,
-                              EvDocument     *document)
+ev_sidebar_links_document_changed_cb (EvDocumentModel *model,
+                                     GParamSpec      *pspec,
+                                     EvSidebarLinks  *sidebar_links)
 {
-       EvSidebarLinks *sidebar_links;
-       EvSidebarLinksPrivate *priv;
+       EvDocument *document = ev_document_model_get_document (model);
+       EvSidebarLinksPrivate *priv = sidebar_links->priv;
 
-       g_return_if_fail (EV_IS_SIDEBAR_PAGE (sidebar_page));
-       g_return_if_fail (EV_IS_DOCUMENT (document));
-       
-       sidebar_links = EV_SIDEBAR_LINKS (sidebar_page);
+       if (!EV_IS_DOCUMENT_LINKS (document))
+               return;
 
-       priv = sidebar_links->priv;
+       if (!ev_document_links_has_document_links (EV_DOCUMENT_LINKS (document)))
+               return;
 
        if (priv->document) {
                gtk_tree_view_set_model (GTK_TREE_VIEW (priv->tree_view), NULL);
@@ -682,7 +675,6 @@ ev_sidebar_links_set_document (EvSidebarPage  *sidebar_page,
        }
 
        priv->document = g_object_ref (document);
-       priv->page_cache = ev_page_cache_get (document);
 
        if (priv->job) {
                g_signal_handlers_disconnect_by_func (priv->job,
@@ -697,7 +689,23 @@ ev_sidebar_links_set_document (EvSidebarPage  *sidebar_page,
                          G_CALLBACK (job_finished_callback),
                          sidebar_links);
        /* The priority doesn't matter for this job */
-       ev_job_queue_add_job (priv->job, EV_JOB_PRIORITY_LOW);
+       ev_job_scheduler_push_job (priv->job, EV_JOB_PRIORITY_NONE);
+}
+
+static void
+ev_sidebar_links_set_model (EvSidebarPage   *sidebar_page,
+                           EvDocumentModel *model)
+{
+       EvSidebarLinks *sidebar_links = EV_SIDEBAR_LINKS (sidebar_page);
+       EvSidebarLinksPrivate *priv = sidebar_links->priv;
+
+       if (priv->doc_model == model)
+               return;
+
+       priv->doc_model = model;
+       g_signal_connect (model, "notify::document",
+                         G_CALLBACK (ev_sidebar_links_document_changed_cb),
+                         sidebar_page);
 }
 
 static gboolean
@@ -715,10 +723,10 @@ ev_sidebar_links_get_label (EvSidebarPage *sidebar_page)
 }
 
 static void
-ev_sidebar_links_page_iface_init (EvSidebarPageIface *iface)
+ev_sidebar_links_page_iface_init (EvSidebarPageInterface *iface)
 {
        iface->support_document = ev_sidebar_links_support_document;
-       iface->set_document = ev_sidebar_links_set_document;
+       iface->set_model = ev_sidebar_links_set_model;
        iface->get_label = ev_sidebar_links_get_label;
 }