[evince] Add navigation history buttons to the toolbar
- From: Carlos Garcia Campos <carlosgc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evince] Add navigation history buttons to the toolbar
- Date: Sun, 17 Feb 2013 19:08:03 +0000 (UTC)
commit 67dc2d3be3c411c53ec32a9a7b2bea3981322526
Author: Carlos Garcia Campos <carlosgc gnome org>
Date: Sun Feb 17 19:49:00 2013 +0100
Add navigation history buttons to the toolbar
Rework EvHistory to use back and forward lists instead of a single
history list and add back/forward buttons to the toolbar to navigate the
history of visited links.
https://bugzilla.gnome.org/show_bug.cgi?id=169903
help/reference/shell/evince-docs.xml | 2 -
help/reference/shell/evince-sections.txt | 28 --
help/reference/shell/evince.types | 2 -
po/POTFILES.in | 3 +-
shell/Makefile.am | 8 +-
shell/ev-history-action-widget.c | 331 ++++++++++++++++++++++++
shell/ev-history-action-widget.h | 58 +++++
shell/ev-history-action.c | 119 +++++++++
shell/ev-history-action.h | 59 +++++
shell/ev-history.c | 402 +++++++++++++++++++++++++-----
shell/ev-history.h | 31 ++-
shell/ev-navigation-action-widget.c | 214 ----------------
shell/ev-navigation-action-widget.h | 46 ----
shell/ev-navigation-action.c | 247 ------------------
shell/ev-navigation-action.h | 64 -----
shell/ev-toolbar.c | 12 +
shell/ev-window.c | 173 +++++--------
17 files changed, 1010 insertions(+), 789 deletions(-)
---
diff --git a/help/reference/shell/evince-docs.xml b/help/reference/shell/evince-docs.xml
index 052ab20..7c1036f 100644
--- a/help/reference/shell/evince-docs.xml
+++ b/help/reference/shell/evince-docs.xml
@@ -93,11 +93,9 @@
<xi:include href="xml/ev-password-view.xml"/>
<xi:include href="xml/eggfindbar.xml"/>
<xi:include href="xml/ev-media-player-keys.xml"/>
- <xi:include href="xml/ev-navigation-action.xml"/>
<xi:include href="xml/ev-file-monitor.xml"/>
<xi:include href="xml/ev-page-action.xml"/>
<xi:include href="xml/ev-window-title.xml"/>
- <xi:include href="xml/ev-navigation-action-widget.xml"/>
<xi:include href="xml/ev-keyring.xml"/>
<xi:include href="xml/ev-utils.xml"/>
<xi:include href="xml/ev-page-action-widget.xml"/>
diff --git a/help/reference/shell/evince-sections.txt b/help/reference/shell/evince-sections.txt
index a775f7e..1bf89a5 100644
--- a/help/reference/shell/evince-sections.txt
+++ b/help/reference/shell/evince-sections.txt
@@ -366,23 +366,6 @@ EV_MEDIA_PLAYER_KEYS_GET_CLASS
</SECTION>
<SECTION>
-<FILE>ev-navigation-action</FILE>
-<TITLE>EvNavigationAction</TITLE>
-EvNavigationAction
-EvNavigationActionPrivate
-EvNavigationActionClass
-ev_navigation_action_set_history
-<SUBSECTION Standard>
-EV_NAVIGATION_ACTION
-EV_IS_NAVIGATION_ACTION
-EV_TYPE_NAVIGATION_ACTION
-ev_navigation_action_get_type
-EV_NAVIGATION_ACTION_CLASS
-EV_IS_NAVIGATION_ACTION_CLASS
-EV_NAVIGATION_ACTION_GET_CLASS
-</SECTION>
-
-<SECTION>
<FILE>ev-file-monitor</FILE>
<TITLE>EvFileMonitor</TITLE>
EvFileMonitor
@@ -430,17 +413,6 @@ ev_window_title_free
</SECTION>
<SECTION>
-<FILE>ev-navigation-action-widget</FILE>
-<TITLE>EvNavigationActionWidget</TITLE>
-EV_TYPE_NAVIGATION_ACTION_WIDGET
-EV_NAVIGATION_ACTION_WIDGET
-EvNavigationActionWidget
-EvNavigationActionWidgetClass
-ev_navigation_action_widget_get_type
-ev_navigation_action_widget_set_menu
-</SECTION>
-
-<SECTION>
<FILE>ev-keyring</FILE>
ev_keyring_is_available
ev_keyring_lookup_password
diff --git a/help/reference/shell/evince.types b/help/reference/shell/evince.types
index dea7db5..1df224b 100644
--- a/help/reference/shell/evince.types
+++ b/help/reference/shell/evince.types
@@ -5,8 +5,6 @@ ev_history_get_type
ev_media_player_keys_get_type
ev_message_area_get_type
ev_metadata_get_type
-ev_navigation_action_get_type
-ev_navigation_action_widget_get_type
ev_open_recent_action_get_type
ev_page_action_get_type
ev_page_action_widget_get_type
diff --git a/po/POTFILES.in b/po/POTFILES.in
index e09f2fa..5455485 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -36,10 +36,9 @@ shell/eggfindbar.c
shell/ev-annotation-properties-dialog.c
shell/ev-application.c
shell/ev-history.c
+shell/ev-history-action-widget.c
shell/ev-keyring.c
shell/ev-loading-message.c
-shell/ev-navigation-action.c
-shell/ev-navigation-action-widget.c
shell/ev-open-recent-action.c
shell/ev-password-view.c
shell/ev-properties-dialog.c
diff --git a/shell/Makefile.am b/shell/Makefile.am
index 38952b6..1ec8dde 100644
--- a/shell/Makefile.am
+++ b/shell/Makefile.am
@@ -39,6 +39,10 @@ evince_SOURCES= \
ev-file-monitor.c \
ev-history.c \
ev-history.h \
+ ev-history-action.c \
+ ev-history-action.h \
+ ev-history-action-widget.c \
+ ev-history-action-widget.h \
ev-keyring.h \
ev-keyring.c \
ev-loading-message.c \
@@ -47,10 +51,6 @@ evince_SOURCES= \
ev-message-area.h \
ev-metadata.c \
ev-metadata.h \
- ev-navigation-action.c \
- ev-navigation-action.h \
- ev-navigation-action-widget.c \
- ev-navigation-action-widget.h \
ev-password-view.h \
ev-password-view.c \
ev-progress-message-area.h \
diff --git a/shell/ev-history-action-widget.c b/shell/ev-history-action-widget.c
new file mode 100644
index 0000000..fc3a707
--- /dev/null
+++ b/shell/ev-history-action-widget.c
@@ -0,0 +1,331 @@
+/* ev-history-action-widget.c
+ * this file is part of evince, a gnome document viewer
+ *
+ * Copyright (C) 2013 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "ev-history-action-widget.h"
+
+#include <glib/gi18n.h>
+#include <math.h>
+
+
+enum {
+ PROP_0,
+
+ PROP_POPUP_SHOWN
+};
+
+struct _EvHistoryActionWidgetPrivate {
+ GtkWidget *back_button;
+ GtkWidget *forward_button;
+
+ EvHistory *history;
+ gboolean popup_shown;
+};
+
+typedef enum {
+ EV_HISTORY_ACTION_BUTTON_BACK,
+ EV_HISTORY_ACTION_BUTTON_FORWARD
+} EvHistoryActionButton;
+
+G_DEFINE_TYPE (EvHistoryActionWidget, ev_history_action_widget, GTK_TYPE_TOOL_ITEM)
+
+static void
+ev_history_action_widget_finalize (GObject *object)
+{
+ EvHistoryActionWidget *control = EV_HISTORY_ACTION_WIDGET (object);
+
+ ev_history_action_widget_set_history (control, NULL);
+
+ G_OBJECT_CLASS (ev_history_action_widget_parent_class)->finalize (object);
+}
+
+static void
+ev_history_action_widget_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EvHistoryActionWidget *history_widget = EV_HISTORY_ACTION_WIDGET (object);
+
+ switch (prop_id) {
+ case PROP_POPUP_SHOWN:
+ g_value_set_boolean (value, history_widget->priv->popup_shown);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+ev_history_action_widget_set_popup_shown (EvHistoryActionWidget *history_widget,
+ gboolean popup_shown)
+{
+ if (history_widget->priv->popup_shown == popup_shown)
+ return;
+
+ history_widget->priv->popup_shown = popup_shown;
+ g_object_notify (G_OBJECT (history_widget), "popup-shown");
+}
+
+static void
+history_menu_link_activated (GtkMenuItem *item,
+ EvHistoryActionWidget *history_widget)
+{
+ EvLink *link;
+
+ link = EV_LINK (g_object_get_data (G_OBJECT (item), "ev-history-menu-item-link"));
+ if (!link)
+ return;
+
+ ev_history_go_to_link (history_widget->priv->history, link);
+}
+
+static void
+popup_menu_hide_cb (GtkMenu *menu,
+ EvHistoryActionWidget *history_widget)
+{
+ ev_history_action_widget_set_popup_shown (history_widget, FALSE);
+}
+
+static void
+ev_history_action_widget_show_popup (EvHistoryActionWidget *history_widget,
+ EvHistoryActionButton action_button,
+ guint button,
+ guint32 event_time)
+{
+ GtkWidget *menu;
+ GList *list = NULL;
+ GList *l;
+
+ switch (action_button) {
+ case EV_HISTORY_ACTION_BUTTON_BACK:
+ list = ev_history_get_back_list (history_widget->priv->history);
+ break;
+ case EV_HISTORY_ACTION_BUTTON_FORWARD:
+ list = ev_history_get_forward_list (history_widget->priv->history);
+ break;
+ }
+
+ if (!list)
+ return;
+
+ menu = gtk_menu_new ();
+
+ for (l = list; l; l = g_list_next (l)) {
+ EvLink *link = EV_LINK (l->data);
+ GtkWidget *item;
+
+ item = gtk_menu_item_new_with_label (ev_link_get_title (link));
+ g_object_set_data_full (G_OBJECT (item), "ev-history-menu-item-link",
+ g_object_ref (link), (GDestroyNotify)g_object_unref);
+ g_signal_connect_object (item, "activate",
+ G_CALLBACK (history_menu_link_activated),
+ history_widget, 0);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show (item);
+ }
+
+ ev_history_action_widget_set_popup_shown (history_widget, TRUE);
+ g_signal_connect (menu, "hide",
+ G_CALLBACK (popup_menu_hide_cb),
+ history_widget);
+ gtk_menu_popup (GTK_MENU (menu),
+ NULL, NULL, NULL, NULL,
+ button, event_time);
+}
+
+static void
+button_clicked (GtkWidget *button,
+ EvHistoryActionWidget *history_widget)
+{
+ EvHistoryActionWidgetPrivate *priv = history_widget->priv;
+
+ if (button == priv->back_button)
+ ev_history_go_back (priv->history);
+ else if (button == priv->forward_button)
+ ev_history_go_forward (priv->history);
+}
+
+static gboolean
+button_pressed (GtkWidget *button,
+ GdkEventButton *event,
+ EvHistoryActionWidget *history_widget)
+{
+ EvHistoryActionWidgetPrivate *priv = history_widget->priv;
+
+ /* TODO: Show the popup menu after a long press too */
+ switch (event->button) {
+ case GDK_BUTTON_SECONDARY:
+ ev_history_action_widget_show_popup (history_widget,
+ button == priv->back_button ?
+ EV_HISTORY_ACTION_BUTTON_BACK :
+ EV_HISTORY_ACTION_BUTTON_FORWARD,
+ event->button, event->time);
+ return GDK_EVENT_STOP;
+ default:
+ break;
+ }
+
+ return GDK_EVENT_PROPAGATE;
+}
+
+static gint
+get_icon_margin (EvHistoryActionWidget *history_widget)
+{
+ gint toolbar_size_px, menu_size_px;
+ GtkSettings *settings = gtk_widget_get_settings (GTK_WIDGET (history_widget));
+
+ gtk_icon_size_lookup_for_settings (settings, GTK_ICON_SIZE_MENU, &menu_size_px, NULL);
+ gtk_icon_size_lookup_for_settings (settings, GTK_ICON_SIZE_LARGE_TOOLBAR, &toolbar_size_px, NULL);
+
+ return (gint)floor ((toolbar_size_px - menu_size_px) / 2.0);
+}
+
+static GtkWidget *
+ev_history_action_widget_create_button (EvHistoryActionWidget *history_widget,
+ EvHistoryActionButton action_button)
+{
+ GtkWidget *button;
+ GtkWidget *image;
+ const gchar *icon_name = NULL;
+ const gchar *tooltip_text = NULL;
+
+ button = gtk_button_new ();
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (button_clicked),
+ history_widget);
+ g_signal_connect (button, "button-press-event",
+ G_CALLBACK (button_pressed),
+ history_widget);
+
+ switch (action_button) {
+ case EV_HISTORY_ACTION_BUTTON_BACK:
+ icon_name = "go-previous-symbolic";
+ tooltip_text = _("Go to previous history item");
+ break;
+ case EV_HISTORY_ACTION_BUTTON_FORWARD:
+ icon_name = "go-next-symbolic";
+ tooltip_text = _("Go to next history item");
+ break;
+ }
+
+ image = gtk_image_new ();
+ g_object_set (image, "margin", get_icon_margin (history_widget), NULL);
+ gtk_button_set_image (GTK_BUTTON (button), image);
+ gtk_image_set_from_icon_name (GTK_IMAGE (image), icon_name, GTK_ICON_SIZE_MENU);
+ gtk_widget_set_tooltip_text (button, tooltip_text);
+ gtk_widget_set_can_focus (button, FALSE);
+
+ return button;
+}
+
+static void
+ev_history_action_widget_init (EvHistoryActionWidget *history_widget)
+{
+ EvHistoryActionWidgetPrivate *priv;
+ GtkWidget *box;
+ GtkStyleContext *style_context;
+
+ history_widget->priv = G_TYPE_INSTANCE_GET_PRIVATE (history_widget, EV_TYPE_HISTORY_ACTION_WIDGET,
EvHistoryActionWidgetPrivate);
+ priv = history_widget->priv;
+
+ box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ style_context = gtk_widget_get_style_context (box);
+ gtk_style_context_add_class (style_context, GTK_STYLE_CLASS_RAISED);
+ gtk_style_context_add_class (style_context, GTK_STYLE_CLASS_LINKED);
+
+ priv->back_button = ev_history_action_widget_create_button (history_widget,
+ EV_HISTORY_ACTION_BUTTON_BACK);
+ gtk_container_add (GTK_CONTAINER (box), priv->back_button);
+ gtk_widget_show (priv->back_button);
+
+ priv->forward_button = ev_history_action_widget_create_button (history_widget,
+ EV_HISTORY_ACTION_BUTTON_FORWARD);
+ gtk_container_add (GTK_CONTAINER (box), priv->forward_button);
+ gtk_widget_show (priv->forward_button);
+
+ gtk_container_add (GTK_CONTAINER (history_widget), box);
+ gtk_widget_show (box);
+
+ gtk_widget_set_sensitive (priv->back_button, FALSE);
+ gtk_widget_set_sensitive (priv->forward_button, FALSE);
+}
+
+static void
+ev_history_action_widget_class_init (EvHistoryActionWidgetClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = ev_history_action_widget_get_property;
+ object_class->finalize = ev_history_action_widget_finalize;
+
+ g_object_class_install_property (object_class,
+ PROP_POPUP_SHOWN,
+ g_param_spec_boolean ("popup-shown",
+ "Popup shown",
+ "Whether the history's dropdown is shown",
+ FALSE,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ g_type_class_add_private (object_class, sizeof (EvHistoryActionWidgetPrivate));
+}
+
+static void
+history_changed_cb (EvHistory *history,
+ EvHistoryActionWidget *history_widget)
+{
+ EvHistoryActionWidgetPrivate *priv = history_widget->priv;
+
+ gtk_widget_set_sensitive (priv->back_button, ev_history_can_go_back (history));
+ gtk_widget_set_sensitive (priv->forward_button, ev_history_can_go_forward (history));
+}
+
+void
+ev_history_action_widget_set_history (EvHistoryActionWidget *history_widget,
+ EvHistory *history)
+{
+ g_return_if_fail (EV_IS_HISTORY_ACTION_WIDGET (history_widget));
+
+ if (history_widget->priv->history == history)
+ return;
+
+ if (history_widget->priv->history) {
+ g_object_remove_weak_pointer (G_OBJECT (history_widget->priv->history),
+ (gpointer)&history_widget->priv->history);
+ g_signal_handlers_disconnect_by_func (history_widget->priv->history,
+ G_CALLBACK (history_changed_cb),
+ history_widget);
+ }
+
+ history_widget->priv->history = history;
+ if (!history)
+ return;
+
+ g_object_add_weak_pointer (G_OBJECT (history),
+ (gpointer)&history_widget->priv->history);
+
+ g_signal_connect (history, "changed",
+ G_CALLBACK (history_changed_cb),
+ history_widget);
+}
+
diff --git a/shell/ev-history-action-widget.h b/shell/ev-history-action-widget.h
new file mode 100644
index 0000000..befa24b
--- /dev/null
+++ b/shell/ev-history-action-widget.h
@@ -0,0 +1,58 @@
+/* ev-history-action-widget.h
+ * this file is part of evince, a gnome document viewer
+ *
+ * Copyright (C) 2013 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef EV_HISTORY_ACTION_WIDGET_H
+#define EV_HISTORY_ACTION_WIDGET_H
+
+#include <gtk/gtk.h>
+
+#include "ev-history.h"
+
+G_BEGIN_DECLS
+
+#define EV_TYPE_HISTORY_ACTION_WIDGET (ev_history_action_widget_get_type())
+#define EV_HISTORY_ACTION_WIDGET(object) (G_TYPE_CHECK_INSTANCE_CAST((object),
EV_TYPE_HISTORY_ACTION_WIDGET, EvHistoryActionWidget))
+#define EV_IS_HISTORY_ACTION_WIDGET(object) (G_TYPE_CHECK_INSTANCE_TYPE((object),
EV_TYPE_HISTORY_ACTION_WIDGET))
+#define EV_HISTORY_ACTION_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),
EV_TYPE_HISTORY_ACTION_WIDGET, EvHistoryActionWidgetClass))
+#define EV_IS_HISTORY_ACTION_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),
EV_TYPE_HISTORY_ACTION_WIDGET))
+#define EV_HISTORY_ACTION_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),
EV_TYPE_HISTORY_ACTION_WIDGET, EvHistoryActionWidgetClass))
+
+typedef struct _EvHistoryActionWidget EvHistoryActionWidget;
+typedef struct _EvHistoryActionWidgetClass EvHistoryActionWidgetClass;
+typedef struct _EvHistoryActionWidgetPrivate EvHistoryActionWidgetPrivate;
+
+struct _EvHistoryActionWidget {
+ GtkToolItem parent_object;
+
+ EvHistoryActionWidgetPrivate *priv;
+};
+
+struct _EvHistoryActionWidgetClass {
+ GtkToolItemClass parent_class;
+};
+
+GType ev_history_action_widget_get_type (void);
+
+void ev_history_action_widget_set_history (EvHistoryActionWidget *history_widget,
+ EvHistory *history);
+
+G_END_DECLS
+
+#endif
diff --git a/shell/ev-history-action.c b/shell/ev-history-action.c
new file mode 100644
index 0000000..cda9fc1
--- /dev/null
+++ b/shell/ev-history-action.c
@@ -0,0 +1,119 @@
+/* ev-history-action.c
+ * this file is part of evince, a gnome document viewer
+ *
+ * Copyright (C) 2013 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "ev-history-action.h"
+#include "ev-history-action-widget.h"
+
+enum {
+ ACTIVATED,
+ LAST_SIGNAL
+};
+
+
+struct _EvHistoryActionPrivate {
+ EvHistory *history;
+ gboolean popup_shown;
+};
+
+G_DEFINE_TYPE (EvHistoryAction, ev_history_action, GTK_TYPE_ACTION)
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static void
+popup_shown_cb (GObject *history_widget,
+ GParamSpec *pspec,
+ EvHistoryAction *history_action)
+{
+ g_object_get (history_widget, "popup-shown", &history_action->priv->popup_shown, NULL);
+}
+
+static void
+connect_proxy (GtkAction *action,
+ GtkWidget *proxy)
+{
+ if (EV_IS_HISTORY_ACTION_WIDGET (proxy)) {
+ EvHistoryAction *history_action = EV_HISTORY_ACTION (action);
+ EvHistoryActionWidget *history_widget = EV_HISTORY_ACTION_WIDGET (proxy);
+
+ ev_history_action_widget_set_history (history_widget, history_action->priv->history);
+ g_signal_connect (history_widget, "notify::popup-shown",
+ G_CALLBACK (popup_shown_cb),
+ action);
+ }
+
+ GTK_ACTION_CLASS (ev_history_action_parent_class)->connect_proxy (action, proxy);
+}
+
+static void
+ev_history_action_class_init (EvHistoryActionClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ GtkActionClass *action_class = GTK_ACTION_CLASS (class);
+
+ action_class->toolbar_item_type = EV_TYPE_HISTORY_ACTION_WIDGET;
+ action_class->connect_proxy = connect_proxy;
+
+ signals[ACTIVATED] =
+ g_signal_new ("activated",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ g_type_class_add_private (object_class, sizeof (EvHistoryActionPrivate));
+}
+
+static void
+ev_history_action_init (EvHistoryAction *action)
+{
+ action->priv = G_TYPE_INSTANCE_GET_PRIVATE (action, EV_TYPE_HISTORY_ACTION, EvHistoryActionPrivate);
+}
+
+void
+ev_history_action_set_history (EvHistoryAction *action,
+ EvHistory *history)
+{
+ GSList *proxies, *l;
+
+ g_return_if_fail (EV_IS_HISTORY_ACTION (action));
+ g_return_if_fail (EV_IS_HISTORY (history));
+
+ if (action->priv->history == history)
+ return;
+
+ action->priv->history = history;
+ proxies = gtk_action_get_proxies (GTK_ACTION (action));
+ for (l = proxies; l && l->data; l = g_slist_next (l)) {
+ if (EV_IS_HISTORY_ACTION_WIDGET (l->data))
+ ev_history_action_widget_set_history (EV_HISTORY_ACTION_WIDGET (l->data), history);
+ }
+}
+
+gboolean
+ev_history_action_get_popup_shown (EvHistoryAction *action)
+{
+ g_return_val_if_fail (EV_IS_HISTORY_ACTION (action), FALSE);
+
+ return action->priv->popup_shown;
+}
+
diff --git a/shell/ev-history-action.h b/shell/ev-history-action.h
new file mode 100644
index 0000000..48b3160
--- /dev/null
+++ b/shell/ev-history-action.h
@@ -0,0 +1,59 @@
+/* ev-history-action.h
+ * this file is part of evince, a gnome document viewer
+ *
+ * Copyright (C) 2013 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef EV_HISTORY_ACTION_H
+#define EV_HISTORY_ACTION_H
+
+#include <gtk/gtk.h>
+
+#include "ev-history.h"
+
+G_BEGIN_DECLS
+
+#define EV_TYPE_HISTORY_ACTION (ev_history_action_get_type ())
+#define EV_HISTORY_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EV_TYPE_HISTORY_ACTION,
EvHistoryAction))
+#define EV_IS_HISTORY_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EV_TYPE_HISTORY_ACTION))
+#define EV_HISTORY_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EV_TYPE_HISTORY_ACTION,
EvHistoryActionClass))
+#define EV_IS_HISTORY_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EV_TYPE_HISTORY_ACTION))
+#define EV_HISTORY_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EV_TYPE_HISTORY_ACTION,
EvHistoryActionClass))
+
+typedef struct _EvHistoryAction EvHistoryAction;
+typedef struct _EvHistoryActionClass EvHistoryActionClass;
+typedef struct _EvHistoryActionPrivate EvHistoryActionPrivate;
+
+struct _EvHistoryAction {
+ GtkAction parent;
+
+ EvHistoryActionPrivate *priv;
+};
+
+struct _EvHistoryActionClass {
+ GtkActionClass parent_class;
+};
+
+GType ev_history_action_get_type (void);
+
+void ev_history_action_set_history (EvHistoryAction *action,
+ EvHistory *history);
+gboolean ev_history_action_get_popup_shown (EvHistoryAction *action);
+
+G_END_DECLS
+
+#endif
diff --git a/shell/ev-history.c b/shell/ev-history.c
index 9b59014..0f3ee2d 100644
--- a/shell/ev-history.c
+++ b/shell/ev-history.c
@@ -24,40 +24,40 @@
#include "ev-history.h"
+enum {
+ CHANGED,
+ ACTIVATE_LINK,
-enum
-{
- HISTORY_CHANGED,
N_SIGNALS
};
static guint signals[N_SIGNALS] = {0, };
-struct _EvHistoryPrivate
-{
- GList *links;
-};
+struct _EvHistoryPrivate {
+ EvLink *current;
+ GList *back_list;
+ GList *forward_list;
-static void ev_history_init (EvHistory *history);
-static void ev_history_class_init (EvHistoryClass *class);
+ EvDocumentModel *model;
+ gulong page_changed_handler_id;
+ gboolean activating_current_link;
+};
G_DEFINE_TYPE (EvHistory, ev_history, G_TYPE_OBJECT)
-#define EV_HISTORY_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EV_TYPE_HISTORY,
EvHistoryPrivate))
+static void ev_history_set_model (EvHistory *history,
+ EvDocumentModel *model);
static void
-ev_history_init (EvHistory *history)
+ev_history_clear (EvHistory *history)
{
- history->priv = EV_HISTORY_GET_PRIVATE (history);
+ g_clear_object (&history->priv->current);
- history->priv->links = NULL;
-}
+ g_list_free_full (history->priv->back_list, (GDestroyNotify)g_object_unref);
+ history->priv->back_list = NULL;
-static void
-free_links_list (GList *l)
-{
- g_list_foreach (l, (GFunc)g_object_unref, NULL);
- g_list_free (l);
+ g_list_free_full (history->priv->forward_list, (GDestroyNotify)g_object_unref);
+ history->priv->forward_list = NULL;
}
static void
@@ -65,7 +65,8 @@ ev_history_finalize (GObject *object)
{
EvHistory *history = EV_HISTORY (object);
- free_links_list (history->priv->links);
+ ev_history_clear (history);
+ ev_history_set_model (history, NULL);
G_OBJECT_CLASS (ev_history_parent_class)->finalize (object);
}
@@ -77,72 +78,347 @@ ev_history_class_init (EvHistoryClass *class)
object_class->finalize = ev_history_finalize;
- signals[HISTORY_CHANGED] =
- g_signal_new ("changed",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET (EvHistoryClass, changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
+ signals[CHANGED] =
+ g_signal_new ("changed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (EvHistoryClass, changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[ACTIVATE_LINK] =
+ g_signal_new ("activate-link",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (EvHistoryClass, activate_link),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ G_TYPE_OBJECT);
g_type_class_add_private (object_class, sizeof (EvHistoryPrivate));
}
-#define HISTORY_LENGTH 7
+static void
+ev_history_init (EvHistory *history)
+{
+ history->priv = G_TYPE_INSTANCE_GET_PRIVATE (history, EV_TYPE_HISTORY, EvHistoryPrivate);
+}
void
-ev_history_add_link (EvHistory *history, EvLink *link)
+ev_history_add_link (EvHistory *history,
+ EvLink *link)
{
- GList *l;
-
g_return_if_fail (EV_IS_HISTORY (history));
g_return_if_fail (EV_IS_LINK (link));
- for (l = history->priv->links; l; l = l->next) {
- if (!strcmp (ev_link_get_title (EV_LINK (l->data)), ev_link_get_title (link))) {
- g_object_unref (G_OBJECT (l->data));
- history->priv->links = g_list_delete_link (history->priv->links, l);
- break;
- }
- }
+ if (history->priv->activating_current_link)
+ return;
+
+ if (ev_history_go_to_link (history, link))
+ return;
+
+ if (history->priv->current) {
+ history->priv->back_list = g_list_prepend (history->priv->back_list,
+ history->priv->current);
+ }
+
+ history->priv->current = g_object_ref (link);
+
+ g_list_free_full (history->priv->forward_list, (GDestroyNotify)g_object_unref);
+ history->priv->forward_list = NULL;
+
+ /* TODO: Decide a history limit and delete old links when the limit is reached */
+
+ g_signal_emit (history, signals[CHANGED], 0);
+}
+
+static void
+ev_history_activate_current_link (EvHistory *history)
+{
+ history->priv->activating_current_link = TRUE;
+ g_signal_handler_block (history->priv->model, history->priv->page_changed_handler_id);
+ g_signal_emit (history, signals[ACTIVATE_LINK], 0, history->priv->current);
+ g_signal_handler_unblock (history->priv->model, history->priv->page_changed_handler_id);
+ history->priv->activating_current_link = FALSE;
+
+ g_signal_emit (history, signals[CHANGED], 0);
+}
+
+gboolean
+ev_history_can_go_back (EvHistory *history)
+{
+ g_return_val_if_fail (EV_IS_HISTORY (history), FALSE);
- g_object_ref (link);
- history->priv->links = g_list_append (history->priv->links,
- link);
-
- if (g_list_length (history->priv->links) > HISTORY_LENGTH) {
- g_object_unref (G_OBJECT (history->priv->links->data));
- history->priv->links = g_list_delete_link (history->priv->links,
- history->priv->links);
- }
-
- g_signal_emit (history, signals[HISTORY_CHANGED], 0);
+ return history->priv->back_list != NULL;
}
-EvLink *
-ev_history_get_link_nth (EvHistory *history, int index)
+void
+ev_history_go_back (EvHistory *history)
{
- GList *l;
+ g_return_if_fail (EV_IS_HISTORY (history));
- g_return_val_if_fail (EV_IS_HISTORY (history), NULL);
+ if (!history->priv->current || !history->priv->back_list)
+ return;
- l = g_list_nth (history->priv->links, index);
+ history->priv->forward_list = g_list_prepend (history->priv->forward_list,
+ history->priv->current);
+ history->priv->current = EV_LINK (history->priv->back_list->data);
+ history->priv->back_list = g_list_delete_link (history->priv->back_list,
+ history->priv->back_list);
- return EV_LINK (l->data);
+ ev_history_activate_current_link (history);
}
-int
-ev_history_get_n_links (EvHistory *history)
+gboolean
+ev_history_can_go_forward (EvHistory *history)
{
- g_return_val_if_fail (EV_IS_HISTORY (history), -1);
+ g_return_val_if_fail (EV_IS_HISTORY (history), FALSE);
- return g_list_length (history->priv->links);
+ return history->priv->forward_list != NULL;
}
-EvHistory *
-ev_history_new (void)
+void
+ev_history_go_forward (EvHistory *history)
+{
+ g_return_if_fail (EV_IS_HISTORY (history));
+
+ if (!history->priv->current || !history->priv->forward_list)
+ return;
+
+ history->priv->back_list = g_list_prepend (history->priv->back_list,
+ history->priv->current);
+ history->priv->current = EV_LINK (history->priv->forward_list->data);
+ history->priv->forward_list = g_list_delete_link (history->priv->forward_list,
+ history->priv->forward_list);
+
+ ev_history_activate_current_link (history);
+}
+
+static gint
+compare_link (EvLink *a,
+ EvLink *b)
+{
+ if (a == b)
+ return 0;
+
+ return ev_link_action_equal (ev_link_get_action (a), ev_link_get_action (b)) ? 0 : 1;
+}
+
+gboolean
+ev_history_go_to_link (EvHistory *history,
+ EvLink *link)
{
- return EV_HISTORY (g_object_new (EV_TYPE_HISTORY, NULL));
+ GList *l;
+
+ g_return_val_if_fail (EV_IS_HISTORY (history), FALSE);
+ g_return_val_if_fail (EV_IS_LINK (link), FALSE);
+
+ if (!history->priv->current || (!history->priv->back_list && !history->priv->forward_list))
+ return FALSE;
+
+ l = g_list_find_custom (history->priv->back_list, link, (GCompareFunc)compare_link);
+ if (l) {
+ if (l->next)
+ l->next->prev = NULL;
+ if (l->prev)
+ l->prev->next = NULL;
+
+ history->priv->forward_list = g_list_prepend (history->priv->forward_list,
+ history->priv->current);
+ history->priv->forward_list = g_list_concat (g_list_reverse (history->priv->back_list),
+ history->priv->forward_list);
+ history->priv->back_list = l->next;
+ history->priv->current = EV_LINK (l->data);
+ g_list_free_1 (l);
+
+ ev_history_activate_current_link (history);
+
+ return TRUE;
+ }
+
+ l = g_list_find_custom (history->priv->forward_list, link, (GCompareFunc)compare_link);
+ if (l) {
+ if (l->next)
+ l->next->prev = NULL;
+ if (l->prev)
+ l->prev->next = NULL;
+
+ history->priv->back_list = g_list_prepend (history->priv->back_list,
+ history->priv->current);
+ history->priv->back_list = g_list_concat (g_list_reverse (history->priv->forward_list),
+ history->priv->back_list);
+ history->priv->forward_list = l->next;
+ history->priv->current = EV_LINK (l->data);
+ g_list_free_1 (l);
+
+ ev_history_activate_current_link (history);
+
+ return TRUE;
+ }
+
+ return FALSE;
}
+GList *
+ev_history_get_back_list (EvHistory *history)
+{
+ g_return_val_if_fail (EV_IS_HISTORY (history), NULL);
+
+ return history->priv->back_list;
+}
+
+GList *
+ev_history_get_forward_list (EvHistory *history)
+{
+ g_return_val_if_fail (EV_IS_HISTORY (history), NULL);
+
+ return history->priv->forward_list;
+}
+
+static gint
+ev_history_get_current_page (EvHistory *history)
+{
+ EvDocument *document;
+ EvLinkDest *dest;
+ EvLinkAction *action;
+
+ if (!history->priv->current)
+ return -1;
+
+ action = ev_link_get_action (history->priv->current);
+ if (!action)
+ return -1;
+
+ dest = ev_link_action_get_dest (action);
+ if (!dest)
+ return -1;
+
+ switch (ev_link_dest_get_dest_type (dest)) {
+ case EV_LINK_DEST_TYPE_NAMED:
+ document = ev_document_model_get_document (history->priv->model);
+ if (!EV_IS_DOCUMENT_LINKS (document))
+ return -1;
+
+ return ev_document_links_find_link_page (EV_DOCUMENT_LINKS (document),
+ ev_link_dest_get_named_dest (dest));
+ case EV_LINK_DEST_TYPE_PAGE_LABEL: {
+ gint page = -1;
+
+ document = ev_document_model_get_document (history->priv->model);
+ ev_document_find_page_by_label (document,
+ ev_link_dest_get_page_label (dest),
+ &page);
+
+ return page;
+ }
+ default:
+ return ev_link_dest_get_page (dest);
+ }
+
+ return -1;
+}
+
+static void
+ev_history_add_link_for_page (EvHistory *history,
+ gint page)
+{
+ EvDocument *document;
+ EvLinkDest *dest;
+ EvLinkAction *action;
+ EvLink *link;
+ gchar *page_label;
+ gchar *title;
+
+ if (ev_history_get_current_page (history) == page)
+ return;
+
+ document = ev_document_model_get_document (history->priv->model);
+ if (!document)
+ return;
+
+ page_label = ev_document_get_page_label (document, page);
+ if (!page_label)
+ return;
+
+ title = g_strdup_printf (_("Page %s"), page_label);
+ g_free (page_label);
+
+ dest = ev_link_dest_new_page (page);
+ action = ev_link_action_new_dest (dest);
+ g_object_unref (dest);
+
+ link = ev_link_new (title, action);
+ g_object_unref (action);
+ g_free (title);
+
+ ev_history_add_link (history, link);
+ g_object_unref (link);
+}
+
+static void
+page_changed_cb (EvDocumentModel *model,
+ gint old_page,
+ gint new_page,
+ EvHistory *history)
+{
+ if (ABS (new_page - old_page) > 1)
+ ev_history_add_link_for_page (history, new_page);
+}
+
+static void
+document_changed_cb (EvDocumentModel *model,
+ GParamSpec *pspec,
+ EvHistory *history)
+{
+ ev_history_clear (history);
+ ev_history_add_link_for_page (history, ev_document_model_get_page (model));
+}
+
+static void
+ev_history_set_model (EvHistory *history,
+ EvDocumentModel *model)
+{
+ if (history->priv->model == model)
+ return;
+
+ if (history->priv->model) {
+ g_object_remove_weak_pointer (G_OBJECT (history->priv->model),
+ (gpointer)&history->priv->model);
+
+ if (history->priv->page_changed_handler_id) {
+ g_signal_handler_disconnect (history->priv->model,
+ history->priv->page_changed_handler_id);
+ history->priv->page_changed_handler_id = 0;
+ }
+ }
+
+ history->priv->model = model;
+ if (!model)
+ return;
+
+ g_object_add_weak_pointer (G_OBJECT (model),
+ (gpointer)&history->priv->model);
+
+ g_signal_connect (history->priv->model, "notify::document",
+ G_CALLBACK (document_changed_cb),
+ history);
+ history->priv->page_changed_handler_id =
+ g_signal_connect (history->priv->model, "page-changed",
+ G_CALLBACK (page_changed_cb),
+ history);
+}
+
+EvHistory *
+ev_history_new (EvDocumentModel *model)
+{
+ EvHistory *history;
+
+ g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), NULL);
+
+ history = EV_HISTORY (g_object_new (EV_TYPE_HISTORY, NULL));
+ ev_history_set_model (history, model);
+
+ return history;
+}
diff --git a/shell/ev-history.h b/shell/ev-history.h
index d8bb53f..02604c7 100644
--- a/shell/ev-history.h
+++ b/shell/ev-history.h
@@ -21,8 +21,8 @@
#define EV_HISTORY_H
#include <glib-object.h>
-
-#include "ev-link.h"
+#include <evince-document.h>
+#include <evince-view.h>
G_BEGIN_DECLS
@@ -40,7 +40,7 @@ typedef struct _EvHistoryClass EvHistoryClass;
struct _EvHistory
{
GObject parent;
-
+
/*< private >*/
EvHistoryPrivate *priv;
};
@@ -48,17 +48,24 @@ struct _EvHistory
struct _EvHistoryClass
{
GObjectClass parent_class;
-
- void (*changed) (EvHistory *history);
+
+ void (* changed) (EvHistory *history);
+ void (* activate_link) (EvHistory *history,
+ EvLink *link);
};
-GType ev_history_get_type (void);
-EvHistory *ev_history_new (void);
-void ev_history_add_link (EvHistory *history,
- EvLink *linkk);
-EvLink *ev_history_get_link_nth (EvHistory *history,
- int index);
-int ev_history_get_n_links (EvHistory *history);
+GType ev_history_get_type (void);
+EvHistory *ev_history_new (EvDocumentModel *model);
+void ev_history_add_link (EvHistory *history,
+ EvLink *link);
+gboolean ev_history_can_go_back (EvHistory *history);
+void ev_history_go_back (EvHistory *history);
+gboolean ev_history_can_go_forward (EvHistory *history);
+void ev_history_go_forward (EvHistory *history);
+gboolean ev_history_go_to_link (EvHistory *history,
+ EvLink *link);
+GList *ev_history_get_back_list (EvHistory *history);
+GList *ev_history_get_forward_list (EvHistory *history);
G_END_DECLS
diff --git a/shell/ev-toolbar.c b/shell/ev-toolbar.c
index 20d3aca..a408769 100644
--- a/shell/ev-toolbar.c
+++ b/shell/ev-toolbar.c
@@ -26,6 +26,7 @@
#include "ev-stock-icons.h"
#include "ev-zoom-action.h"
+#include "ev-history-action.h"
#include <math.h>
enum
@@ -203,6 +204,13 @@ ev_toolbar_constructed (GObject *object)
gtk_container_add (GTK_CONTAINER (ev_toolbar), tool_item);
gtk_widget_show (tool_item);
+ /* History */
+ action = gtk_action_group_get_action (action_group, "History");
+ tool_item = gtk_action_create_tool_item (action);
+ gtk_widget_set_margin_right (tool_item, 12);
+ gtk_container_add (GTK_CONTAINER (ev_toolbar), tool_item);
+ gtk_widget_show (tool_item);
+
/* Zoom selector */
action = gtk_action_group_get_action (action_group, "ViewZoom");
tool_item = gtk_action_create_tool_item (action);
@@ -314,6 +322,10 @@ ev_toolbar_has_visible_popups (EvToolbar *ev_toolbar)
if (ev_zoom_action_get_popup_shown (EV_ZOOM_ACTION (action)))
return TRUE;
+ action = gtk_action_group_get_action (action_group, "History");
+ if (ev_history_action_get_popup_shown (EV_HISTORY_ACTION (action)))
+ return TRUE;
+
return FALSE;
}
diff --git a/shell/ev-window.c b/shell/ev-window.c
index 009a67e..2a3e67d 100644
--- a/shell/ev-window.c
+++ b/shell/ev-window.c
@@ -62,9 +62,9 @@
#include "ev-loading-message.h"
#include "ev-message-area.h"
#include "ev-metadata.h"
-#include "ev-navigation-action.h"
#include "ev-open-recent-action.h"
#include "ev-page-action.h"
+#include "ev-history-action.h"
#include "ev-password-view.h"
#include "ev-properties-dialog.h"
#include "ev-sidebar-annotations.h"
@@ -237,7 +237,7 @@ struct _EvWindowPrivate {
#define PAGE_SELECTOR_ACTION "PageSelector"
#define ZOOM_CONTROL_ACTION "ViewZoom"
-#define NAVIGATION_ACTION "Navigation"
+#define HISTORY_ACTION "History"
#define GS_LOCKDOWN_SCHEMA_NAME "org.gnome.desktop.lockdown"
#define GS_LOCKDOWN_SAVE "disable-save-to-disk"
@@ -481,7 +481,6 @@ ev_window_setup_action_sensitivity (EvWindow *ev_window)
/* 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);
- ev_window_set_action_sensitive (ev_window, NAVIGATION_ACTION, FALSE);
ev_window_update_actions_sensitivity (ev_window);
}
@@ -801,122 +800,98 @@ ev_window_hide_loading_message (EvWindow *window)
gtk_widget_hide (window->priv->loading_message);
}
-typedef struct _PageTitleData {
- const gchar *page_label;
- gchar *page_title;
-} PageTitleData;
+typedef struct _LinkTitleData {
+ EvLink *link;
+ const gchar *link_title;
+} LinkTitleData;
static gboolean
-ev_window_find_page_title (GtkTreeModel *tree_model,
- GtkTreePath *path,
- GtkTreeIter *iter,
- PageTitleData *data)
+find_link_cb (GtkTreeModel *tree_model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ LinkTitleData *data)
{
- gchar *page_string;
-
+ EvLink *link;
+ gboolean retval = FALSE;
+
gtk_tree_model_get (tree_model, iter,
- EV_DOCUMENT_LINKS_COLUMN_PAGE_LABEL, &page_string,
+ EV_DOCUMENT_LINKS_COLUMN_LINK, &link,
-1);
-
- if (!page_string)
- return FALSE;
-
- if (!strcmp (page_string, data->page_label)) {
- gtk_tree_model_get (tree_model, iter,
- EV_DOCUMENT_LINKS_COLUMN_MARKUP, &data->page_title,
- -1);
- g_free (page_string);
- return TRUE;
+ if (!link)
+ return retval;
+
+ if (ev_link_action_equal (ev_link_get_action (data->link), ev_link_get_action (link))) {
+ data->link_title = ev_link_get_title (link);
+ retval = TRUE;
}
-
- g_free (page_string);
- return FALSE;
+
+ g_object_unref (link);
+
+ return retval;
}
-static gchar *
-ev_window_get_page_title (EvWindow *window,
- const gchar *page_label)
+static const gchar *
+ev_window_find_title_for_link (EvWindow *window,
+ EvLink *link)
{
if (EV_IS_DOCUMENT_LINKS (window->priv->document) &&
ev_document_links_has_document_links (EV_DOCUMENT_LINKS (window->priv->document))) {
- PageTitleData data;
+ LinkTitleData data;
GtkTreeModel *model;
- data.page_label = page_label;
- data.page_title = NULL;
+ data.link = link;
+ data.link_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,
+ (GtkTreeModelForeachFunc)find_link_cb,
&data);
g_object_unref (model);
}
- return data.page_title;
+ return data.link_title;
}
return NULL;
}
static void
-ev_window_add_history (EvWindow *window, gint page, EvLink *link)
+view_handle_link_cb (EvView *view, EvLink *link, EvWindow *window)
{
- gchar *page_label = NULL;
- gchar *page_title;
- gchar *link_title;
- EvLink *real_link;
- EvLinkAction *action;
- EvLinkDest *dest;
-
- if (window->priv->history == NULL)
- return;
+ EvLink *new_link = NULL;
- if (!EV_IS_DOCUMENT_LINKS (window->priv->document))
- return;
-
- if (link) {
- action = g_object_ref (ev_link_get_action (link));
- dest = ev_link_action_get_dest (action);
- page_label = ev_document_links_get_dest_page_label (EV_DOCUMENT_LINKS
(window->priv->document), dest);
- } else {
- dest = ev_link_dest_new_page (page);
- action = ev_link_action_new_dest (dest);
- g_object_unref (dest);
- page_label = ev_document_get_page_label (window->priv->document, page);
- }
+ if (!ev_link_get_title (link)) {
+ const gchar *link_title;
- if (!page_label)
- return;
-
- 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);
- }
+ link_title = ev_window_find_title_for_link (window, link);
+ if (link_title) {
+ new_link = ev_link_new (link_title, ev_link_get_action (link));
+ } else {
+ EvLinkAction *action;
+ EvLinkDest *dest;
+ gchar *page_label;
+ gchar *title;
- real_link = ev_link_new (link_title, action);
- g_object_unref (action);
+ action = ev_link_get_action (link);
+ dest = ev_link_action_get_dest (action);
+ page_label = ev_document_links_get_dest_page_label (EV_DOCUMENT_LINKS
(window->priv->document), dest);
+ if (!page_label)
+ return;
- ev_history_add_link (window->priv->history, real_link);
+ title = g_strdup_printf (_("Page %s"), page_label);
+ g_free (page_label);
- g_free (link_title);
- g_free (page_label);
- g_object_unref (real_link);
-}
-
-static void
-view_handle_link_cb (EvView *view, EvLink *link, EvWindow *window)
-{
- int current_page = ev_document_model_get_page (window->priv->model);
-
- ev_window_add_history (window, 0, link);
- ev_window_add_history (window, current_page, NULL);
+ new_link = ev_link_new (title, action);
+ g_free (title);
+ }
+ }
+ ev_history_add_link (window->priv->history, new_link ? new_link : link);
+ if (new_link)
+ g_object_unref (new_link);
}
static void
@@ -955,11 +930,6 @@ ev_window_page_changed_cb (EvWindow *ev_window,
ev_window_update_find_status_message (ev_window);
- if (abs (new_page - old_page) > 1) {
- ev_window_add_history (ev_window, new_page, NULL);
- ev_window_add_history (ev_window, old_page, NULL);
- }
-
if (ev_window->priv->metadata && !ev_window_is_empty (ev_window))
ev_metadata_set_int (ev_window->priv->metadata, "page", new_page);
}
@@ -1437,7 +1407,6 @@ ev_window_setup_document (EvWindow *ev_window)
{
const EvDocumentInfo *info;
EvDocument *document = ev_window->priv->document;
- GtkAction *action;
ev_window->priv->setup_document_idle = 0;
@@ -1461,12 +1430,6 @@ ev_window_setup_document (EvWindow *ev_window)
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->uri,
@@ -6072,17 +6035,12 @@ register_custom_actions (EvWindow *window, GtkActionGroup *group)
gtk_action_group_add_action (group, action);
g_object_unref (action);
- action = g_object_new (EV_TYPE_NAVIGATION_ACTION,
- "name", NAVIGATION_ACTION,
- "label", _("Navigation"),
- "is_important", TRUE,
- "short_label", _("Back"),
- "stock_id", GTK_STOCK_GO_BACK,
- /*translators: this is the history action*/
- "tooltip", _("Move across visited pages"),
+ action = g_object_new (EV_TYPE_HISTORY_ACTION,
+ "name", HISTORY_ACTION,
+ "label", _("History"),
NULL);
- g_signal_connect (action, "activate_link",
- G_CALLBACK (navigation_action_activate_link_cb), window);
+ ev_history_action_set_history (EV_HISTORY_ACTION (action),
+ window->priv->history);
gtk_action_group_add_action (group, action);
g_object_unref (action);
@@ -7082,6 +7040,11 @@ ev_window_init (EvWindow *ev_window)
ev_window->priv->presentation_mode_inhibit_id = 0;
ev_window->priv->title = ev_window_title_new (ev_window);
+ ev_window->priv->history = ev_history_new (ev_window->priv->model);
+ g_signal_connect (ev_window->priv->history, "activate-link",
+ G_CALLBACK (activate_link_cb),
+ ev_window);
+
ev_window->priv->main_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_container_add (GTK_CONTAINER (ev_window), ev_window->priv->main_box);
gtk_widget_show (ev_window->priv->main_box);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]