]> www.fi.muni.cz Git - evince.git/blobdiff - shell/ev-sidebar-links.c
Acquire lock document when drawing "Loading..." text so that only one
[evince.git] / shell / ev-sidebar-links.c
index 84b49dd292b47175aa5c0ac03df28e149082aba5..46394019f47a248874b097cf9f70c3d4eb181851 100644 (file)
@@ -55,6 +55,10 @@ enum {
        PROP_WIDGET,
 };
 
+enum {
+       LINK_ACTIVATED,
+       N_SIGNALS
+};
 
 static void links_page_num_func                                (GtkTreeViewColumn *tree_column,
                                                         GtkCellRenderer   *cell,
@@ -77,6 +81,7 @@ static gboolean ev_sidebar_links_support_document     (EvSidebarPage  *sidebar_page,
                                                         EvDocument     *document);
 static const gchar* ev_sidebar_links_get_label                 (EvSidebarPage *sidebar_page);
 
+static guint signals[N_SIGNALS];
 
 G_DEFINE_TYPE_EXTENDED (EvSidebarLinks, 
                         ev_sidebar_links, 
@@ -143,12 +148,6 @@ ev_sidebar_links_dispose (GObject *object)
 {
        EvSidebarLinks *sidebar = EV_SIDEBAR_LINKS (object);
 
-       if (sidebar->priv->document) {
-               g_object_unref (sidebar->priv->document);
-               sidebar->priv->document = NULL;
-               sidebar->priv->page_cache = NULL;
-       }
-
        if (sidebar->priv->job) {
                g_signal_handlers_disconnect_by_func (sidebar->priv->job,
                                                      job_finished_callback, sidebar);
@@ -157,6 +156,18 @@ ev_sidebar_links_dispose (GObject *object)
                sidebar->priv->job = NULL;
        }
 
+       if (sidebar->priv->model) {
+               g_object_unref (sidebar->priv->model);
+               sidebar->priv->model = NULL;
+       }
+
+       if (sidebar->priv->document) {
+               g_object_unref (sidebar->priv->document);
+               sidebar->priv->document = NULL;
+               sidebar->priv->page_cache = NULL;
+       }
+
+
        G_OBJECT_CLASS (ev_sidebar_links_parent_class)->dispose (object);
 }
 
@@ -171,6 +182,14 @@ ev_sidebar_links_class_init (EvSidebarLinksClass *ev_sidebar_links_class)
        g_object_class->get_property = ev_sidebar_links_get_property;
        g_object_class->dispose = ev_sidebar_links_dispose;
 
+       signals[LINK_ACTIVATED] = g_signal_new ("link-activated",
+                        G_TYPE_FROM_CLASS (g_object_class),
+                        G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                        G_STRUCT_OFFSET (EvSidebarLinksClass, link_activated),
+                        NULL, NULL,
+                        g_cclosure_marshal_VOID__OBJECT,
+                        G_TYPE_NONE, 1, G_TYPE_OBJECT);
+
        g_object_class_install_property (g_object_class,
                                         PROP_MODEL,
                                         g_param_spec_object ("model",
@@ -210,10 +229,11 @@ selection_changed_callback (GtkTreeSelection   *selection,
 
                g_signal_handler_block (ev_sidebar_links->priv->page_cache,
                                        ev_sidebar_links->priv->page_changed_id);
-               /* FIXME: we should handle this better.  This breaks w/ URLs */
-               ev_page_cache_set_link (ev_sidebar_links->priv->page_cache, link);
+               g_signal_emit (ev_sidebar_links, signals[LINK_ACTIVATED], 0, link);
                g_signal_handler_unblock (ev_sidebar_links->priv->page_cache,
                                          ev_sidebar_links->priv->page_changed_id);
+
+               g_object_unref (link);
        }
 }
 
@@ -242,6 +262,27 @@ create_loading_model (void)
        return retval;
 }
 
+static gint
+get_page_from_link (EvLink *link)
+{
+       EvLinkAction *action;
+       EvLinkDest *dest;
+
+       action = ev_link_get_action (link);
+       if (!action)
+               return -1;
+
+       if (ev_link_action_get_action_type (action) !=
+           EV_LINK_ACTION_TYPE_GOTO_DEST)
+               return -1;
+
+       dest = ev_link_action_get_dest (action);
+       if (dest)
+               return ev_link_dest_get_page (dest);
+               
+       return -1;
+}
+
 static void
 print_section_cb (GtkWidget *menuitem, EvSidebarLinks *sidebar)
 {
@@ -255,26 +296,46 @@ print_section_cb (GtkWidget *menuitem, EvSidebarLinks *sidebar)
 
        if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
                EvLink *link;
-               int first_page, last_page;
+               int first_page, last_page = -1;
 
                gtk_tree_model_get (model, &iter,
                                    EV_DOCUMENT_LINKS_COLUMN_LINK, &link,
                                    -1);
-               first_page = ev_link_get_page (link) + 1;
+
+               if (!link)
+                       return;
+
+               first_page = get_page_from_link (link);
+               if (first_page == -1) {
+                       g_object_unref (link);
+                       return;
+               }
+               
+               first_page++;
+               g_object_unref (link);
 
                if (gtk_tree_model_iter_next (model, &iter)) {
                        gtk_tree_model_get (model, &iter,
                                            EV_DOCUMENT_LINKS_COLUMN_LINK, &link,
                                            -1);
-                       last_page = ev_link_get_page (link);
+
+                       if (link) {
+                               last_page = get_page_from_link (link);
+                               g_object_unref (link);
+                       }
                } else {
-                       last_page = -1;
+                       last_page = ev_page_cache_get_n_pages (sidebar->priv->page_cache);
                }
+
+               if (last_page == -1)
+                       last_page = ev_page_cache_get_n_pages (sidebar->priv->page_cache);
        
                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
                }
        }
 }
@@ -414,17 +475,27 @@ links_page_num_func (GtkTreeViewColumn *tree_column,
                     EvSidebarLinks    *sidebar_links)
 {
        EvLink *link;
+       gint page;
 
        gtk_tree_model_get (tree_model, iter,
                            EV_DOCUMENT_LINKS_COLUMN_LINK, &link,
                            -1);
-       
-       if (link != NULL &&
-           ev_link_get_link_type (link) == EV_LINK_TYPE_PAGE) {
+
+       if (!link) {
+               g_object_set (cell,
+                             "visible", FALSE,
+                             NULL);
+               return;
+       }
+
+       page = get_page_from_link (link);
+
+       if (page >= 0) {
                gchar *page_label;
                gchar *page_string;
 
-               page_label = ev_page_cache_get_page_label (sidebar_links->priv->page_cache, ev_link_get_page (link));
+               page_label = ev_page_cache_get_page_label (sidebar_links->priv->page_cache,
+                                                          page);
                page_string = g_markup_printf_escaped ("<i>%s</i>", page_label);
 
                g_object_set (cell,
@@ -439,6 +510,8 @@ links_page_num_func (GtkTreeViewColumn *tree_column,
                              "visible", FALSE,
                              NULL);
        }
+
+       g_object_unref (link);
 }
 
 /* Public Functions */
@@ -466,21 +539,27 @@ update_page_callback_foreach (GtkTreeModel *model,
                            EV_DOCUMENT_LINKS_COLUMN_LINK, &link,
                            -1);
 
-       if (link && ev_link_get_link_type (link) == EV_LINK_TYPE_PAGE) {
+       if (link) {
                int current_page;
+               int dest_page;
 
+               dest_page = get_page_from_link (link);
+               g_object_unref (link);
+               
                current_page = ev_page_cache_get_current_page (sidebar_links->priv->page_cache);
-               if (ev_link_get_page (link) == current_page) {
+                        
+               if (dest_page == current_page) {
                        GtkTreeSelection *selection;
 
                        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (sidebar_links->priv->tree_view));
-
+                       gtk_tree_view_expand_to_path (GTK_TREE_VIEW (sidebar_links->priv->tree_view),
+                                                     path);
                        gtk_tree_selection_select_path (selection, path);
-
+                       
                        return TRUE;
                }
        }
-       
+
        return FALSE;
 }
 
@@ -490,21 +569,42 @@ update_page_callback (EvPageCache    *page_cache,
                      EvSidebarLinks *sidebar_links)
 {
        GtkTreeSelection *selection;
+       GtkTreeModel *model;
+       GtkTreeIter iter;
+
+       selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (sidebar_links->priv->tree_view));
+
+       if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+               EvLink *link;
+
+               gtk_tree_model_get (model, &iter,
+                                   EV_DOCUMENT_LINKS_COLUMN_LINK, &link,
+                                   -1);
+               if (link) {
+                       gint current_page;
+                       gint dest_page;
+
+                       dest_page = get_page_from_link (link);
+                       g_object_unref (link);
+                       
+                       current_page = ev_page_cache_get_current_page (sidebar_links->priv->page_cache);
+                       if (dest_page == current_page)
+                               return;
+               }
+       }               
+
        /* We go through the tree linearly looking for the first page that
         * matches.  This is pretty inefficient.  We can do something neat with
         * a GtkTreeModelSort here to make it faster, if it turns out to be
         * slow.
         */
-
-       selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (sidebar_links->priv->tree_view));
-
        g_signal_handler_block (selection, sidebar_links->priv->selection_id);
        g_signal_handler_block (sidebar_links->priv->tree_view, sidebar_links->priv->row_activated_id);
 
-       gtk_tree_selection_unselect_all (selection);
-       gtk_tree_model_foreach (sidebar_links->priv->model,
+       gtk_tree_model_foreach (model,
                                update_page_callback_foreach,
                                sidebar_links);
+       
 
        g_signal_handler_unblock (selection, sidebar_links->priv->selection_id);
        g_signal_handler_unblock (sidebar_links->priv->tree_view, sidebar_links->priv->row_activated_id);
@@ -529,13 +629,11 @@ static void
 expand_open_links (GtkTreeView *tree_view, GtkTreeModel *model, GtkTreeIter *parent)
 {
        GtkTreeIter iter;
-       EvLink *link;
        gboolean expand;
 
        if (gtk_tree_model_iter_children (model, &iter, parent)) {
                do {
                        gtk_tree_model_get (model, &iter,
-                                           EV_DOCUMENT_LINKS_COLUMN_LINK, &link,
                                            EV_DOCUMENT_LINKS_COLUMN_EXPAND, &expand,
                                            -1);
                        if (expand) {
@@ -559,11 +657,12 @@ job_finished_callback (EvJobLinks     *job,
        GtkTreeSelection *selection;
 
        priv = sidebar_links->priv;
-
-       priv->model = g_object_ref (job->model);
+       
+       priv->model = job->model;
        g_object_notify (G_OBJECT (sidebar_links), "model");
 
        gtk_tree_view_set_model (GTK_TREE_VIEW (priv->tree_view), job->model);
+       
        g_object_unref (job);
        priv->job = NULL;