Move filtering of the recent files list into the shared implementation; do

2007-03-15  Emmanuele Bassi  <ebassi@gnome.org>

	* gtk/gtkrecentchooserprivate.h:
	* gtk/gtkrecentchooserutils.c: Move filtering of the recent
	files list into the shared implementation; do the filtering
	before the sorting, so that we always clamp on the desired
	size. (#418219)

	* gtk/gtkrecentchoosermenu.c: Remove the filtering of the
	list, as it's already been done.

	* gtk/gtkrecentchooserdefault.c: Ditto; also remove the
	GtkTreeModelFilter: just reload the view if the sorting and
	filtering properties change.

	* gtk/testrecentchoosermenu.c: Exercise the limit property.

svn path=/trunk/; revision=17516
This commit is contained in:
Emmanuele Bassi 2007-03-15 10:05:34 +00:00 committed by Emmanuele Bassi
parent d953ce8775
commit 4191ec6a02
6 changed files with 150 additions and 240 deletions

View File

@ -1,3 +1,20 @@
2007-03-15 Emmanuele Bassi <ebassi@gnome.org>
* gtk/gtkrecentchooserprivate.h:
* gtk/gtkrecentchooserutils.c: Move filtering of the recent
files list into the shared implementation; do the filtering
before the sorting, so that we always clamp on the desired
size. (#418219)
* gtk/gtkrecentchoosermenu.c: Remove the filtering of the
list, as it's already been done.
* gtk/gtkrecentchooserdefault.c: Ditto; also remove the
GtkTreeModelFilter: just reload the view if the sorting and
filtering properties change.
* gtk/testrecentchoosermenu.c: Exercise the limit property.
2007-03-14 Michael Natterer <mitch@imendio.com>
Make gtk_widget_set_extension_events() work on already realized

View File

@ -115,7 +115,6 @@ struct _GtkRecentChooserDefault
GtkWidget *recent_view;
GtkListStore *recent_store;
GtkTreeModel *recent_store_filter;
GtkTreeViewColumn *icon_column;
GtkTreeViewColumn *meta_column;
GtkCellRenderer *meta_renderer;
@ -234,10 +233,6 @@ static void set_recent_manager (GtkRecentChooserDefault *impl,
static void chooser_set_sort_type (GtkRecentChooserDefault *impl,
GtkRecentSortType sort_type);
static gboolean recent_store_filter_func (GtkTreeModel *model,
GtkTreeIter *iter,
gpointer user_data);
static void recent_manager_changed_cb (GtkRecentManager *manager,
gpointer user_data);
static void recent_icon_data_func (GtkTreeViewColumn *tree_column,
@ -491,10 +486,6 @@ gtk_recent_chooser_default_set_property (GObject *object,
break;
case GTK_RECENT_CHOOSER_PROP_SHOW_PRIVATE:
impl->show_private = g_value_get_boolean (value);
if (impl->recent_store && impl->recent_store_filter)
gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (impl->recent_store_filter));
if (impl->recent_popup_menu_show_private_item)
{
GtkCheckMenuItem *item = GTK_CHECK_MENU_ITEM (impl->recent_popup_menu_show_private_item);
@ -502,12 +493,11 @@ gtk_recent_chooser_default_set_property (GObject *object,
gtk_check_menu_item_set_active (item, impl->show_private);
g_signal_handlers_unblock_by_func (item, G_CALLBACK (show_private_toggled_cb), impl);
}
reload_recent_items (impl);
break;
case GTK_RECENT_CHOOSER_PROP_SHOW_NOT_FOUND:
impl->show_not_found = g_value_get_boolean (value);
if (impl->recent_store && impl->recent_store_filter)
gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (impl->recent_store_filter));
reload_recent_items (impl);
break;
case GTK_RECENT_CHOOSER_PROP_SHOW_TIPS:
impl->show_tips = g_value_get_boolean (value);
@ -531,9 +521,11 @@ gtk_recent_chooser_default_set_property (GObject *object,
break;
case GTK_RECENT_CHOOSER_PROP_LOCAL_ONLY:
impl->local_only = g_value_get_boolean (value);
reload_recent_items (impl);
break;
case GTK_RECENT_CHOOSER_PROP_LIMIT:
impl->limit = g_value_get_int (value);
reload_recent_items (impl);
break;
case GTK_RECENT_CHOOSER_PROP_SORT_TYPE:
chooser_set_sort_type (impl, g_value_get_enum (value));
@ -627,12 +619,6 @@ gtk_recent_chooser_default_dispose (GObject *object)
impl->current_filter = NULL;
}
if (impl->recent_store_filter)
{
g_object_unref (impl->recent_store_filter);
impl->recent_store_filter = NULL;
}
if (impl->recent_store)
{
g_object_unref (impl->recent_store);
@ -753,17 +739,10 @@ static void
chooser_set_model (GtkRecentChooserDefault *impl)
{
g_assert (impl->recent_store != NULL);
g_assert (impl->recent_store_filter == NULL);
g_assert (impl->load_state == LOAD_LOADING);
impl->recent_store_filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (impl->recent_store), NULL);
gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (impl->recent_store_filter),
recent_store_filter_func,
impl,
NULL);
gtk_tree_view_set_model (GTK_TREE_VIEW (impl->recent_view),
impl->recent_store_filter);
GTK_TREE_MODEL (impl->recent_store));
gtk_tree_view_columns_autosize (GTK_TREE_VIEW (impl->recent_view));
gtk_tree_view_set_enable_search (GTK_TREE_VIEW (impl->recent_view), TRUE);
gtk_tree_view_set_search_column (GTK_TREE_VIEW (impl->recent_view),
@ -836,13 +815,7 @@ load_recent_items (gpointer user_data)
impl->recent_items = NULL;
impl->n_recent_items = 0;
impl->loaded_items = 0;
if (impl->recent_store_filter)
{
g_object_unref (impl->recent_store_filter);
impl->recent_store_filter = NULL;
}
/* load the filled up model */
chooser_set_model (impl);
@ -1258,6 +1231,7 @@ gtk_recent_chooser_default_get_items (GtkRecentChooser *chooser)
impl = GTK_RECENT_CHOOSER_DEFAULT (chooser);
return _gtk_recent_chooser_get_items (chooser,
impl->current_filter,
impl->sort_func,
impl->sort_data);
}
@ -1354,103 +1328,6 @@ gtk_recent_chooser_default_list_filters (GtkRecentChooser *chooser)
return g_slist_copy (impl->filters);
}
static gboolean
get_is_recent_filtered (GtkRecentChooserDefault *impl,
GtkRecentInfo *info)
{
GtkRecentFilter *current_filter;
GtkRecentFilterInfo filter_info;
GtkRecentFilterFlags needed;
gboolean retval;
g_assert (info != NULL);
if (!impl->current_filter)
return FALSE;
current_filter = impl->current_filter;
needed = gtk_recent_filter_get_needed (current_filter);
filter_info.contains = GTK_RECENT_FILTER_URI | GTK_RECENT_FILTER_MIME_TYPE;
filter_info.uri = gtk_recent_info_get_uri (info);
filter_info.mime_type = gtk_recent_info_get_mime_type (info);
if (needed & GTK_RECENT_FILTER_DISPLAY_NAME)
{
filter_info.display_name = gtk_recent_info_get_display_name (info);
filter_info.contains |= GTK_RECENT_FILTER_DISPLAY_NAME;
}
else
filter_info.uri = NULL;
if (needed & GTK_RECENT_FILTER_APPLICATION)
{
filter_info.applications = (const gchar **) gtk_recent_info_get_applications (info, NULL);
filter_info.contains |= GTK_RECENT_FILTER_APPLICATION;
}
else
filter_info.applications = NULL;
if (needed & GTK_RECENT_FILTER_GROUP)
{
filter_info.groups = (const gchar **) gtk_recent_info_get_groups (info, NULL);
filter_info.contains |= GTK_RECENT_FILTER_GROUP;
}
else
filter_info.groups = NULL;
if (needed & GTK_RECENT_FILTER_AGE)
{
filter_info.age = gtk_recent_info_get_age (info);
filter_info.contains |= GTK_RECENT_FILTER_AGE;
}
else
filter_info.age = -1;
retval = gtk_recent_filter_filter (current_filter, &filter_info);
/* this we own */
if (filter_info.applications)
g_strfreev ((gchar **) filter_info.applications);
if (filter_info.groups)
g_strfreev ((gchar **) filter_info.groups);
return !retval;
}
static gboolean
recent_store_filter_func (GtkTreeModel *model,
GtkTreeIter *iter,
gpointer user_data)
{
GtkRecentChooserDefault *impl = GTK_RECENT_CHOOSER_DEFAULT (user_data);
GtkRecentInfo *info = NULL;
if (!impl->current_filter)
return TRUE;
gtk_tree_model_get (model, iter,
RECENT_INFO_COLUMN, &info,
-1);
if (!info)
return TRUE;
if (get_is_recent_filtered (impl, info))
return FALSE;
if (impl->local_only && !gtk_recent_info_is_local (info))
return FALSE;
if ((!impl->show_private) && gtk_recent_info_get_private_hint (info))
return FALSE;
if ((!impl->show_not_found) && !gtk_recent_info_exists (info))
return FALSE;
return TRUE;
}
static void
set_current_filter (GtkRecentChooserDefault *impl,
GtkRecentFilter *filter)
@ -1477,11 +1354,9 @@ set_current_filter (GtkRecentChooserDefault *impl,
gtk_combo_box_set_active (GTK_COMBO_BOX (impl->filter_combo),
filter_idx);
if (impl->recent_store && impl->recent_store_filter)
{
gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (impl->recent_store_filter));
}
if (impl->recent_store)
reload_recent_items (impl);
g_object_notify (G_OBJECT (impl), "filter");
}
}
@ -1490,12 +1365,13 @@ static void
chooser_set_sort_type (GtkRecentChooserDefault *impl,
GtkRecentSortType sort_type)
{
if (impl->sort_type == sort_type)
return;
if (impl->sort_type != sort_type)
{
impl->sort_type = sort_type;
reload_recent_items (impl);
impl->sort_type = sort_type;
reload_recent_items (impl);
g_object_notify (G_OBJECT (impl), "sort-type");
}
}

View File

@ -625,6 +625,7 @@ gtk_recent_chooser_menu_get_items (GtkRecentChooser *chooser)
GtkRecentChooserMenuPrivate *priv = menu->priv;
return _gtk_recent_chooser_get_items (chooser,
priv->current_filter,
priv->sort_func,
priv->sort_data);
}
@ -697,78 +698,12 @@ gtk_recent_chooser_menu_set_current_filter (GtkRecentChooserMenu *menu,
priv->current_filter = filter;
g_object_ref_sink (priv->current_filter);
}
gtk_recent_chooser_menu_populate (menu);
g_object_notify (G_OBJECT (menu), "filter");
}
static gboolean
get_is_recent_filtered (GtkRecentChooserMenu *menu,
GtkRecentInfo *info)
{
GtkRecentChooserMenuPrivate *priv;
GtkRecentFilter *current_filter;
GtkRecentFilterInfo filter_info;
GtkRecentFilterFlags needed;
gboolean retval;
g_assert (info != NULL);
priv = menu->priv;
if (!priv->current_filter)
return FALSE;
current_filter = priv->current_filter;
needed = gtk_recent_filter_get_needed (current_filter);
filter_info.contains = GTK_RECENT_FILTER_URI | GTK_RECENT_FILTER_MIME_TYPE;
filter_info.uri = gtk_recent_info_get_uri (info);
filter_info.mime_type = gtk_recent_info_get_mime_type (info);
if (needed & GTK_RECENT_FILTER_DISPLAY_NAME)
{
filter_info.display_name = gtk_recent_info_get_display_name (info);
filter_info.contains |= GTK_RECENT_FILTER_DISPLAY_NAME;
}
else
filter_info.uri = NULL;
if (needed & GTK_RECENT_FILTER_APPLICATION)
{
filter_info.applications = (const gchar **) gtk_recent_info_get_applications (info, NULL);
filter_info.contains |= GTK_RECENT_FILTER_APPLICATION;
}
else
filter_info.applications = NULL;
if (needed & GTK_RECENT_FILTER_GROUP)
{
filter_info.groups = (const gchar **) gtk_recent_info_get_groups (info, NULL);
filter_info.contains |= GTK_RECENT_FILTER_GROUP;
}
else
filter_info.groups = NULL;
if (needed & GTK_RECENT_FILTER_AGE)
{
filter_info.age = gtk_recent_info_get_age (info);
filter_info.contains |= GTK_RECENT_FILTER_AGE;
}
else
filter_info.age = -1;
retval = gtk_recent_filter_filter (current_filter, &filter_info);
/* this we own */
if (filter_info.applications)
g_strfreev ((gchar **) filter_info.applications);
if (filter_info.groups)
g_strfreev ((gchar **) filter_info.groups);
return !retval;
}
/* taken from libeel/eel-strings.c */
static gchar *
escape_underscores (const gchar *string)
@ -1021,33 +956,6 @@ idle_populate_func (gpointer data)
}
info = g_list_nth_data (pdata->items, pdata->loaded_items);
/* skip non-local items on request */
if (priv->local_only &&
!gtk_recent_info_is_local (info))
{
goto check_and_return;
}
/* skip private items on request */
if (!priv->show_private &&
gtk_recent_info_get_private_hint (info))
{
goto check_and_return;
}
/* skip non-existing items on request */
if (!priv->show_not_found &&
!gtk_recent_info_exists (info))
{
goto check_and_return;
}
/* filter items based on the currently set filter object */
if (get_is_recent_filtered (pdata->menu, info))
{
goto check_and_return;
}
item = gtk_recent_chooser_menu_create_item (pdata->menu,
info,
pdata->displayed_items);

View File

@ -32,6 +32,7 @@ G_BEGIN_DECLS
GtkRecentManager *_gtk_recent_chooser_get_recent_manager (GtkRecentChooser *chooser);
GList * _gtk_recent_chooser_get_items (GtkRecentChooser *chooser,
GtkRecentFilter *filter,
GtkRecentSortFunc func,
gpointer data);

View File

@ -340,21 +340,84 @@ sort_recent_items_proxy (gpointer *a,
return 0;
}
static gboolean
get_is_recent_filtered (GtkRecentFilter *filter,
GtkRecentInfo *info)
{
GtkRecentFilterInfo filter_info;
GtkRecentFilterFlags needed;
gboolean retval;
g_assert (info != NULL);
needed = gtk_recent_filter_get_needed (filter);
filter_info.contains = GTK_RECENT_FILTER_URI | GTK_RECENT_FILTER_MIME_TYPE;
filter_info.uri = gtk_recent_info_get_uri (info);
filter_info.mime_type = gtk_recent_info_get_mime_type (info);
if (needed & GTK_RECENT_FILTER_DISPLAY_NAME)
{
filter_info.display_name = gtk_recent_info_get_display_name (info);
filter_info.contains |= GTK_RECENT_FILTER_DISPLAY_NAME;
}
else
filter_info.uri = NULL;
if (needed & GTK_RECENT_FILTER_APPLICATION)
{
filter_info.applications = (const gchar **) gtk_recent_info_get_applications (info, NULL);
filter_info.contains |= GTK_RECENT_FILTER_APPLICATION;
}
else
filter_info.applications = NULL;
if (needed & GTK_RECENT_FILTER_GROUP)
{
filter_info.groups = (const gchar **) gtk_recent_info_get_groups (info, NULL);
filter_info.contains |= GTK_RECENT_FILTER_GROUP;
}
else
filter_info.groups = NULL;
if (needed & GTK_RECENT_FILTER_AGE)
{
filter_info.age = gtk_recent_info_get_age (info);
filter_info.contains |= GTK_RECENT_FILTER_AGE;
}
else
filter_info.age = -1;
retval = gtk_recent_filter_filter (filter, &filter_info);
/* these we own */
if (filter_info.applications)
g_strfreev ((gchar **) filter_info.applications);
if (filter_info.groups)
g_strfreev ((gchar **) filter_info.groups);
return !retval;
}
/*
* _gtk_recent_chooser_get_items:
* @chooser: a #GtkRecentChooser
* @filter: a #GtkRecentFilter
* @sort_func: sorting function, or %NULL
* @sort_data: sorting function data, or %NULL
*
* Default implementation for getting the (sorted and clamped) list
* of recently used resources from a #GtkRecentChooser. This function
* should be used by implementations of the #GtkRecentChooser
* interface inside the GtkRecentChooser::get_items vfunc.
* Default implementation for getting the filtered, sorted and
* clamped list of recently used resources from a #GtkRecentChooser.
* This function should be used by implementations of the
* #GtkRecentChooser interface inside the GtkRecentChooser::get_items
* vfunc.
*
* Return value: a list of #GtkRecentInfo objects
*/
GList *
_gtk_recent_chooser_get_items (GtkRecentChooser *chooser,
GtkRecentFilter *filter,
GtkRecentSortFunc sort_func,
gpointer sort_data)
{
@ -379,6 +442,50 @@ _gtk_recent_chooser_get_items (GtkRecentChooser *chooser,
if (limit == 0)
return NULL;
if (filter)
{
GList *filter_items, *l;
gboolean local_only = FALSE;
gboolean show_private = FALSE;
gboolean show_not_found = FALSE;
g_object_get (G_OBJECT (chooser),
"local-only", &local_only,
"show-private", &show_private,
"show-not-found", &show_not_found,
NULL);
filter_items = NULL;
for (l = items; l != NULL; l = l->next)
{
GtkRecentInfo *info = l->data;
gboolean remove_item = FALSE;
if (get_is_recent_filtered (filter, info))
remove_item = TRUE;
if (local_only && !gtk_recent_info_is_local (info))
remove_item = TRUE;
if (!show_private && gtk_recent_info_get_private_hint (info))
remove_item = TRUE;
if (!show_not_found && !gtk_recent_info_exists (info))
remove_item = TRUE;
if (!remove_item)
filter_items = g_list_prepend (filter_items, info);
else
gtk_recent_info_unref (info);
}
g_list_free (items);
items = filter_items;
}
if (!items)
return NULL;
sort_type = gtk_recent_chooser_get_sort_type (chooser);
switch (sort_type)
{

View File

@ -61,6 +61,7 @@ create_recent_chooser_menu (void)
menu = gtk_recent_chooser_menu_new_for_manager (manager);
gtk_recent_chooser_set_limit (GTK_RECENT_CHOOSER (menu), 4);
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),