+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
GtkWidget *recent_view;
GtkListStore *recent_store;
- GtkTreeModel *recent_store_filter;
GtkTreeViewColumn *icon_column;
GtkTreeViewColumn *meta_column;
GtkCellRenderer *meta_renderer;
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,
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);
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);
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));
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);
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),
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);
impl = GTK_RECENT_CHOOSER_DEFAULT (chooser);
return _gtk_recent_chooser_get_items (chooser,
+ impl->current_filter,
impl->sort_func,
impl->sort_data);
}
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)
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");
}
}
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");
+ }
}
GtkRecentChooserMenuPrivate *priv = menu->priv;
return _gtk_recent_chooser_get_items (chooser,
+ priv->current_filter,
priv->sort_func,
priv->sort_data);
}
priv->current_filter = filter;
g_object_ref_sink (priv->current_filter);
}
-
- 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);
+ gtk_recent_chooser_menu_populate (menu);
- return !retval;
+ g_object_notify (G_OBJECT (menu), "filter");
}
/* taken from libeel/eel-strings.c */
}
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);
GtkRecentManager *_gtk_recent_chooser_get_recent_manager (GtkRecentChooser *chooser);
GList * _gtk_recent_chooser_get_items (GtkRecentChooser *chooser,
+ GtkRecentFilter *filter,
GtkRecentSortFunc func,
gpointer data);
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)
{
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)
{
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),