From 5c03d6a9437d92acf89d43109e82e628ef822251 Mon Sep 17 00:00:00 2001 From: William Jon McCann Date: Sun, 8 Jul 2012 03:25:02 -0400 Subject: [PATCH] Desensitize filtered folders when in folder selection mode https://bugzilla.gnome.org/show_bug.cgi?id=679333 --- gtk/gtkfilechooserdefault.c | 65 ++++++++++++++------- gtk/gtkfilesystemmodel.c | 109 ++++++++++++++++++++++++++++-------- gtk/gtkfilesystemmodel.h | 2 + 3 files changed, 132 insertions(+), 44 deletions(-) diff --git a/gtk/gtkfilechooserdefault.c b/gtk/gtkfilechooserdefault.c index f89a672b1a..0f668a096a 100644 --- a/gtk/gtkfilechooserdefault.c +++ b/gtk/gtkfilechooserdefault.c @@ -205,6 +205,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, @@ -221,6 +222,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 */ \ @@ -6710,6 +6712,33 @@ 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; + } + else if (!_gtk_file_info_consider_as_directory (info)) + { + sensitive = FALSE; + } + else + { + 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 (model, &iter); + } + + g_value_set_boolean (value, sensitive); + } + else + g_value_set_boolean (value, TRUE); + break; case MODEL_COL_PIXBUF: if (info) { @@ -7399,16 +7428,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); @@ -9917,14 +9949,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; } @@ -9974,6 +10008,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); @@ -9983,9 +10018,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); return; @@ -10026,10 +10062,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() */ @@ -10052,10 +10084,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); @@ -10066,10 +10096,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 */ @@ -10079,10 +10107,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); } diff --git a/gtk/gtkfilesystemmodel.c b/gtk/gtkfilesystemmodel.c index ac27cacabb..c023aa4dae 100644 --- a/gtk/gtkfilesystemmodel.c +++ b/gtk/gtkfilesystemmodel.c @@ -123,6 +123,7 @@ struct _FileModelNode */ guint visible :1; /* if the file is currently visible */ + guint filtered :1; /* if the file is currently filtered */ 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 */ @@ -308,6 +309,18 @@ emit_row_deleted_for_row (GtkFileSystemModel *model, guint row) gtk_tree_path_free (path); } +static void +node_set_filtered (GtkFileSystemModel *model, guint id, gboolean filtered) +{ + FileModelNode *node = get_node (model, id); + + if (node->filtered == filtered || + node->frozen_add) + return; + + node->filtered = filtered; +} + static void node_set_visible (GtkFileSystemModel *model, guint id, gboolean visible) { @@ -337,7 +350,7 @@ node_set_visible (GtkFileSystemModel *model, guint id, gboolean visible) } static gboolean -node_should_be_visible (GtkFileSystemModel *model, guint id) +node_should_be_filtered (GtkFileSystemModel *model, guint id) { FileModelNode *node = get_node (model, id); GtkFileFilterInfo filter_info = { 0, }; @@ -348,28 +361,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); @@ -411,7 +406,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); @@ -420,6 +415,38 @@ node_should_be_visible (GtkFileSystemModel *model, guint id) return result; } +static gboolean +node_should_be_visible (GtkFileSystemModel *model, guint id) +{ + 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 = !node_should_be_filtered (model, id); + + return result; +} + /*** GtkTreeModel ***/ static GtkTreeModelFlags @@ -1403,6 +1430,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_filtered (model, i, node_should_be_filtered (model, i)); node_set_visible (model, i, node_should_be_visible (model, i)); } @@ -1549,6 +1577,31 @@ _gtk_file_system_model_iter_is_visible (GtkFileSystemModel *model, return node->visible; } +/** + * _gtk_file_system_model_iter_is_filtered: + * @model: the model + * @iter: a valid iterator + * + * Checks if the iterator is filtered. A filtered iterator references + * a row that is currently exposed using the #GtkTreeModel API. If + * the iterator is filtered, it references a file that filtered by + * the current filter. + * + * Returns: %TRUE if the iterator is filtered + **/ +gboolean +_gtk_file_system_model_iter_is_filtered (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; +} + /** * _gtk_file_system_model_get_info: * @model: a #GtkFileSystemModel @@ -1746,8 +1799,12 @@ 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_set_filtered (model, model->files->len -1, + node_should_be_filtered (model, model->files->len - 1)); + node_set_visible (model, model->files->len -1, + node_should_be_visible (model, model->files->len - 1)); + } gtk_file_system_model_sort_node (model, model->files->len -1); } @@ -1776,6 +1833,7 @@ remove_file (GtkFileSystemModel *model, node = get_node (model, id); node_set_visible (model, id, FALSE); + node_set_filtered (model, id, FALSE); g_hash_table_remove (model->file_lookup, file); g_object_unref (node->file); @@ -1887,6 +1945,7 @@ _gtk_file_system_model_add_editable (GtkFileSystemModel *model, GtkTreeIter *ite g_return_if_fail (!get_node (model, 0)->visible); node_set_visible (model, 0, TRUE); + node_set_filtered (model, 0, FALSE); ITER_INIT_FROM_INDEX (model, iter, 0); } @@ -1905,6 +1964,7 @@ _gtk_file_system_model_remove_editable (GtkFileSystemModel *model) g_return_if_fail (get_node (model, 0)->visible); node_set_visible (model, 0, FALSE); + node_set_filtered (model, 0, FALSE); } /** @@ -1962,6 +2022,7 @@ _gtk_file_system_model_thaw_updates (GtkFileSystemModel *model) continue; node->frozen_add = FALSE; node_set_visible (model, i, node_should_be_visible (model, i)); + node_set_filtered (model, i, node_should_be_filtered (model, i)); } } } diff --git a/gtk/gtkfilesystemmodel.h b/gtk/gtkfilesystemmodel.h index 4a533daddb..83da3e4c46 100644 --- a/gtk/gtkfilesystemmodel.h +++ b/gtk/gtkfilesystemmodel.h @@ -55,6 +55,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 (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,