Compare commits

...

8 Commits

Author SHA1 Message Date
Matthias Clasen
48872232f7 Clear cached row sensitivity when the filter changes
Now that filters may affect sensitivity of rows, we need
to clear the sensitivity column from the cache when the
filter changes. This fixes the problem where selecting a
different filter does not update the sensitivity of folders
until you change directories.
2012-07-15 00:39:02 -04:00
Matthias Clasen
523d897550 Emit row-changed notification
Emit row-changed when the filteredness of a visible row
changes in GtkFileSystemModel.
2012-07-15 00:37:41 -04:00
Matthias Clasen
aff313788a Test folder filtering
Add a filter to testfilechooser that can demonstrate folder
filtering on common directories, such as Documents or Downloads.
2012-07-14 21:16:39 -04:00
Federico Mena Quintero
fdb5a5bda1 Make the logic for setting the sensitivity column a bit more clear
Signed-off-by: Federico Mena Quintero <federico@gnome.org>
2012-07-11 17:50:15 -05:00
Federico Mena Quintero
dcf780cef7 Make computing and setting the visibility/filters atomic operations
This way we remove paired function calls (compute/set pairs), and also make
it possible to avoid computing a filter twice, as setting the visibility
depends on filteredness.

Signed-off-by: Federico Mena Quintero <federico@gnome.org>
2012-07-11 16:32:52 -05:00
Federico Mena Quintero
4a7b80cf4b Make it clear that 'filtered' means 'filtered_out'
It bothers me that we call gtk_file_filter_filter(), then negate the result,
and the return *that* from node_should_be_filtered().  So, rename 'filtered'
throughout GtkFileSystemModel to 'filtered_out' to mean things that didn't
pass the filter.

Signed-off-by: Federico Mena Quintero <federico@gnome.org>
2012-07-11 15:47:53 -05:00
Federico Mena Quintero
8dce83c464 Remove superfluous check in node_set_filtered()
This was a copy-paste leftover from node_set_visible().  Filters are not
concerned with model freezes, so node_set_filtered() does not
need to handle freezes, either.

Signed-off-by: Federico Mena Quintero <federico@gnome.org>
2012-07-11 15:03:13 -05:00
William Jon McCann
b13f1528a5 Desensitize filtered folders when in folder selection mode
https://bugzilla.gnome.org/show_bug.cgi?id=679333
2012-07-11 14:56:57 -05:00
4 changed files with 161 additions and 64 deletions

View File

@@ -206,6 +206,7 @@ enum {
MODEL_COL_FILE,
MODEL_COL_NAME_COLLATED,
MODEL_COL_IS_FOLDER,
MODEL_COL_IS_SENSITIVE,
MODEL_COL_PIXBUF,
MODEL_COL_SIZE_TEXT,
MODEL_COL_MTIME_TEXT,
@@ -222,6 +223,7 @@ enum {
G_TYPE_FILE, /* MODEL_COL_FILE */ \
G_TYPE_STRING, /* MODEL_COL_NAME_COLLATED */ \
G_TYPE_BOOLEAN, /* MODEL_COL_IS_FOLDER */ \
G_TYPE_BOOLEAN, /* MODEL_COL_IS_SENSITIVE */ \
GDK_TYPE_PIXBUF, /* MODEL_COL_PIXBUF */ \
G_TYPE_STRING, /* MODEL_COL_SIZE_TEXT */ \
G_TYPE_STRING, /* MODEL_COL_MTIME_TEXT */ \
@@ -6202,13 +6204,6 @@ gtk_file_chooser_default_unmap (GtkWidget *widget)
GTK_WIDGET_CLASS (_gtk_file_chooser_default_parent_class)->unmap (widget);
}
static void
install_list_model_filter (GtkFileChooserDefault *impl)
{
_gtk_file_system_model_set_filter (impl->browse_files_model,
impl->current_filter);
}
#define COMPARE_DIRECTORIES \
GtkFileChooserDefault *impl = user_data; \
GtkFileSystemModel *fs_model = GTK_FILE_SYSTEM_MODEL (model); \
@@ -6838,6 +6833,34 @@ file_system_model_set (GtkFileSystemModel *model,
case MODEL_COL_IS_FOLDER:
g_value_set_boolean (value, info == NULL || _gtk_file_info_consider_as_directory (info));
break;
case MODEL_COL_IS_SENSITIVE:
if (info)
{
gboolean sensitive = TRUE;
if (!(impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
|| impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER))
{
sensitive = TRUE; /* for file modes... */
}
else if (!_gtk_file_info_consider_as_directory (info))
{
sensitive = FALSE; /* for folder modes, files are not sensitive... */
}
else
{
/* ... and for folder modes, folders are sensitive only if the filter says so */
GtkTreeIter iter;
if (!_gtk_file_system_model_get_iter_for_file (model, &iter, file))
g_assert_not_reached ();
sensitive = !_gtk_file_system_model_iter_is_filtered_out (model, &iter);
}
g_value_set_boolean (value, sensitive);
}
else
g_value_set_boolean (value, TRUE);
break;
case MODEL_COL_PIXBUF:
if (info)
{
@@ -6961,7 +6984,7 @@ set_list_model (GtkFileChooserDefault *impl,
g_signal_connect (impl->browse_files_model, "finished-loading",
G_CALLBACK (browse_files_model_finished_loading_cb), impl);
install_list_model_filter (impl);
_gtk_file_system_model_set_filter (impl->browse_files_model, impl->current_filter);
profile_end ("end", NULL);
@@ -7532,16 +7555,19 @@ maybe_select (GtkTreeModel *model,
{
GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (data);
GtkTreeSelection *selection;
gboolean is_sensitive;
gboolean is_folder;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
gtk_tree_model_get (model, iter,
MODEL_COL_IS_FOLDER, &is_folder,
MODEL_COL_IS_SENSITIVE, &is_sensitive,
-1);
if ((is_folder && impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER) ||
(!is_folder && impl->action == GTK_FILE_CHOOSER_ACTION_OPEN))
if (is_sensitive &&
((is_folder && impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER) ||
(!is_folder && impl->action == GTK_FILE_CHOOSER_ACTION_OPEN)))
gtk_tree_selection_select_iter (selection, iter);
else
gtk_tree_selection_unselect_iter (selection, iter);
@@ -9655,13 +9681,22 @@ set_current_filter (GtkFileChooserDefault *impl,
filter_index);
if (impl->browse_files_model)
install_list_model_filter (impl);
{
_gtk_file_system_model_set_filter (impl->browse_files_model, impl->current_filter);
_gtk_file_system_model_clear_cache (impl->browse_files_model, MODEL_COL_IS_SENSITIVE);
}
if (impl->search_model)
_gtk_file_system_model_set_filter (impl->search_model, filter);
{
_gtk_file_system_model_set_filter (impl->search_model, filter);
_gtk_file_system_model_clear_cache (impl->search_model, MODEL_COL_IS_SENSITIVE);
}
if (impl->recent_model)
_gtk_file_system_model_set_filter (impl->recent_model, filter);
{
_gtk_file_system_model_set_filter (impl->recent_model, filter);
_gtk_file_system_model_clear_cache (impl->recent_model, MODEL_COL_IS_SENSITIVE);
}
g_object_notify (G_OBJECT (impl), "filter");
}
@@ -10052,14 +10087,16 @@ list_select_func (GtkTreeSelection *selection,
impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
{
GtkTreeIter iter;
gboolean is_sensitive;
gboolean is_folder;
if (!gtk_tree_model_get_iter (model, &iter, path))
return FALSE;
gtk_tree_model_get (model, &iter,
MODEL_COL_IS_SENSITIVE, &is_sensitive,
MODEL_COL_IS_FOLDER, &is_folder,
-1);
if (!is_folder)
if (!is_sensitive || !is_folder)
return FALSE;
}
@@ -10110,6 +10147,7 @@ list_row_activated (GtkTreeView *tree_view,
GtkTreeIter iter;
GtkTreeModel *model;
gboolean is_folder;
gboolean is_sensitive;
model = gtk_tree_view_get_model (tree_view);
@@ -10119,9 +10157,10 @@ list_row_activated (GtkTreeView *tree_view,
gtk_tree_model_get (model, &iter,
MODEL_COL_FILE, &file,
MODEL_COL_IS_FOLDER, &is_folder,
MODEL_COL_IS_SENSITIVE, &is_sensitive,
-1);
if (is_folder && file)
if (is_sensitive && is_folder && file)
{
change_folder_and_display_error (impl, file, FALSE);
goto out;
@@ -10164,10 +10203,6 @@ update_cell_renderer_attributes (GtkFileChooserDefault *impl)
GtkTreeViewColumn *column;
GtkCellRenderer *renderer;
GList *walk, *list;
gboolean always_sensitive;
always_sensitive = impl->action != GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER &&
impl->action != GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER;
/* Keep the following column numbers in sync with create_file_list() */
@@ -10190,10 +10225,8 @@ update_cell_renderer_attributes (GtkFileChooserDefault *impl)
"ellipsize", MODEL_COL_ELLIPSIZE,
NULL);
}
if (always_sensitive)
g_object_set (renderer, "sensitive", TRUE, NULL);
else
gtk_tree_view_column_add_attribute (column, renderer, "sensitive", MODEL_COL_IS_FOLDER);
gtk_tree_view_column_add_attribute (column, renderer, "sensitive", MODEL_COL_IS_SENSITIVE);
}
g_list_free (list);
@@ -10204,10 +10237,8 @@ update_cell_renderer_attributes (GtkFileChooserDefault *impl)
gtk_tree_view_column_set_attributes (column, renderer,
"text", MODEL_COL_SIZE_TEXT,
NULL);
if (always_sensitive)
g_object_set (renderer, "sensitive", TRUE, NULL);
else
gtk_tree_view_column_add_attribute (column, renderer, "sensitive", MODEL_COL_IS_FOLDER);
gtk_tree_view_column_add_attribute (column, renderer, "sensitive", MODEL_COL_IS_SENSITIVE);
g_list_free (list);
/* mtime */
@@ -10217,10 +10248,7 @@ update_cell_renderer_attributes (GtkFileChooserDefault *impl)
gtk_tree_view_column_set_attributes (column, renderer,
"text", MODEL_COL_MTIME_TEXT,
NULL);
if (always_sensitive)
g_object_set (renderer, "sensitive", TRUE, NULL);
else
gtk_tree_view_column_add_attribute (column, renderer, "sensitive", MODEL_COL_IS_FOLDER);
gtk_tree_view_column_add_attribute (column, renderer, "sensitive", MODEL_COL_IS_SENSITIVE);
g_list_free (list);
}

View File

@@ -120,6 +120,7 @@ struct _FileModelNode
*/
guint visible :1; /* if the file is currently visible */
guint filtered_out :1;/* if the file is currently filtered out (i.e. it didn't pass the filters) */
guint frozen_add :1; /* true if the model was frozen and the entry has not been added yet */
GValue values[1]; /* actually n_columns values */
@@ -306,10 +307,21 @@ emit_row_deleted_for_row (GtkFileSystemModel *model, guint row)
}
static void
node_set_visible (GtkFileSystemModel *model, guint id, gboolean visible)
node_set_visible_and_filtered_out (GtkFileSystemModel *model, guint id, gboolean visible, gboolean filtered_out)
{
FileModelNode *node = get_node (model, id);
/* Filteredness */
if (node->filtered_out != filtered_out)
{
node->filtered_out = filtered_out;
if (node->visible && visible)
emit_row_changed_for_node (model, id);
}
/* Visibility */
if (node->visible == visible ||
node->frozen_add)
return;
@@ -334,7 +346,7 @@ node_set_visible (GtkFileSystemModel *model, guint id, gboolean visible)
}
static gboolean
node_should_be_visible (GtkFileSystemModel *model, guint id)
node_should_be_filtered_out (GtkFileSystemModel *model, guint id)
{
FileModelNode *node = get_node (model, id);
GtkFileFilterInfo filter_info = { 0, };
@@ -345,28 +357,10 @@ node_should_be_visible (GtkFileSystemModel *model, guint id)
char *uri = NULL;
if (node->info == NULL)
return FALSE;
if (!model->show_hidden &&
(g_file_info_get_is_hidden (node->info) || g_file_info_get_is_backup (node->info)))
return FALSE;
if (_gtk_file_info_consider_as_directory (node->info))
{
if (!model->show_folders)
return FALSE;
if (!model->filter_folders)
return TRUE;
}
else
{
if (!model->show_files)
return FALSE;
}
return TRUE;
if (model->filter == NULL)
return TRUE;
return FALSE;
/* fill info */
required = gtk_file_filter_get_needed (model->filter);
@@ -408,7 +402,7 @@ node_should_be_visible (GtkFileSystemModel *model, guint id)
}
}
result = gtk_file_filter_filter (model->filter, &filter_info);
result = !gtk_file_filter_filter (model->filter, &filter_info);
g_free (mime_type);
g_free (filename);
@@ -417,6 +411,50 @@ node_should_be_visible (GtkFileSystemModel *model, guint id)
return result;
}
static gboolean
node_should_be_visible (GtkFileSystemModel *model, guint id, gboolean filtered_out)
{
FileModelNode *node = get_node (model, id);
gboolean result;
if (node->info == NULL)
return FALSE;
if (!model->show_hidden &&
(g_file_info_get_is_hidden (node->info) || g_file_info_get_is_backup (node->info)))
return FALSE;
if (_gtk_file_info_consider_as_directory (node->info))
{
if (!model->show_folders)
return FALSE;
if (!model->filter_folders)
return TRUE;
}
else
{
if (!model->show_files)
return FALSE;
}
result = !filtered_out;
return result;
}
static void
node_compute_visibility_and_filters (GtkFileSystemModel *model, guint id)
{
gboolean filtered_out;
gboolean visible;
filtered_out = node_should_be_filtered_out (model, id);
visible = node_should_be_visible (model, id, filtered_out);
node_set_visible_and_filtered_out (model, id, visible, filtered_out);
}
/*** GtkTreeModel ***/
static GtkTreeModelFlags
@@ -1399,9 +1437,7 @@ gtk_file_system_model_refilter_all (GtkFileSystemModel *model)
/* start at index 1, don't change the editable */
for (i = 1; i < model->files->len; i++)
{
node_set_visible (model, i, node_should_be_visible (model, i));
}
node_compute_visibility_and_filters (model, i);
model->filter_on_thaw = FALSE;
_gtk_file_system_model_thaw_updates (model);
@@ -1528,7 +1564,7 @@ _gtk_file_system_model_get_cancellable (GtkFileSystemModel *model)
* Checks if the iterator is visible. A visible iterator references
* a row that is currently exposed using the #GtkTreeModel API. If
* the iterator is invisible, it references a file that is not shown
* for some reason, such as being filtered by the current filter or
* for some reason, such as being filtered out by the current filter or
* being a hidden file.
*
* Returns: %TRUE if the iterator is visible
@@ -1546,6 +1582,32 @@ _gtk_file_system_model_iter_is_visible (GtkFileSystemModel *model,
return node->visible;
}
/**
* _gtk_file_system_model_iter_is_filtered_out:
* @model: the model
* @iter: a valid iterator
*
* Checks if the iterator is filtered out. This is only useful for rows
* that refer to folders, as those are always visible regardless
* of what the current filter says. This function lets you see
* the results of the filter.
*
* Returns: %TRUE if the iterator passed the current filter; %FALSE if the
* filter would not have let the row pass.
**/
gboolean
_gtk_file_system_model_iter_is_filtered_out (GtkFileSystemModel *model,
GtkTreeIter *iter)
{
FileModelNode *node;
g_return_val_if_fail (GTK_IS_FILE_SYSTEM_MODEL (model), FALSE);
g_return_val_if_fail (iter != NULL, FALSE);
node = get_node (model, ITER_INDEX (iter));
return node->filtered_out;
}
/**
* _gtk_file_system_model_get_info:
* @model: a #GtkFileSystemModel
@@ -1743,8 +1805,8 @@ add_file (GtkFileSystemModel *model,
g_slice_free1 (model->node_size, node);
if (!model->frozen)
node_set_visible (model, model->files->len -1,
node_should_be_visible (model, model->files->len - 1));
node_compute_visibility_and_filters (model, model->files->len -1);
gtk_file_system_model_sort_node (model, model->files->len -1);
}
@@ -1772,7 +1834,7 @@ remove_file (GtkFileSystemModel *model,
return;
node = get_node (model, id);
node_set_visible (model, id, FALSE);
node_set_visible_and_filtered_out (model, id, FALSE, FALSE);
g_hash_table_remove (model->file_lookup, file);
g_object_unref (node->file);
@@ -1883,7 +1945,7 @@ _gtk_file_system_model_add_editable (GtkFileSystemModel *model, GtkTreeIter *ite
g_return_if_fail (GTK_IS_FILE_SYSTEM_MODEL (model));
g_return_if_fail (!get_node (model, 0)->visible);
node_set_visible (model, 0, TRUE);
node_set_visible_and_filtered_out (model, 0, TRUE, FALSE);
ITER_INIT_FROM_INDEX (model, iter, 0);
}
@@ -1901,7 +1963,7 @@ _gtk_file_system_model_remove_editable (GtkFileSystemModel *model)
g_return_if_fail (GTK_IS_FILE_SYSTEM_MODEL (model));
g_return_if_fail (get_node (model, 0)->visible);
node_set_visible (model, 0, FALSE);
node_set_visible_and_filtered_out (model, 0, FALSE, FALSE);
}
/**
@@ -1958,7 +2020,7 @@ _gtk_file_system_model_thaw_updates (GtkFileSystemModel *model)
if (!node->frozen_add)
continue;
node->frozen_add = FALSE;
node_set_visible (model, i, node_should_be_visible (model, i));
node_compute_visibility_and_filters (model, i);
}
}
}

View File

@@ -53,6 +53,8 @@ GtkFileSystemModel *_gtk_file_system_model_new_for_directory(GFile *
GCancellable * _gtk_file_system_model_get_cancellable (GtkFileSystemModel *model);
gboolean _gtk_file_system_model_iter_is_visible (GtkFileSystemModel *model,
GtkTreeIter *iter);
gboolean _gtk_file_system_model_iter_is_filtered_out (GtkFileSystemModel *model,
GtkTreeIter *iter);
GFileInfo * _gtk_file_system_model_get_info (GtkFileSystemModel *model,
GtkTreeIter *iter);
gboolean _gtk_file_system_model_get_iter_for_file(GtkFileSystemModel *model,

View File

@@ -577,6 +577,11 @@ main (int argc, char **argv)
gtk_file_filter_add_mime_type (filter, "image/png");
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
filter = gtk_file_filter_new ();
gtk_file_filter_set_name (filter, "Starts with D");
gtk_file_filter_add_pattern (filter, "D*");
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
g_signal_connect (dialog, "notify::filter",
G_CALLBACK (filter_changed), NULL);