diff --git a/ChangeLog b/ChangeLog index c9b6234000..5f5fadd175 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2008-04-15 Emmanuele Bassi + + Bug 488507 – boundless growth of .recently-used.xbel file + slows down applications + + * gtk/gtkrecentmanager.c: + (gtk_recent_manager_init), + (gtk_recent_manager_real_changed), + (gtk_recent_manager_set_filename), + (gtk_recent_manager_clamp_to_age): Clamp the recently + used resources list by the age of its items, using + the newly added GtkSettings property. + + * gtk/gtksettings.c (gtk_settings_class_init): Add the + gtk-recent-files-max-age property, controlling the + maximum age of the items in the recently used resources + list. + 2008-04-15 Emmanuele Bassi * gtk/gtkrecentmanager.c: diff --git a/gtk/gtkrecentmanager.c b/gtk/gtkrecentmanager.c index 1cbd9bd342..b6ec94b009 100644 --- a/gtk/gtkrecentmanager.c +++ b/gtk/gtkrecentmanager.c @@ -137,6 +137,9 @@ static void gtk_recent_manager_changed (GtkRecentManager *manag static void gtk_recent_manager_real_changed (GtkRecentManager *manager); static void gtk_recent_manager_set_filename (GtkRecentManager *manager, const gchar *filename); +static void gtk_recent_manager_clamp_to_age (GtkRecentManager *manager, + gint age); + static void build_recent_items_list (GtkRecentManager *manager); static void purge_recent_items_list (GtkRecentManager *manager, @@ -278,19 +281,13 @@ static void gtk_recent_manager_init (GtkRecentManager *manager) { GtkRecentManagerPrivate *priv; - gchar *filename; manager->priv = priv = GTK_RECENT_MANAGER_GET_PRIVATE (manager); priv->limit = DEFAULT_LIMIT; priv->size = 0; - /* this will take care of building the files list */ - filename = g_build_filename (g_get_home_dir (), - GTK_RECENTLY_USED_FILE, - NULL); - gtk_recent_manager_set_filename (manager, filename); - g_free (filename); + priv->filename = NULL; } static void @@ -388,14 +385,23 @@ gtk_recent_manager_real_changed (GtkRecentManager *manager) */ g_assert (priv->filename != NULL); - /* if no container object has been defined, we create a new - * empty container, and dump it - */ if (!priv->recent_items) { + /* if no container object has been defined, we create a new + * empty container, and dump it + */ priv->recent_items = g_bookmark_file_new (); priv->size = 0; } + else + { + GtkSettings *settings = gtk_settings_get_default (); + gint age = 30; + + g_object_get (G_OBJECT (settings), "gtk-recent-files-max-age", &age, NULL); + if (age > 0) + gtk_recent_manager_clamp_to_age (manager, age); + } write_error = NULL; g_bookmark_file_to_file (priv->recent_items, priv->filename, &write_error); @@ -458,22 +464,43 @@ gtk_recent_manager_set_filename (GtkRecentManager *manager, g_assert (GTK_IS_RECENT_MANAGER (manager)); priv = manager->priv; - - g_free (priv->filename); - if (priv->monitor) + /* if a filename is already set and filename is not NULL, then copy + * it and reset the monitor; otherwise, if it's NULL we're being + * called from the finalization sequence, so we simply disconnect the + * monitoring and return. + * + * if no filename is set and filename is NULL, use the default. + */ + if (priv->filename) { - g_signal_handlers_disconnect_by_func (priv->monitor, - G_CALLBACK (gtk_recent_manager_monitor_changed), - manager); - g_object_unref (priv->monitor); - priv->monitor = NULL; + g_free (priv->filename); + + if (priv->monitor) + { + g_signal_handlers_disconnect_by_func (priv->monitor, + G_CALLBACK (gtk_recent_manager_monitor_changed), + manager); + g_object_unref (priv->monitor); + priv->monitor = NULL; + } + + if (!filename || *filename == '\0') + return; + else + priv->filename = g_strdup (filename); + } + else + { + if (!filename || *filename == '\0') + priv->filename = g_build_filename (g_get_user_data_dir (), + GTK_RECENTLY_USED_FILE, + NULL); + else + priv->filename = g_strdup (filename); } - if (!filename || filename[0] == '\0') - return; - - priv->filename = g_strdup (filename); + g_assert (priv->filename != NULL); file = g_file_new_for_path (priv->filename); error = NULL; @@ -1312,6 +1339,34 @@ gtk_recent_manager_changed (GtkRecentManager *recent_manager) g_signal_emit (recent_manager, signal_changed, 0); } +static void +gtk_recent_manager_clamp_to_age (GtkRecentManager *manager, + gint age) +{ + GtkRecentManagerPrivate *priv = manager->priv; + gchar **uris; + gsize n_uris, i; + time_t now; + + if (G_UNLIKELY (!priv->recent_items)) + return; + + now = time (NULL); + + uris = g_bookmark_file_get_uris (priv->recent_items, &n_uris); + for (i = 0; i < n_uris; i++) + { + const gchar *uri = uris[i]; + time_t modified; + gint item_age; + + modified = g_bookmark_file_get_modified (priv->recent_items, uri, NULL); + item_age = (gint) ((now - modified) / (60 * 60 * 24)); + if (item_age > age) + g_bookmark_file_remove_item (priv->recent_items, uri, NULL); + } +} + /***************** * GtkRecentInfo * *****************/ diff --git a/gtk/gtksettings.c b/gtk/gtksettings.c index 3081e8711a..a19ad33099 100644 --- a/gtk/gtksettings.c +++ b/gtk/gtksettings.c @@ -107,7 +107,8 @@ enum { PROP_ENABLE_MNEMONICS, PROP_ENABLE_ACCELS, PROP_RECENT_FILES_LIMIT, - PROP_IM_MODULE + PROP_IM_MODULE, + PROP_RECENT_FILES_MAX_AGE }; @@ -820,6 +821,26 @@ gtk_settings_class_init (GtkSettingsClass *class) GTK_PARAM_READWRITE), NULL); g_assert (result == PROP_IM_MODULE); + + /** + * GtkSettings:gtk-recent-files-max-age: + * + * The maximum age, in days, of the items inside the recently used + * resources list. Items older than this setting will be excised + * from the list. If set to 0, the list will always be empty; if + * set to -1, no item will be removed. + * + * Since: 2.14 + */ + result = settings_install_property_parser (class, + g_param_spec_int ("gtk-recent-files-max-age", + P_("Recent Files Max Age"), + P_("Maximum age of recently used files, in days"), + -1, G_MAXINT, + 30, + GTK_PARAM_READWRITE), + NULL); + g_assert (result == PROP_RECENT_FILES_MAX_AGE); } static void