[gnome-documents] Add a places dialog
- From: William Jon McCann <mccann src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-documents] Add a places dialog
- Date: Tue, 8 Jan 2013 23:17:25 +0000 (UTC)
commit 64d200a6edfd41c21add329952136aed21b42f4a
Author: William Jon McCann <jmccann redhat com>
Date: Sat Jan 5 09:51:58 2013 -0500
Add a places dialog
https://bugzilla.gnome.org/show_bug.cgi?id=691215
src/Makefile-js.am | 1 +
src/Makefile-lib.am | 4 +
src/application.js | 3 +
src/lib/gd-places-links.c | 523 +++++++++++++++++++++++++++++++++++++++++++++
src/lib/gd-places-links.h | 59 +++++
src/lib/gd-places-page.c | 96 +++++++++
src/lib/gd-places-page.h | 66 ++++++
src/places.js | 100 +++++++++
src/preview.js | 11 +
9 files changed, 863 insertions(+), 0 deletions(-)
---
diff --git a/src/Makefile-js.am b/src/Makefile-js.am
index 4f7a576..0e609f4 100644
--- a/src/Makefile-js.am
+++ b/src/Makefile-js.am
@@ -10,6 +10,7 @@ dist_js_DATA = \
manager.js \
miners.js \
notifications.js \
+ places.js \
preview.js \
properties.js\
query.js \
diff --git a/src/Makefile-lib.am b/src/Makefile-lib.am
index 78b1172..da1b13e 100644
--- a/src/Makefile-lib.am
+++ b/src/Makefile-lib.am
@@ -11,6 +11,8 @@ gdprivate_source_h = \
lib/gd-metadata.h \
lib/gd-pdf-loader.h \
lib/gd-nav-bar.h \
+ lib/gd-places-page.h \
+ lib/gd-places-links.h \
$(NULL)
gdprivate_source_c = \
@@ -18,6 +20,8 @@ gdprivate_source_c = \
lib/gd-metadata.c \
lib/gd-pdf-loader.c \
lib/gd-nav-bar.c \
+ lib/gd-places-page.c \
+ lib/gd-places-links.c \
$(NULL)
pkglib_LTLIBRARIES += libgdprivate-1.0.la
diff --git a/src/application.js b/src/application.js
index 9e0ae56..7838a6e 100644
--- a/src/application.js
+++ b/src/application.js
@@ -399,6 +399,9 @@ const Application = new Lang.Class({
window_mode: WindowMode.WindowMode.OVERVIEW },
{ name: 'properties',
callback: this._onActionProperties,
+ window_mode: WindowMode.WindowMode.PREVIEW },
+ { name: 'places',
+ accel: 'F3',
window_mode: WindowMode.WindowMode.PREVIEW }
];
diff --git a/src/lib/gd-places-links.c b/src/lib/gd-places-links.c
new file mode 100644
index 0000000..aab1ca2
--- /dev/null
+++ b/src/lib/gd-places-links.c
@@ -0,0 +1,523 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8; -*-
+ *
+ * Copyright (C) 2004 Red Hat, Inc.
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include <evince-document.h>
+#include <evince-view.h>
+
+#include "gd-places-links.h"
+#include "gd-places-page.h"
+
+struct _GdPlacesLinksPrivate {
+ GtkWidget *tree_view;
+
+ guint selection_id;
+ guint page_changed_id;
+ guint link_activated_id;
+
+ EvJob *job;
+ GtkTreeModel *model;
+ EvDocument *document;
+ EvDocumentModel *document_model;
+};
+
+enum {
+ LINK_ACTIVATED,
+ N_SIGNALS
+};
+
+static guint signals[N_SIGNALS];
+
+static void gd_places_links_page_iface_init (GdPlacesPageInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (GdPlacesLinks,
+ gd_places_links,
+ GTK_TYPE_BOX,
+ 0,
+ G_IMPLEMENT_INTERFACE (GD_TYPE_PLACES_PAGE,
+ gd_places_links_page_iface_init))
+
+
+#define GD_PLACES_LINKS_GET_PRIVATE(object) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((object), GD_TYPE_PLACES_LINKS, GdPlacesLinksPrivate))
+
+static gboolean
+emit_link_activated (GdPlacesLinks *self)
+{
+ GtkTreeSelection *selection;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self->priv->tree_view));
+
+ if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+ EvLink *link;
+ EvDocumentModel *document_model;
+
+ gtk_tree_model_get (model, &iter,
+ EV_DOCUMENT_LINKS_COLUMN_LINK, &link,
+ -1);
+
+ if (link == NULL) {
+ return;
+ }
+
+
+ document_model = g_object_ref (self->priv->document_model);
+ if (self->priv->page_changed_id > 0) {
+ g_signal_handler_block (document_model,
+ self->priv->page_changed_id);
+ }
+ g_signal_emit (self, signals[LINK_ACTIVATED], 0, link);
+ if (self->priv->page_changed_id > 0) {
+ g_signal_handler_unblock (document_model,
+ self->priv->page_changed_id);
+ }
+ g_object_unref (document_model);
+
+ g_object_unref (link);
+ }
+
+ self->priv->link_activated_id = 0;
+
+ return FALSE;
+}
+
+static void
+selection_changed_cb (GtkTreeSelection *selection,
+ GdPlacesLinks *self)
+{
+ g_return_if_fail (self->priv->document != NULL);
+
+ /* jump through some hoops to avoid destroying in the middle
+ of a button press handler */
+ if (self->priv->link_activated_id == 0) {
+ self->priv->link_activated_id = g_idle_add ((GSourceFunc)emit_link_activated, self);
+ }
+}
+
+static gboolean
+update_page_cb_foreach (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ GdPlacesLinks *self)
+{
+ EvLink *link;
+ int current_page;
+ int dest_page;
+ EvDocumentLinks *document_links;
+
+ gtk_tree_model_get (model, iter,
+ EV_DOCUMENT_LINKS_COLUMN_LINK, &link,
+ -1);
+ if (link == NULL) {
+ return FALSE;
+ }
+
+ document_links = EV_DOCUMENT_LINKS (self->priv->document);
+
+ dest_page = ev_document_links_get_link_page (document_links, link);
+ g_object_unref (link);
+
+ current_page = ev_document_model_get_page (self->priv->document_model);
+
+ if (dest_page == current_page) {
+ gtk_tree_view_expand_to_path (GTK_TREE_VIEW (self->priv->tree_view),
+ path);
+ gtk_tree_view_set_cursor (GTK_TREE_VIEW (self->priv->tree_view),
+ path, NULL, FALSE);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+gd_places_links_set_current_page (GdPlacesLinks *self,
+ int current_page)
+{
+ GtkTreeSelection *selection;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self->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 != NULL) {
+ int dest_page;
+ EvDocumentLinks *document_links = EV_DOCUMENT_LINKS (self->priv->document);
+
+ dest_page = ev_document_links_get_link_page (document_links, link);
+ g_object_unref (link);
+
+ 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.
+ */
+ g_signal_handler_block (selection, self->priv->selection_id);
+
+ gtk_tree_model_foreach (model,
+ (GtkTreeModelForeachFunc)update_page_cb_foreach,
+ self);
+
+ g_signal_handler_unblock (selection, self->priv->selection_id);
+}
+
+static void
+update_page_cb (GdPlacesLinks *self,
+ int old_page,
+ int new_page)
+{
+ gd_places_links_set_current_page (self, new_page);
+}
+
+static void
+job_finished_cb (EvJobLinks *job,
+ GdPlacesLinks *self)
+{
+ GdPlacesLinksPrivate *priv = self->priv;
+ GtkTreeSelection *selection;
+
+ g_clear_object (&priv->model);
+ priv->model = g_object_ref (job->model);
+
+ gtk_tree_view_set_model (GTK_TREE_VIEW (priv->tree_view), job->model);
+
+ g_clear_object (&priv->job);
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree_view));
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+
+ gtk_tree_view_expand_all (GTK_TREE_VIEW (priv->tree_view));
+
+ if (priv->selection_id <= 0) {
+ priv->selection_id =
+ g_signal_connect (selection, "changed",
+ G_CALLBACK (selection_changed_cb),
+ self);
+ }
+
+ if (priv->page_changed_id <= 0) {
+ priv->page_changed_id =
+ g_signal_connect_swapped (priv->document_model, "page-changed",
+ G_CALLBACK (update_page_cb),
+ self);
+ }
+
+ gd_places_links_set_current_page (self,
+ ev_document_model_get_page (priv->document_model));
+}
+
+static GtkTreeModel *
+create_loading_model (void)
+{
+ GtkTreeModel *retval;
+ GtkTreeIter iter;
+
+ /* Creates a fake model to indicate that we're loading */
+ retval = (GtkTreeModel *)gtk_list_store_new (EV_DOCUMENT_LINKS_COLUMN_NUM_COLUMNS,
+ G_TYPE_STRING,
+ G_TYPE_OBJECT,
+ G_TYPE_BOOLEAN,
+ G_TYPE_STRING);
+
+ gtk_list_store_append (GTK_LIST_STORE (retval), &iter);
+ gtk_list_store_set (GTK_LIST_STORE (retval), &iter,
+ EV_DOCUMENT_LINKS_COLUMN_MARKUP, _("Loadingâ"),
+ EV_DOCUMENT_LINKS_COLUMN_EXPAND, FALSE,
+ EV_DOCUMENT_LINKS_COLUMN_LINK, NULL,
+ -1);
+
+ return retval;
+}
+
+static void
+gd_places_links_construct (GdPlacesLinks *self)
+{
+ GdPlacesLinksPrivate *priv;
+ GtkWidget *swindow;
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *renderer;
+ GtkTreeSelection *selection;
+
+ priv = self->priv;
+
+ swindow = gtk_scrolled_window_new (NULL, NULL);
+
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (swindow),
+ GTK_SHADOW_IN);
+
+ /* Create tree view */
+ priv->tree_view = gtk_tree_view_new ();
+
+ gtk_tree_view_set_show_expanders (GTK_TREE_VIEW (priv->tree_view), FALSE);
+ gtk_tree_view_set_level_indentation (GTK_TREE_VIEW (priv->tree_view), 20);
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree_view));
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_NONE);
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->tree_view), FALSE);
+ gtk_container_add (GTK_CONTAINER (swindow), priv->tree_view);
+
+ gtk_box_pack_start (GTK_BOX (self), swindow, TRUE, TRUE, 0);
+ gtk_widget_show_all (GTK_WIDGET (self));
+
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_column_set_expand (GTK_TREE_VIEW_COLUMN (column), TRUE);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (priv->tree_view), column);
+
+ renderer = (GtkCellRenderer *)
+ g_object_new (GTK_TYPE_CELL_RENDERER_TEXT,
+ "ellipsize", PANGO_ELLIPSIZE_END,
+ "weight", PANGO_WEIGHT_BOLD,
+ "xpad", 10,
+ NULL);
+ gtk_tree_view_column_pack_start (GTK_TREE_VIEW_COLUMN (column), renderer, TRUE);
+ gtk_tree_view_column_set_attributes (GTK_TREE_VIEW_COLUMN (column), renderer,
+ "markup", EV_DOCUMENT_LINKS_COLUMN_MARKUP,
+ NULL);
+
+ renderer = (GtkCellRenderer *)
+ g_object_new (GTK_TYPE_CELL_RENDERER_TEXT,
+ "ellipsize", PANGO_ELLIPSIZE_MIDDLE,
+ "foreground", "#cccccc",
+ "max-width-chars", 12,
+ "scale", PANGO_SCALE_SMALL,
+ "xalign", 1.0,
+ "xpad", 10,
+ NULL);
+ gtk_tree_view_column_pack_end (GTK_TREE_VIEW_COLUMN (column), renderer, FALSE);
+ gtk_tree_view_column_set_attributes (GTK_TREE_VIEW_COLUMN (column), renderer,
+ "text", EV_DOCUMENT_LINKS_COLUMN_PAGE_LABEL,
+ NULL);
+}
+
+static GtkTreeModel *
+create_failed_model (void)
+{
+ GtkTreeModel *retval;
+ GtkTreeIter iter;
+
+ /* Creates a fake model to indicate there is no contents */
+ retval = (GtkTreeModel *)gtk_list_store_new (EV_DOCUMENT_LINKS_COLUMN_NUM_COLUMNS,
+ G_TYPE_STRING,
+ G_TYPE_OBJECT,
+ G_TYPE_BOOLEAN,
+ G_TYPE_STRING);
+
+ gtk_list_store_append (GTK_LIST_STORE (retval), &iter);
+ gtk_list_store_set (GTK_LIST_STORE (retval), &iter,
+ EV_DOCUMENT_LINKS_COLUMN_MARKUP, _("No table of contents"),
+ EV_DOCUMENT_LINKS_COLUMN_EXPAND, FALSE,
+ EV_DOCUMENT_LINKS_COLUMN_LINK, NULL,
+ -1);
+
+ return retval;
+}
+
+static void
+gd_places_links_document_changed_cb (EvDocumentModel *model,
+ GParamSpec *pspec,
+ GdPlacesLinks *self)
+{
+ EvDocument *document = ev_document_model_get_document (model);
+ GdPlacesLinksPrivate *priv = self->priv;
+
+ if (!EV_IS_DOCUMENT_LINKS (document)) {
+ return;
+ }
+
+ g_clear_object (&priv->document);
+ priv->document = g_object_ref (document);
+
+ if (priv->job != NULL) {
+ ev_job_cancel (self->priv->job);
+ g_clear_object (&priv->job);
+ }
+
+ if (!gd_places_page_supports_document (GD_PLACES_PAGE (self), document)) {
+ GtkTreeModel *failed_model;
+
+ failed_model = create_failed_model ();
+ gtk_tree_view_set_model (GTK_TREE_VIEW (priv->tree_view), failed_model);
+ g_object_unref (failed_model);
+ } else {
+ GtkTreeModel *loading_model;
+
+ loading_model = create_loading_model ();
+ gtk_tree_view_set_model (GTK_TREE_VIEW (priv->tree_view), loading_model);
+ g_object_unref (loading_model);
+
+ priv->job = ev_job_links_new (document);
+ g_signal_connect (priv->job,
+ "finished",
+ G_CALLBACK (job_finished_cb),
+ self);
+
+ /* The priority doesn't matter for this job */
+ ev_job_scheduler_push_job (priv->job, EV_JOB_PRIORITY_NONE);
+ }
+}
+
+static gboolean
+gd_places_links_supports_document (GdPlacesPage *places_page,
+ EvDocument *document)
+{
+ return (EV_IS_DOCUMENT_LINKS (document) &&
+ ev_document_links_has_document_links (EV_DOCUMENT_LINKS (document)));
+}
+
+static const char *
+gd_places_links_get_label (GdPlacesPage *places_page)
+{
+ return _("Contents");
+}
+
+static const char *
+gd_places_links_get_icon_name (GdPlacesPage *places_page)
+{
+ return "view-list-symbolic";
+}
+
+static void
+gd_places_links_set_document_model (GdPlacesPage *places_page,
+ EvDocumentModel *model)
+{
+ GdPlacesLinks *self = GD_PLACES_LINKS (places_page);
+ GdPlacesLinksPrivate *priv = self->priv;
+
+ if (priv->document_model == model) {
+ return;
+ }
+
+ if (priv->page_changed_id > 0) {
+ g_signal_handler_disconnect (priv->document_model, priv->page_changed_id);
+ priv->page_changed_id = 0;
+ }
+
+ if (priv->document_model != NULL) {
+ g_signal_handlers_disconnect_by_func (priv->document_model,
+ gd_places_links_document_changed_cb,
+ places_page);
+ }
+
+ g_clear_object (&priv->document_model);
+
+ priv->document_model = model;
+
+ if (priv->document_model != NULL) {
+ g_object_ref (priv->document_model);
+ g_signal_connect (priv->document_model,
+ "notify::document",
+ G_CALLBACK (gd_places_links_document_changed_cb),
+ places_page);
+ gd_places_links_document_changed_cb (priv->document_model,
+ NULL,
+ self);
+ }
+}
+
+static void
+gd_places_links_dispose (GObject *object)
+{
+ GdPlacesLinks *self = GD_PLACES_LINKS (object);
+
+ if (self->priv->link_activated_id > 0) {
+ g_source_remove (self->priv->link_activated_id);
+ self->priv->link_activated_id = 0;
+ }
+
+ if (self->priv->job != NULL) {
+ ev_job_cancel (self->priv->job);
+ g_clear_object (&self->priv->job);
+ }
+
+ if (self->priv->page_changed_id > 0) {
+ g_signal_handler_disconnect (self->priv->document_model, self->priv->page_changed_id);
+ self->priv->page_changed_id = 0;
+ }
+
+ g_clear_object (&self->priv->model);
+ g_clear_object (&self->priv->document);
+ g_clear_object (&self->priv->document_model);
+
+ G_OBJECT_CLASS (gd_places_links_parent_class)->dispose (object);
+}
+
+
+static void
+gd_places_links_init (GdPlacesLinks *self)
+{
+ self->priv = GD_PLACES_LINKS_GET_PRIVATE (self);
+
+ gd_places_links_construct (self);
+}
+
+static void
+gd_places_links_page_iface_init (GdPlacesPageInterface *iface)
+{
+ iface->supports_document = gd_places_links_supports_document;
+ iface->set_document_model = gd_places_links_set_document_model;
+ iface->get_label = gd_places_links_get_label;
+}
+
+static void
+gd_places_links_class_init (GdPlacesLinksClass *klass)
+{
+ GObjectClass *oclass = G_OBJECT_CLASS (klass);
+
+ oclass->dispose = gd_places_links_dispose;
+
+ signals[LINK_ACTIVATED] = g_signal_new ("link-activated",
+ G_TYPE_FROM_CLASS (oclass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, G_TYPE_OBJECT);
+
+ g_type_class_add_private (oclass, sizeof (GdPlacesLinksPrivate));
+}
+
+GtkWidget *
+gd_places_links_new (void)
+{
+ return g_object_new (GD_TYPE_PLACES_LINKS, NULL);
+}
diff --git a/src/lib/gd-places-links.h b/src/lib/gd-places-links.h
new file mode 100644
index 0000000..3dc6644
--- /dev/null
+++ b/src/lib/gd-places-links.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8; -*-
+ *
+ * Copyright (C) 2004 Red Hat, Inc.
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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 __GD_PLACES_LINKS_H__
+#define __GD_PLACES_LINKS_H__
+
+#include <gtk/gtk.h>
+
+#include <evince-document.h>
+#include <evince-view.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GdPlacesLinks GdPlacesLinks;
+typedef struct _GdPlacesLinksClass GdPlacesLinksClass;
+typedef struct _GdPlacesLinksPrivate GdPlacesLinksPrivate;
+
+#define GD_TYPE_PLACES_LINKS (gd_places_links_get_type())
+#define GD_PLACES_LINKS(object) (G_TYPE_CHECK_INSTANCE_CAST((object), GD_TYPE_PLACES_LINKS, GdPlacesLinks))
+#define GD_PLACES_LINKS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GD_TYPE_PLACES_LINKS, GdPlacesLinksClass))
+#define GD_IS_PLACES_LINKS(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), GD_TYPE_PLACES_LINKS))
+#define GD_IS_PLACES_LINKS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GD_TYPE_PLACES_LINKS))
+#define GD_PLACES_LINKS_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), GD_TYPE_PLACES_LINKS, GdPlacesLinksClass))
+
+struct _GdPlacesLinks {
+ GtkBox base_instance;
+
+ GdPlacesLinksPrivate *priv;
+};
+
+struct _GdPlacesLinksClass {
+ GtkBoxClass base_class;
+};
+
+GType gd_places_links_get_type (void);
+GtkWidget *gd_places_links_new (void);
+
+G_END_DECLS
+
+#endif /* __GD_PLACES_LINKS_H__ */
+
+
diff --git a/src/lib/gd-places-page.c b/src/lib/gd-places-page.c
new file mode 100644
index 0000000..f1de582
--- /dev/null
+++ b/src/lib/gd-places-page.c
@@ -0,0 +1,96 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2005 Marco Pesenti Gritti
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gtk/gtk.h>
+
+#include "gd-places-page.h"
+
+G_DEFINE_INTERFACE (GdPlacesPage, gd_places_page, G_TYPE_INVALID)
+
+gboolean
+gd_places_page_supports_document (GdPlacesPage *places_page,
+ EvDocument *document)
+{
+ GdPlacesPageInterface *iface;
+
+ g_return_val_if_fail (GD_IS_PLACES_PAGE (places_page), FALSE);
+ g_return_val_if_fail (EV_IS_DOCUMENT (document), FALSE);
+
+ iface = GD_PLACES_PAGE_GET_IFACE (places_page);
+
+ g_return_val_if_fail (iface->supports_document, FALSE);
+
+ return iface->supports_document (places_page, document);
+}
+
+void
+gd_places_page_set_document_model (GdPlacesPage *places_page,
+ EvDocumentModel *model)
+{
+ GdPlacesPageInterface *iface;
+
+ g_return_if_fail (GD_IS_PLACES_PAGE (places_page));
+ g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
+
+ iface = GD_PLACES_PAGE_GET_IFACE (places_page);
+
+ g_assert (iface->set_document_model);
+
+ iface->set_document_model (places_page, model);
+}
+
+const char *
+gd_places_page_get_label (GdPlacesPage *places_page)
+{
+ GdPlacesPageInterface *iface;
+
+ g_return_val_if_fail (GD_IS_PLACES_PAGE (places_page), NULL);
+
+ iface = GD_PLACES_PAGE_GET_IFACE (places_page);
+
+ g_assert (iface->get_label);
+
+ return iface->get_label (places_page);
+}
+
+const char *
+gd_places_page_get_icon_name (GdPlacesPage *places_page)
+{
+ GdPlacesPageInterface *iface;
+
+ g_return_val_if_fail (GD_IS_PLACES_PAGE (places_page), NULL);
+
+ iface = GD_PLACES_PAGE_GET_IFACE (places_page);
+
+ g_assert (iface->get_icon_name);
+
+ return iface->get_icon_name (places_page);
+}
+
+
+static void
+gd_places_page_default_init (GdPlacesPageInterface *iface)
+{
+}
diff --git a/src/lib/gd-places-page.h b/src/lib/gd-places-page.h
new file mode 100644
index 0000000..1c123f0
--- /dev/null
+++ b/src/lib/gd-places-page.h
@@ -0,0 +1,66 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8; -*-
+ *
+ * Copyright (C) 2005 Marco Pesenti Gritti
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * This program 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, or (at your option)
+ * any later version.
+ *
+ * This program 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 GD_PLACES_PAGE_H
+#define GD_PLACES_PAGE_H
+
+#include <glib-object.h>
+#include <glib.h>
+
+#include <evince-document.h>
+#include <evince-view.h>
+
+G_BEGIN_DECLS
+
+#define GD_TYPE_PLACES_PAGE (gd_places_page_get_type ())
+#define GD_PLACES_PAGE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GD_TYPE_PLACES_PAGE, GdPlacesPage))
+#define GD_PLACES_PAGE_IFACE(k) (G_TYPE_CHECK_CLASS_CAST((k), GD_TYPE_PLACES_PAGE, GdPlacesPageInterface))
+#define GD_IS_PLACES_PAGE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GD_TYPE_PLACES_PAGE))
+#define GD_IS_PLACES_PAGE_IFACE(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GD_TYPE_PLACES_PAGE))
+#define GD_PLACES_PAGE_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GD_TYPE_PLACES_PAGE, GdPlacesPageInterface))
+
+typedef struct _GdPlacesPage GdPlacesPage;
+typedef struct _GdPlacesPageInterface GdPlacesPageInterface;
+
+struct _GdPlacesPageInterface
+{
+ GTypeInterface base_iface;
+
+ /* Methods */
+ gboolean (* supports_document) (GdPlacesPage *places_page,
+ EvDocument *document);
+ void (* set_document_model) (GdPlacesPage *places_page,
+ EvDocumentModel *model);
+ const char * (* get_label) (GdPlacesPage *places_page);
+ const char * (* get_icon_name ) (GdPlacesPage *places_page);
+};
+
+GType gd_places_page_get_type (void) G_GNUC_CONST;
+gboolean gd_places_page_supports_document (GdPlacesPage *places_page,
+ EvDocument *document);
+void gd_places_page_set_document_model (GdPlacesPage *places_page,
+ EvDocumentModel *model);
+const char * gd_places_page_get_label (GdPlacesPage *page);
+const char * gd_places_page_get_icon_name (GdPlacesPage *page);
+
+G_END_DECLS
+
+#endif /* GD_PLACES_PAGE */
diff --git a/src/places.js b/src/places.js
new file mode 100644
index 0000000..76c7bf7
--- /dev/null
+++ b/src/places.js
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2013 Red Hat, Inc.
+ *
+ * Gnome Documents 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.
+ *
+ * Gnome Documents 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 Gnome Documents; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+const Gio = imports.gi.Gio;
+const GLib = imports.gi.GLib;
+const Gtk = imports.gi.Gtk;
+const _ = imports.gettext.gettext;
+
+const EvDocument = imports.gi.EvinceDocument;
+const GdPrivate = imports.gi.GdPrivate;
+const Application = imports.application;
+const Documents = imports.documents;
+const Mainloop = imports.mainloop;
+
+const Lang = imports.lang;
+
+const PlacesDialog = new Lang.Class({
+ Name: 'PlacesDialog',
+
+ _init: function(model) {
+ this._model = model;
+ this._createWindow();
+ this.widget.show_all();
+ },
+
+ _createWindow: function() {
+ let toplevel = Application.application.get_windows()[0];
+ this.widget = new Gtk.Dialog ({ resizable: true,
+ transient_for: toplevel,
+ modal: true,
+ destroy_with_parent: true,
+ default_width: 600, // FIXME use toplevel size
+ default_height: 600,
+ title: "",
+ hexpand: true });
+ this.widget.add_button(Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE);
+
+ this._notebook = new Gtk.Notebook ({ show_tabs: false,
+ border_width: 5 });
+
+ this._linksPage = new GdPrivate.PlacesLinks ();
+ this._linksPage.connect('link-activated', Lang.bind(this,
+ function(widget, link) {
+ this._handleLink(link);
+ }));
+
+ this._addPage(this._linksPage);
+
+ let contentArea = this.widget.get_content_area();
+ contentArea.pack_start(this._notebook, true, true, 0);
+ },
+
+ _handleLink: function(link) {
+ if (link.action.type == EvDocument.LinkActionType.GOTO_DEST) {
+ this._gotoDest(link.action.dest);
+ }
+ this.widget.response(Gtk.ResponseType.CLOSE);
+ },
+
+ _gotoDest: function(dest) {
+ switch (dest.type) {
+ case EvDocument.LinkDestType.PAGE:
+ case EvDocument.LinkDestType.XYZ:
+ this._model.set_page(dest.page);
+ break;
+ case EvDocument.LinkDestType.NAMED:
+ let doc = this._model.get_document();
+ let dest2 = doc.find_link_dest(dest.named);
+ if (dest2)
+ this._gotoDest(dest2);
+ break;
+ case EvDocument.LinkDestType.PAGE_LABEL:
+ this._model.set_page_by_label(dest.page_label);
+ break;
+ }
+ },
+
+ _addPage: function(widget) {
+ let label = new Gtk.Label({ label: widget.get_label() });
+ widget.set_document_model(this._model);
+ this._notebook.append_page(widget, label);
+ }
+
+});
diff --git a/src/preview.js b/src/preview.js
index e00cae6..a3f92b1 100644
--- a/src/preview.js
+++ b/src/preview.js
@@ -35,6 +35,7 @@ const Signals = imports.signals;
const Application = imports.application;
const Tweener = imports.util.tweener;
const MainToolbar = imports.mainToolbar;
+const Places = imports.places;
const Searchbar = imports.searchbar;
const Utils = imports.utils;
const View = imports.view;
@@ -114,6 +115,16 @@ const PreviewView = new Lang.Class({
function() {
this._changeRotation(90);
}));
+ let showPlaces = Application.application.lookup_action('places');
+ showPlaces.connect('activate', Lang.bind(this, this._showPlaces));
+ },
+
+ _showPlaces: function() {
+ let dialog = new Places.PlacesDialog(this._model);
+ dialog.widget.connect('response', Lang.bind(this,
+ function(widget, response) {
+ widget.destroy();
+ }));
},
_onViewSelectionChanged: function() {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]