Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/shell
diff options
context:
space:
mode:
authorMarco Pesenti Gritti <mpg@redhat.com>2005-06-30 13:32:05 (GMT)
committer Marco Pesenti Gritti <marco@src.gnome.org>2005-06-30 13:32:05 (GMT)
commitd0e4d9279d7aa4be1ddec50c2a87c63638632712 (patch)
treea4ae2c0a4f5318d73b8100215fd733d02410cac2 /shell
parent616f5c97013f1344caa6e899de6cc99664faa5e9 (diff)
Metadata manager from gedit but modified to use GValue, so that we dont
2005-06-30 Marco Pesenti Gritti <mpg@redhat.com> * shell/Makefile.am: * shell/ev-metadata-manager.c: (item_free), (ev_metadata_manager_init), (ev_metadata_manager_shutdown), (parse_value), (parseItem), (load_values), (ev_metadata_manager_get), (value_free), (ev_metadata_manager_set), (save_values), (save_item), (get_oldest), (resize_items), (ev_metadata_manager_save), (ev_metadata_manager_set_int): * shell/ev-metadata-manager.h: Metadata manager from gedit but modified to use GValue, so that we dont need to keep converting from strings. * configure.ac: ENABLE_METADATA conditional, on when dbus is on * shell/ev-application.c: (ev_application_open_uri): Show the window after load so that we can initialize window size before it's showed. * shell/ev-window.c: (ev_window_setup_from_metadata), (ev_window_open_uri), (window_configure_event_cb), (ev_window_init): Save and load metadata information about window size. Not yet keeping states in account. * shell/main.c: (main): Shutdown metadata manager.
Diffstat (limited to 'shell')
-rw-r--r--shell/.cvsignore1
-rw-r--r--shell/Makefile.am6
-rw-r--r--shell/ev-application.c4
-rw-r--r--shell/ev-metadata-manager.c551
-rw-r--r--shell/ev-metadata-manager.h44
-rw-r--r--shell/ev-window.c44
-rw-r--r--shell/main.c4
7 files changed, 652 insertions, 2 deletions
diff --git a/shell/.cvsignore b/shell/.cvsignore
index 20713ba..c292c6a 100644
--- a/shell/.cvsignore
+++ b/shell/.cvsignore
@@ -2,4 +2,5 @@ Makefile
Makefile.in
evince
ev-marshal.[ch]
+ev-application-service.h
*pdf
diff --git a/shell/Makefile.am b/shell/Makefile.am
index 689199e..71faed5 100644
--- a/shell/Makefile.am
+++ b/shell/Makefile.am
@@ -105,6 +105,12 @@ evince_SOURCES= \
main.c \
$(NULL)
+if ENABLE_METADATA
+evince_SOURCES += \
+ ev-metadata-manager.h \
+ ev-metadata-manager.c
+endif
+
evince_LDADD= \
$(SHELL_LIBS) \
$(top_builddir)/cut-n-paste/recent-files/librecent.la \
diff --git a/shell/ev-application.c b/shell/ev-application.c
index 6a106fc..6b8ef37 100644
--- a/shell/ev-application.c
+++ b/shell/ev-application.c
@@ -177,10 +177,10 @@ ev_application_open_uri (EvApplication *application,
new_window = EV_WINDOW (ev_window_new ());
}
- gtk_window_present (GTK_WINDOW (new_window));
-
ev_window_open_uri (new_window, uri);
+ gtk_window_present (GTK_WINDOW (new_window));
+
if (page_label != NULL) {
ev_window_open_page_label (new_window, page_label);
}
diff --git a/shell/ev-metadata-manager.c b/shell/ev-metadata-manager.c
new file mode 100644
index 0000000..bbf5f76
--- /dev/null
+++ b/shell/ev-metadata-manager.c
@@ -0,0 +1,551 @@
+/* -*- 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-file-helpers.h"
+
+#define METADATA_FILE "ev-metadata.xml"
+
+#define MAX_ITEMS 50
+
+typedef struct _GeditMetadataManager GeditMetadataManager;
+
+typedef struct _Item Item;
+
+struct _Item
+{
+ time_t atime; /* time of last access */
+
+ GHashTable *values;
+};
+
+struct _GeditMetadataManager
+{
+ gboolean values_loaded; /* It is true if the file
+ has been read */
+
+ gboolean modified; /* It is true if the file
+ has top be written */
+
+ guint timeout_id;
+
+ GHashTable *items;
+};
+
+static void ev_metadata_manager_save (gpointer data);
+
+
+static GeditMetadataManager *ev_metadata_manager = NULL;
+
+static void
+item_free (gpointer data)
+{
+ Item *item;
+
+ g_return_if_fail (data != NULL);
+
+ item = (Item *)data;
+
+ if (item->values != NULL)
+ g_hash_table_destroy (item->values);
+
+ g_free (item);
+}
+
+static gboolean
+ev_metadata_manager_init (void)
+{
+ if (ev_metadata_manager != NULL)
+ return TRUE;
+
+ ev_metadata_manager = g_new0 (GeditMetadataManager, 1);
+
+ ev_metadata_manager->values_loaded = FALSE;
+ ev_metadata_manager->modified = FALSE;
+
+ ev_metadata_manager->items =
+ g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ item_free);
+
+ ev_metadata_manager->timeout_id =
+ g_timeout_add_full (G_PRIORITY_DEFAULT_IDLE,
+ 2000, /* 2 sec */
+ (GSourceFunc)ev_metadata_manager_save,
+ NULL,
+ NULL);
+
+ return TRUE;
+}
+
+/* This function must be called before exiting ev */
+void
+ev_metadata_manager_shutdown (void)
+{
+ if (ev_metadata_manager == NULL)
+ return;
+
+ g_source_remove (ev_metadata_manager->timeout_id);
+
+ ev_metadata_manager_save (NULL);
+
+ if (ev_metadata_manager->items != NULL)
+ g_hash_table_destroy (ev_metadata_manager->items);
+
+ g_free (ev_metadata_manager);
+ ev_metadata_manager = NULL;
+}
+
+static GValue *
+parse_value (xmlChar *value, xmlChar *type)
+{
+ GType ret_type;
+ GValue *ret;
+
+ ret_type = g_type_from_name ((char *)type);
+ ret = g_new0 (GValue, 1);
+ 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, atoi ((char *)value));
+ 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_new0 (Item, 1);
+
+ item->atime = atol ((char *)atime);
+
+ item->values = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ g_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 (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_dot_dir (), 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;
+}
+
+gboolean
+ev_metadata_manager_get (const gchar *uri,
+ const gchar *key,
+ GValue *value)
+{
+ Item *item;
+ GValue *ret;
+
+ g_return_val_if_fail (uri != NULL, FALSE);
+ g_return_val_if_fail (key != NULL, FALSE);
+
+ if (ev_metadata_manager == NULL)
+ ev_metadata_manager_init ();
+
+ if (!ev_metadata_manager->values_loaded)
+ {
+ gboolean res;
+
+ res = load_values ();
+
+ if (!res)
+ return FALSE;
+ }
+
+ item = (Item *)g_hash_table_lookup (ev_metadata_manager->items,
+ 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) {
+ return FALSE;
+ } else {
+ g_value_init (value, G_VALUE_TYPE (ret));
+ g_value_copy (ret, value);
+
+ return TRUE;
+ }
+}
+
+static void
+value_free (gpointer data)
+{
+ GValue *value = (GValue *)data;
+
+ g_value_unset (value);
+ g_free (value);
+}
+
+void
+ev_metadata_manager_set (const gchar *uri,
+ const gchar *key,
+ const GValue *value)
+{
+ Item *item;
+
+ g_return_if_fail (uri != NULL);
+ g_return_if_fail (key != NULL);
+
+ if (ev_metadata_manager == NULL)
+ ev_metadata_manager_init ();
+
+ if (!ev_metadata_manager->values_loaded)
+ {
+ gboolean res;
+
+ res = load_values ();
+
+ if (!res)
+ return;
+ }
+
+ item = (Item *)g_hash_table_lookup (ev_metadata_manager->items,
+ uri);
+
+ if (item == NULL)
+ {
+ item = g_new0 (Item, 1);
+
+ 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_new0 (GValue, 1);
+ 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_manager->modified = TRUE;
+}
+
+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_strdup (g_value_get_string (value));
+ break;
+ case G_TYPE_INT:
+ string_value = g_strdup_printf ("%d", g_value_get_int (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);
+
+ /* FIXME: is the cast right? - Paolo */
+ atime = g_strdup_printf ("%d", (int)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 void
+ev_metadata_manager_save (gpointer data)
+{
+ xmlDocPtr doc;
+ xmlNodePtr root;
+ gchar *file_name;
+
+ if (!ev_metadata_manager->modified)
+ return;
+
+ resize_items ();
+
+ xmlIndentTreeOutput = TRUE;
+
+ doc = xmlNewDoc ((const xmlChar *)"1.0");
+ if (doc == NULL)
+ return;
+
+ /* 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_dot_dir (), METADATA_FILE, NULL);
+ xmlSaveFormatFile (file_name, doc, 1);
+ g_free (file_name);
+
+ xmlFreeDoc (doc);
+
+ ev_metadata_manager->modified = 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);
+}
diff --git a/shell/ev-metadata-manager.h b/shell/ev-metadata-manager.h
new file mode 100644
index 0000000..5c4d61d
--- /dev/null
+++ b/shell/ev-metadata-manager.h
@@ -0,0 +1,44 @@
+/* -*- 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
+
+gboolean ev_metadata_manager_get (const gchar *uri,
+ const gchar *key,
+ GValue *value);
+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_shutdown (void);
+
+G_END_DECLS
+
+#endif /* __EV_METADATA_MANAGER_H__ */
diff --git a/shell/ev-window.c b/shell/ev-window.c
index 11ee1ad..63b1b9c 100644
--- a/shell/ev-window.c
+++ b/shell/ev-window.c
@@ -60,6 +60,7 @@
#include "ev-application.h"
#include "ev-stock-icons.h"
#include "ev-file-helpers.h"
+#include "ev-metadata-manager.h"
#include <poppler.h>
@@ -906,6 +907,23 @@ ev_window_xfer_job_cb (EvJobXfer *job,
}
}
+#ifdef ENABLE_METADATA
+static void
+ev_window_setup_from_metadata (EvWindow *window)
+{
+ char *uri = window->priv->uri;
+ GValue width = { 0, };
+ GValue height = { 0, };
+
+ ev_metadata_manager_get (uri, "window_width", &width);
+ ev_metadata_manager_get (uri, "window_height", &height);
+
+ gtk_window_set_default_size (GTK_WINDOW (window),
+ g_value_get_int (&width),
+ g_value_get_int (&height));
+}
+#endif
+
void
ev_window_open_uri (EvWindow *ev_window, const char *uri)
{
@@ -914,6 +932,10 @@ ev_window_open_uri (EvWindow *ev_window, const char *uri)
g_free (ev_window->priv->uri);
ev_window->priv->uri = g_strdup (uri);
+
+#ifdef ENABLE_METADATA
+ ev_window_setup_from_metadata (ev_window);
+#endif
ev_window_clear_jobs (ev_window);
ev_window_clear_local_uri (ev_window);
@@ -2975,6 +2997,25 @@ sidebar_page_main_widget_update_cb (GObject *ev_sidebar_page,
}
}
+static gboolean
+window_configure_event_cb (EvWindow *window, gpointer dummy)
+{
+#ifdef ENABLE_METADATA
+ int width, height;
+
+ if (window->priv->uri == NULL) {
+ return FALSE;
+ }
+
+ gtk_window_get_size (GTK_WINDOW (window), &width, &height);
+
+ ev_metadata_manager_set_int (window->priv->uri, "window_width", width);
+ ev_metadata_manager_set_int (window->priv->uri, "window_height", height);
+
+ return FALSE;
+#endif
+}
+
static void
ev_window_init (EvWindow *ev_window)
{
@@ -2986,6 +3027,9 @@ ev_window_init (EvWindow *ev_window)
GConfClient *client;
int sidebar_size;
+ g_signal_connect (ev_window, "configure_event",
+ G_CALLBACK (window_configure_event_cb), NULL);
+
ev_window->priv = EV_WINDOW_GET_PRIVATE (ev_window);
ev_window->priv->page_mode = PAGE_MODE_DOCUMENT;
diff --git a/shell/main.c b/shell/main.c
index d412a5e..0b50cbd 100644
--- a/shell/main.c
+++ b/shell/main.c
@@ -21,6 +21,7 @@
#include "config.h"
#include "ev-application.h"
+#include "ev-metadata-manager.h"
#include <glib/gi18n.h>
#include <gtk/gtkmain.h>
@@ -164,6 +165,9 @@ main (int argc, char *argv[])
gnome_accelerators_sync ();
poptFreeContext (context);
ev_file_helpers_shutdown ();
+#if ENABLE_METADATA
+ ev_metadata_manager_shutdown ();
+#endif
return 0;
}