File 0008-Reintroduce-the-builtin-metadata-manager.patch of Package mingw32-evince

From f5d612d218f7e2577f16a9f1355c555dd4258fc8 Mon Sep 17 00:00:00 2001
From: Hib Eris <hib@hiberis.nl>
Date: Tue, 26 Jul 2011 11:58:18 +0200
Subject: [PATCH 08/12] Reintroduce the builtin metadata-manager

On Windows, gvfs is not available, and thus Evince cannot use its
metadata storage. This patch brings back Evince metadata manager from the
days before gvfs.

Ideally, we would not need this patch and gio/gvfs would support metadata
on Windows. For now, however, weh have to uglify Evince code with this patch.
---
 configure.ac                |   24 ++
 shell/Makefile.am           |   10 +-
 shell/ev-metadata-manager.c |  763 +++++++++++++++++++++++++++++++++++++++++++
 shell/ev-metadata-manager.h |   56 ++++
 shell/ev-metadata.c         |   56 ++++
 5 files changed, 907 insertions(+), 2 deletions(-)
 create mode 100644 shell/ev-metadata-manager.c
 create mode 100644 shell/ev-metadata-manager.h

diff --git a/configure.ac b/configure.ac
index 4dfd6ed..dce6c5d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -305,6 +305,30 @@ if test "$with_keyring" = "yes"; then
         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
 # ****
diff --git a/shell/Makefile.am b/shell/Makefile.am
index 18d75fc..7c75ceb 100644
--- a/shell/Makefile.am
+++ b/shell/Makefile.am
@@ -45,8 +45,8 @@ evince_SOURCES=				\
 	ev-keyring.c			\
 	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	\
@@ -91,6 +91,12 @@ nodist_evince_SOURCES = \
 	ev-resources.c \
 	$(NULL)
 
+if WITH_METADATA_BUILTIN
+evince_SOURCES += \
+	ev-metadata.c			\
+	ev-metadata.h
+endif
+
 if ENABLE_DBUS
 evince_SOURCES += \
 	ev-media-player-keys.c \
diff --git a/shell/ev-metadata-manager.c b/shell/ev-metadata-manager.c
new file mode 100644
index 0000000..2c2b719
--- /dev/null
+++ b/shell/ev-metadata-manager.c
@@ -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 --git a/shell/ev-metadata-manager.h b/shell/ev-metadata-manager.h
new file mode 100644
index 0000000..6f2c61a
--- /dev/null
+++ b/shell/ev-metadata-manager.h
@@ -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 --git a/shell/ev-metadata.c b/shell/ev-metadata.c
index b0e23a1..c4aab59 100644
--- a/shell/ev-metadata.c
+++ b/shell/ev-metadata.c
@@ -18,17 +18,25 @@
  * 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"
 #include "ev-file-helpers.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 {
@@ -54,12 +62,24 @@ ev_metadata_finalize (GObject *object)
 		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,
@@ -75,8 +95,28 @@ ev_metadata_class_init (EvMetadataClass *klass)
 }
 
 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;
@@ -120,6 +160,7 @@ ev_metadata_load (EvMetadata *metadata)
 	}
 	g_strfreev (attrs);
 	g_object_unref (info);
+#endif
 }
 
 EvMetadata *
@@ -130,6 +171,9 @@ ev_metadata_new (GFile *file)
 	g_return_val_if_fail (G_IS_FILE (file), NULL);
 
 	metadata = EV_METADATA (g_object_new (EV_TYPE_METADATA, NULL));
+#ifdef WITH_METADATA_BUILTIN
+	metadata->uri = g_file_get_uri(file);
+#endif
         if (!ev_file_is_temp (file)) {
                 metadata->file = g_object_ref (file);
                 ev_metadata_load (metadata);
@@ -159,6 +203,7 @@ ev_metadata_get_string (EvMetadata  *metadata,
 	return TRUE;
 }
 
+#ifndef WITH_METADATA_BUILTIN
 static void
 metadata_set_callback (GObject      *file,
 		       GAsyncResult *result,
@@ -171,12 +216,16 @@ metadata_set_callback (GObject      *file,
 		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;
 
@@ -204,6 +253,9 @@ ev_metadata_set_string (EvMetadata  *metadata,
 				     (GAsyncReadyCallback)metadata_set_callback,
 				     metadata);
 	g_object_unref (info);
+#endif
+
+	g_hash_table_insert (metadata->items, g_strdup (key), g_strdup (value));
 
 	return TRUE;
 }
@@ -304,6 +356,9 @@ ev_metadata_has_key (EvMetadata  *metadata,
 gboolean
 ev_is_metadata_supported_for_file (GFile *file)
 {
+#ifdef WITH_METADATA_BUILTIN
+	return TRUE;
+#else
 	GFileAttributeInfoList *namespaces;
 	gint i;
 	gboolean retval = FALSE;
@@ -322,4 +377,5 @@ ev_is_metadata_supported_for_file (GFile *file)
 	g_file_attribute_info_list_unref (namespaces);
 
 	return retval;
+#endif
 }
-- 
1.7.5.4

openSUSE Build Service is sponsored by