[evince] shell: Add bookmarks menu to add and show internal bookmarks



commit f7eb83a4ad43b1b30af202eb8f33f3057c2a51c5
Author: Carlos Garcia Campos <carlosgc gnome org>
Date:   Mon Dec 6 17:40:48 2010 +0100

    shell: Add bookmarks menu to add and show internal bookmarks
    
    Fixes bug #590655.

 data/evince-ui.xml         |    6 ++
 shell/Makefile.am          |    2 +
 shell/ev-bookmark-action.c |  105 +++++++++++++++++++++++
 shell/ev-bookmark-action.h |   45 ++++++++++
 shell/ev-window.c          |  203 ++++++++++++++++++++++++++++++++++++-------
 5 files changed, 328 insertions(+), 33 deletions(-)
---
diff --git a/data/evince-ui.xml b/data/evince-ui.xml
index 8067546..3aca084 100644
--- a/data/evince-ui.xml
+++ b/data/evince-ui.xml
@@ -60,6 +60,12 @@
       <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"/>
diff --git a/shell/Makefile.am b/shell/Makefile.am
index 7a30326..d760955 100644
--- a/shell/Makefile.am
+++ b/shell/Makefile.am
@@ -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
index 0000000..3689d7a
--- /dev/null
+++ b/shell/ev-bookmark-action.c
@@ -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
index 0000000..8a36cdc
--- /dev/null
+++ b/shell/ev-bookmark-action.h
@@ -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 */
diff --git a/shell/ev-window.c b/shell/ev-window.c
index e5acd40..4fe7183 100644
--- a/shell/ev-window.c
+++ b/shell/ev-window.c
@@ -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,
@@ -4339,6 +4374,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)
 {
 	ev_window_reload_document (ev_window, NULL);
@@ -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) },



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]