Commit 13277b42 authored by Matthias Clasen's avatar Matthias Clasen Committed by Matthias Clasen

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
parent 5a58d1ab
......@@ -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,
......
......@@ -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,
......
......@@ -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;
......
......@@ -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);
......
......@@ -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
......
......@@ -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
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment