File evince-2.32.0-metadata.patch of Package mingw32-evince
diff -Naur evince-2.32.0/configure.ac evince-2.32.0.new/configure.ac
--- evince-2.32.0/configure.ac 2011-07-26 18:13:18.614571661 +0200
+++ evince-2.32.0.new/configure.ac 2011-07-26 18:13:50.294728757 +0200
@@ -286,6 +286,30 @@
AC_DEFINE([WITH_KEYRING],[1],[Define if KEYRING support is enabled])
fi
+# *********************
+# Metadata support
+# *********************
+
+AC_MSG_CHECKING([which metadata backend to use])
+AC_ARG_WITH([metadata],
+ [AS_HELP_STRING([--with-metadata=gvfs|builtin],
+ [Setting metadata backend ])],
+ [case "$withval" in
+ gvfs|builtin) ;;
+ *) AC_MSG_ERROR([invalid argument "$withval" for --with-metadata]) ;;
+ esac],
+ [case "$host" in
+ *-*-mingw*|*-*-cygwin*) with_metadata="builtin" ;;
+ *) with_metadata=gvfs ;;
+ esac])
+AC_MSG_RESULT([$with_metadata])
+
+if test "$with_metadata" = "builtin"; then
+ AC_DEFINE([WITH_METADATA_BUILTIN],[1],[Define to build builtin metadata support])
+fi
+AM_CONDITIONAL([WITH_METADATA_BUILTIN], [test "$with_metadata" = "builtin"])
+
+
# ****
# DBUS
# ****
@@ -877,6 +901,7 @@
GConf Support......: $with_gconf
GTK+ Unix Print....: $with_gtk_unix_print
Keyring Support....: $with_keyring
+ Metadata support...: $with_metadata
DBUS Support.......: $enable_dbus
SM client support..: $with_smclient
Help files.........: $enable_help
diff -Naur evince-2.32.0/configure.ac.orig evince-2.32.0.new/configure.ac.orig
--- evince-2.32.0/configure.ac.orig 2011-07-26 18:13:18.598571586 +0200
+++ evince-2.32.0.new/configure.ac.orig 2011-07-26 18:13:34.958652708 +0200
@@ -505,6 +505,7 @@
AC_CHECK_FUNCS(poppler_page_get_text_layout)
AC_CHECK_FUNCS(poppler_page_get_selected_text)
AC_CHECK_FUNCS(poppler_page_add_annot)
+ AC_CHECK_FUNCS(poppler_document_is_linearized)
LIBS=$evince_save_LIBS
PKG_CHECK_MODULES(CAIRO_PDF, cairo-pdf, enable_cairo_pdf=yes, enable_cairo_pdf=no)
if test x$enable_cairo_pdf = xyes; then
diff -Naur evince-2.32.0/shell/ev-metadata.c evince-2.32.0.new/shell/ev-metadata.c
--- evince-2.32.0/shell/ev-metadata.c 2010-07-27 17:47:54.000000000 +0200
+++ evince-2.32.0.new/shell/ev-metadata.c 2011-07-26 18:13:50.298728778 +0200
@@ -18,16 +18,24 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#include "config.h"
+
#include <gio/gio.h>
#include <string.h>
#include "ev-metadata.h"
+#ifdef WITH_METADATA_BUILTIN
+#include "ev-metadata-manager.h"
+#endif
struct _EvMetadata {
GObject base;
GFile *file;
GHashTable *items;
+#ifdef WITH_METADATA_BUILTIN
+ gchar *uri;
+#endif
};
struct _EvMetadataClass {
@@ -53,12 +61,24 @@
metadata->file = NULL;
}
+#ifdef WITH_METADATA_BUILTIN
+ if (metadata->uri) {
+ g_free (metadata->uri);
+ metadata->uri = NULL;
+ }
+ ev_metadata_manager_shutdown ();
+#endif
+
G_OBJECT_CLASS (ev_metadata_parent_class)->finalize (object);
}
static void
ev_metadata_init (EvMetadata *metadata)
{
+#ifdef WITH_METADATA_BUILTIN
+ ev_metadata_manager_init ();
+ metadata->uri = NULL;
+#endif
metadata->items = g_hash_table_new_full (g_str_hash,
g_str_equal,
g_free,
@@ -74,8 +94,28 @@
}
static void
+hash_metadata_manager_items (const gchar *key,
+ const gpointer *data,
+ GHashTable *items)
+{
+ const GValue *value = (const GValue *)data;
+
+ g_hash_table_insert (items,
+ g_strdup (key),
+ g_strdup (g_value_get_string(value)));
+}
+
+static void
ev_metadata_load (EvMetadata *metadata)
{
+#ifdef WITH_METADATA_BUILTIN
+ GHashTable *items = ev_metadata_manager_get_items (metadata->uri);
+ if (items == NULL)
+ return;
+
+ g_hash_table_foreach (items, (GHFunc)hash_metadata_manager_items,
+ metadata->items);
+#else
GFileInfo *info;
gchar **attrs;
gint i;
@@ -119,6 +159,7 @@
}
g_strfreev (attrs);
g_object_unref (info);
+#endif
}
EvMetadata *
@@ -131,6 +172,9 @@
metadata = EV_METADATA (g_object_new (EV_TYPE_METADATA, NULL));
metadata->file = g_object_ref (file);
+#ifdef WITH_METADATA_BUILTIN
+ metadata->uri = g_file_get_uri(file);
+#endif
ev_metadata_load (metadata);
return metadata;
@@ -157,6 +201,7 @@
return TRUE;
}
+#ifndef WITH_METADATA_BUILTIN
static void
metadata_set_callback (GObject *file,
GAsyncResult *result,
@@ -169,12 +214,16 @@
g_error_free (error);
}
}
+#endif
gboolean
ev_metadata_set_string (EvMetadata *metadata,
const gchar *key,
const gchar *value)
{
+#ifdef WITH_METADATA_BUILTIN
+ ev_metadata_manager_set_string (metadata->uri, key, value);
+#else
GFileInfo *info;
gchar *gio_key;
@@ -190,7 +239,6 @@
}
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,
@@ -199,6 +247,9 @@
(GAsyncReadyCallback)metadata_set_callback,
metadata);
g_object_unref (info);
+#endif
+
+ g_hash_table_insert (metadata->items, g_strdup (key), g_strdup (value));
return TRUE;
}
@@ -292,6 +343,9 @@
gboolean
ev_is_metadata_supported_for_file (GFile *file)
{
+#ifdef WITH_METADATA_BUILTIN
+ return TRUE;
+#else
GFileAttributeInfoList *namespaces;
gint i;
gboolean retval = FALSE;
@@ -310,4 +364,5 @@
g_file_attribute_info_list_unref (namespaces);
return retval;
+#endif
}
diff -Naur evince-2.32.0/shell/ev-metadata-manager.c evince-2.32.0.new/shell/ev-metadata-manager.c
--- evince-2.32.0/shell/ev-metadata-manager.c 1970-01-01 01:00:00.000000000 +0100
+++ evince-2.32.0.new/shell/ev-metadata-manager.c 2011-07-26 18:13:50.298728778 +0200
@@ -0,0 +1,763 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * ev-metadata-manager.c
+ * This file is part of ev
+ *
+ * Copyright (C) 2003 Paolo Maggi
+ *
+ * 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the ev Team, 2003. See the AUTHORS file for a
+ * list of people on the ev Team.
+ * See the ChangeLog files for a list of changes.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <time.h>
+#include <stdlib.h>
+
+#include <libxml/xmlreader.h>
+
+#include "ev-metadata-manager.h"
+#include "ev-application.h"
+#include "ev-file-helpers.h"
+
+#define METADATA_FILE "ev-metadata.xml"
+
+#define MAX_ITEMS 50
+
+typedef struct _EvMetadataManager EvMetadataManager;
+
+typedef struct _Item Item;
+
+struct _Item
+{
+ time_t atime; /* time of last access */
+
+ GHashTable *values;
+};
+
+struct _EvMetadataManager
+{
+ guint ref;
+ gboolean values_loaded; /* It is true if the file
+ has been read */
+
+ guint timeout_id;
+
+ GHashTable *items;
+};
+
+static gboolean ev_metadata_manager_save (gpointer data);
+
+
+static EvMetadataManager *ev_metadata_manager = NULL;
+
+/**
+ * item_free:
+ * @data: a pointer to a #Item data
+ *
+ * It does free the values on the #GHashTable where data points.
+ */
+static void
+item_free (gpointer data)
+{
+ Item *item = (Item *) data;
+
+ if (item->values != NULL)
+ g_hash_table_destroy (item->values);
+
+ g_slice_free (Item, item);
+}
+
+/**
+ * ev_metadata_arm_timeout
+ *
+ * Setup a timeout for saving the metadata to disk.
+ */
+static void
+ev_metadata_arm_timeout(void)
+{
+ if (ev_metadata_manager->timeout_id)
+ return;
+
+ ev_metadata_manager->timeout_id =
+ g_timeout_add_seconds_full (G_PRIORITY_DEFAULT_IDLE,
+ 2,
+ (GSourceFunc)ev_metadata_manager_save,
+ NULL,
+ NULL);
+}
+
+/**
+ * ev_metadata_manager_init:
+ *
+ * Creates an EvMetadataManager with default values.
+ *
+ * values_loaded -> %FALSE.
+ * timeout_id -> the id of the event source.
+ * items -> a new full empty #GHashTable.
+ */
+void
+ev_metadata_manager_init (void)
+{
+ if (ev_metadata_manager != NULL) {
+ ev_metadata_manager->ref++;
+ return;
+ }
+
+ ev_metadata_manager = g_slice_new0 (EvMetadataManager);
+
+ ev_metadata_manager->values_loaded = FALSE;
+
+ ev_metadata_manager->items =
+ g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ item_free);
+}
+
+/* This function must be called before exiting ev */
+void
+ev_metadata_manager_shutdown (void)
+{
+ if (ev_metadata_manager == NULL)
+ return;
+
+ ev_metadata_manager->ref--;
+ if (ev_metadata_manager->ref)
+ return;
+
+ if (ev_metadata_manager->timeout_id) {
+ g_source_remove (ev_metadata_manager->timeout_id);
+ ev_metadata_manager->timeout_id = 0;
+ ev_metadata_manager_save (NULL);
+ }
+
+ if (ev_metadata_manager->items != NULL)
+ g_hash_table_destroy (ev_metadata_manager->items);
+
+ g_slice_free (EvMetadataManager, ev_metadata_manager);
+ ev_metadata_manager = NULL;
+}
+
+static void
+value_free (gpointer data)
+{
+ GValue *value = (GValue *)data;
+
+ g_value_unset (value);
+ g_slice_free (GValue, value);
+}
+
+static GValue *
+parse_value (xmlChar *value, xmlChar *type)
+{
+ GType ret_type;
+ GValue *ret;
+
+ ret_type = g_type_from_name ((char *)type);
+ ret = g_slice_new0 (GValue);
+ g_value_init (ret, ret_type);
+
+ switch (ret_type) {
+ case G_TYPE_STRING:
+ g_value_set_string (ret, (char *)value);
+ break;
+ case G_TYPE_INT:
+ g_value_set_int (ret, g_ascii_strtoull ((char *)value, NULL, 0));
+ break;
+ case G_TYPE_DOUBLE:
+ g_value_set_double (ret, g_ascii_strtod ((char *)value, NULL));
+ break;
+ case G_TYPE_BOOLEAN:
+ g_value_set_boolean (ret, g_ascii_strtoull ((char *)value, NULL, 0));
+ break;
+ }
+
+ return ret;
+}
+
+static void
+parseItem (xmlDocPtr doc, xmlNodePtr cur)
+{
+ Item *item;
+
+ xmlChar *uri;
+ xmlChar *atime;
+
+ if (xmlStrcmp (cur->name, (const xmlChar *)"document") != 0)
+ return;
+
+ uri = xmlGetProp (cur, (const xmlChar *)"uri");
+ if (uri == NULL)
+ return;
+
+ atime = xmlGetProp (cur, (const xmlChar *)"atime");
+ if (atime == NULL)
+ {
+ xmlFree (uri);
+ return;
+ }
+
+ item = g_slice_new0 (Item);
+
+ item->atime = g_ascii_strtoull((char*)atime, NULL, 0);
+
+ item->values = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ value_free);
+
+ cur = cur->xmlChildrenNode;
+
+ while (cur != NULL)
+ {
+ if (xmlStrcmp (cur->name, (const xmlChar *)"entry") == 0)
+ {
+ xmlChar *key;
+ xmlChar *xml_value;
+ xmlChar *type;
+ GValue *value;
+
+ key = xmlGetProp (cur, (const xmlChar *)"key");
+ xml_value = xmlGetProp (cur, (const xmlChar *)"value");
+ type = xmlGetProp (cur, (const xmlChar *)"type");
+ value = parse_value (xml_value, type);
+
+ if ((key != NULL) && (value != NULL))
+ g_hash_table_insert (item->values,
+ xmlStrdup (key),
+ value);
+
+ if (key != NULL)
+ xmlFree (key);
+ if (type != NULL)
+ xmlFree (type);
+ if (xml_value != NULL)
+ xmlFree (xml_value);
+ }
+
+ cur = cur->next;
+ }
+
+ g_hash_table_insert (ev_metadata_manager->items,
+ xmlStrdup (uri),
+ item);
+
+ xmlFree (uri);
+ xmlFree (atime);
+}
+
+static gboolean
+load_values ()
+{
+ xmlDocPtr doc;
+ xmlNodePtr cur;
+ gchar *file_name;
+
+ g_return_val_if_fail (ev_metadata_manager != NULL, FALSE);
+ g_return_val_if_fail (ev_metadata_manager->values_loaded == FALSE, FALSE);
+
+ ev_metadata_manager->values_loaded = TRUE;
+
+ xmlKeepBlanksDefault (0);
+
+ /* FIXME: file locking - Paolo */
+ file_name = g_build_filename (ev_application_get_dot_dir (EV_APP, TRUE), METADATA_FILE, NULL);
+ if (!g_file_test (file_name, G_FILE_TEST_EXISTS))
+ {
+ g_free (file_name);
+ return FALSE;
+ }
+
+ doc = xmlParseFile (file_name);
+ g_free (file_name);
+
+ if (doc == NULL)
+ {
+ return FALSE;
+ }
+
+ cur = xmlDocGetRootElement (doc);
+ if (cur == NULL)
+ {
+ g_message ("The metadata file ā%sā is empty", METADATA_FILE);
+ xmlFreeDoc (doc);
+
+ return FALSE;
+ }
+
+ if (xmlStrcmp (cur->name, (const xmlChar *) "metadata"))
+ {
+ g_message ("File ā%sā is of the wrong type", METADATA_FILE);
+ xmlFreeDoc (doc);
+
+ return FALSE;
+ }
+
+ cur = xmlDocGetRootElement (doc);
+ cur = cur->xmlChildrenNode;
+
+ while (cur != NULL)
+ {
+ parseItem (doc, cur);
+
+ cur = cur->next;
+ }
+
+ xmlFreeDoc (doc);
+
+ return TRUE;
+}
+
+#define LAST_URI "last-used-value"
+
+static gboolean
+ev_metadata_manager_get_last (const gchar *key,
+ GValue *value,
+ gboolean ignore)
+{
+ Item *item;
+ GValue *ret;
+
+ g_assert (ev_metadata_manager->values_loaded);
+
+ if (ignore)
+ return FALSE;
+
+ item = (Item *)g_hash_table_lookup (ev_metadata_manager->items,
+ LAST_URI);
+
+ if (item == NULL)
+ return FALSE;
+
+ item->atime = time (NULL);
+
+ if (item->values == NULL)
+ return FALSE;
+
+ ret = (GValue *)g_hash_table_lookup (item->values, key);
+
+ if (ret != NULL) {
+ g_value_init (value, G_VALUE_TYPE (ret));
+ g_value_copy (ret, value);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+ev_metadata_manager_set_last (const gchar *key,
+ const GValue *value)
+{
+ Item *item;
+
+ g_assert (ev_metadata_manager->values_loaded);
+
+ item = (Item *)g_hash_table_lookup (ev_metadata_manager->items,
+ LAST_URI);
+
+ if (item == NULL)
+ {
+ item = g_slice_new0 (Item);
+
+ g_hash_table_insert (ev_metadata_manager->items,
+ g_strdup (LAST_URI),
+ item);
+ }
+
+ if (item->values == NULL)
+ item->values = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ value_free);
+ if (value != NULL) {
+ GValue *new;
+
+ new = g_slice_new0 (GValue);
+ g_value_init (new, G_VALUE_TYPE (value));
+ g_value_copy (value, new);
+
+ g_hash_table_insert (item->values,
+ g_strdup (key),
+ new);
+ } else {
+ g_hash_table_remove (item->values,
+ key);
+ }
+
+ item->atime = time (NULL);
+ ev_metadata_arm_timeout ();
+ return;
+}
+
+GHashTable *
+ev_metadata_manager_get_items (const gchar *uri)
+{
+ Item *item;
+
+ if (uri == NULL)
+ return NULL;
+
+ if (!ev_metadata_manager->values_loaded) {
+ load_values ();
+ }
+
+ item = (Item *) g_hash_table_lookup (
+ ev_metadata_manager->items, uri);
+ if (item == NULL)
+ return NULL;
+
+ return item->values;
+}
+
+/**
+ * ev_metadata_manager_get:
+ * @uri: Uri to set data for, if @NULL, we return default value
+ * @key: Key to set uri
+ * @value: GValue struct filled up with value
+ * @ignore_last: if @TRUE, default value is ignored
+ *
+ * Retrieve value for uri in metadata database
+ *
+ * Returns: @TRUE if value was taken.
+ **/
+gboolean
+ev_metadata_manager_get (const gchar *uri,
+ const gchar *key,
+ GValue *value,
+ gboolean ignore_last)
+{
+ Item *item;
+ GValue *ret;
+
+ g_return_val_if_fail (key != NULL, FALSE);
+
+ if (ev_metadata_manager == NULL)
+ return FALSE;
+
+ if (!ev_metadata_manager->values_loaded)
+ {
+ gboolean res;
+
+ res = load_values ();
+
+ if (!res)
+ return ev_metadata_manager_get_last (key, value, ignore_last);
+ }
+
+ if (uri == NULL)
+ return ev_metadata_manager_get_last (key, value, ignore_last);
+
+ item = (Item *)g_hash_table_lookup (ev_metadata_manager->items,
+ uri);
+
+ if (item == NULL)
+ return ev_metadata_manager_get_last (key, value, ignore_last);
+
+ item->atime = time (NULL);
+
+ if (item->values == NULL)
+ return ev_metadata_manager_get_last (key, value, ignore_last);
+
+ ret = (GValue *)g_hash_table_lookup (item->values, key);
+
+ if (ret != NULL) {
+ g_value_init (value, G_VALUE_TYPE (ret));
+ g_value_copy (ret, value);
+ return TRUE;
+ }
+
+ return ev_metadata_manager_get_last (key, value, ignore_last);
+}
+
+/**
+ * ev_metadata_manager_set:
+ * @uri: Uri to set data for, if @NULL, we set default value
+ * @key: Key to set uri
+ * @value: GValue struct containing value
+ *
+ * Set value for key in metadata database
+ **/
+void
+ev_metadata_manager_set (const gchar *uri,
+ const gchar *key,
+ const GValue *value)
+{
+ Item *item;
+
+ g_return_if_fail (key != NULL);
+
+ if (ev_metadata_manager == NULL)
+ return;
+
+ if (!ev_metadata_manager->values_loaded)
+ {
+ gboolean res;
+
+ res = load_values ();
+
+ if (!res)
+ return;
+ }
+
+ if (uri == NULL)
+ {
+ ev_metadata_manager_set_last (key, value);
+ return;
+ }
+
+ item = (Item *)g_hash_table_lookup (ev_metadata_manager->items,
+ uri);
+
+ if (item == NULL)
+ {
+ item = g_slice_new0 (Item);
+
+ g_hash_table_insert (ev_metadata_manager->items,
+ g_strdup (uri),
+ item);
+ }
+
+ if (item->values == NULL)
+ item->values = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ value_free);
+ if (value != NULL) {
+ GValue *new;
+
+ new = g_slice_new0 (GValue);
+ g_value_init (new, G_VALUE_TYPE (value));
+ g_value_copy (value, new);
+
+ g_hash_table_insert (item->values,
+ g_strdup (key),
+ new);
+ ev_metadata_manager_set_last (key, value);
+ } else {
+ g_hash_table_remove (item->values,
+ key);
+ }
+
+ item->atime = time (NULL);
+
+ ev_metadata_arm_timeout ();
+}
+
+static void
+save_values (const gchar *key, GValue *value, xmlNodePtr parent)
+{
+ char *string_value;
+ xmlNodePtr xml_node;
+
+ g_return_if_fail (key != NULL);
+
+ if (value == NULL)
+ return;
+
+ xml_node = xmlNewChild (parent, NULL, (const xmlChar *)"entry", NULL);
+
+ xmlSetProp (xml_node, (const xmlChar *)"key", (const xmlChar *)key);
+ xmlSetProp (xml_node,
+ (const xmlChar *)"type",
+ (const xmlChar *)g_type_name (G_VALUE_TYPE (value)));
+
+ switch (G_VALUE_TYPE (value)) {
+ case G_TYPE_STRING:
+ string_value = g_value_dup_string (value);
+ break;
+ case G_TYPE_INT:
+ string_value = g_strdup_printf ("%d", g_value_get_int (value));
+ break;
+ case G_TYPE_DOUBLE:
+ {
+ gchar buf[G_ASCII_DTOSTR_BUF_SIZE];
+ g_ascii_dtostr (buf, G_ASCII_DTOSTR_BUF_SIZE, g_value_get_double (value));
+ string_value = g_strdup (buf);
+ }
+ break;
+ case G_TYPE_BOOLEAN:
+ string_value = g_strdup_printf ("%d", g_value_get_boolean (value));
+ break;
+ default:
+ string_value = NULL;
+ g_assert_not_reached ();
+ }
+
+ xmlSetProp (xml_node, (const xmlChar *)"value", (const xmlChar *)string_value);
+
+ g_free (string_value);
+}
+
+static void
+save_item (const gchar *key, const gpointer *data, xmlNodePtr parent)
+{
+ xmlNodePtr xml_node;
+ const Item *item = (const Item *)data;
+ gchar *atime;
+
+ g_return_if_fail (key != NULL);
+
+ if (item == NULL)
+ return;
+
+ xml_node = xmlNewChild (parent, NULL, (const xmlChar *)"document", NULL);
+
+ xmlSetProp (xml_node, (const xmlChar *)"uri", (const xmlChar *)key);
+
+ atime = g_strdup_printf ("%ld", item->atime);
+ xmlSetProp (xml_node, (const xmlChar *)"atime", (const xmlChar *)atime);
+ g_free (atime);
+
+ g_hash_table_foreach (item->values,
+ (GHFunc)save_values, xml_node);
+}
+
+static void
+get_oldest (const gchar *key, const gpointer value, const gchar ** key_to_remove)
+{
+ const Item *item = (const Item *)value;
+
+ if (*key_to_remove == NULL)
+ {
+ *key_to_remove = key;
+ }
+ else
+ {
+ const Item *item_to_remove =
+ g_hash_table_lookup (ev_metadata_manager->items,
+ *key_to_remove);
+
+ g_return_if_fail (item_to_remove != NULL);
+
+ if (item->atime < item_to_remove->atime)
+ {
+ *key_to_remove = key;
+ }
+ }
+}
+
+static void
+resize_items ()
+{
+ while (g_hash_table_size (ev_metadata_manager->items) > MAX_ITEMS)
+ {
+ gpointer key_to_remove = NULL;
+
+ g_hash_table_foreach (ev_metadata_manager->items,
+ (GHFunc)get_oldest,
+ &key_to_remove);
+
+ g_return_if_fail (key_to_remove != NULL);
+
+ g_hash_table_remove (ev_metadata_manager->items,
+ key_to_remove);
+ }
+}
+
+static gboolean
+ev_metadata_manager_save (gpointer data)
+{
+ xmlDocPtr doc;
+ xmlNodePtr root;
+ gchar *file_name;
+
+ ev_metadata_manager->timeout_id = 0;
+
+ resize_items ();
+
+ xmlIndentTreeOutput = TRUE;
+
+ doc = xmlNewDoc ((const xmlChar *)"1.0");
+ if (doc == NULL)
+ return TRUE;
+
+ /* Create metadata root */
+ root = xmlNewDocNode (doc, NULL, (const xmlChar *)"metadata", NULL);
+ xmlDocSetRootElement (doc, root);
+
+ g_hash_table_foreach (ev_metadata_manager->items,
+ (GHFunc)save_item, root);
+
+ /* FIXME: lock file - Paolo */
+ file_name = g_build_filename (ev_application_get_dot_dir (EV_APP, TRUE), METADATA_FILE, NULL);
+ xmlSaveFormatFile (file_name, doc, 1);
+ g_free (file_name);
+
+ xmlFreeDoc (doc);
+
+ return FALSE;
+}
+
+void
+ev_metadata_manager_set_int (const gchar *uri, const gchar *key, int value)
+{
+ GValue val = { 0, };
+
+ g_value_init (&val, G_TYPE_INT);
+ g_value_set_int (&val, value);
+
+ ev_metadata_manager_set (uri, key, &val);
+
+ g_value_unset (&val);
+}
+
+void
+ev_metadata_manager_set_double (const gchar *uri, const gchar *key, double value)
+{
+ GValue val = { 0, };
+
+ g_value_init (&val, G_TYPE_DOUBLE);
+ g_value_set_double (&val, value);
+
+ ev_metadata_manager_set (uri, key, &val);
+
+ g_value_unset (&val);
+}
+
+void
+ev_metadata_manager_set_string (const gchar *uri, const gchar *key, const gchar *value)
+{
+ GValue val = { 0, };
+
+ g_value_init (&val, G_TYPE_STRING);
+ g_value_set_static_string (&val, value);
+
+ ev_metadata_manager_set (uri, key, &val);
+
+ g_value_unset (&val);
+}
+
+void
+ev_metadata_manager_set_boolean (const gchar *uri, const gchar *key, gboolean value)
+{
+ GValue val = { 0, };
+
+ g_value_init (&val, G_TYPE_BOOLEAN);
+ g_value_set_boolean (&val, value);
+
+ ev_metadata_manager_set (uri, key, &val);
+
+ g_value_unset (&val);
+}
diff -Naur evince-2.32.0/shell/ev-metadata-manager.h evince-2.32.0.new/shell/ev-metadata-manager.h
--- evince-2.32.0/shell/ev-metadata-manager.h 1970-01-01 01:00:00.000000000 +0100
+++ evince-2.32.0.new/shell/ev-metadata-manager.h 2011-07-26 18:13:50.298728778 +0200
@@ -0,0 +1,56 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * ev-metadata-manager.h
+ *
+ * Copyright (C) 2003 Paolo Maggi
+ *
+ * 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EV_METADATA_MANAGER_H__
+#define __EV_METADATA_MANAGER_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+void ev_metadata_manager_init (void);
+GHashTable* ev_metadata_manager_get_items (const gchar *uri);
+gboolean ev_metadata_manager_get (const gchar *uri,
+ const gchar *key,
+ GValue *value,
+ gboolean ignore_last);
+void ev_metadata_manager_set (const gchar *uri,
+ const gchar *key,
+ const GValue *value);
+void ev_metadata_manager_set_int (const gchar *uri,
+ const gchar *key,
+ int value);
+void ev_metadata_manager_set_double (const gchar *uri,
+ const gchar *key,
+ double value);
+void ev_metadata_manager_set_string (const gchar *uri,
+ const gchar *key,
+ const gchar *value);
+void ev_metadata_manager_set_boolean (const gchar *uri,
+ const gchar *key,
+ gboolean value);
+void ev_metadata_manager_shutdown (void);
+
+G_END_DECLS
+
+#endif /* __EV_METADATA_MANAGER_H__ */
diff -Naur evince-2.32.0/shell/Makefile.am evince-2.32.0.new/shell/Makefile.am
--- evince-2.32.0/shell/Makefile.am 2010-09-27 18:54:36.000000000 +0200
+++ evince-2.32.0.new/shell/Makefile.am 2011-07-26 18:13:50.294728757 +0200
@@ -46,8 +46,8 @@
ev-marshal.h \
ev-message-area.c \
ev-message-area.h \
- ev-metadata.c \
- ev-metadata.h \
+ ev-metadata-manager.c \
+ ev-metadata-manager.h \
ev-navigation-action.c \
ev-navigation-action.h \
ev-navigation-action-widget.c \
@@ -86,6 +86,12 @@
ev-sidebar-thumbnails.h \
main.c
+if WITH_METADATA_BUILTIN
+evince_SOURCES += \
+ ev-metadata.c \
+ ev-metadata.h
+endif
+
if ENABLE_DBUS
evince_SOURCES += \
ev-media-player-keys.c \
diff -Naur evince-2.32.0/shell/Makefile.am.orig evince-2.32.0.new/shell/Makefile.am.orig
--- evince-2.32.0/shell/Makefile.am.orig 1970-01-01 01:00:00.000000000 +0100
+++ evince-2.32.0.new/shell/Makefile.am.orig 2011-07-26 18:13:34.890652377 +0200
@@ -0,0 +1,160 @@
+INCLUDES= \
+ -DEVINCEDATADIR=\"$(pkgdatadir)\" \
+ -DGNOMEDATADIR=\"$(datadir)\" \
+ -I$(top_srcdir) \
+ -I$(top_builddir) \
+ -I$(top_srcdir)/cut-n-paste/zoom-control/ \
+ -I$(top_srcdir)/cut-n-paste/toolbar-editor/ \
+ -I$(top_srcdir)/cut-n-paste/totem-screensaver/ \
+ -I$(top_srcdir)/cut-n-paste/gimpcellrenderertoggle/ \
+ -I$(top_srcdir)/cut-n-paste/smclient/ \
+ -I$(top_srcdir)/libdocument \
+ -I$(top_builddir)/libdocument \
+ -I$(top_srcdir)/libview \
+ -I$(top_builddir)/libview \
+ -I$(top_srcdir)/libmisc \
+ -I$(top_srcdir)/properties \
+ -DGNOMEICONDIR=\""$(datadir)/pixmaps"\" \
+ -DBINDIR=\""$(bindir)"\" \
+ -DLIBEXECDIR=\""$(libexecdir)"\" \
+ -DEVINCE_COMPILATION \
+ $(SHELL_CFLAGS) \
+ $(WARN_CFLAGS) \
+ $(DISABLE_DEPRECATED)
+
+bin_PROGRAMS=evince
+
+libexec_PROGRAMS=evince-convert-metadata
+if ENABLE_DBUS
+libexec_PROGRAMS += evinced
+endif
+
+evince_SOURCES= \
+ eggfindbar.c \
+ eggfindbar.h \
+ ev-annotation-properties-dialog.h \
+ ev-annotation-properties-dialog.c \
+ ev-application.c \
+ ev-application.h \
+ ev-file-monitor.h \
+ ev-file-monitor.c \
+ ev-history.c \
+ ev-history.h \
+ ev-keyring.h \
+ ev-keyring.c \
+ ev-marshal.c \
+ ev-marshal.h \
+ ev-message-area.c \
+ 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 \
+ ev-progress-message-area.c \
+ ev-properties-dialog.c \
+ ev-properties-dialog.h \
+ ev-properties-fonts.c \
+ ev-properties-fonts.h \
+ ev-properties-license.c \
+ ev-properties-license.h \
+ ev-open-recent-action.c \
+ ev-open-recent-action.h \
+ ev-utils.c \
+ ev-utils.h \
+ ev-window.c \
+ ev-window.h \
+ ev-window-title.c \
+ ev-window-title.h \
+ ev-sidebar.c \
+ ev-sidebar.h \
+ ev-sidebar-annotations.c \
+ ev-sidebar-annotations.h \
+ ev-sidebar-attachments.c \
+ ev-sidebar-attachments.h \
+ ev-sidebar-layers.c \
+ ev-sidebar-layers.h \
+ ev-sidebar-links.c \
+ ev-sidebar-links.h \
+ ev-sidebar-page.c \
+ ev-sidebar-page.h \
+ ev-sidebar-thumbnails.c \
+ ev-sidebar-thumbnails.h \
+ main.c
+
+if ENABLE_DBUS
+evince_SOURCES += \
+ ev-media-player-keys.c \
+ ev-media-player-keys.h
+endif
+
+
+evince_LDFLAGS = $(AM_LDFLAGS)
+
+if PLATFORM_WIN32
+evince_LDFLAGS += -mwindows
+endif
+
+evince_LDADD= \
+ $(top_builddir)/cut-n-paste/zoom-control/libephyzoom.la \
+ $(top_builddir)/cut-n-paste/toolbar-editor/libtoolbareditor.la \
+ $(top_builddir)/cut-n-paste/totem-screensaver/libtotemscrsaver.la \
+ $(top_builddir)/cut-n-paste/gimpcellrenderertoggle/libgimpcellrenderertoggle.la \
+ $(top_builddir)/cut-n-paste/smclient/libsmclient.la \
+ $(top_builddir)/properties/libevproperties.la \
+ $(top_builddir)/libdocument/libevdocument.la \
+ $(top_builddir)/libview/libevview.la \
+ $(top_builddir)/libmisc/libevmisc.la \
+ $(SHELL_LIBS)
+
+if PLATFORM_WIN32
+evince_LDADD += evince-icon.o
+
+evince-icon.o: $(srcdir)/evince-icon.rc $(top_srcdir)/data/evince.ico
+ $(WINDRES) $(srcdir)/evince-icon.rc -I $(top_srcdir)/data evince-icon.o
+endif
+
+BUILT_SOURCES = ev-marshal.h ev-marshal.c
+
+evince_convert_metadata_SOURCES= \
+ ev-convert-metadata.c
+
+evince_convert_metadata_LDADD= \
+ $(SHELL_LIBS)
+
+if ENABLE_DBUS
+evinced_SOURCES= \
+ ev-daemon.c
+
+evinced_CFLAGS= \
+ -DEVINCEDATADIR=\"$(pkgdatadir)\" \
+ -DGNOMEDATADIR=\"$(datadir)\" \
+ -I$(top_srcdir) \
+ -I$(top_builddir) \
+ -DLIBEXECDIR=\""$(libexecdir)"\" \
+ -DEVINCE_COMPILATION \
+ $(EV_DAEMON_CFLAGS) \
+ $(WARN_CFLAGS) \
+ $(DISABLE_DEPRECATED)
+
+evinced_LDADD= \
+ $(EV_DAEMON_LIBS)
+endif
+
+EXTRA_DIST = ev-marshal.list \
+ evince-icon.rc
+
+ev-marshal.h: $(srcdir)/ev-marshal.list
+ $(AM_V_GEN)$(GLIB_GENMARSHAL) --prefix=ev_marshal $(srcdir)/ev-marshal.list --header > ev-marshal.h
+
+ev-marshal.c: $(srcdir)/ev-marshal.list
+ echo '#include "ev-marshal.h"' > ev-marshal.c
+ $(AM_V_GEN)$(GLIB_GENMARSHAL) --prefix=ev_marshal $(srcdir)/ev-marshal.list --body >> ev-marshal.c
+
+DISTCLEANFILES =
+
+-include $(top_srcdir)/git.mk