]> www.fi.muni.cz Git - evince.git/commitdiff
shell: Add bookmarks menu to add and show internal bookmarks
authorCarlos Garcia Campos <carlosgc@gnome.org>
Mon, 6 Dec 2010 16:40:48 +0000 (17:40 +0100)
committerCarlos Garcia Campos <carlosgc@gnome.org>
Mon, 6 Dec 2010 17:15:38 +0000 (18:15 +0100)
Fixes bug #590655.

data/evince-ui.xml
shell/Makefile.am
shell/ev-bookmark-action.c [new file with mode: 0644]
shell/ev-bookmark-action.h [new file with mode: 0644]
shell/ev-window.c

index 8067546680d259a471db0f2ed55d3b3c5cf3c630..3aca084f951b6d32fef6ba42efe38c91153459c9 100644 (file)
       <menuitem name="GoLastPageMenu" action="GoLastPage"/>
     </menu>
 
+    <menu name="BookmarksMenu" action="Bookmarks">
+      <menuitem name="BookmarksAddMenu" action="BookmarksAdd"/>
+      <separator/>
+      <placeholder name="BookmarksItems"/>
+    </menu>
+
     <menu name="HelpMenu" action="Help">
       <menuitem name="HelpContentsMenu" action="HelpContents"/>
       <menuitem name="HelpAboutMenu" action="HelpAbout"/>
index 7a303264e9d2bf75524a918a4025cbb1b8ddf5a7..d760955da0f0b00ea7991ed628c9229c7f12a00c 100644 (file)
@@ -35,6 +35,8 @@ evince_SOURCES=                               \
        ev-annotation-properties-dialog.c \
        ev-bookmarks.h                  \
        ev-bookmarks.c                  \
+       ev-bookmark-action.h            \
+       ev-bookmark-action.c            \
        ev-application.c                \
        ev-application.h                \
        ev-file-monitor.h               \
diff --git a/shell/ev-bookmark-action.c b/shell/ev-bookmark-action.c
new file mode 100644 (file)
index 0000000..3689d7a
--- /dev/null
@@ -0,0 +1,105 @@
+/* ev-bookmark-action.c
+ *  this file is part of evince, a gnome document viewer
+ *
+ * Copyright (C) 2010 Carlos Garcia Campos  <carlosgc@gnome.org>
+ *
+ * Evince is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Evince is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include "ev-bookmark-action.h"
+
+enum {
+        PROP_0,
+        PROP_PAGE
+};
+
+struct _EvBookmarkAction {
+        GtkAction base;
+
+        guint     page;
+};
+
+struct _EvBookmarkActionClass {
+        GtkActionClass base_class;
+};
+
+G_DEFINE_TYPE (EvBookmarkAction, ev_bookmark_action, GTK_TYPE_ACTION)
+
+static void
+ev_bookmark_action_init (EvBookmarkAction *action)
+{
+}
+
+static void
+ev_bookmark_action_set_property (GObject      *object,
+                                 guint         prop_id,
+                                 const GValue *value,
+                                 GParamSpec   *pspec)
+{
+        EvBookmarkAction *action = EV_BOOKMARK_ACTION (object);
+
+        switch (prop_id) {
+        case PROP_PAGE:
+                action->page = g_value_get_uint (value);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+        }
+}
+
+static void
+ev_bookmark_action_class_init (EvBookmarkActionClass *klass)
+{
+        GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+        gobject_class->set_property = ev_bookmark_action_set_property;
+
+        g_object_class_install_property (gobject_class,
+                                         PROP_PAGE,
+                                         g_param_spec_uint ("page",
+                                                            "Page",
+                                                            "The bookmark page",
+                                                            0, G_MAXUINT, 0,
+                                                            G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
+}
+
+GtkAction *
+ev_bookmark_action_new (EvBookmark *bookmark)
+{
+        GtkAction *action;
+        gchar *name;
+
+        g_return_val_if_fail (bookmark->title != NULL, NULL);
+
+        name = g_strdup_printf ("EvBookmark%u", bookmark->page);
+        action = GTK_ACTION (g_object_new (EV_TYPE_BOOKMARK_ACTION,
+                                           "name", name,
+                                           "label", bookmark->title,
+                                           "page", bookmark->page,
+                                           NULL));
+        g_free (name);
+
+        return action;
+}
+
+guint
+ev_bookmark_action_get_page (EvBookmarkAction *action)
+{
+        g_return_val_if_fail (EV_IS_BOOKMARK_ACTION (action), 0);
+
+        return action->page;
+}
diff --git a/shell/ev-bookmark-action.h b/shell/ev-bookmark-action.h
new file mode 100644 (file)
index 0000000..8a36cdc
--- /dev/null
@@ -0,0 +1,45 @@
+/* ev-bookmark-action.h
+ *  this file is part of evince, a gnome document viewer
+ *
+ * Copyright (C) 2010 Carlos Garcia Campos  <carlosgc@gnome.org>
+ *
+ * Evince is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Evince is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef EV_BOOKMARK_ACTION_H
+#define EV_BOOKMARK_ACTION_H
+
+#include <gtk/gtk.h>
+#include <glib-object.h>
+
+#include "ev-bookmarks.h"
+
+G_BEGIN_DECLS
+
+#define EV_TYPE_BOOKMARK_ACTION         (ev_bookmark_action_get_type())
+#define EV_BOOKMARK_ACTION(object)      (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_BOOKMARK_ACTION, EvBookmarkAction))
+#define EV_BOOKMARK_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_BOOKMARK_ACTION, EvBookmarkActionClass))
+#define EV_IS_BOOKMARK_ACTION(object)   (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_BOOKMARK_ACTION))
+
+typedef struct _EvBookmarkAction      EvBookmarkAction;
+typedef struct _EvBookmarkActionClass EvBookmarkActionClass;
+
+GType      ev_bookmark_action_get_type (void) G_GNUC_CONST;
+GtkAction *ev_bookmark_action_new      (EvBookmark       *bookmark);
+guint      ev_bookmark_action_get_page (EvBookmarkAction *action);
+
+G_END_DECLS
+
+#endif /* EV_BOOKMARK_ACTION_H */
index e5acd4089c2dbd64f5850e6746220383bc3fed80..4fe718333f0890a131cef978b55c8269f922865b 100644 (file)
@@ -91,6 +91,8 @@
 #include "ev-print-operation.h"
 #include "ev-progress-message-area.h"
 #include "ev-annotation-properties-dialog.h"
+#include "ev-bookmarks.h"
+#include "ev-bookmark-action.h"
 
 #ifdef ENABLE_DBUS
 #include "ev-media-player-keys.h"
@@ -163,6 +165,8 @@ struct _EvWindowPrivate {
        GtkRecentManager *recent_manager;
        GtkActionGroup   *recent_action_group;
        guint             recent_ui_id;
+       GtkActionGroup   *bookmarks_action_group;
+       guint             bookmarks_ui_id;
        GtkUIManager     *ui_manager;
 
        /* Fullscreen mode */
@@ -192,6 +196,7 @@ struct _EvWindowPrivate {
        EvWindowPageMode page_mode;
        EvWindowTitle *title;
        EvMetadata *metadata;
+       EvBookmarks *bookmarks;
        gboolean is_new_doc;
 
        /* Load params */
@@ -345,6 +350,7 @@ static void     ev_window_update_max_min_scale          (EvWindow         *windo
 static void    ev_window_emit_closed                   (EvWindow         *window);
 static void    ev_window_emit_doc_loaded               (EvWindow         *window);
 #endif
+static void     ev_window_setup_bookmarks               (EvWindow         *window);
 
 static guint ev_window_n_copies = 0;
 
@@ -448,6 +454,10 @@ ev_window_setup_action_sensitivity (EvWindow *ev_window)
        ev_window_set_action_sensitive (ev_window, "ViewAutoscroll", has_pages);
        ev_window_set_action_sensitive (ev_window, "ViewInvertedColors", has_pages);
 
+       /* Bookmarks menu */
+       ev_window_set_action_sensitive (ev_window, "BookmarksAdd",
+                                       has_pages && ev_window->priv->bookmarks);
+
        /* 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);
@@ -784,18 +794,17 @@ ev_window_warning_message (EvWindow    *window,
        ev_window_set_message_area (window, area);
 }
 
-typedef struct _FindTask {
+typedef struct _PageTitleData {
        const gchar *page_label;
-       gchar *chapter;
-} FindTask;
+       gchar       *page_title;
+} PageTitleData;
 
 static gboolean
-ev_window_find_chapter (GtkTreeModel *tree_model,
-                       GtkTreePath  *path,
-                       GtkTreeIter  *iter,
-                       gpointer      data)
+ev_window_find_page_title (GtkTreeModel  *tree_model,
+                          GtkTreePath   *path,
+                          GtkTreeIter   *iter,
+                          PageTitleData *data)
 {
-       FindTask *task = (FindTask *)data;
        gchar *page_string;
        
        gtk_tree_model_get (tree_model, iter,
@@ -805,9 +814,9 @@ ev_window_find_chapter (GtkTreeModel *tree_model,
        if (!page_string)
                return FALSE;
        
-       if (!strcmp (page_string, task->page_label)) {
+       if (!strcmp (page_string, data->page_label)) {
                gtk_tree_model_get (tree_model, iter,
-                                   EV_DOCUMENT_LINKS_COLUMN_MARKUP, &task->chapter
+                                   EV_DOCUMENT_LINKS_COLUMN_MARKUP, &data->page_title
                                    -1);
                g_free (page_string);
                return TRUE;
@@ -817,12 +826,41 @@ ev_window_find_chapter (GtkTreeModel *tree_model,
        return FALSE;
 }
 
+static gchar *
+ev_window_get_page_title (EvWindow    *window,
+                         const gchar *page_label)
+{
+       if (EV_IS_DOCUMENT_LINKS (window->priv->document) &&
+           ev_document_links_has_document_links (EV_DOCUMENT_LINKS (window->priv->document))) {
+               PageTitleData data;
+               GtkTreeModel *model;
+
+               data.page_label = page_label;
+               data.page_title = NULL;
+
+               g_object_get (G_OBJECT (window->priv->sidebar_links),
+                             "model", &model,
+                             NULL);
+               if (model) {
+                       gtk_tree_model_foreach (model,
+                                               (GtkTreeModelForeachFunc)ev_window_find_page_title,
+                                               &data);
+
+                       g_object_unref (model);
+               }
+
+               return data.page_title;
+       }
+
+       return NULL;
+}
+
 static void
 ev_window_add_history (EvWindow *window, gint page, EvLink *link)
 {
        gchar *page_label = NULL;
+       gchar *page_title;
        gchar *link_title;
-       FindTask find_task;
        EvLink *real_link;
        EvLinkAction *action;
        EvLinkDest *dest;
@@ -845,34 +883,19 @@ ev_window_add_history (EvWindow *window, gint page, EvLink *link)
 
        if (!page_label)
                return;
-       
-       find_task.page_label = page_label;
-       find_task.chapter = NULL;
-       
-       if (ev_document_links_has_document_links (EV_DOCUMENT_LINKS (window->priv->document))) {
-               GtkTreeModel *model;
-       
-               g_object_get (G_OBJECT (window->priv->sidebar_links), "model", &model, NULL);
-               
-               if (model) {
-                       gtk_tree_model_foreach (model,
-                                               ev_window_find_chapter,
-                                               &find_task);
-       
-                       g_object_unref (model);
-               }
-       }
 
-       if (find_task.chapter)
-               link_title = g_strdup_printf (_("Page %s — %s"), page_label, find_task.chapter);
-       else
+       page_title = ev_window_get_page_title (window, page_label);
+       if (page_title) {
+               link_title = g_strdup_printf (_("Page %s — %s"), page_label, page_title);
+               g_free (page_title);
+       } else {
                link_title = g_strdup_printf (_("Page %s"), page_label);
-       
+       }
+
        real_link = ev_link_new (link_title, action);
        
        ev_history_add_link (window->priv->history, real_link);
 
-       g_free (find_task.chapter);
        g_free (link_title);
        g_free (page_label);
        g_object_unref (real_link);
@@ -2008,6 +2031,8 @@ ev_window_open_uri (EvWindow       *ev_window,
 
        if (ev_window->priv->metadata)
                g_object_unref (ev_window->priv->metadata);
+       if (ev_window->priv->bookmarks)
+               g_object_unref (ev_window->priv->bookmarks);
 
        source_file = g_file_new_for_uri (uri);
        if (!ev_file_is_temp (source_file) && ev_is_metadata_supported_for_file (source_file)) {
@@ -2017,6 +2042,15 @@ ev_window_open_uri (EvWindow       *ev_window,
                ev_window->priv->metadata = NULL;
        }
 
+       if (ev_window->priv->metadata) {
+               ev_window->priv->bookmarks = ev_bookmarks_new (ev_window->priv->metadata);
+               g_signal_connect_swapped (ev_window->priv->bookmarks, "changed",
+                                         G_CALLBACK (ev_window_setup_bookmarks),
+                                         ev_window);
+       } else {
+               ev_window->priv->bookmarks = NULL;
+       }
+
        if (ev_window->priv->search_string)
                g_free (ev_window->priv->search_string);
        ev_window->priv->search_string = search_string ?
@@ -2028,6 +2062,7 @@ ev_window_open_uri (EvWindow       *ev_window,
 
        setup_size_from_metadata (ev_window);
        setup_model_from_metadata (ev_window);
+       ev_window_setup_bookmarks (ev_window);
 
        ev_window->priv->load_job = ev_job_load_new (uri);
        g_signal_connect (ev_window->priv->load_job,
@@ -4338,6 +4373,92 @@ ev_window_cmd_go_backward (GtkAction *action, EvWindow *ev_window)
        }
 }
 
+static void
+ev_window_cmd_bookmark_activate (GtkAction *action,
+                                EvWindow  *window)
+{
+       guint page = ev_bookmark_action_get_page (EV_BOOKMARK_ACTION (action));
+
+       ev_document_model_set_page (window->priv->model, page);
+}
+
+static gint
+compare_bookmarks (EvBookmark *a,
+                  EvBookmark *b)
+{
+       return strcmp (a->title, b->title);
+}
+
+static void
+ev_window_setup_bookmarks (EvWindow *window)
+{
+       GList *items, *l;
+
+       if (!window->priv->bookmarks)
+               return;
+
+       if (window->priv->bookmarks_ui_id > 0) {
+               gtk_ui_manager_remove_ui (window->priv->ui_manager,
+                                         window->priv->bookmarks_ui_id);
+               gtk_ui_manager_ensure_update (window->priv->ui_manager);
+       }
+       window->priv->bookmarks_ui_id = gtk_ui_manager_new_merge_id (window->priv->ui_manager);
+
+       if (window->priv->bookmarks_action_group) {
+               gtk_ui_manager_remove_action_group (window->priv->ui_manager,
+                                                   window->priv->bookmarks_action_group);
+               g_object_unref (window->priv->bookmarks_action_group);
+       }
+       window->priv->bookmarks_action_group = gtk_action_group_new ("BookmarksActions");
+       gtk_ui_manager_insert_action_group (window->priv->ui_manager,
+                                           window->priv->bookmarks_action_group, -1);
+
+       items = ev_bookmarks_get_bookmarks (window->priv->bookmarks);
+       items = g_list_sort (items, (GCompareFunc)compare_bookmarks);
+
+       for (l = items; l && l->data; l = g_list_next (l)) {
+               EvBookmark *bm = (EvBookmark *)l->data;
+               GtkAction  *action;
+
+               action = ev_bookmark_action_new (bm);
+               g_signal_connect (action, "activate",
+                                 G_CALLBACK (ev_window_cmd_bookmark_activate),
+                                 window);
+               gtk_action_group_add_action (window->priv->bookmarks_action_group,
+                                            action);
+
+               gtk_ui_manager_add_ui (window->priv->ui_manager,
+                                      window->priv->bookmarks_ui_id,
+                                      "/MainMenu/BookmarksMenu/BookmarksItems",
+                                      gtk_action_get_label (action),
+                                      gtk_action_get_name (action),
+                                      GTK_UI_MANAGER_MENUITEM,
+                                      FALSE);
+
+               g_object_unref (action);
+       }
+
+       g_list_free (items);
+}
+
+static void
+ev_window_cmd_bookmarks_add (GtkAction *action,
+                            EvWindow  *window)
+{
+       EvBookmark bm;
+       gchar     *page_label;
+       gchar     *page_title;
+
+       bm.page = ev_document_model_get_page (window->priv->model);
+       page_label = ev_document_get_page_label (window->priv->document, bm.page);
+       page_title = ev_window_get_page_title (window, page_label);
+       bm.title = page_title ? page_title : g_strdup_printf (_("Page %s"), page_label);
+       g_free (page_label);
+
+       /* EvBookmarks takes ownership of bookmark */
+       ev_bookmarks_add (window->priv->bookmarks, &bm);
+}
+
 static void
 ev_window_cmd_view_reload (GtkAction *action, EvWindow *ev_window)
 {
@@ -5172,6 +5293,11 @@ ev_window_dispose (GObject *object)
        }
 #endif /* ENABLE_DBUS */
 
+       if (priv->bookmarks) {
+               g_object_unref (priv->bookmarks);
+               priv->bookmarks = NULL;
+       }
+
        if (priv->metadata) {
                g_object_unref (priv->metadata);
                priv->metadata = NULL;
@@ -5217,6 +5343,11 @@ ev_window_dispose (GObject *object)
                priv->recent_action_group = NULL;
        }
 
+       if (priv->bookmarks_action_group) {
+               g_object_unref (priv->bookmarks_action_group);
+               priv->bookmarks_action_group = NULL;
+       }
+
        if (priv->recent_manager) {
                g_signal_handlers_disconnect_by_func (priv->recent_manager,
                                                      ev_window_setup_recent,
@@ -5446,6 +5577,7 @@ static const GtkActionEntry entries[] = {
         { "Edit", NULL, N_("_Edit") },
        { "View", NULL, N_("_View") },
         { "Go", NULL, N_("_Go") },
+       { "Bookmarks", NULL, N_("_Bookmarks") },
        { "Help", NULL, N_("_Help") },
 
        /* File menu */
@@ -5519,6 +5651,11 @@ static const GtkActionEntry entries[] = {
           N_("Go to the last page"),
           G_CALLBACK (ev_window_cmd_go_last_page) },
 
+       /* Bookmarks menu */
+       { "BookmarksAdd", GTK_STOCK_ADD, N_("_Add Bookmark"), "<control>D",
+         N_("Add a bookmark for the current page"),
+         G_CALLBACK (ev_window_cmd_bookmarks_add) },
+
        /* Help menu */
        { "HelpContents", GTK_STOCK_HELP, N_("_Contents"), "F1", NULL,
          G_CALLBACK (ev_window_cmd_help_contents) },