summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2007-07-20 10:39:03 +0000
committerMatthias Clasen <matthiasc@src.gnome.org>2007-07-20 10:39:03 +0000
commit13277b42e28a987c0e26f4e0ecb458b73d7f06ff (patch)
tree7eac6762224e958e7215c5754c33a453ba2d05e3
parent5a58d1ab187546908a81c1525e9bc435021ce2f1 (diff)
downloadgtk+-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
-rw-r--r--gtk/gtkfilechooserdefault.c61
-rw-r--r--gtk/gtkrecentchooserdefault.c32
-rw-r--r--gtk/gtkrecentchoosermenu.c3
-rw-r--r--gtk/gtkrecentchooserutils.c15
-rw-r--r--gtk/gtkrecentmanager.c39
-rw-r--r--gtk/gtksettings.c22
-rw-r--r--tests/testrecentchoosermenu.c9
7 files changed, 149 insertions, 32 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
diff --git a/tests/testrecentchoosermenu.c b/tests/testrecentchoosermenu.c
index 3c760d0068..d1110ee1a1 100644
--- a/tests/testrecentchoosermenu.c
+++ b/tests/testrecentchoosermenu.c
@@ -53,7 +53,7 @@ item_activated_cb (GtkRecentChooser *chooser,
}
static GtkWidget *
-create_recent_chooser_menu (void)
+create_recent_chooser_menu (gint limit)
{
GtkWidget *menu;
GtkRecentFilter *filter;
@@ -61,7 +61,8 @@ create_recent_chooser_menu (void)
menu = gtk_recent_chooser_menu_new_for_manager (manager);
- gtk_recent_chooser_set_limit (GTK_RECENT_CHOOSER (menu), 4);
+ if (limit > 0)
+ gtk_recent_chooser_set_limit (GTK_RECENT_CHOOSER (menu), limit);
gtk_recent_chooser_set_local_only (GTK_RECENT_CHOOSER (menu), TRUE);
gtk_recent_chooser_set_show_icons (GTK_RECENT_CHOOSER (menu), TRUE);
gtk_recent_chooser_set_sort_type (GTK_RECENT_CHOOSER (menu),
@@ -122,7 +123,7 @@ create_file_menu (GtkAccelGroup *accelgroup)
gtk_widget_show (menuitem);
menuitem = gtk_menu_item_new_with_mnemonic ("_Open Recent");
- recentmenu = create_recent_chooser_menu ();
+ recentmenu = create_recent_chooser_menu (-1);
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), recentmenu);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
gtk_widget_show (menuitem);
@@ -176,7 +177,7 @@ main (int argc, char *argv[])
gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
gtk_widget_show (menuitem);
- menu = create_recent_chooser_menu ();
+ menu = create_recent_chooser_menu (4);
menuitem = gtk_menu_item_new_with_mnemonic ("_Recently Used");
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);