From a01ee906243a9982de7590787a5beee7d922dd31 Mon Sep 17 00:00:00 2001 From: Marcin Banasiak Date: Fri, 26 Sep 2008 20:53:23 +0000 Subject: [PATCH] - obsolete Changed files: gnome-desktop-crystalsvg.patch -> 1.2 gnome-desktop-recently-used-apps.patch -> 1.3 --- gnome-desktop-crystalsvg.patch | 97 - gnome-desktop-recently-used-apps.patch | 2668 ------------------------ 2 files changed, 2765 deletions(-) delete mode 100644 gnome-desktop-crystalsvg.patch delete mode 100644 gnome-desktop-recently-used-apps.patch diff --git a/gnome-desktop-crystalsvg.patch b/gnome-desktop-crystalsvg.patch deleted file mode 100644 index 6d1d7d2..0000000 --- a/gnome-desktop-crystalsvg.patch +++ /dev/null @@ -1,97 +0,0 @@ ---- gnome-desktop-2.3.7/libgnome-desktop/gnome-desktop-item.c.crystalsvg 2003-08-01 16:51:49.000000000 +0200 -+++ gnome-desktop-2.3.7/libgnome-desktop/gnome-desktop-item.c 2003-08-28 19:46:11.000000000 +0200 -@@ -2343,6 +2343,10 @@ - static GSList *hicolor_kde_32 = NULL; - static GSList *hicolor_kde_22 = NULL; - static GSList *hicolor_kde_16 = NULL; -+static GSList *crystalsvg_kde_48 = NULL; -+static GSList *crystalsvg_kde_32 = NULL; -+static GSList *crystalsvg_kde_22 = NULL; -+static GSList *crystalsvg_kde_16 = NULL; - /* XXX: maybe we don't care about locolor - static GSList *locolor_kde_48 = NULL; - static GSList *locolor_kde_32 = NULL; -@@ -2401,6 +2405,11 @@ - ADD_DIRS (hicolor, 22); - ADD_DIRS (hicolor, 16); - -+ ADD_DIRS (crystalsvg, 48); -+ ADD_DIRS (crystalsvg, 32); -+ ADD_DIRS (crystalsvg, 22); -+ ADD_DIRS (crystalsvg, 16); -+ - /* XXX: maybe we don't care about locolor - ADD_DIRS (locolor, 48); - ADD_DIRS (locolor, 32); -@@ -2420,36 +2429,68 @@ - - if (size > 32) { - /* 48-inf */ -- list = g_slist_concat (g_slist_copy (hicolor_kde_48), -+ list = g_slist_concat (g_slist_copy (crystalsvg_kde_48), -+ g_slist_copy (hicolor_kde_48)); -+ list = g_slist_concat (list, - g_slist_copy (hicolor_kde_32)); - list = g_slist_concat (list, -+ g_slist_copy (crystalsvg_kde_32)); -+ list = g_slist_concat (list, - g_slist_copy (hicolor_kde_22)); - list = g_slist_concat (list, -+ g_slist_copy (crystalsvg_kde_22)); -+ list = g_slist_concat (list, - g_slist_copy (hicolor_kde_16)); -+ list = g_slist_concat (list, -+ g_slist_copy (crystalsvg_kde_16)); - } else if (size > 22) { - /* 23-32 */ -- list = g_slist_concat (g_slist_copy (hicolor_kde_32), -+ list = g_slist_concat (g_slist_copy (crystalsvg_kde_32), -+ g_slist_copy (hicolor_kde_32)); -+ list = g_slist_concat (list, - g_slist_copy (hicolor_kde_48)); - list = g_slist_concat (list, -+ g_slist_copy (crystalsvg_kde_48)); -+ list = g_slist_concat (list, - g_slist_copy (hicolor_kde_22)); - list = g_slist_concat (list, -+ g_slist_copy (crystalsvg_kde_22)); -+ list = g_slist_concat (list, - g_slist_copy (hicolor_kde_16)); -+ list = g_slist_concat (list, -+ g_slist_copy (crystalsvg_kde_16)); - } else if (size > 16) { - /* 17-22 */ -+ list = g_slist_concat (list, -+ g_slist_copy (crystalsvg_kde_22)); - list = g_slist_concat (g_slist_copy (hicolor_kde_22), - g_slist_copy (hicolor_kde_32)); - list = g_slist_concat (list, -+ g_slist_copy (crystalsvg_kde_32)); -+ list = g_slist_concat (list, - g_slist_copy (hicolor_kde_48)); - list = g_slist_concat (list, -+ g_slist_copy (crystalsvg_kde_48)); -+ list = g_slist_concat (list, - g_slist_copy (hicolor_kde_16)); -+ list = g_slist_concat (list, -+ g_slist_copy (crystalsvg_kde_16)); - } else { - /* 1-16 */ -- list = g_slist_concat (g_slist_copy (hicolor_kde_16), -+ list = g_slist_concat (g_slist_copy (crystalsvg_kde_16), -+ g_slist_copy (hicolor_kde_16)); -+ list = g_slist_concat (list, - g_slist_copy (hicolor_kde_22)); - list = g_slist_concat (list, -+ g_slist_copy (crystalsvg_kde_22)); -+ list = g_slist_concat (list, - g_slist_copy (hicolor_kde_32)); - list = g_slist_concat (list, -+ g_slist_copy (crystalsvg_kde_32)); -+ list = g_slist_concat (list, - g_slist_copy (hicolor_kde_48)); -+ list = g_slist_concat (list, -+ g_slist_copy (crystalsvg_kde_48)); - } - - list = g_slist_append (list, kde_icondir); diff --git a/gnome-desktop-recently-used-apps.patch b/gnome-desktop-recently-used-apps.patch deleted file mode 100644 index 04fad4d..0000000 --- a/gnome-desktop-recently-used-apps.patch +++ /dev/null @@ -1,2668 +0,0 @@ -diff -urN ../gnome-desktop-2.12.2-pristine/libgnome-desktop/egg-recent-item.c ./libgnome-desktop/egg-recent-item.c ---- ../gnome-desktop-2.12.2-pristine/libgnome-desktop/egg-recent-item.c 1969-12-31 19:00:00.000000000 -0500 -+++ ./libgnome-desktop/egg-recent-item.c 2006-05-08 16:18:44.000000000 -0400 -@@ -0,0 +1,426 @@ -+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -+/* -+ * 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. -+ * -+ * Authors: -+ * James Willcox -+ */ -+ -+ -+#include -+#include -+#include -+#include -+#include -+#include "egg-recent-item.h" -+ -+ -+ -+EggRecentItem * -+egg_recent_item_new (void) -+{ -+ EggRecentItem *item; -+ -+ item = g_new (EggRecentItem, 1); -+ -+ item->groups = NULL; -+ item->private_data = FALSE; -+ item->uri = NULL; -+ item->mime_type = NULL; -+ item->mime_type_is_explicit = FALSE; -+ -+ item->refcount = 1; -+ -+ return item; -+} -+ -+static void -+egg_recent_item_free (EggRecentItem *item) -+{ -+ if (item->uri) -+ g_free (item->uri); -+ -+ if (item->mime_type) -+ g_free (item->mime_type); -+ -+ if (item->groups) { -+ g_list_foreach (item->groups, (GFunc)g_free, NULL); -+ g_list_free (item->groups); -+ item->groups = NULL; -+ } -+ -+ g_free (item); -+} -+ -+EggRecentItem * -+egg_recent_item_ref (EggRecentItem *item) -+{ -+ item->refcount++; -+ return item; -+} -+ -+EggRecentItem * -+egg_recent_item_unref (EggRecentItem *item) -+{ -+ item->refcount--; -+ -+ if (item->refcount == 0) { -+ egg_recent_item_free (item); -+ } -+ -+ return item; -+} -+ -+ -+EggRecentItem * -+egg_recent_item_new_from_uri (const gchar *uri) -+{ -+ EggRecentItem *item; -+ -+ g_return_val_if_fail (uri != NULL, NULL); -+ -+ item = egg_recent_item_new (); -+ -+ if (!egg_recent_item_set_uri (item ,uri)) { -+ egg_recent_item_free (item); -+ return NULL; -+ } -+ -+ return item; -+} -+ -+static void -+egg_recent_item_update_mime_type (EggRecentItem *item) -+{ -+ if (!item->mime_type_is_explicit) { -+ g_free (item->mime_type); -+ item->mime_type = NULL; -+ -+ if (item->uri) -+ item->mime_type = gnome_vfs_get_mime_type (item->uri); -+ -+ if (!item->mime_type) -+ item->mime_type = g_strdup (GNOME_VFS_MIME_TYPE_UNKNOWN); -+ } -+} -+ -+gboolean -+egg_recent_item_set_uri (EggRecentItem *item, const gchar *uri) -+{ -+ gchar *utf8_uri; -+ -+ /* if G_BROKEN_FILENAMES is not set, this should succede */ -+ if (g_utf8_validate (uri, -1, NULL)) { -+ item->uri = gnome_vfs_make_uri_from_input (uri); -+ } else { -+ utf8_uri = g_filename_to_utf8 (uri, -1, NULL, NULL, NULL); -+ -+ if (utf8_uri == NULL) { -+ g_warning ("Couldn't convert URI to UTF-8"); -+ return FALSE; -+ } -+ -+ if (g_utf8_validate (utf8_uri, -1, NULL)) { -+ item->uri = gnome_vfs_make_uri_from_input (utf8_uri); -+ } else { -+ g_free (utf8_uri); -+ return FALSE; -+ } -+ -+ g_free (utf8_uri); -+ } -+ -+ return TRUE; -+} -+ -+gchar * -+egg_recent_item_get_uri (const EggRecentItem *item) -+{ -+ return g_strdup (item->uri); -+} -+ -+G_CONST_RETURN gchar * -+egg_recent_item_peek_uri (const EggRecentItem *item) -+{ -+ return item->uri; -+} -+ -+gchar * -+egg_recent_item_get_uri_utf8 (const EggRecentItem *item) -+{ -+ /* this could fail, but it's not likely, since we've already done it -+ * once in set_uri() -+ */ -+ return g_filename_to_utf8 (item->uri, -1, NULL, NULL, NULL); -+} -+ -+gchar * -+egg_recent_item_get_uri_for_display (const EggRecentItem *item) -+{ -+ return gnome_vfs_format_uri_for_display (item->uri); -+} -+ -+/* Stolen from gnome_vfs_make_valid_utf8() */ -+static char * -+make_valid_utf8 (const char *name) -+{ -+ GString *string; -+ const char *remainder, *invalid; -+ int remaining_bytes, valid_bytes; -+ -+ string = NULL; -+ remainder = name; -+ remaining_bytes = name ? strlen (name) : 0; -+ -+ while (remaining_bytes != 0) { -+ if (g_utf8_validate (remainder, remaining_bytes, &invalid)) -+ break; -+ -+ valid_bytes = invalid - remainder; -+ -+ if (string == NULL) -+ string = g_string_sized_new (remaining_bytes); -+ -+ g_string_append_len (string, remainder, valid_bytes); -+ g_string_append_c (string, '?'); -+ -+ remaining_bytes -= valid_bytes + 1; -+ remainder = invalid + 1; -+ } -+ -+ if (string == NULL) -+ return g_strdup (name); -+ -+ g_string_append (string, remainder); -+/* g_string_append (string, _(" (invalid file name)")); */ -+ g_assert (g_utf8_validate (string->str, -1, NULL)); -+ -+ return g_string_free (string, FALSE); -+} -+ -+static gchar * -+get_uri_shortname_for_display (GnomeVFSURI *uri) -+{ -+ gchar *name; -+ gboolean validated; -+ -+ validated = FALSE; -+ name = gnome_vfs_uri_extract_short_name (uri); -+ -+ if (name == NULL) -+ { -+ name = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_PASSWORD); -+ } -+ else if (g_ascii_strcasecmp (uri->method_string, "file") == 0) -+ { -+ gchar *text_uri; -+ gchar *local_file; -+ text_uri = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_PASSWORD); -+ local_file = gnome_vfs_get_local_path_from_uri (text_uri); -+ -+ if (local_file != NULL) -+ { -+ g_free (name); -+ name = g_filename_display_basename (local_file); -+ validated = TRUE; -+ } -+ -+ g_free (local_file); -+ g_free (text_uri); -+ } -+ else if (!gnome_vfs_uri_has_parent (uri)) -+ { -+ const gchar *method; -+ -+ method = uri->method_string; -+ -+ if (name == NULL || -+ strcmp (name, GNOME_VFS_URI_PATH_STR) == 0) -+ { -+ g_free (name); -+ name = g_strdup (method); -+ } -+ else -+ { -+ gchar *tmp; -+ -+ tmp = name; -+ name = g_strdup_printf ("%s: %s", method, name); -+ g_free (tmp); -+ } -+ } -+ -+ if (!validated && !g_utf8_validate (name, -1, NULL)) -+ { -+ gchar *utf8_name; -+ -+ utf8_name = make_valid_utf8 (name); -+ g_free (name); -+ name = utf8_name; -+ } -+ -+ return name; -+} -+ -+/** -+ * egg_recent_item_get_short_name: -+ * @item: an #EggRecentItem -+ * -+ * Computes a valid UTF-8 string that can be used as the name of the item in a -+ * menu or list. For example, calling this function on an item that refers to -+ * "file:///foo/bar.txt" will yield "bar.txt". -+ * -+ * Return value: A newly-allocated string in UTF-8 encoding; free it with -+ * g_free(). -+ **/ -+gchar * -+egg_recent_item_get_short_name (const EggRecentItem *item) -+{ -+ GnomeVFSURI *uri; -+ gchar *short_name; -+ -+ g_return_val_if_fail (item != NULL, NULL); -+ -+ if (item->uri == NULL) -+ return NULL; -+ -+ uri = gnome_vfs_uri_new (item->uri); -+ if (uri == NULL) -+ return NULL; -+ -+ short_name = get_uri_shortname_for_display (uri); -+ -+ gnome_vfs_uri_unref (uri); -+ -+ return short_name; -+} -+ -+void -+egg_recent_item_set_mime_type (EggRecentItem *item, const gchar *mime) -+{ -+ g_free (item->mime_type); -+ item->mime_type = NULL; -+ -+ if (mime && mime[0]) { -+ item->mime_type_is_explicit = TRUE; -+ item->mime_type = g_strdup (mime); -+ } else { -+ item->mime_type_is_explicit = FALSE; -+ } -+} -+ -+gchar * -+egg_recent_item_get_mime_type (EggRecentItem *item) -+{ -+ egg_recent_item_update_mime_type (item); -+ -+ return g_strdup (item->mime_type); -+} -+ -+void -+egg_recent_item_set_timestamp (EggRecentItem *item, time_t timestamp) -+{ -+ if (timestamp == (time_t) -1) -+ time (×tamp); -+ -+ item->timestamp = timestamp; -+} -+ -+time_t -+egg_recent_item_get_timestamp (const EggRecentItem *item) -+{ -+ return item->timestamp; -+} -+ -+G_CONST_RETURN GList * -+egg_recent_item_get_groups (const EggRecentItem *item) -+{ -+ return item->groups; -+} -+ -+gboolean -+egg_recent_item_in_group (const EggRecentItem *item, const gchar *group_name) -+{ -+ GList *tmp; -+ -+ tmp = item->groups; -+ while (tmp != NULL) { -+ gchar *val = (gchar *)tmp->data; -+ -+ if (strcmp (group_name, val) == 0) -+ return TRUE; -+ -+ tmp = tmp->next; -+ } -+ -+ return FALSE; -+} -+ -+void -+egg_recent_item_add_group (EggRecentItem *item, const gchar *group_name) -+{ -+ g_return_if_fail (group_name != NULL); -+ -+ if (!egg_recent_item_in_group (item, group_name)) -+ item->groups = g_list_append (item->groups, g_strdup (group_name)); -+} -+ -+void -+egg_recent_item_remove_group (EggRecentItem *item, const gchar *group_name) -+{ -+ GList *tmp; -+ -+ g_return_if_fail (group_name != NULL); -+ -+ tmp = item->groups; -+ while (tmp != NULL) { -+ gchar *val = (gchar *)tmp->data; -+ -+ if (strcmp (group_name, val) == 0) { -+ item->groups = g_list_remove (item->groups, -+ val); -+ g_free (val); -+ break; -+ } -+ -+ tmp = tmp->next; -+ } -+} -+ -+void -+egg_recent_item_set_private (EggRecentItem *item, gboolean priv) -+{ -+ item->private_data = priv; -+} -+ -+gboolean -+egg_recent_item_get_private (const EggRecentItem *item) -+{ -+ return item->private_data; -+} -+ -+GType -+egg_recent_item_get_type (void) -+{ -+ static GType boxed_type = 0; -+ -+ if (!boxed_type) { -+ boxed_type = g_boxed_type_register_static ("EggRecentItem", -+ (GBoxedCopyFunc)egg_recent_item_ref, -+ (GBoxedFreeFunc)egg_recent_item_unref); -+ } -+ -+ return boxed_type; -+} -diff -urN ../gnome-desktop-2.12.2-pristine/libgnome-desktop/egg-recent-item.h ./libgnome-desktop/egg-recent-item.h ---- ../gnome-desktop-2.12.2-pristine/libgnome-desktop/egg-recent-item.h 1969-12-31 19:00:00.000000000 -0500 -+++ ./libgnome-desktop/egg-recent-item.h 2006-05-08 16:18:44.000000000 -0400 -@@ -0,0 +1,80 @@ -+ -+#ifndef __EGG_RECENT_ITEM_H__ -+#define __EGG_RECENT_ITEM_H__ -+ -+#include -+#include -+#include -+ -+G_BEGIN_DECLS -+ -+#define EGG_TYPE_RECENT_ITEM (egg_recent_item_get_type ()) -+ -+#define EGG_RECENT_ITEM_LIST_UNREF(list) \ -+ g_list_foreach (list, (GFunc)egg_recent_item_unref, NULL); \ -+ g_list_free (list); -+ -+typedef struct _EggRecentItem EggRecentItem; -+ -+struct _EggRecentItem { -+ /* do not access any of these directly */ -+ gchar *uri; -+ gchar *mime_type; -+ time_t timestamp; -+ -+ gboolean private_data; -+ -+ GList *groups; -+ -+ int refcount; -+ -+ guint mime_type_is_explicit : 1; -+}; -+ -+GType egg_recent_item_get_type (void) G_GNUC_CONST; -+ -+/* constructors */ -+EggRecentItem * egg_recent_item_new (void); -+ -+EggRecentItem * egg_recent_item_ref (EggRecentItem *item); -+EggRecentItem * egg_recent_item_unref (EggRecentItem *item); -+ -+/* automatically fetches the mime type, etc */ -+EggRecentItem * egg_recent_item_new_from_uri (const gchar *uri); -+ -+gboolean egg_recent_item_set_uri (EggRecentItem *item, const gchar *uri); -+gchar * egg_recent_item_get_uri (const EggRecentItem *item); -+gchar * egg_recent_item_get_uri_utf8 (const EggRecentItem *item); -+gchar * egg_recent_item_get_uri_for_display (const EggRecentItem *item); -+gchar * egg_recent_item_get_short_name (const EggRecentItem *item); -+ -+void egg_recent_item_set_mime_type (EggRecentItem *item, const gchar *mime); -+gchar * egg_recent_item_get_mime_type (EggRecentItem *item); -+ -+void egg_recent_item_set_timestamp (EggRecentItem *item, time_t timestamp); -+time_t egg_recent_item_get_timestamp (const EggRecentItem *item); -+ -+G_CONST_RETURN gchar *egg_recent_item_peek_uri (const EggRecentItem *item); -+ -+ -+/* groups */ -+G_CONST_RETURN GList * egg_recent_item_get_groups (const EggRecentItem *item); -+ -+gboolean egg_recent_item_in_group (const EggRecentItem *item, -+ const gchar *group_name); -+ -+void egg_recent_item_add_group (EggRecentItem *item, -+ const gchar *group_name); -+ -+void egg_recent_item_remove_group (EggRecentItem *item, -+ const gchar *group_name); -+ -+void egg_recent_item_set_private (EggRecentItem *item, -+ gboolean priv); -+ -+gboolean egg_recent_item_get_private (const EggRecentItem *item); -+ -+ -+G_END_DECLS -+ -+#endif /* __EGG_RECENT_ITEM_H__ */ -diff -urN ../gnome-desktop-2.12.2-pristine/libgnome-desktop/egg-recent-model-multi.c ./libgnome-desktop/egg-recent-model-multi.c ---- ../gnome-desktop-2.12.2-pristine/libgnome-desktop/egg-recent-model-multi.c 1969-12-31 19:00:00.000000000 -0500 -+++ ./libgnome-desktop/egg-recent-model-multi.c 2006-05-08 17:03:13.000000000 -0400 -@@ -0,0 +1,1990 @@ -+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -+/* -+ * 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. -+ * -+ * Authors: -+ * James Willcox -+ */ -+ -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "egg-recent-model-multi.h" -+#include "egg-recent-item.h" -+ -+#define EGG_RECENT_MODEL_MULTI_DEFAULT_FILE_PATH ".recently-used" -+#define EGG_RECENT_MODEL_MULTI_BUFFER_SIZE 8192 -+ -+#define EGG_RECENT_MODEL_MULTI_MAX_ITEMS 500 -+#define EGG_RECENT_MODEL_MULTI_DEFAULT_LIMIT 10 -+#define EGG_RECENT_MODEL_MULTI_TIMEOUT_LENGTH 200 -+#define EGG_RECENT_MODEL_MULTI_POLL_TIME 3 -+ -+/* needed for Darwin */ -+#if !HAVE_DECL_LOCKF -+int lockf (int filedes, int function, off_t size); -+#endif -+ -+#define EGG_RECENT_MODEL_MULTI_KEY_DIR "/desktop/gnome/recent_files" -+#define EGG_RECENT_MODEL_MULTI_DEFAULT_LIMIT_KEY EGG_RECENT_MODEL_MULTI_KEY_DIR "/default_limit" -+#define EGG_RECENT_MODEL_MULTI_EXPIRE_KEY EGG_RECENT_MODEL_MULTI_KEY_DIR "/expire" -+ -+struct _EggRecentModelMultiPrivate { -+ GSList *mime_filter_values; /* list of mime types we allow */ -+ GSList *group_filter_values; /* list of groups we allow */ -+ GSList *scheme_filter_values; /* list of URI schemes we allow */ -+ -+ EggRecentModelMultiSort sort_type; /* type of sorting to be done */ -+ -+ int limit; /* soft limit for length of the list */ -+ int expire_days; /* number of days to hold an item */ -+ -+ char *path; /* path to the file we store stuff in */ -+ -+ GHashTable *monitors; -+ -+ GnomeVFSMonitorHandle *monitor; -+ -+ GConfClient *client; -+ gboolean use_default_limit; -+ -+ guint limit_change_notify_id; -+ guint expiration_change_notify_id; -+ -+ guint changed_timeout; -+ guint poll_timeout; -+ time_t last_mtime; -+}; -+ -+/* signals */ -+enum { -+ CHANGED, -+ LAST_SIGNAL -+}; -+ -+static GType model_signals[LAST_SIGNAL] = { 0 }; -+ -+/* properties */ -+enum { -+ PROP_BOGUS, -+ PROP_MIME_FILTERS, -+ PROP_GROUP_FILTERS, -+ PROP_SCHEME_FILTERS, -+ PROP_SORT_TYPE, -+ PROP_LIMIT, -+ PROP_FILE_PATH -+}; -+ -+typedef struct { -+ GSList *states; -+ GList *items; -+ EggRecentItem *current_item; -+} ParseInfo; -+ -+typedef enum { -+ STATE_START, -+ STATE_RECENT_FILES, -+ STATE_RECENT_ITEM, -+ STATE_URI, -+ STATE_MIME_TYPE, -+ STATE_TIMESTAMP, -+ STATE_PRIVATE, -+ STATE_GROUPS, -+ STATE_GROUP -+} ParseState; -+ -+typedef struct { -+ EggRecentModelMulti *model; -+ GList *list; -+} ChangedData; -+ -+#define TAG_RECENT_FILES "RecentFiles" -+#define TAG_RECENT_ITEM "RecentItem" -+#define TAG_URI "URI" -+#define TAG_MIME_TYPE "Mime-Type" -+#define TAG_TIMESTAMP "Timestamp" -+#define TAG_PRIVATE "Private" -+#define TAG_GROUPS "Groups" -+#define TAG_GROUP "Group" -+ -+static void start_element_handler (GMarkupParseContext *context, -+ const gchar *element_name, -+ const gchar **attribute_names, -+ const gchar **attribute_values, -+ gpointer user_data, -+ GError **error); -+ -+static void end_element_handler (GMarkupParseContext *context, -+ const gchar *element_name, -+ gpointer user_data, -+ GError **error); -+ -+static void text_handler (GMarkupParseContext *context, -+ const gchar *text, -+ gsize text_len, -+ gpointer user_data, -+ GError **error); -+ -+static void error_handler (GMarkupParseContext *context, -+ GError *error, -+ gpointer user_data); -+ -+static GMarkupParser parser = {start_element_handler, end_element_handler, -+ text_handler, -+ NULL, -+ error_handler}; -+ -+static GObjectClass *parent_class; -+ -+static void egg_recent_model_multi_clear_mime_filter (EggRecentModelMulti *model); -+static void egg_recent_model_multi_clear_group_filter (EggRecentModelMulti *model); -+static void egg_recent_model_multi_clear_scheme_filter (EggRecentModelMulti *model); -+ -+static GObjectClass *parent_class; -+ -+static gboolean -+egg_recent_model_multi_string_match (const GSList *list, const gchar *str) -+{ -+ const GSList *tmp; -+ -+ if (list == NULL || str == NULL) -+ return TRUE; -+ -+ tmp = list; -+ -+ while (tmp) { -+ if (g_pattern_match_string (tmp->data, str)) -+ return TRUE; -+ -+ tmp = tmp->next; -+ } -+ -+ return FALSE; -+} -+ -+static gboolean -+egg_recent_model_multi_write_raw (EggRecentModelMulti *model, FILE *file, -+ const gchar *content) -+{ -+ int len; -+ int fd; -+ struct stat sbuf; -+ -+ rewind (file); -+ -+ len = strlen (content); -+ fd = fileno (file); -+ -+ if (fstat (fd, &sbuf) < 0) -+ g_warning ("Couldn't stat XML document."); -+ -+ if ((off_t)len < sbuf.st_size) { -+ ftruncate (fd, len); -+ } -+ -+ if (fputs (content, file) == EOF) -+ return FALSE; -+ -+#ifndef G_OS_WIN32 -+ fsync (fd); -+#endif -+ rewind (file); -+ -+ return TRUE; -+} -+ -+static GList * -+egg_recent_model_multi_delete_from_list (GList *list, -+ const gchar *uri) -+{ -+ GList *tmp; -+ -+ if (!uri) -+ return list; -+ -+ tmp = list; -+ -+ while (tmp) { -+ EggRecentItem *item = tmp->data; -+ GList *next; -+ -+ next = tmp->next; -+ -+ if (!strcmp (egg_recent_item_peek_uri (item), uri)) { -+ egg_recent_item_unref (item); -+ -+ list = g_list_remove_link (list, tmp); -+ g_list_free_1 (tmp); -+ } -+ -+ tmp = next; -+ } -+ -+ return list; -+} -+ -+static void -+egg_recent_model_multi_add_new_groups (EggRecentItem *item, -+ EggRecentItem *upd_item) -+{ -+ const GList *tmp; -+ -+ tmp = egg_recent_item_get_groups (upd_item); -+ -+ while (tmp) { -+ char *group = tmp->data; -+ -+ if (!egg_recent_item_in_group (item, group)) -+ egg_recent_item_add_group (item, group); -+ -+ tmp = tmp->next; -+ } -+} -+ -+static gboolean -+egg_recent_model_multi_update_item (GList *items, EggRecentItem *upd_item) -+{ -+ GList *tmp; -+ const char *uri; -+ -+ uri = egg_recent_item_peek_uri (upd_item); -+ -+ tmp = items; -+ -+ while (tmp) { -+ EggRecentItem *item = tmp->data; -+ -+ if (gnome_vfs_uris_match (egg_recent_item_peek_uri (item), uri)) { -+ egg_recent_item_set_timestamp (item, (time_t) -1); -+ -+ egg_recent_model_multi_add_new_groups (item, upd_item); -+ -+ return TRUE; -+ } -+ -+ tmp = tmp->next; -+ } -+ -+ return FALSE; -+} -+ -+static gchar * -+egg_recent_model_multi_read_raw (EggRecentModelMulti *model, FILE *file) -+{ -+ GString *string; -+ char buf[EGG_RECENT_MODEL_MULTI_BUFFER_SIZE]; -+ -+ rewind (file); -+ -+ string = g_string_new (NULL); -+ while (fgets (buf, EGG_RECENT_MODEL_MULTI_BUFFER_SIZE, file)) { -+ string = g_string_append (string, buf); -+ } -+ -+ rewind (file); -+ -+ return g_string_free (string, FALSE); -+} -+ -+ -+ -+static ParseInfo * -+parse_info_init (void) -+{ -+ ParseInfo *retval; -+ -+ retval = g_new0 (ParseInfo, 1); -+ retval->states = g_slist_prepend (NULL, STATE_START); -+ retval->items = NULL; -+ -+ return retval; -+} -+ -+static void -+parse_info_free (ParseInfo *info) -+{ -+ g_slist_free (info->states); -+ g_free (info); -+} -+ -+static void -+push_state (ParseInfo *info, -+ ParseState state) -+{ -+ info->states = g_slist_prepend (info->states, GINT_TO_POINTER (state)); -+} -+ -+static void -+pop_state (ParseInfo *info) -+{ -+ g_return_if_fail (info->states != NULL); -+ -+ info->states = g_slist_remove (info->states, info->states->data); -+} -+ -+static ParseState -+peek_state (ParseInfo *info) -+{ -+ g_return_val_if_fail (info->states != NULL, STATE_START); -+ -+ return GPOINTER_TO_INT (info->states->data); -+} -+ -+#define ELEMENT_IS(name) (strcmp (element_name, (name)) == 0) -+ -+static gboolean -+valid_element (ParseInfo *info, -+ int valid_parent_state, -+ const gchar *element_name, -+ const gchar *valid_element, -+ GError **error) -+{ -+ if (peek_state (info) != valid_parent_state) { -+ g_set_error (error, -+ G_MARKUP_ERROR, -+ G_MARKUP_ERROR_INVALID_CONTENT, -+ "Unexpected tag '%s', tag '%s' expected", -+ element_name, valid_element); -+ return FALSE; -+ } -+ -+ return TRUE; -+} -+ -+static void -+start_element_handler (GMarkupParseContext *context, -+ const gchar *element_name, -+ const gchar **attribute_names, -+ const gchar **attribute_values, -+ gpointer user_data, -+ GError **error) -+{ -+ ParseInfo *info = (ParseInfo *)user_data; -+ -+ if (ELEMENT_IS (TAG_RECENT_FILES)) -+ push_state (info, STATE_RECENT_FILES); -+ else if (ELEMENT_IS (TAG_RECENT_ITEM)) { -+ if (valid_element (info, STATE_RECENT_FILES, -+ TAG_RECENT_ITEM, TAG_RECENT_FILES, error)) { -+ info->current_item = egg_recent_item_new (); -+ push_state (info, STATE_RECENT_ITEM); -+ } -+ } else if (ELEMENT_IS (TAG_URI)) { -+ if (valid_element (info, STATE_RECENT_ITEM, -+ TAG_URI, TAG_RECENT_ITEM, error)) { -+ push_state (info, STATE_URI); -+ } -+ } else if (ELEMENT_IS (TAG_MIME_TYPE)) { -+ if (valid_element (info, STATE_RECENT_ITEM, -+ TAG_MIME_TYPE, TAG_RECENT_ITEM, error)) { -+ push_state (info, STATE_MIME_TYPE); -+ } -+ } else if (ELEMENT_IS (TAG_TIMESTAMP)) { -+ if (valid_element (info, STATE_RECENT_ITEM, -+ TAG_TIMESTAMP, TAG_RECENT_ITEM, error)) { -+ push_state (info, STATE_TIMESTAMP); -+ } -+ } else if (ELEMENT_IS (TAG_PRIVATE)) { -+ if (valid_element (info, STATE_RECENT_ITEM, -+ TAG_PRIVATE, TAG_RECENT_ITEM, error)) { -+ push_state (info, STATE_PRIVATE); -+ egg_recent_item_set_private (info->current_item, TRUE); -+ } -+ } else if (ELEMENT_IS (TAG_GROUPS)) { -+ if (valid_element (info, STATE_RECENT_ITEM, -+ TAG_GROUPS, TAG_RECENT_ITEM, error)) { -+ push_state (info, STATE_GROUPS); -+ } -+ } else if (ELEMENT_IS (TAG_GROUP)) { -+ if (valid_element (info, STATE_GROUPS, -+ TAG_GROUP, TAG_GROUPS, error)) { -+ push_state (info, STATE_GROUP); -+ } -+ } -+} -+ -+static gint -+list_compare_func_mru (gpointer a, gpointer b) -+{ -+ EggRecentItem *item_a = (EggRecentItem *)a; -+ EggRecentItem *item_b = (EggRecentItem *)b; -+ -+ return item_a->timestamp < item_b->timestamp; -+} -+ -+static gint -+list_compare_func_lru (gpointer a, gpointer b) -+{ -+ EggRecentItem *item_a = (EggRecentItem *)a; -+ EggRecentItem *item_b = (EggRecentItem *)b; -+ -+ return item_a->timestamp > item_b->timestamp; -+} -+ -+ -+ -+static void -+end_element_handler (GMarkupParseContext *context, -+ const gchar *element_name, -+ gpointer user_data, -+ GError **error) -+{ -+ ParseInfo *info = (ParseInfo *)user_data; -+ -+ switch (peek_state (info)) { -+ case STATE_RECENT_ITEM: -+ if (!info->current_item) { -+ g_warning ("No recent item found\n"); -+ break; -+ } -+ -+ if (!info->current_item->uri) { -+ g_warning ("Invalid item found\n"); -+ break; -+ } -+ -+ info->items = g_list_prepend (info->items, -+ info->current_item); -+ info->current_item = NULL; -+ break; -+ default: -+ break; -+ } -+ -+ pop_state (info); -+} -+ -+static void -+text_handler (GMarkupParseContext *context, -+ const gchar *text, -+ gsize text_len, -+ gpointer user_data, -+ GError **error) -+{ -+ ParseInfo *info = (ParseInfo *)user_data; -+ gchar *value; -+ -+ value = g_strndup (text, text_len); -+ -+ switch (peek_state (info)) { -+ case STATE_START: -+ case STATE_RECENT_FILES: -+ case STATE_RECENT_ITEM: -+ case STATE_PRIVATE: -+ case STATE_GROUPS: -+ break; -+ case STATE_URI: -+ egg_recent_item_set_uri (info->current_item, value); -+ break; -+ case STATE_MIME_TYPE: -+ egg_recent_item_set_mime_type (info->current_item, value); -+ break; -+ case STATE_TIMESTAMP: -+ egg_recent_item_set_timestamp (info->current_item, -+ (time_t)atoi (value)); -+ break; -+ case STATE_GROUP: -+ egg_recent_item_add_group (info->current_item, -+ text); -+ break; -+ } -+ -+ g_free (value); -+} -+ -+static void -+error_handler (GMarkupParseContext *context, -+ GError *error, -+ gpointer user_data) -+{ -+ g_warning ("Error in parse: %s", error->message); -+} -+ -+static void -+egg_recent_model_multi_enforce_limit (GList *list, int limit) -+{ -+ int len; -+ GList *end; -+ -+ /* limit < 0 means unlimited */ -+ if (limit <= 0) -+ return; -+ -+ len = g_list_length (list); -+ -+ if (len > limit) { -+ GList *next; -+ -+ end = g_list_nth (list, limit-1); -+ next = end->next; -+ -+ end->next = NULL; -+ -+ EGG_RECENT_ITEM_LIST_UNREF (next); -+ } -+} -+ -+static GList * -+egg_recent_model_multi_sort (EggRecentModelMulti *model, GList *list) -+{ -+ switch (model->priv->sort_type) { -+ case EGG_RECENT_MODEL_MULTI_SORT_MRU: -+ list = g_list_sort (list, -+ (GCompareFunc)list_compare_func_mru); -+ break; -+ case EGG_RECENT_MODEL_MULTI_SORT_LRU: -+ list = g_list_sort (list, -+ (GCompareFunc)list_compare_func_lru); -+ break; -+ case EGG_RECENT_MODEL_MULTI_SORT_NONE: -+ break; -+ } -+ -+ return list; -+} -+ -+static gboolean -+egg_recent_model_multi_group_match (EggRecentItem *item, GSList *groups) -+{ -+ GSList *tmp; -+ -+ tmp = groups; -+ -+ while (tmp != NULL) { -+ const gchar * group = (const gchar *)tmp->data; -+ -+ if (egg_recent_item_in_group (item, group)) -+ return TRUE; -+ -+ tmp = tmp->next; -+ } -+ -+ return FALSE; -+} -+ -+static GList * -+egg_recent_model_multi_filter (EggRecentModelMulti *model, GList *list) -+{ -+ GList *newlist = NULL; -+ GList *l; -+ gchar *mime_type; -+ gchar *uri; -+ -+ g_return_val_if_fail (list != NULL, NULL); -+ -+ for (l = list; l != NULL ; l = l->next) { -+ EggRecentItem *item = (EggRecentItem *) l->data; -+ gboolean pass_mime_test = FALSE; -+ gboolean pass_group_test = FALSE; -+ gboolean pass_scheme_test = FALSE; -+ -+ g_assert (item != NULL); -+ -+ uri = egg_recent_item_get_uri (item); -+ -+ /* filter by mime type */ -+ if (model->priv->mime_filter_values != NULL) { -+ mime_type = egg_recent_item_get_mime_type (item); -+ -+ if (egg_recent_model_multi_string_match -+ (model->priv->mime_filter_values, -+ mime_type)) -+ pass_mime_test = TRUE; -+ -+ g_free (mime_type); -+ } else -+ pass_mime_test = TRUE; -+ -+ /* filter by group */ -+ if (pass_mime_test && model->priv->group_filter_values != NULL) { -+ if (egg_recent_model_multi_group_match -+ (item, model->priv->group_filter_values)) -+ pass_group_test = TRUE; -+ } else if (egg_recent_item_get_private (item)) { -+ pass_group_test = FALSE; -+ } else -+ pass_group_test = TRUE; -+ -+ /* filter by URI scheme */ -+ if (pass_mime_test && pass_group_test && -+ model->priv->scheme_filter_values != NULL) { -+ gchar *scheme; -+ -+ scheme = gnome_vfs_get_uri_scheme (uri); -+ -+ if (egg_recent_model_multi_string_match -+ (model->priv->scheme_filter_values, scheme)) -+ pass_scheme_test = TRUE; -+ -+ g_free (scheme); -+ } else -+ pass_scheme_test = TRUE; -+ -+ if (pass_mime_test && pass_group_test && pass_scheme_test) -+ newlist = g_list_prepend (newlist, item); -+ else -+ egg_recent_item_unref (item); -+ -+ g_free (uri); -+ } -+ -+ g_list_free (list); -+ -+ return g_list_reverse (newlist); -+} -+ -+ -+ -+#if 0 -+static void -+egg_recent_model_multi_monitor_list_cb (GnomeVFSMonitorHandle *handle, -+ const gchar *monitor_uri, -+ const gchar *info_uri, -+ GnomeVFSMonitorEventType event_type, -+ gpointer user_data) -+{ -+ EggRecentModelMulti *model; -+ -+ model = EGG_RECENT_MODEL_MULTI (user_data); -+ -+ if (event_type == GNOME_VFS_MONITOR_EVENT_DELETED) { -+ egg_recent_model_multi_delete (model, monitor_uri); -+ g_hash_table_remove (model->priv->monitors, monitor_uri); -+ } -+} -+ -+ -+ -+static void -+egg_recent_model_multi_monitor_list (EggRecentModelMulti *model, GList *list) -+{ -+ GList *tmp; -+ -+ tmp = list; -+ while (tmp) { -+ EggRecentItem *item = (EggRecentItem *)tmp->data; -+ GnomeVFSMonitorHandle *handle; -+ GnomeVFSResult res; -+ gchar *uri; -+ -+ tmp = tmp->next; -+ -+ uri = egg_recent_item_get_uri (item); -+ if (g_hash_table_lookup (model->priv->monitors, uri)) { -+ /* already monitoring this one */ -+ g_free (uri); -+ continue; -+ } -+ -+ res = gnome_vfs_monitor_add (&handle, uri, -+ GNOME_VFS_MONITOR_FILE, -+ egg_recent_model_multi_monitor_list_cb, -+ model); -+ -+ if (res == GNOME_VFS_OK) -+ g_hash_table_insert (model->priv->monitors, uri, handle); -+ else -+ g_free (uri); -+ } -+} -+#endif -+ -+ -+static gboolean -+egg_recent_model_multi_changed_timeout (EggRecentModelMulti *model) -+{ -+ model->priv->changed_timeout = 0; -+ -+ egg_recent_model_multi_changed (model); -+ -+ return FALSE; -+} -+ -+static void -+egg_recent_model_multi_monitor_cb (GnomeVFSMonitorHandle *handle, -+ const gchar *monitor_uri, -+ const gchar *info_uri, -+ GnomeVFSMonitorEventType event_type, -+ gpointer user_data) -+{ -+ EggRecentModelMulti *model; -+ -+ g_return_if_fail (user_data != NULL); -+ g_return_if_fail (EGG_IS_RECENT_MODEL_MULTI (user_data)); -+ model = EGG_RECENT_MODEL_MULTI (user_data); -+ -+ if (event_type == GNOME_VFS_MONITOR_EVENT_CHANGED || -+ event_type == GNOME_VFS_MONITOR_EVENT_CREATED || -+ event_type == GNOME_VFS_MONITOR_EVENT_DELETED) { -+ if (model->priv->changed_timeout > 0) { -+ g_source_remove (model->priv->changed_timeout); -+ } -+ -+ model->priv->changed_timeout = g_timeout_add ( -+ EGG_RECENT_MODEL_MULTI_TIMEOUT_LENGTH, -+ (GSourceFunc)egg_recent_model_multi_changed_timeout, -+ model); -+ } -+} -+ -+static gboolean -+egg_recent_model_multi_poll_timeout (gpointer user_data) -+{ -+ EggRecentModelMulti *model; -+ struct stat stat_buf; -+ int stat_res; -+ -+ model = EGG_RECENT_MODEL_MULTI (user_data); -+ stat_res = stat (model->priv->path, &stat_buf); -+ -+ if (!stat_res && stat_buf.st_mtime && -+ stat_buf.st_mtime != model->priv->last_mtime) { -+ model->priv->last_mtime = stat_buf.st_mtime; -+ -+ if (model->priv->changed_timeout > 0) -+ g_source_remove (model->priv->changed_timeout); -+ -+ model->priv->changed_timeout = g_timeout_add ( -+ EGG_RECENT_MODEL_MULTI_TIMEOUT_LENGTH, -+ (GSourceFunc)egg_recent_model_multi_changed_timeout, -+ model); -+ } -+ return TRUE; -+} -+ -+static void -+egg_recent_model_multi_monitor (EggRecentModelMulti *model, gboolean should_monitor) -+{ -+ if (should_monitor && model->priv->monitor == NULL) { -+ char *uri; -+ GnomeVFSResult result; -+ -+ uri = gnome_vfs_get_uri_from_local_path (model->priv->path); -+ -+ result = gnome_vfs_monitor_add (&model->priv->monitor, -+ uri, -+ GNOME_VFS_MONITOR_FILE, -+ egg_recent_model_multi_monitor_cb, -+ model); -+ -+ g_free (uri); -+ -+ /* if the above fails, don't worry about it. -+ * local notifications will still happen -+ */ -+ if (result == GNOME_VFS_ERROR_NOT_SUPPORTED) { -+ if (model->priv->poll_timeout > 0) -+ g_source_remove (model->priv->poll_timeout); -+ -+ model->priv->poll_timeout = g_timeout_add ( -+ EGG_RECENT_MODEL_MULTI_POLL_TIME * 1000, -+ egg_recent_model_multi_poll_timeout, -+ model); -+ } -+ -+ } else if (!should_monitor && model->priv->monitor != NULL) { -+ gnome_vfs_monitor_cancel (model->priv->monitor); -+ model->priv->monitor = NULL; -+ } -+} -+ -+static void -+egg_recent_model_multi_set_limit_internal (EggRecentModelMulti *model, int limit) -+{ -+ model->priv->limit = limit; -+ -+ if (limit <= 0) -+ egg_recent_model_multi_monitor (model, FALSE); -+ else { -+ egg_recent_model_multi_monitor (model, TRUE); -+ egg_recent_model_multi_changed (model); -+ } -+} -+ -+static GList * -+egg_recent_model_multi_read (EggRecentModelMulti *model, FILE *file) -+{ -+ GList *list=NULL; -+ gchar *content; -+ GMarkupParseContext *ctx; -+ ParseInfo *info; -+ GError *error; -+ -+ content = egg_recent_model_multi_read_raw (model, file); -+ -+ if (strlen (content) <= 0) { -+ g_free (content); -+ return NULL; -+ } -+ -+ info = parse_info_init (); -+ -+ ctx = g_markup_parse_context_new (&parser, 0, info, NULL); -+ -+ error = NULL; -+ if (!g_markup_parse_context_parse (ctx, content, strlen (content), &error)) { -+ g_warning ("Error while parsing the .recently-used file: %s\n", -+ error->message); -+ -+ g_error_free (error); -+ parse_info_free (info); -+ -+ return NULL; -+ } -+ -+ error = NULL; -+ if (!g_markup_parse_context_end_parse (ctx, &error)) { -+ g_warning ("Unable to complete parsing of the .recently-used file: %s\n", -+ error->message); -+ -+ g_error_free (error); -+ g_markup_parse_context_free (ctx); -+ parse_info_free (info); -+ -+ return NULL; -+ } -+ -+ list = g_list_reverse (info->items); -+ -+ g_markup_parse_context_free (ctx); -+ parse_info_free (info); -+ g_free (content); -+ -+ return list; -+} -+ -+ -+static gboolean -+egg_recent_model_multi_write (EggRecentModelMulti *model, FILE *file, GList *list) -+{ -+ GString *string; -+ gchar *data; -+ EggRecentItem *item; -+ const GList *groups; -+ int i; -+ int ret; -+ -+ string = g_string_new ("\n"); -+ string = g_string_append (string, "<" TAG_RECENT_FILES ">\n"); -+ -+ i=0; -+ while (list) { -+ gchar *uri; -+ gchar *mime_type; -+ gchar *escaped_uri; -+ time_t timestamp; -+ item = (EggRecentItem *)list->data; -+ -+ -+ uri = egg_recent_item_get_uri_utf8 (item); -+ escaped_uri = g_markup_escape_text (uri, -+ strlen (uri)); -+ g_free (uri); -+ -+ mime_type = egg_recent_item_get_mime_type (item); -+ timestamp = egg_recent_item_get_timestamp (item); -+ -+ string = g_string_append (string, " <" TAG_RECENT_ITEM ">\n"); -+ -+ g_string_append_printf (string, -+ " <" TAG_URI ">%s\n", escaped_uri); -+ -+ if (mime_type) -+ g_string_append_printf (string, -+ " <" TAG_MIME_TYPE ">%s\n", mime_type); -+ else -+ g_string_append_printf (string, -+ " <" TAG_MIME_TYPE ">\n"); -+ -+ -+ g_string_append_printf (string, -+ " <" TAG_TIMESTAMP ">%d\n", (int)timestamp); -+ -+ if (egg_recent_item_get_private (item)) -+ string = g_string_append (string, -+ " <" TAG_PRIVATE "/>\n"); -+ -+ /* write the groups */ -+ string = g_string_append (string, -+ " <" TAG_GROUPS ">\n"); -+ groups = egg_recent_item_get_groups (item); -+ -+ if (groups == NULL && egg_recent_item_get_private (item)) -+ g_warning ("Item with URI \"%s\" marked as private, but" -+ " does not belong to any groups.\n", uri); -+ -+ while (groups) { -+ const gchar *group = (const gchar *)groups->data; -+ gchar *escaped_group; -+ -+ escaped_group = g_markup_escape_text (group, strlen(group)); -+ -+ g_string_append_printf (string, -+ " <" TAG_GROUP ">%s\n", -+ escaped_group); -+ -+ g_free (escaped_group); -+ -+ groups = groups->next; -+ } -+ -+ string = g_string_append (string, " \n"); -+ -+ string = g_string_append (string, -+ " \n"); -+ -+ g_free (mime_type); -+ g_free (escaped_uri); -+ -+ list = list->next; -+ i++; -+ } -+ -+ string = g_string_append (string, ""); -+ -+ data = g_string_free (string, FALSE); -+ -+ ret = egg_recent_model_multi_write_raw (model, file, data); -+ -+ g_free (data); -+ -+ return ret; -+} -+ -+static FILE * -+egg_recent_model_multi_open_file (EggRecentModelMulti *model, -+ gboolean for_writing) -+{ -+ FILE *file; -+ mode_t prev_umask; -+ -+ file = fopen (model->priv->path, "r+"); -+ if (file == NULL && for_writing) { -+ /* be paranoid */ -+ prev_umask = umask (077); -+ -+ file = fopen (model->priv->path, "w+"); -+ -+ umask (prev_umask); -+ -+ g_return_val_if_fail (file != NULL, NULL); -+ } -+ -+ return file; -+} -+ -+static gboolean -+egg_recent_model_multi_lock_file (FILE *file) -+{ -+#ifdef HAVE_LOCKF -+ int fd; -+ gint try = 5; -+ -+ rewind (file); -+ fd = fileno (file); -+ -+ /* Attempt to lock the file 5 times, -+ * waiting a random interval (< 1 second) -+ * in between attempts. -+ * We should really be doing asynchronous -+ * locking, but requires substantially larger -+ * changes. -+ */ -+ -+ while (try > 0) -+ { -+ int rand_interval; -+ -+ if (lockf (fd, F_TLOCK, 0) == 0) -+ return TRUE; -+ -+ rand_interval = 1 + (int) (10.0 * rand()/(RAND_MAX + 1.0)); -+ -+ g_usleep (100000 * rand_interval); -+ -+ --try; -+ } -+ -+ return FALSE; -+#else -+ return TRUE; -+#endif /* HAVE_LOCKF */ -+} -+ -+static gboolean -+egg_recent_model_multi_unlock_file (FILE *file) -+{ -+#ifdef HAVE_LOCKF -+ int fd; -+ -+ rewind (file); -+ fd = fileno (file); -+ -+ return (lockf (fd, F_ULOCK, 0) == 0) ? TRUE : FALSE; -+#else -+ return TRUE; -+#endif /* HAVE_LOCKF */ -+} -+ -+static void -+egg_recent_model_multi_finalize (GObject *object) -+{ -+ EggRecentModelMulti *model = EGG_RECENT_MODEL_MULTI (object); -+ -+ if (model->priv->changed_timeout > 0) { -+ g_source_remove (model->priv->changed_timeout); -+ } -+ -+ egg_recent_model_multi_monitor (model, FALSE); -+ -+ -+ g_slist_foreach (model->priv->mime_filter_values, -+ (GFunc) g_pattern_spec_free, NULL); -+ g_slist_free (model->priv->mime_filter_values); -+ model->priv->mime_filter_values = NULL; -+ -+ g_slist_foreach (model->priv->scheme_filter_values, -+ (GFunc) g_pattern_spec_free, NULL); -+ g_slist_free (model->priv->scheme_filter_values); -+ model->priv->scheme_filter_values = NULL; -+ -+ g_slist_foreach (model->priv->group_filter_values, -+ (GFunc) g_free, NULL); -+ g_slist_free (model->priv->group_filter_values); -+ model->priv->group_filter_values = NULL; -+ -+ -+ if (model->priv->limit_change_notify_id) -+ gconf_client_notify_remove (model->priv->client, -+ model->priv->limit_change_notify_id); -+ model->priv->expiration_change_notify_id = 0; -+ -+ if (model->priv->expiration_change_notify_id) -+ gconf_client_notify_remove (model->priv->client, -+ model->priv->expiration_change_notify_id); -+ model->priv->expiration_change_notify_id = 0; -+ -+ g_object_unref (model->priv->client); -+ model->priv->client = NULL; -+ -+ -+ g_free (model->priv->path); -+ model->priv->path = NULL; -+ -+ g_hash_table_destroy (model->priv->monitors); -+ model->priv->monitors = NULL; -+ -+ if (model->priv->poll_timeout > 0) -+ g_source_remove (model->priv->poll_timeout); -+ model->priv->poll_timeout =0; -+ -+ g_free (model->priv); -+ -+ parent_class->finalize (object); -+} -+ -+static void -+egg_recent_model_multi_set_property (GObject *object, -+ guint prop_id, -+ const GValue *value, -+ GParamSpec *pspec) -+{ -+ EggRecentModelMulti *model = EGG_RECENT_MODEL_MULTI (object); -+ -+ switch (prop_id) -+ { -+ case PROP_MIME_FILTERS: -+ if (model->priv->mime_filter_values != NULL) -+ egg_recent_model_multi_clear_mime_filter (model); -+ -+ model->priv->mime_filter_values = -+ (GSList *)g_value_get_pointer (value); -+ break; -+ -+ case PROP_GROUP_FILTERS: -+ if (model->priv->group_filter_values != NULL) -+ egg_recent_model_multi_clear_group_filter (model); -+ -+ model->priv->group_filter_values = -+ (GSList *)g_value_get_pointer (value); -+ break; -+ -+ case PROP_SCHEME_FILTERS: -+ if (model->priv->scheme_filter_values != NULL) -+ egg_recent_model_multi_clear_scheme_filter (model); -+ -+ model->priv->scheme_filter_values = -+ (GSList *)g_value_get_pointer (value); -+ break; -+ -+ case PROP_SORT_TYPE: -+ model->priv->sort_type = g_value_get_int (value); -+ break; -+ -+ case PROP_FILE_PATH: -+ model->priv->path = g_strdup_printf ( -+ "%s/%s", -+ g_get_home_dir (), -+ g_value_get_string (value) -+ ); -+ egg_recent_model_multi_monitor (model, TRUE); -+ break; -+ -+ case PROP_LIMIT: -+ egg_recent_model_multi_set_limit (model, -+ g_value_get_int (value)); -+ break; -+ -+ default: -+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); -+ break; -+ } -+} -+ -+static void -+egg_recent_model_multi_get_property (GObject *object, -+ guint prop_id, -+ GValue *value, -+ GParamSpec *pspec) -+{ -+ EggRecentModelMulti *model = EGG_RECENT_MODEL_MULTI (object); -+ -+ switch (prop_id) -+ { -+ case PROP_MIME_FILTERS: -+ g_value_set_pointer (value, model->priv->mime_filter_values); -+ break; -+ -+ case PROP_GROUP_FILTERS: -+ g_value_set_pointer (value, model->priv->group_filter_values); -+ break; -+ -+ case PROP_SCHEME_FILTERS: -+ g_value_set_pointer (value, model->priv->scheme_filter_values); -+ break; -+ -+ case PROP_SORT_TYPE: -+ g_value_set_int (value, model->priv->sort_type); -+ break; -+ -+ case PROP_FILE_PATH: -+ g_value_set_string (value, model->priv->path); -+ break; -+ -+ case PROP_LIMIT: -+ g_value_set_int (value, model->priv->limit); -+ break; -+ -+ default: -+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); -+ break; -+ } -+} -+ -+static void -+egg_recent_model_multi_class_init (EggRecentModelMultiClass * klass) -+{ -+ GObjectClass *object_class; -+ -+ parent_class = g_type_class_peek_parent (klass); -+ -+ parent_class = g_type_class_peek_parent (klass); -+ -+ object_class = G_OBJECT_CLASS (klass); -+ object_class->set_property = egg_recent_model_multi_set_property; -+ object_class->get_property = egg_recent_model_multi_get_property; -+ object_class->finalize = egg_recent_model_multi_finalize; -+ -+ model_signals[CHANGED] = g_signal_new ("changed", -+ G_OBJECT_CLASS_TYPE (object_class), -+ G_SIGNAL_RUN_LAST, -+ G_STRUCT_OFFSET (EggRecentModelMultiClass, changed), -+ NULL, NULL, -+ g_cclosure_marshal_VOID__POINTER, -+ G_TYPE_NONE, 1, -+ G_TYPE_POINTER); -+ -+ -+ g_object_class_install_property (object_class, -+ PROP_MIME_FILTERS, -+ g_param_spec_pointer ("mime-filters", -+ "Mime Filters", -+ "List of mime types to be allowed.", -+ G_PARAM_READWRITE)); -+ -+ g_object_class_install_property (object_class, -+ PROP_GROUP_FILTERS, -+ g_param_spec_pointer ("group-filters", -+ "Group Filters", -+ "List of groups to be allowed.", -+ G_PARAM_READWRITE)); -+ -+ g_object_class_install_property (object_class, -+ PROP_SCHEME_FILTERS, -+ g_param_spec_pointer ("scheme-filters", -+ "Scheme Filters", -+ "List of URI schemes to be allowed.", -+ G_PARAM_READWRITE)); -+ -+ g_object_class_install_property (object_class, -+ PROP_SORT_TYPE, -+ g_param_spec_int ("sort-type", -+ "Sort Type", -+ "Type of sorting to be done.", -+ 0, EGG_RECENT_MODEL_MULTI_SORT_NONE, -+ EGG_RECENT_MODEL_MULTI_SORT_MRU, -+ G_PARAM_READWRITE)); -+ -+ g_object_class_install_property (object_class, -+ PROP_FILE_PATH, -+ g_param_spec_string ("file-path", -+ "File Path", -+ "File path relative to $HOME.", -+ EGG_RECENT_MODEL_MULTI_DEFAULT_FILE_PATH, -+ G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY)); -+ -+ g_object_class_install_property (object_class, -+ PROP_LIMIT, -+ g_param_spec_int ("limit", -+ "Limit", -+ "Max number of items allowed.", -+ -1, EGG_RECENT_MODEL_MULTI_MAX_ITEMS, -+ EGG_RECENT_MODEL_MULTI_DEFAULT_LIMIT, -+ G_PARAM_READWRITE)); -+ -+ klass->changed = NULL; -+} -+ -+ -+ -+static void -+egg_recent_model_multi_limit_changed (GConfClient *client, guint cnxn_id, -+ GConfEntry *entry, gpointer user_data) -+{ -+ EggRecentModelMulti *model; -+ GConfValue *value; -+ -+ model = EGG_RECENT_MODEL_MULTI (user_data); -+ -+ g_return_if_fail (model != NULL); -+ -+ if (model->priv->use_default_limit == FALSE) -+ return; /* ignore this key */ -+ -+ /* the key was unset, and the schema has apparently failed */ -+ if (entry == NULL) -+ return; -+ -+ value = gconf_entry_get_value (entry); -+ -+ if (value->type != GCONF_VALUE_INT) { -+ g_warning ("Expected GConfValue of type integer, " -+ "got something else"); -+ } -+ -+ -+ egg_recent_model_multi_set_limit_internal (model, gconf_value_get_int (value)); -+} -+ -+static void -+egg_recent_model_multi_expiration_changed (GConfClient *client, guint cnxn_id, -+ GConfEntry *entry, gpointer user_data) -+{ -+ -+} -+ -+static void -+egg_recent_model_multi_init (EggRecentModelMulti * model) -+{ -+ if (!gnome_vfs_init ()) { -+ g_warning ("gnome-vfs initialization failed."); -+ return; -+ } -+ -+ -+ model->priv = g_new0 (EggRecentModelMultiPrivate, 1); -+ -+ model->priv->mime_filter_values = NULL; -+ model->priv->group_filter_values = NULL; -+ model->priv->scheme_filter_values = NULL; -+ -+ model->priv->client = gconf_client_get_default (); -+ gconf_client_add_dir (model->priv->client, EGG_RECENT_MODEL_MULTI_KEY_DIR, -+ GCONF_CLIENT_PRELOAD_ONELEVEL, NULL); -+ -+ model->priv->limit_change_notify_id = -+ gconf_client_notify_add (model->priv->client, -+ EGG_RECENT_MODEL_MULTI_DEFAULT_LIMIT_KEY, -+ egg_recent_model_multi_limit_changed, -+ model, NULL, NULL); -+ -+ model->priv->expiration_change_notify_id = -+ gconf_client_notify_add (model->priv->client, -+ EGG_RECENT_MODEL_MULTI_EXPIRE_KEY, -+ egg_recent_model_multi_expiration_changed, -+ model, NULL, NULL); -+ -+ model->priv->expire_days = gconf_client_get_int ( -+ model->priv->client, -+ EGG_RECENT_MODEL_MULTI_EXPIRE_KEY, -+ NULL); -+ -+#if 0 -+ /* keep this out, for now */ -+ model->priv->limit = gconf_client_get_int ( -+ model->priv->client, -+ EGG_RECENT_MODEL_MULTI_DEFAULT_LIMIT_KEY, NULL); -+ model->priv->use_default_limit = TRUE; -+#endif -+ model->priv->limit = EGG_RECENT_MODEL_MULTI_DEFAULT_LIMIT; -+ model->priv->use_default_limit = FALSE; -+ -+ model->priv->monitors = g_hash_table_new_full ( -+ g_str_hash, g_str_equal, -+ (GDestroyNotify) g_free, -+ (GDestroyNotify) gnome_vfs_monitor_cancel); -+ -+ model->priv->monitor = NULL; -+ model->priv->poll_timeout = 0; -+ model->priv->last_mtime = 0; -+} -+ -+ -+/** -+ * egg_recent_model_multi_new: -+ * @sort: the type of sorting to use -+ * @limit: maximum number of items in the list -+ * -+ * This creates a new EggRecentModelMulti object. -+ * -+ * Returns: a EggRecentModelMulti object -+ */ -+EggRecentModelMulti * -+egg_recent_model_multi_new (EggRecentModelMultiSort sort) -+{ -+ return egg_recent_model_multi_new_with_file_path (sort, EGG_RECENT_MODEL_MULTI_DEFAULT_FILE_PATH); -+} -+ -+EggRecentModelMulti * -+egg_recent_model_multi_new_with_file_path (EggRecentModelMultiSort sort, const gchar *file_path) -+{ -+ EggRecentModelMulti *model; -+ -+ if (! file_path) -+ file_path = EGG_RECENT_MODEL_MULTI_DEFAULT_FILE_PATH; -+ -+ model = EGG_RECENT_MODEL_MULTI (g_object_new (egg_recent_model_multi_get_type (), -+ "sort-type", sort, "file-path", file_path, NULL)); -+ -+ g_return_val_if_fail (model, NULL); -+ -+ return model; -+} -+ -+/** -+ * egg_recent_model_multi_add_full: -+ * @model: A EggRecentModelMulti object. -+ * @item: A EggRecentItem -+ * -+ * This function adds an item to the list of recently used URIs. -+ * -+ * Returns: gboolean -+ */ -+gboolean -+egg_recent_model_multi_add_full (EggRecentModelMulti * model, EggRecentItem *item) -+{ -+ FILE *file; -+ GList *list = NULL; -+ gboolean ret = FALSE; -+ gboolean updated = FALSE; -+ char *uri; -+ time_t t; -+ -+ g_return_val_if_fail (model != NULL, FALSE); -+ g_return_val_if_fail (EGG_IS_RECENT_MODEL_MULTI (model), FALSE); -+ -+ uri = egg_recent_item_get_uri (item); -+ if (strncmp (uri, "recent-files://", strlen ("recent-files://")) == 0) { -+ g_free (uri); -+ return FALSE; -+ } else { -+ g_free (uri); -+ } -+ -+ file = egg_recent_model_multi_open_file (model, TRUE); -+ g_return_val_if_fail (file != NULL, FALSE); -+ -+ time (&t); -+ egg_recent_item_set_timestamp (item, t); -+ -+ if (egg_recent_model_multi_lock_file (file)) { -+ -+ /* read existing stuff */ -+ list = egg_recent_model_multi_read (model, file); -+ -+ /* if it's already there, we just update it */ -+ updated = egg_recent_model_multi_update_item (list, item); -+ -+ if (!updated) { -+ list = g_list_prepend (list, item); -+ -+ egg_recent_model_multi_enforce_limit (list, -+ EGG_RECENT_MODEL_MULTI_MAX_ITEMS); -+ } -+ -+ /* write new stuff */ -+ if (!egg_recent_model_multi_write (model, file, list)) -+ g_warning ("Write failed: %s", strerror (errno)); -+ -+ if (!updated) -+ list = g_list_remove (list, item); -+ -+ EGG_RECENT_ITEM_LIST_UNREF (list); -+ ret = TRUE; -+ } else { -+ g_warning ("Failed to lock: %s", strerror (errno)); -+ fclose (file); -+ return FALSE; -+ } -+ -+ if (!egg_recent_model_multi_unlock_file (file)) -+ g_warning ("Failed to unlock: %s", strerror (errno)); -+ -+ fclose (file); -+ -+ if (model->priv->monitor == NULL) { -+ /* since monitoring isn't working, at least give a -+ * local notification -+ */ -+ egg_recent_model_multi_changed (model); -+ } -+ -+ return ret; -+} -+ -+/** -+ * egg_recent_model_multi_add: -+ * @model: A EggRecentModelMulti object. -+ * @uri: A string URI -+ * -+ * This function adds an item to the list of recently used URIs. -+ * -+ * Returns: gboolean -+ */ -+gboolean -+egg_recent_model_multi_add (EggRecentModelMulti *model, const gchar *uri) -+{ -+ EggRecentItem *item; -+ gboolean ret = FALSE; -+ -+ g_return_val_if_fail (model != NULL, FALSE); -+ g_return_val_if_fail (uri != NULL, FALSE); -+ -+ item = egg_recent_item_new_from_uri (uri); -+ -+ g_return_val_if_fail (item != NULL, FALSE); -+ -+ ret = egg_recent_model_multi_add_full (model, item); -+ -+ egg_recent_item_unref (item); -+ -+ return ret; -+} -+ -+ -+ -+/** -+ * egg_recent_model_multi_delete: -+ * @model: A EggRecentModelMulti object. -+ * @uri: The URI you want to delete. -+ * -+ * This function deletes a URI from the file of recently used URIs. -+ * -+ * Returns: gboolean -+ */ -+gboolean -+egg_recent_model_multi_delete (EggRecentModelMulti * model, const gchar * uri) -+{ -+ FILE *file; -+ GList *list; -+ unsigned int length; -+ gboolean ret = FALSE; -+ -+ g_return_val_if_fail (model != NULL, FALSE); -+ g_return_val_if_fail (EGG_IS_RECENT_MODEL_MULTI (model), FALSE); -+ g_return_val_if_fail (uri != NULL, FALSE); -+ -+ file = egg_recent_model_multi_open_file (model, TRUE); -+ g_return_val_if_fail (file != NULL, FALSE); -+ -+ if (egg_recent_model_multi_lock_file (file)) { -+ list = egg_recent_model_multi_read (model, file); -+ -+ if (list == NULL) -+ goto out; -+ -+ length = g_list_length (list); -+ -+ list = egg_recent_model_multi_delete_from_list (list, uri); -+ -+ if (length == g_list_length (list)) { -+ /* nothing was deleted */ -+ EGG_RECENT_ITEM_LIST_UNREF (list); -+ } else { -+ egg_recent_model_multi_write (model, file, list); -+ EGG_RECENT_ITEM_LIST_UNREF (list); -+ ret = TRUE; -+ -+ } -+ } else { -+ g_warning ("Failed to lock: %s", strerror (errno)); -+ return FALSE; -+ } -+ -+out: -+ -+ if (!egg_recent_model_multi_unlock_file (file)) -+ g_warning ("Failed to unlock: %s", strerror (errno)); -+ -+ fclose (file); -+ -+ g_hash_table_remove (model->priv->monitors, uri); -+ -+ if (model->priv->monitor == NULL && ret) { -+ /* since monitoring isn't working, at least give a -+ * local notification -+ */ -+ egg_recent_model_multi_changed (model); -+ } -+ -+ return ret; -+} -+ -+ -+/** -+ * egg_recent_model_multi_get_list: -+ * @model: A EggRecentModelMulti object. -+ * -+ * This function gets the current contents of the file -+ * -+ * Returns: a GList -+ */ -+GList * -+egg_recent_model_multi_get_list (EggRecentModelMulti *model) -+{ -+ FILE *file; -+ GList *list = NULL; -+ -+ file = egg_recent_model_multi_open_file (model, FALSE); -+ if (file == NULL) -+ return NULL; -+ -+ if (egg_recent_model_multi_lock_file (file)) -+ list = egg_recent_model_multi_read (model, file); -+ else { -+ g_warning ("Failed to lock: %s", strerror (errno)); -+ fclose (file); -+ return NULL; -+ } -+ -+ if (!egg_recent_model_multi_unlock_file (file)) -+ g_warning ("Failed to unlock: %s", strerror (errno)); -+ -+ if (list != NULL) { -+ list = egg_recent_model_multi_filter (model, list); -+ list = egg_recent_model_multi_sort (model, list); -+ -+ egg_recent_model_multi_enforce_limit (list, model->priv->limit); -+ } -+ -+ fclose (file); -+ -+ return list; -+} -+ -+ -+ -+/** -+ * egg_recent_model_multi_set_limit: -+ * @model: A EggRecentModelMulti object. -+ * @limit: The maximum length of the list -+ * -+ * This function sets the maximum length of the list. Note: This only affects -+ * the length of the list emitted in the "changed" signal, not the list stored -+ * on disk. -+ * -+ * Returns: void -+ */ -+void -+egg_recent_model_multi_set_limit (EggRecentModelMulti *model, int limit) -+{ -+ model->priv->use_default_limit = FALSE; -+ -+ egg_recent_model_multi_set_limit_internal (model, limit); -+} -+ -+/** -+ * egg_recent_model_multi_get_limit: -+ * @model: A EggRecentModelMulti object. -+ * -+ * This function gets the maximum length of the list. -+ * -+ * Returns: int -+ */ -+int -+egg_recent_model_multi_get_limit (EggRecentModelMulti *model) -+{ -+ return model->priv->limit; -+} -+ -+ -+/** -+ * egg_recent_model_multi_clear: -+ * @model: A EggRecentModelMulti object. -+ * -+ * This function clears the contents of the file -+ * -+ * Returns: void -+ */ -+void -+egg_recent_model_multi_clear (EggRecentModelMulti *model) -+{ -+ FILE *file; -+ int fd; -+ -+ file = egg_recent_model_multi_open_file (model, TRUE); -+ g_return_if_fail (file != NULL); -+ -+ fd = fileno (file); -+ -+ if (egg_recent_model_multi_lock_file (file)) { -+ ftruncate (fd, 0); -+ } else { -+ g_warning ("Failed to lock: %s", strerror (errno)); -+ return; -+ } -+ -+ if (!egg_recent_model_multi_unlock_file (file)) -+ g_warning ("Failed to unlock: %s", strerror (errno)); -+ -+ fclose (file); -+ -+ if (model->priv->monitor == NULL) { -+ /* since monitoring isn't working, at least give a -+ * local notification -+ */ -+ egg_recent_model_multi_changed (model); -+ } -+} -+ -+static void -+egg_recent_model_multi_clear_mime_filter (EggRecentModelMulti *model) -+{ -+ g_return_if_fail (model != NULL); -+ -+ if (model->priv->mime_filter_values != NULL) { -+ g_slist_foreach (model->priv->mime_filter_values, -+ (GFunc) g_pattern_spec_free, NULL); -+ g_slist_free (model->priv->mime_filter_values); -+ model->priv->mime_filter_values = NULL; -+ } -+} -+ -+/** -+ * egg_recent_model_multi_set_filter_mime_types: -+ * @model: A EggRecentModelMulti object. -+ * -+ * Sets which mime types are allowed in the list. -+ * -+ * Returns: void -+ */ -+void -+egg_recent_model_multi_set_filter_mime_types (EggRecentModelMulti *model, -+ ...) -+{ -+ va_list valist; -+ GSList *list = NULL; -+ gchar *str; -+ -+ g_return_if_fail (model != NULL); -+ -+ egg_recent_model_multi_clear_mime_filter (model); -+ -+ va_start (valist, model); -+ -+ str = va_arg (valist, gchar*); -+ -+ while (str != NULL) { -+ list = g_slist_prepend (list, g_pattern_spec_new (str)); -+ -+ str = va_arg (valist, gchar*); -+ } -+ -+ va_end (valist); -+ -+ model->priv->mime_filter_values = list; -+} -+ -+static void -+egg_recent_model_multi_clear_group_filter (EggRecentModelMulti *model) -+{ -+ g_return_if_fail (model != NULL); -+ -+ if (model->priv->group_filter_values != NULL) { -+ g_slist_foreach (model->priv->group_filter_values, (GFunc)g_free, NULL); -+ g_slist_free (model->priv->group_filter_values); -+ model->priv->group_filter_values = NULL; -+ } -+} -+ -+/** -+ * egg_recent_model_multi_set_filter_groups: -+ * @model: A EggRecentModelMulti object. -+ * -+ * Sets which groups are allowed in the list. -+ * -+ * Returns: void -+ */ -+void -+egg_recent_model_multi_set_filter_groups (EggRecentModelMulti *model, -+ ...) -+{ -+ va_list valist; -+ GSList *list = NULL; -+ gchar *str; -+ -+ g_return_if_fail (model != NULL); -+ -+ egg_recent_model_multi_clear_group_filter (model); -+ -+ va_start (valist, model); -+ -+ str = va_arg (valist, gchar*); -+ -+ while (str != NULL) { -+ list = g_slist_prepend (list, g_strdup (str)); -+ -+ str = va_arg (valist, gchar*); -+ } -+ -+ va_end (valist); -+ -+ model->priv->group_filter_values = list; -+} -+ -+static void -+egg_recent_model_multi_clear_scheme_filter (EggRecentModelMulti *model) -+{ -+ g_return_if_fail (model != NULL); -+ -+ if (model->priv->scheme_filter_values != NULL) { -+ g_slist_foreach (model->priv->scheme_filter_values, -+ (GFunc) g_pattern_spec_free, NULL); -+ g_slist_free (model->priv->scheme_filter_values); -+ model->priv->scheme_filter_values = NULL; -+ } -+} -+ -+/** -+ * egg_recent_model_multi_set_filter_uri_schemes: -+ * @model: A EggRecentModelMulti object. -+ * -+ * Sets which URI schemes (file, http, ftp, etc) are allowed in the list. -+ * -+ * Returns: void -+ */ -+void -+egg_recent_model_multi_set_filter_uri_schemes (EggRecentModelMulti *model, ...) -+{ -+ va_list valist; -+ GSList *list = NULL; -+ gchar *str; -+ -+ g_return_if_fail (model != NULL); -+ -+ egg_recent_model_multi_clear_scheme_filter (model); -+ -+ va_start (valist, model); -+ -+ str = va_arg (valist, gchar*); -+ -+ while (str != NULL) { -+ list = g_slist_prepend (list, g_pattern_spec_new (str)); -+ -+ str = va_arg (valist, gchar*); -+ } -+ -+ va_end (valist); -+ -+ model->priv->scheme_filter_values = list; -+} -+ -+/** -+ * egg_recent_model_multi_set_sort: -+ * @model: A EggRecentModelMulti object. -+ * @sort: A EggRecentModelMultiSort type -+ * -+ * Sets the type of sorting to be used. -+ * -+ * Returns: void -+ */ -+void -+egg_recent_model_multi_set_sort (EggRecentModelMulti *model, -+ EggRecentModelMultiSort sort) -+{ -+ g_return_if_fail (model != NULL); -+ -+ model->priv->sort_type = sort; -+} -+ -+/** -+ * egg_recent_model_multi_changed: -+ * @model: A EggRecentModelMulti object. -+ * -+ * This function causes a "changed" signal to be emitted. -+ * -+ * Returns: void -+ */ -+void -+egg_recent_model_multi_changed (EggRecentModelMulti *model) -+{ -+ GList *list = NULL; -+ -+ if (model->priv->limit > 0) { -+ list = egg_recent_model_multi_get_list (model); -+ /* egg_recent_model_multi_monitor_list (model, list); */ -+ -+ g_signal_emit (G_OBJECT (model), model_signals[CHANGED], 0, -+ list); -+ } -+ -+ if (list) -+ EGG_RECENT_ITEM_LIST_UNREF (list); -+} -+ -+static void -+egg_recent_model_multi_remove_expired_list (EggRecentModelMulti *model, GList *list) -+{ -+ time_t current_time; -+ time_t day_seconds; -+ -+ time (¤t_time); -+ day_seconds = model->priv->expire_days*24*60*60; -+ -+ while (list != NULL) { -+ EggRecentItem *item = list->data; -+ time_t timestamp; -+ -+ timestamp = egg_recent_item_get_timestamp (item); -+ -+ if ((timestamp+day_seconds) < current_time) { -+ gchar *uri = egg_recent_item_get_uri (item); -+ egg_recent_model_multi_delete (model, uri); -+ -+ g_strdup (uri); -+ } -+ -+ list = list->next; -+ } -+} -+ -+ -+/** -+ * egg_recent_model_multi_remove_expired: -+ * @model: A EggRecentModelMulti object. -+ * -+ * Goes through the entire list, and removes any items that are older than -+ * the user-specified expiration period. -+ * -+ * Returns: void -+ */ -+void -+egg_recent_model_multi_remove_expired (EggRecentModelMulti *model) -+{ -+ FILE *file; -+ GList *list=NULL; -+ -+ g_return_if_fail (model != NULL); -+ -+ file = egg_recent_model_multi_open_file (model, FALSE); -+ if (file == NULL) -+ return; -+ -+ if (egg_recent_model_multi_lock_file (file)) { -+ list = egg_recent_model_multi_read (model, file); -+ -+ } else { -+ g_warning ("Failed to lock: %s", strerror (errno)); -+ return; -+ } -+ -+ if (!egg_recent_model_multi_unlock_file (file)) -+ g_warning ("Failed to unlock: %s", strerror (errno)); -+ -+ if (list != NULL) { -+ egg_recent_model_multi_remove_expired_list (model, list); -+ EGG_RECENT_ITEM_LIST_UNREF (list); -+ } -+ -+ fclose (file); -+} -+ -+/** -+ * egg_recent_model_multi_get_type: -+ * -+ * This returns a GType representing a EggRecentModelMulti object. -+ * -+ * Returns: a GType -+ */ -+GType -+egg_recent_model_multi_get_type (void) -+{ -+ static GType egg_recent_model_multi_type = 0; -+ -+ if(!egg_recent_model_multi_type) { -+ static const GTypeInfo egg_recent_model_multi_info = { -+ sizeof (EggRecentModelMultiClass), -+ NULL, /* base init */ -+ NULL, /* base finalize */ -+ (GClassInitFunc)egg_recent_model_multi_class_init, /* class init */ -+ NULL, /* class finalize */ -+ NULL, /* class data */ -+ sizeof (EggRecentModelMulti), -+ 0, -+ (GInstanceInitFunc) egg_recent_model_multi_init -+ }; -+ -+ egg_recent_model_multi_type = g_type_register_static (G_TYPE_OBJECT, -+ "EggRecentModelMulti", -+ &egg_recent_model_multi_info, 0); -+ } -+ -+ return egg_recent_model_multi_type; -+} -+ -diff -urN ../gnome-desktop-2.12.2-pristine/libgnome-desktop/egg-recent-model-multi.h ./libgnome-desktop/egg-recent-model-multi.h ---- ../gnome-desktop-2.12.2-pristine/libgnome-desktop/egg-recent-model-multi.h 1969-12-31 19:00:00.000000000 -0500 -+++ ./libgnome-desktop/egg-recent-model-multi.h 2006-05-08 16:48:27.000000000 -0400 -@@ -0,0 +1,81 @@ -+/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -+#ifndef __EGG_RECENT_MODEL_MULTI_H__ -+#define __EGG_RECENT_MODEL_MULTI_H__ -+ -+#include "egg-recent-item.h" -+ -+G_BEGIN_DECLS -+ -+#define EGG_TYPE_RECENT_MODEL_MULTI (egg_recent_model_multi_get_type ()) -+#define EGG_RECENT_MODEL_MULTI(obj) G_TYPE_CHECK_INSTANCE_CAST (obj, EGG_TYPE_RECENT_MODEL_MULTI, EggRecentModelMulti) -+#define EGG_RECENT_MODEL_MULTI_CLASS(klass) G_TYPE_CHECK_CLASS_CAST (klass, EGG_TYPE_RECENT_MODEL_MULTI, EggRecentModelMultiClass) -+#define EGG_IS_RECENT_MODEL_MULTI(obj) G_TYPE_CHECK_INSTANCE_TYPE (obj, egg_recent_model_multi_get_type ()) -+ -+typedef struct _EggRecentModelMulti EggRecentModelMulti; -+typedef struct _EggRecentModelMultiPrivate EggRecentModelMultiPrivate; -+typedef struct _EggRecentModelMultiClass EggRecentModelMultiClass; -+ -+struct _EggRecentModelMulti { -+ GObject parent_instance; -+ -+ EggRecentModelMultiPrivate *priv; -+}; -+ -+struct _EggRecentModelMultiClass { -+ GObjectClass parent_class; -+ -+ void (*changed) (EggRecentModelMulti *model, GList *list); -+}; -+ -+typedef enum { -+ EGG_RECENT_MODEL_MULTI_SORT_MRU, -+ EGG_RECENT_MODEL_MULTI_SORT_LRU, -+ EGG_RECENT_MODEL_MULTI_SORT_NONE -+} EggRecentModelMultiSort; -+ -+ -+/* Standard group names */ -+#define EGG_RECENT_GROUP_LAUNCHERS "Launchers" -+ -+ -+GType egg_recent_model_multi_get_type (void); -+ -+/* constructors */ -+EggRecentModelMulti * egg_recent_model_multi_new (EggRecentModelMultiSort sort); -+EggRecentModelMulti * egg_recent_model_multi_new_with_file_path (EggRecentModelMultiSort sort, const gchar *file_path); -+ -+/* public methods */ -+void egg_recent_model_multi_set_filter_mime_types (EggRecentModelMulti *model, -+ ...); -+ -+void egg_recent_model_multi_set_filter_groups (EggRecentModelMulti *model, ...); -+ -+void egg_recent_model_multi_set_filter_uri_schemes (EggRecentModelMulti *model, -+ ...); -+ -+void egg_recent_model_multi_set_sort (EggRecentModelMulti *model, -+ EggRecentModelMultiSort sort); -+ -+gboolean egg_recent_model_multi_add_full (EggRecentModelMulti *model, -+ EggRecentItem *item); -+ -+gboolean egg_recent_model_multi_add (EggRecentModelMulti *model, -+ const gchar *uri); -+ -+gboolean egg_recent_model_multi_delete (EggRecentModelMulti *model, -+ const gchar *uri); -+ -+void egg_recent_model_multi_clear (EggRecentModelMulti *model); -+ -+GList * egg_recent_model_multi_get_list (EggRecentModelMulti *model); -+ -+void egg_recent_model_multi_changed (EggRecentModelMulti *model); -+ -+void egg_recent_model_multi_set_limit (EggRecentModelMulti *model, int limit); -+int egg_recent_model_multi_get_limit (EggRecentModelMulti *model); -+ -+void egg_recent_model_multi_remove_expired (EggRecentModelMulti *model); -+ -+G_END_DECLS -+ -+#endif /* __EGG_RECENT_MODEL_MULTI_H__ */ -diff -urN ../gnome-desktop-2.12.2-pristine/libgnome-desktop/gnome-desktop-item.c ./libgnome-desktop/gnome-desktop-item.c ---- ../gnome-desktop-2.12.2-pristine/libgnome-desktop/gnome-desktop-item.c 2005-11-04 03:43:42.000000000 -0500 -+++ ./libgnome-desktop/gnome-desktop-item.c 2006-05-08 17:07:23.000000000 -0400 -@@ -59,6 +59,9 @@ - #include - #endif - -+#include "egg-recent-item.h" -+#include "egg-recent-model-multi.h" -+ - #define sure_string(s) ((s)!=NULL?(s):"") - - struct _GnomeDesktopItem { -@@ -128,6 +131,8 @@ - const char *uri, - GError **error); - -+static void update_recently_used_apps (const GnomeDesktopItem *item); -+ - static int - readbuf_getc (ReadBuf *rb) - { -@@ -2091,6 +2096,8 @@ - (flags & GNOME_DESKTOP_ITEM_LAUNCH_APPEND_PATHS), - error); - -+ update_recently_used_apps (item); -+ - return ret; - } - -@@ -4095,3 +4102,22 @@ - - return q; - } -+ -+static void -+update_recently_used_apps (const GnomeDesktopItem *item) -+{ -+ EggRecentModelMulti *model; -+ -+ -+ if (! item) -+ return; -+ -+ model = egg_recent_model_multi_new_with_file_path (EGG_RECENT_MODEL_MULTI_SORT_MRU, ".recently-used-apps"); -+ -+ if (! model) -+ return; -+ -+ egg_recent_model_multi_add (model, gnome_desktop_item_get_location (item)); -+ -+ g_object_unref (G_OBJECT (model)); -+} -Files ../gnome-desktop-2.12.2-pristine/libgnome-desktop/.gnome-desktop-item.c.swp and ./libgnome-desktop/.gnome-desktop-item.c.swp differ -diff -urN ../gnome-desktop-2.12.2-pristine/libgnome-desktop/Makefile.am ./libgnome-desktop/Makefile.am ---- ../gnome-desktop-2.12.2-pristine/libgnome-desktop/Makefile.am 2004-11-18 12:42:53.000000000 -0500 -+++ ./libgnome-desktop/Makefile.am 2006-05-08 16:55:25.000000000 -0400 -@@ -16,9 +16,13 @@ - - noinst_PROGRAMS = test-ditem test-hint test-ditem-edit - --libgnome_desktop_2_la_SOURCES = \ -- gnome-desktop-item.c \ -- gnome-ditem-edit.c \ -+libgnome_desktop_2_la_SOURCES = \ -+ gnome-desktop-item.c \ -+ gnome-ditem-edit.c \ -+ egg-recent-item.h \ -+ egg-recent-item.c \ -+ egg-recent-model-multi.h \ -+ egg-recent-model-multi.c \ - gnome-hint.c \ - gnome-bg.c - -- 2.44.0