diff options
author | Matthias Clasen <mclasen@redhat.com> | 2007-07-20 10:39:03 +0000 |
---|---|---|
committer | Matthias Clasen <matthiasc@src.gnome.org> | 2007-07-20 10:39:03 +0000 |
commit | 13277b42e28a987c0e26f4e0ecb458b73d7f06ff (patch) | |
tree | 7eac6762224e958e7215c5754c33a453ba2d05e3 /gtk | |
parent | 5a58d1ab187546908a81c1525e9bc435021ce2f1 (diff) | |
download | gtk+-13277b42e28a987c0e26f4e0ecb458b73d7f06ff.tar.gz |
Apply a patch by Emmanuele Bassi to limit the number of shown recent
2007-07-20 Matthias Clasen <mclasen@redhat.com>
Apply a patch by Emmanuele Bassi to limit the number
of shown recent files. (#439715)
* gtk/gtksettings.c: Add a setting for the number
of recent files to display by default.
* gtk/gtkrecentchooserdefault.c:
* gtk/gtkfilechooserdefault.c: Respect the limit.
* gtk/gtkrecentmanager.c: Remove the poll timeout in
dispose, and do not stat more often than every 5 seconds.
* gtk/gtkrecentchooserutils.c:
* gtk/gtkrecentchoosermenu.c: Cleanups
* tests/testrecentchoosermenu.c: Test limits.
svn path=/trunk/; revision=18510
Diffstat (limited to 'gtk')
-rw-r--r-- | gtk/gtkfilechooserdefault.c | 61 | ||||
-rw-r--r-- | gtk/gtkrecentchooserdefault.c | 32 | ||||
-rw-r--r-- | gtk/gtkrecentchoosermenu.c | 3 | ||||
-rw-r--r-- | gtk/gtkrecentchooserutils.c | 15 | ||||
-rw-r--r-- | gtk/gtkrecentmanager.c | 39 | ||||
-rw-r--r-- | gtk/gtksettings.c | 22 |
6 files changed, 144 insertions, 28 deletions
diff --git a/gtk/gtkfilechooserdefault.c b/gtk/gtkfilechooserdefault.c index 372f6c9bda..f27e4bf84f 100644 --- a/gtk/gtkfilechooserdefault.c +++ b/gtk/gtkfilechooserdefault.c @@ -9765,6 +9765,7 @@ typedef struct GList *items; gint n_items; gint n_loaded_items; + guint needs_sorting : 1; } RecentLoadData; static void @@ -9848,6 +9849,32 @@ out: g_object_unref (handle); } +static gint +recent_sort_mru (gconstpointer a, + gconstpointer b) +{ + GtkRecentInfo *info_a = (GtkRecentInfo *) a; + GtkRecentInfo *info_b = (GtkRecentInfo *) b; + + return (gtk_recent_info_get_modified (info_a) < gtk_recent_info_get_modified (info_b)); +} + +static gint +get_recent_files_limit (GtkWidget *widget) +{ + GtkSettings *settings; + gint limit; + + if (gtk_widget_has_screen (widget)) + settings = gtk_settings_get_for_screen (gtk_widget_get_screen (widget)); + else + settings = gtk_settings_get_default (); + + g_object_get (G_OBJECT (settings), "gtk-recent-files-limit", &limit, NULL); + + return limit; +} + static gboolean recent_idle_load (gpointer data) { @@ -9864,14 +9891,47 @@ recent_idle_load (gpointer data) if (!impl->recent_manager) return FALSE; + /* first iteration: load all the items */ if (!load_data->items) { load_data->items = gtk_recent_manager_get_items (impl->recent_manager); if (!load_data->items) return FALSE; + load_data->needs_sorting = TRUE; + + return TRUE; + } + + /* second iteration: preliminary MRU sorting and clamping */ + if (load_data->needs_sorting) + { + gint limit; + + load_data->items = g_list_sort (load_data->items, recent_sort_mru); load_data->n_items = g_list_length (load_data->items); + + limit = get_recent_files_limit (GTK_WIDGET (impl)); + + if (limit != -1 && (load_data->n_items > limit)) + { + GList *clamp, *l; + + clamp = g_list_nth (load_data->items, limit - 1); + if (G_LIKELY (clamp)) + { + l = clamp->next; + clamp->next = NULL; + + g_list_foreach (l, (GFunc) gtk_recent_info_unref, NULL); + g_list_free (l); + + load_data->n_items = limit; + } + } + load_data->n_loaded_items = 0; + load_data->needs_sorting = FALSE; return TRUE; } @@ -9943,6 +10003,7 @@ recent_start_loading (GtkFileChooserDefault *impl) load_data->items = NULL; load_data->n_items = 0; load_data->n_loaded_items = 0; + load_data->needs_sorting = TRUE; /* begin lazy loading the recent files into the model */ impl->load_recent_id = gdk_threads_add_idle_full (G_PRIORITY_HIGH_IDLE + 30, diff --git a/gtk/gtkrecentchooserdefault.c b/gtk/gtkrecentchooserdefault.c index 60d5566856..d4350d8621 100644 --- a/gtk/gtkrecentchooserdefault.c +++ b/gtk/gtkrecentchooserdefault.c @@ -99,6 +99,8 @@ struct _GtkRecentChooserDefault guint show_tips : 1; guint show_icons : 1; guint local_only : 1; + + guint limit_set : 1; GSList *filters; GtkRecentFilter *current_filter; @@ -223,6 +225,7 @@ static void set_current_filter (GtkRecentChooserDefault *impl, static GtkIconTheme *get_icon_theme_for_widget (GtkWidget *widget); static gint get_icon_size_for_widget (GtkWidget *widget, GtkIconSize icon_size); +static gint get_recent_files_limit (GtkWidget *widget); static void reload_recent_items (GtkRecentChooserDefault *impl); static void chooser_set_model (GtkRecentChooserDefault *impl); @@ -373,6 +376,8 @@ gtk_recent_chooser_default_constructor (GType type, g_assert (impl->manager); gtk_widget_push_composite_child (); + + impl->limit = get_recent_files_limit (GTK_WIDGET (impl)); scrollw = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrollw), @@ -525,6 +530,7 @@ gtk_recent_chooser_default_set_property (GObject *object, break; case GTK_RECENT_CHOOSER_PROP_LIMIT: impl->limit = g_value_get_int (value); + impl->limit_set = TRUE; reload_recent_items (impl); break; case GTK_RECENT_CHOOSER_PROP_SORT_TYPE: @@ -864,19 +870,26 @@ cleanup_after_load (gpointer user_data) static void reload_recent_items (GtkRecentChooserDefault *impl) { + GtkWidget *widget; + /* reload is already in progress - do not disturb */ if (impl->load_id) return; + widget = GTK_WIDGET (impl); + gtk_tree_view_set_model (GTK_TREE_VIEW (impl->recent_view), NULL); gtk_list_store_clear (impl->recent_store); if (!impl->icon_theme) - impl->icon_theme = get_icon_theme_for_widget (GTK_WIDGET (impl)); + impl->icon_theme = get_icon_theme_for_widget (widget); - impl->icon_size = get_icon_size_for_widget (GTK_WIDGET (impl), + impl->icon_size = get_icon_size_for_widget (widget, GTK_ICON_SIZE_BUTTON); + if (!impl->limit_set) + impl->limit = get_recent_files_limit (widget); + set_busy_cursor (impl, TRUE); impl->load_state = LOAD_EMPTY; @@ -1402,6 +1415,21 @@ get_icon_size_for_widget (GtkWidget *widget, return FALLBACK_ICON_SIZE; } +static gint +get_recent_files_limit (GtkWidget *widget) +{ + GtkSettings *settings; + gint limit; + + if (gtk_widget_has_screen (widget)) + settings = gtk_settings_get_for_screen (gtk_widget_get_screen (widget)); + else + settings = gtk_settings_get_default (); + + g_object_get (G_OBJECT (settings), "gtk-recent-files-limit", &limit, NULL); + + return limit; +} static void recent_manager_changed_cb (GtkRecentManager *manager, diff --git a/gtk/gtkrecentchoosermenu.c b/gtk/gtkrecentchoosermenu.c index b7c479d5f6..fb2ab4f1e1 100644 --- a/gtk/gtkrecentchoosermenu.c +++ b/gtk/gtkrecentchoosermenu.c @@ -234,11 +234,8 @@ gtk_recent_chooser_menu_init (GtkRecentChooserMenu *menu) priv->local_only = TRUE; priv->limit = FALLBACK_ITEM_LIMIT; - priv->sort_type = GTK_RECENT_SORT_NONE; - priv->icon_size = FALLBACK_ICON_SIZE; - priv->label_width = DEFAULT_LABEL_WIDTH; priv->first_recent_item_pos = -1; diff --git a/gtk/gtkrecentchooserutils.c b/gtk/gtkrecentchooserutils.c index 102e2fdfd6..06665ede50 100644 --- a/gtk/gtkrecentchooserutils.c +++ b/gtk/gtkrecentchooserutils.c @@ -332,9 +332,7 @@ sort_recent_items_proxy (gpointer *a, SortRecentData *sort_recent = user_data; if (sort_recent->func) - return (* sort_recent->func) (info_a, - info_b, - sort_recent->data); + return (* sort_recent->func) (info_a, info_b, sort_recent->data); /* fallback */ return 0; @@ -508,15 +506,12 @@ _gtk_recent_chooser_get_items (GtkRecentChooser *chooser, if (compare_func) { - SortRecentData *sort_recent; + SortRecentData sort_recent; - sort_recent = g_slice_new (SortRecentData); - sort_recent->func = sort_func; - sort_recent->data = sort_data; + sort_recent.func = sort_func; + sort_recent.data = sort_data; - items = g_list_sort_with_data (items, compare_func, sort_recent); - - g_slice_free (SortRecentData, sort_recent); + items = g_list_sort_with_data (items, compare_func, &sort_recent); } length = g_list_length (items); diff --git a/gtk/gtkrecentmanager.c b/gtk/gtkrecentmanager.c index e9bfa2d469..de5b396639 100644 --- a/gtk/gtkrecentmanager.c +++ b/gtk/gtkrecentmanager.c @@ -125,6 +125,7 @@ enum PROP_SIZE }; +static void gtk_recent_manager_dispose (GObject *object); static void gtk_recent_manager_finalize (GObject *object); static void gtk_recent_manager_set_property (GObject *object, @@ -232,6 +233,7 @@ gtk_recent_manager_class_init (GtkRecentManagerClass *klass) gobject_class->set_property = gtk_recent_manager_set_property; gobject_class->get_property = gtk_recent_manager_get_property; + gobject_class->dispose = gtk_recent_manager_dispose; gobject_class->finalize = gtk_recent_manager_finalize; /** @@ -388,21 +390,31 @@ gtk_recent_manager_get_property (GObject *object, } static void -gtk_recent_manager_finalize (GObject *object) +gtk_recent_manager_dispose (GObject *object) { GtkRecentManager *manager = GTK_RECENT_MANAGER (object); GtkRecentManagerPrivate *priv = manager->priv; - /* remove the poll timeout */ if (priv->poll_timeout) - g_source_remove (priv->poll_timeout); - + { + g_source_remove (priv->poll_timeout); + priv->poll_timeout = 0; + } + + G_OBJECT_CLASS (gtk_recent_manager_parent_class)->dispose (object); +} + +static void +gtk_recent_manager_finalize (GObject *object) +{ + GtkRecentManager *manager = GTK_RECENT_MANAGER (object); + GtkRecentManagerPrivate *priv = manager->priv; + g_free (priv->filename); if (priv->recent_items) g_bookmark_file_free (priv->recent_items); - /* chain up parent's finalize method */ G_OBJECT_CLASS (gtk_recent_manager_parent_class)->finalize (object); } @@ -435,10 +447,7 @@ gtk_recent_manager_real_changed (GtkRecentManager *manager) } write_error = NULL; - g_bookmark_file_to_file (priv->recent_items, - priv->filename, - &write_error); - + g_bookmark_file_to_file (priv->recent_items, priv->filename, &write_error); if (write_error) { filename_warning ("Attempting to store changes into `%s', " @@ -491,6 +500,7 @@ gtk_recent_manager_poll_timeout (gpointer data) { GtkRecentManager *manager = GTK_RECENT_MANAGER (data); GtkRecentManagerPrivate *priv = manager->priv; + time_t now; struct stat stat_buf; int stat_res; @@ -498,6 +508,11 @@ gtk_recent_manager_poll_timeout (gpointer data) if (priv->write_in_progress || priv->read_in_progress) return TRUE; + /* do not stat the file if we're within 5 seconds from the last stat() */ + now = time (NULL); + if (now < priv->last_mtime + 5); + return TRUE; + stat_res = g_stat (priv->filename, &stat_buf); if (stat_res < 0) { @@ -513,7 +528,7 @@ gtk_recent_manager_poll_timeout (gpointer data) return TRUE; } - /* the file didn't change from the last poll(), so we bail out */ + /* the file didn't change from the last poll, so we bail out */ if (stat_buf.st_mtime == priv->last_mtime) return TRUE; @@ -796,11 +811,11 @@ gtk_recent_manager_get_limit (GtkRecentManager *manager) * Adds a new resource, pointed by @uri, into the recently used * resources list. * - * This function automatically retrieving some of the needed + * This function automatically retrieves some of the needed * metadata and setting other metadata to common default values; it * then feeds the data to gtk_recent_manager_add_full(). * - * See gtk_recent_manager_add_full() if you want to explicitely + * See gtk_recent_manager_add_full() if you want to explicitly * define the metadata for the resource pointed by @uri. * * Return value: %TRUE if the new item was successfully added diff --git a/gtk/gtksettings.c b/gtk/gtksettings.c index 4488389e59..cc1b6ac1fb 100644 --- a/gtk/gtksettings.c +++ b/gtk/gtksettings.c @@ -105,7 +105,8 @@ enum { PROP_PRINT_BACKENDS, PROP_PRINT_PREVIEW_COMMAND, PROP_ENABLE_MNEMONICS, - PROP_ENABLE_ACCELS + PROP_ENABLE_ACCELS, + PROP_RECENT_FILES_LIMIT }; @@ -785,6 +786,25 @@ gtk_settings_class_init (GtkSettingsClass *class) GTK_PARAM_READWRITE), NULL); g_assert (result == PROP_ENABLE_ACCELS); + + /** + * GtkSettings:gtk-recent-files-limit: + * + * The number of recently used files that should be displayed by default by + * #GtkRecentChooser implementations and by the #GtkFileChooser. A value of + * -1 means every recently used file stored. + * + * Since: 2.12 + */ + result = settings_install_property_parser (class, + g_param_spec_int ("gtk-recent-files-limit", + P_("Recent Files Limit"), + P_("Number of recently used files"), + -1, G_MAXINT, + 50, + GTK_PARAM_READWRITE), + NULL); + g_assert (result == PROP_RECENT_FILES_LIMIT); } static void |