[gnome-documents] metadata: import an adapted copy of EvMetadata from Evince
- From: Cosimo Cecchi <cosimoc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-documents] metadata: import an adapted copy of EvMetadata from Evince
- Date: Tue, 17 Jul 2012 20:42:26 +0000 (UTC)
commit fc3b979a6bca449b75bc6a3de048c7d71f5b73a7
Author: Cosimo Cecchi <cosimoc gnome org>
Date: Tue Jul 17 16:29:40 2012 -0400
metadata: import an adapted copy of EvMetadata from Evince
For now, only hook up a 'page' key, that remembers the last page in the
document.
https://bugzilla.gnome.org/show_bug.cgi?id=672196
src/Makefile-lib.am | 2 +
src/documents.js | 56 ++++++-
src/lib/gd-metadata.c | 389 +++++++++++++++++++++++++++++++++++++++++++++++++
src/lib/gd-metadata.h | 71 +++++++++
4 files changed, 509 insertions(+), 9 deletions(-)
---
diff --git a/src/Makefile-lib.am b/src/Makefile-lib.am
index 7fdb07a..1ae8f87 100644
--- a/src/Makefile-lib.am
+++ b/src/Makefile-lib.am
@@ -17,6 +17,7 @@ gdprivate_source_h = \
lib/gd-main-list-view.h \
lib/gd-main-view.h \
lib/gd-margin-container.h \
+ lib/gd-metadata.h \
lib/gd-notification.h \
lib/gd-pdf-loader.h \
lib/gd-sidebar-thumbnails.h \
@@ -37,6 +38,7 @@ gdprivate_source_c = \
lib/gd-main-list-view.c \
lib/gd-main-view.c \
lib/gd-margin-container.c \
+ lib/gd-metadata.c \
lib/gd-notification.c \
lib/gd-pdf-loader.c \
lib/gd-sidebar-thumbnails.c \
diff --git a/src/documents.js b/src/documents.js
index af7d4a6..04a60f9 100644
--- a/src/documents.js
+++ b/src/documents.js
@@ -905,6 +905,7 @@ const DocumentManager = new Lang.Class({
this.parent();
this._activeDocModel = null;
+ this._activeDocModelIds = [];
this._loaderCancellable = null;
Global.changeMonitor.connect('changes-pending',
@@ -1005,7 +1006,8 @@ const DocumentManager = new Lang.Class({
return;
}
- this._activeDocModel = docModel;
+ // save loaded model and connect metadata
+ this._initLoadState(docModel);
this.emit('load-finished', doc, docModel);
},
@@ -1013,14 +1015,8 @@ const DocumentManager = new Lang.Class({
if (!this.parent(doc))
return;
- // cancel any pending load operation
- if (this._loaderCancellable) {
- this._loaderCancellable.cancel();
- this._loaderCancellable = null;
- }
-
- // clear any previously loaded document model
- this._activeDocModel = null;
+ // cleanup any state we have for previously loaded model
+ this._cleanupLoadState();
if (!doc)
return;
@@ -1036,5 +1032,47 @@ const DocumentManager = new Lang.Class({
this._loaderCancellable = new Gio.Cancellable();
doc.load(this._loaderCancellable, Lang.bind(this, this._onDocumentLoaded));
this.emit('load-started', doc);
+ },
+
+ _cleanupLoadState: function() {
+ // cancel any pending load operation
+ if (this._loaderCancellable) {
+ this._loaderCancellable.cancel();
+ this._loaderCancellable = null;
+ }
+
+ // clear any previously loaded document model
+ if (this._activeDocModel) {
+ this._activeDocModelIds.forEach(Lang.bind(this,
+ function(id) {
+ this._activeDocModel.disconnect(id);
+ }));
+
+ this._activeDocModel = null;
+ this._activeDocModelIds = [];
+ }
+ },
+
+ _initLoadState: function(docModel) {
+ this._activeDocModel = docModel;
+
+ let evDoc = docModel.get_document();
+ let file = Gio.File.new_for_uri(evDoc.get_uri());
+
+ if (!Gd.is_metadata_supported_for_file(file))
+ return;
+
+ let metadata = new Gd.Metadata({ file: file });
+
+ // save current page in metadata
+ let [res, val] = metadata.get_int('page');
+ if (res)
+ docModel.set_page(val);
+ this._activeDocModelIds.push(
+ docModel.connect('page-changed', Lang.bind(this,
+ function(source, oldPage, newPage) {
+ metadata.set_int('page', newPage);
+ }))
+ );
}
});
diff --git a/src/lib/gd-metadata.c b/src/lib/gd-metadata.c
new file mode 100644
index 0000000..c366c41
--- /dev/null
+++ b/src/lib/gd-metadata.c
@@ -0,0 +1,389 @@
+/* gd-metadata.c - adapted from ev-metadata.c, part of evince,
+ * a gnome document viewer
+ *
+ * Copyright (C) 2009 Carlos Garcia Campos <carlosgc gnome org>
+ *
+ * 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 of the License, 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.
+ */
+
+#include <gio/gio.h>
+#include <string.h>
+
+#include "gd-metadata.h"
+
+struct _GdMetadata {
+ GObject base;
+
+ GFile *file;
+ GHashTable *items;
+};
+
+struct _GdMetadataClass {
+ GObjectClass base_class;
+};
+
+enum {
+ PROP_FILE = 1,
+ NUM_PROPERTIES
+};
+
+static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
+
+G_DEFINE_TYPE (GdMetadata, gd_metadata, G_TYPE_OBJECT)
+
+#define GD_METADATA_NAMESPACE "metadata::gnome-documents"
+
+static void
+gd_metadata_finalize (GObject *object)
+{
+ GdMetadata *metadata = GD_METADATA (object);
+
+ g_clear_pointer (&metadata->items, (GDestroyNotify) g_hash_table_unref);
+ g_clear_object (&metadata->file);
+
+ G_OBJECT_CLASS (gd_metadata_parent_class)->finalize (object);
+}
+
+static void
+gd_metadata_init (GdMetadata *metadata)
+{
+ metadata->items = g_hash_table_new_full
+ (g_str_hash, g_str_equal, g_free, g_free);
+}
+
+static void
+gd_metadata_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GdMetadata *self = GD_METADATA (object);
+
+ switch (property_id)
+ {
+ case PROP_FILE:
+ self->file = g_value_dup_object (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gd_metadata_load (GdMetadata *metadata)
+{
+ GFileInfo *info;
+ gchar **attrs;
+ gint i;
+ GError *error = NULL;
+
+ info = g_file_query_info (metadata->file, "metadata::*", 0, NULL, &error);
+ if (!info)
+ {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+
+ return;
+ }
+
+ if (!g_file_info_has_namespace (info, "metadata"))
+ {
+ g_object_unref (info);
+ return;
+ }
+
+ attrs = g_file_info_list_attributes (info, "metadata");
+ for (i = 0; attrs[i]; i++)
+ {
+ GFileAttributeType type;
+ gpointer value;
+ const gchar *key;
+
+ if (!g_str_has_prefix (attrs[i], GD_METADATA_NAMESPACE))
+ continue;
+
+ if (!g_file_info_get_attribute_data (info, attrs[i],
+ &type, &value, NULL))
+ continue;
+
+ key = attrs[i] + strlen (GD_METADATA_NAMESPACE"::");
+
+ if (type == G_FILE_ATTRIBUTE_TYPE_STRING)
+ g_hash_table_insert (metadata->items,
+ g_strdup (key), g_strdup (value));
+ }
+
+ g_strfreev (attrs);
+ g_object_unref (info);
+}
+
+static void
+gd_metadata_constructed (GObject *object)
+{
+ GdMetadata *self = GD_METADATA (object);
+
+ G_OBJECT_CLASS (gd_metadata_parent_class)->constructed (object);
+
+ if (self->file == NULL)
+ return;
+
+ gd_metadata_load (self);
+}
+
+static void
+gd_metadata_class_init (GdMetadataClass *klass)
+{
+ GObjectClass *oclass = G_OBJECT_CLASS (klass);
+
+ oclass->finalize = gd_metadata_finalize;
+ oclass->set_property = gd_metadata_set_property;
+ oclass->constructed = gd_metadata_constructed;
+
+ properties[PROP_FILE] =
+ g_param_spec_object ("file", "Document file",
+ "Document file",
+ G_TYPE_FILE,
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
+ g_object_class_install_properties (oclass, NUM_PROPERTIES, properties);
+}
+
+GdMetadata *
+gd_metadata_new (GFile *file)
+{
+ return g_object_new (GD_TYPE_METADATA, "file", file, NULL);
+}
+
+/**
+ * gd_metadata_get_string:
+ * @metadata:
+ * @key:
+ * @value: (out):
+ *
+ * Returns:
+ */
+gboolean
+gd_metadata_get_string (GdMetadata *metadata,
+ const gchar *key,
+ const gchar **value)
+{
+ const gchar *v;
+
+ v = g_hash_table_lookup (metadata->items, key);
+ if (!v)
+ return FALSE;
+
+ *value = v;
+ return TRUE;
+}
+
+static void
+metadata_set_callback (GObject *file,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GError *error = NULL;
+
+ if (!g_file_set_attributes_finish (G_FILE (file), result, NULL, &error))
+ {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ }
+}
+
+/**
+ * gd_metadata_set_string:
+ * @metadata:
+ * @key:
+ * @value: (allow-none):
+ *
+ * Returns:
+ */
+gboolean
+gd_metadata_set_string (GdMetadata *metadata,
+ const gchar *key,
+ const gchar *value)
+{
+ GFileInfo *info;
+ gchar *gio_key;
+
+ info = g_file_info_new ();
+
+ gio_key = g_strconcat (GD_METADATA_NAMESPACE"::", key, NULL);
+ if (value)
+ g_file_info_set_attribute_string (info, gio_key, value);
+ else
+ g_file_info_set_attribute (info, gio_key,
+ G_FILE_ATTRIBUTE_TYPE_INVALID,
+ NULL);
+
+ g_free (gio_key);
+
+ g_hash_table_insert (metadata->items, g_strdup (key), g_strdup (value));
+ g_file_set_attributes_async (metadata->file, info,
+ 0, G_PRIORITY_DEFAULT, NULL,
+ metadata_set_callback, metadata);
+ g_object_unref (info);
+
+ return TRUE;
+}
+
+/**
+ * gd_metadata_get_int:
+ * @metadata:
+ * @key:
+ * @value: (out):
+ *
+ * Returns:
+ */
+gboolean
+gd_metadata_get_int (GdMetadata *metadata,
+ const gchar *key,
+ gint *value)
+{
+ const gchar *string_value;
+ gchar *endptr;
+ gint int_value;
+
+ if (!gd_metadata_get_string (metadata, key, &string_value))
+ return FALSE;
+
+ int_value = g_ascii_strtoull (string_value, &endptr, 0);
+ if (int_value == 0 && string_value == endptr)
+ return FALSE;
+
+ *value = int_value;
+ return TRUE;
+}
+
+gboolean
+gd_metadata_set_int (GdMetadata *metadata,
+ const gchar *key,
+ gint value)
+{
+ gchar string_value[32];
+
+ g_snprintf (string_value, sizeof (string_value), "%d", value);
+
+ return gd_metadata_set_string (metadata, key, string_value);
+}
+
+/**
+ * gd_metadata_get_double:
+ * @metadata:
+ * @key:
+ * @value: (out):
+ *
+ * Returns:
+ */
+gboolean
+gd_metadata_get_double (GdMetadata *metadata,
+ const gchar *key,
+ gdouble *value)
+{
+ const gchar *string_value;
+ gchar *endptr;
+ gdouble double_value;
+
+ if (!gd_metadata_get_string (metadata, key, &string_value))
+ return FALSE;
+
+ double_value = g_ascii_strtod (string_value, &endptr);
+ if (double_value == 0. && string_value == endptr)
+ return FALSE;
+
+ *value = double_value;
+ return TRUE;
+}
+
+gboolean
+gd_metadata_set_double (GdMetadata *metadata,
+ const gchar *key,
+ gdouble value)
+{
+ gchar string_value[G_ASCII_DTOSTR_BUF_SIZE];
+
+ g_ascii_dtostr (string_value, G_ASCII_DTOSTR_BUF_SIZE, value);
+
+ return gd_metadata_set_string (metadata, key, string_value);
+}
+
+/**
+ * gd_metadata_get_boolean:
+ * @metadata:
+ * @key:
+ * @value: (out):
+ *
+ * Returns:
+ */
+gboolean
+gd_metadata_get_boolean (GdMetadata *metadata,
+ const gchar *key,
+ gboolean *value)
+{
+ gint int_value;
+
+ if (!gd_metadata_get_int (metadata, key, &int_value))
+ return FALSE;
+
+ *value = int_value;
+ return TRUE;
+}
+
+gboolean
+gd_metadata_set_boolean (GdMetadata *metadata,
+ const gchar *key,
+ gboolean value)
+{
+ return gd_metadata_set_string (metadata, key, value ? "1" : "0");
+}
+
+/**
+ * gd_metadata_has_key:
+ * @metadata:
+ * @key: (allow-none):
+ *
+ * Returns:
+ */
+gboolean
+gd_metadata_has_key (GdMetadata *metadata,
+ const gchar *key)
+{
+ return g_hash_table_lookup (metadata->items, key) != NULL;
+}
+
+gboolean
+gd_is_metadata_supported_for_file (GFile *file)
+{
+ GFileAttributeInfoList *namespaces;
+ gint i;
+ gboolean retval = FALSE;
+
+ namespaces = g_file_query_writable_namespaces (file, NULL, NULL);
+ if (!namespaces)
+ return retval;
+
+ for (i = 0; i < namespaces->n_infos; i++)
+ {
+ if (strcmp (namespaces->infos[i].name, "metadata") == 0) {
+ retval = TRUE;
+ break;
+ }
+ }
+
+ g_file_attribute_info_list_unref (namespaces);
+
+ return retval;
+}
diff --git a/src/lib/gd-metadata.h b/src/lib/gd-metadata.h
new file mode 100644
index 0000000..23ee658
--- /dev/null
+++ b/src/lib/gd-metadata.h
@@ -0,0 +1,71 @@
+/* gd-metadata.h - adapted from ev-metadata.h, part of evince,
+ * a gnome document viewer
+ *
+ * Copyright (C) 2009 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 __GD_METADATA_H__
+#define __GD_METADATA_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define GD_TYPE_METADATA (gd_metadata_get_type())
+#define GD_METADATA(object) (G_TYPE_CHECK_INSTANCE_CAST((object), GD_TYPE_METADATA, GdMetadata))
+#define GD_METADATA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GD_TYPE_METADATA, GdMetadataClass))
+#define GD_IS_METADATA(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), GD_TYPE_METADATA))
+
+typedef struct _GdMetadata GdMetadata;
+typedef struct _GdMetadataClass GdMetadataClass;
+
+GType gd_metadata_get_type (void) G_GNUC_CONST;
+GdMetadata *gd_metadata_new (GFile *file);
+
+gboolean gd_metadata_get_string (GdMetadata *metadata,
+ const gchar *key,
+ const gchar **value);
+gboolean gd_metadata_set_string (GdMetadata *metadata,
+ const gchar *key,
+ const gchar *value);
+gboolean gd_metadata_get_int (GdMetadata *metadata,
+ const gchar *key,
+ gint *value);
+gboolean gd_metadata_set_int (GdMetadata *metadata,
+ const gchar *key,
+ gint value);
+gboolean gd_metadata_get_double (GdMetadata *metadata,
+ const gchar *key,
+ gdouble *value);
+gboolean gd_metadata_set_double (GdMetadata *metadata,
+ const gchar *key,
+ gdouble value);
+gboolean gd_metadata_get_boolean (GdMetadata *metadata,
+ const gchar *key,
+ gboolean *value);
+gboolean gd_metadata_set_boolean (GdMetadata *metadata,
+ const gchar *key,
+ gboolean value);
+gboolean gd_metadata_has_key (GdMetadata *metadata,
+ const gchar *key);
+
+gboolean gd_is_metadata_supported_for_file (GFile *file);
+
+G_END_DECLS
+
+#endif /* __GD_METADATA_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]