Improve show_and_select_files() function
The previous function enumerated the whole directory and used a lot of outdated API to decide how to show files. The new code queries the filesystem model to decide about this. The now unused old functions were removed.
This commit is contained in:
@@ -369,11 +369,6 @@ static void list_row_activated (GtkTreeView *tree_view,
|
||||
GtkTreeViewColumn *column,
|
||||
GtkFileChooserDefault *impl);
|
||||
|
||||
static void select_func (GtkFileSystemModel *model,
|
||||
GtkTreePath *path,
|
||||
GtkTreeIter *iter,
|
||||
gpointer user_data);
|
||||
|
||||
static void path_bar_clicked (GtkPathBar *path_bar,
|
||||
GFile *file,
|
||||
GFile *child,
|
||||
@@ -5641,12 +5636,6 @@ gtk_file_chooser_default_dispose (GObject *object)
|
||||
impl->update_current_folder_cancellable = NULL;
|
||||
}
|
||||
|
||||
if (impl->show_and_select_files_cancellable)
|
||||
{
|
||||
g_cancellable_cancel (impl->show_and_select_files_cancellable);
|
||||
impl->show_and_select_files_cancellable = NULL;
|
||||
}
|
||||
|
||||
if (impl->should_respond_get_info_cancellable)
|
||||
{
|
||||
g_cancellable_cancel (impl->should_respond_get_info_cancellable);
|
||||
@@ -5866,52 +5855,6 @@ gtk_file_chooser_default_size_allocate (GtkWidget *widget,
|
||||
GTK_WIDGET_CLASS (_gtk_file_chooser_default_parent_class)->size_allocate (widget, allocation);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
get_is_file_filtered (GtkFileChooserDefault *impl,
|
||||
GFile *file,
|
||||
GFileInfo *file_info)
|
||||
{
|
||||
GtkFileFilterInfo filter_info;
|
||||
GtkFileFilterFlags needed;
|
||||
gboolean result;
|
||||
|
||||
if (!impl->current_filter)
|
||||
return FALSE;
|
||||
|
||||
filter_info.contains = GTK_FILE_FILTER_DISPLAY_NAME | GTK_FILE_FILTER_MIME_TYPE;
|
||||
|
||||
needed = gtk_file_filter_get_needed (impl->current_filter);
|
||||
|
||||
filter_info.display_name = g_file_info_get_display_name (file_info);
|
||||
filter_info.mime_type = g_content_type_get_mime_type (g_file_info_get_content_type (file_info));
|
||||
|
||||
if (needed & GTK_FILE_FILTER_FILENAME)
|
||||
{
|
||||
filter_info.filename = g_file_get_path (file);
|
||||
if (filter_info.filename)
|
||||
filter_info.contains |= GTK_FILE_FILTER_FILENAME;
|
||||
}
|
||||
else
|
||||
filter_info.filename = NULL;
|
||||
|
||||
if (needed & GTK_FILE_FILTER_URI)
|
||||
{
|
||||
filter_info.uri = g_file_get_uri (file);
|
||||
if (filter_info.uri)
|
||||
filter_info.contains |= GTK_FILE_FILTER_URI;
|
||||
}
|
||||
else
|
||||
filter_info.uri = NULL;
|
||||
|
||||
result = gtk_file_filter_filter (impl->current_filter, &filter_info);
|
||||
|
||||
g_free ((gchar *)filter_info.filename);
|
||||
g_free ((gchar *)filter_info.uri);
|
||||
g_free ((gchar *)filter_info.mime_type);
|
||||
|
||||
return !result;
|
||||
}
|
||||
|
||||
static void
|
||||
set_sort_column (GtkFileChooserDefault *impl)
|
||||
{
|
||||
@@ -6360,151 +6303,58 @@ browse_files_center_selected_row (GtkFileChooserDefault *impl)
|
||||
gtk_tree_selection_selected_foreach (selection, center_selected_row_foreach_cb, &closure);
|
||||
}
|
||||
|
||||
struct ShowAndSelectPathsData
|
||||
{
|
||||
GtkFileChooserDefault *impl;
|
||||
GSList *files;
|
||||
};
|
||||
|
||||
static void
|
||||
show_and_select_files_finished_loading (GtkFolder *folder,
|
||||
gpointer user_data)
|
||||
{
|
||||
gboolean have_hidden;
|
||||
gboolean have_filtered;
|
||||
GSList *l;
|
||||
struct ShowAndSelectPathsData *data = user_data;
|
||||
|
||||
have_hidden = FALSE;
|
||||
have_filtered = FALSE;
|
||||
|
||||
for (l = data->files; l; l = l->next)
|
||||
{
|
||||
GFile *file;
|
||||
GFileInfo *info;
|
||||
|
||||
file = l->data;
|
||||
|
||||
info = _gtk_folder_get_info (folder, file);
|
||||
if (info)
|
||||
{
|
||||
if (!have_hidden)
|
||||
have_hidden = g_file_info_get_is_hidden (info)
|
||||
|| g_file_info_get_is_backup (info);
|
||||
|
||||
if (!have_filtered)
|
||||
have_filtered = (! _gtk_file_info_consider_as_directory (info)) &&
|
||||
get_is_file_filtered (data->impl, file, info);
|
||||
|
||||
g_object_unref (info);
|
||||
|
||||
if (have_hidden && have_filtered)
|
||||
break; /* we now have all the information we need */
|
||||
}
|
||||
}
|
||||
|
||||
g_signal_handlers_disconnect_by_func (folder,
|
||||
show_and_select_files_finished_loading,
|
||||
user_data);
|
||||
|
||||
if (have_hidden)
|
||||
g_object_set (data->impl, "show-hidden", TRUE, NULL);
|
||||
|
||||
if (have_filtered)
|
||||
set_current_filter (data->impl, NULL);
|
||||
|
||||
for (l = data->files; l; l = l->next)
|
||||
{
|
||||
GFile *file;
|
||||
GtkTreePath *path;
|
||||
GtkTreeIter iter;
|
||||
|
||||
file = l->data;
|
||||
if (!_gtk_file_system_model_get_iter_for_file (data->impl->browse_files_model,
|
||||
&iter,
|
||||
file))
|
||||
return;
|
||||
|
||||
path = gtk_tree_model_get_path (GTK_TREE_MODEL (data->impl->browse_files_model), &iter);
|
||||
select_func (data->impl->browse_files_model, path, &iter, data->impl);
|
||||
gtk_tree_path_free (path);
|
||||
}
|
||||
|
||||
browse_files_center_selected_row (data->impl);
|
||||
|
||||
g_object_unref (data->impl);
|
||||
g_slist_foreach (data->files, (GFunc) g_object_unref, NULL);
|
||||
g_slist_free (data->files);
|
||||
g_free (data);
|
||||
}
|
||||
|
||||
static void
|
||||
show_and_select_files_get_folder_cb (GCancellable *cancellable,
|
||||
GtkFolder *folder,
|
||||
const GError *error,
|
||||
gpointer user_data)
|
||||
{
|
||||
gboolean cancelled = g_cancellable_is_cancelled (cancellable);
|
||||
struct ShowAndSelectPathsData *data = user_data;
|
||||
|
||||
if (data->impl->show_and_select_files_cancellable != cancellable)
|
||||
goto out;
|
||||
|
||||
data->impl->show_and_select_files_cancellable = NULL;
|
||||
|
||||
if (cancelled || error)
|
||||
goto out;
|
||||
|
||||
g_object_unref (cancellable);
|
||||
|
||||
if (_gtk_folder_is_finished_loading (folder))
|
||||
show_and_select_files_finished_loading (folder, user_data);
|
||||
else
|
||||
g_signal_connect (folder, "finished-loading",
|
||||
G_CALLBACK (show_and_select_files_finished_loading),
|
||||
user_data);
|
||||
|
||||
return;
|
||||
|
||||
out:
|
||||
g_object_unref (data->impl);
|
||||
g_slist_foreach (data->files, (GFunc) g_object_unref, NULL);
|
||||
g_slist_free (data->files);
|
||||
g_free (data);
|
||||
|
||||
g_object_unref (cancellable);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
show_and_select_files (GtkFileChooserDefault *impl,
|
||||
GFile *parent_file,
|
||||
GSList *files)
|
||||
{
|
||||
struct ShowAndSelectPathsData *info;
|
||||
GtkTreeSelection *selection;
|
||||
GtkFileSystemModel *fsmodel;
|
||||
gboolean can_have_hidden, can_have_filtered, selected_a_file;
|
||||
GSList *walk;
|
||||
|
||||
profile_start ("start", NULL);
|
||||
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
|
||||
fsmodel = GTK_FILE_SYSTEM_MODEL (gtk_tree_view_get_model (GTK_TREE_VIEW (impl->browse_files_tree_view)));
|
||||
can_have_hidden = !impl->show_hidden;
|
||||
can_have_filtered = impl->current_filter != NULL;
|
||||
selected_a_file = FALSE;
|
||||
|
||||
if (!files)
|
||||
for (walk = files; walk && (can_have_hidden || can_have_filtered); walk = walk->next)
|
||||
{
|
||||
profile_end ("end", NULL);
|
||||
return TRUE;
|
||||
GFile *file = walk->data;
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (!_gtk_file_system_model_get_iter_for_file (fsmodel, &iter, file))
|
||||
continue;
|
||||
|
||||
if (!_gtk_file_system_model_get_is_visible (fsmodel, &iter))
|
||||
{
|
||||
GFileInfo *info = _gtk_file_system_model_get_info (fsmodel, &iter);
|
||||
|
||||
if (can_have_hidden &&
|
||||
(g_file_info_get_is_hidden (info) ||
|
||||
g_file_info_get_is_backup (info)))
|
||||
{
|
||||
g_object_set (impl, "show-hidden", TRUE, NULL);
|
||||
can_have_hidden = FALSE;
|
||||
}
|
||||
|
||||
if (can_have_filtered)
|
||||
{
|
||||
set_current_filter (impl, NULL);
|
||||
can_have_filtered = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (_gtk_file_system_model_get_is_visible (fsmodel, &iter))
|
||||
{
|
||||
gtk_tree_selection_select_iter (selection, &iter);
|
||||
selected_a_file = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
info = g_new (struct ShowAndSelectPathsData, 1);
|
||||
info->impl = g_object_ref (impl);
|
||||
info->files = g_slist_copy (files);
|
||||
g_slist_foreach (info->files, (GFunc) g_object_ref, NULL);
|
||||
browse_files_center_selected_row (impl);
|
||||
|
||||
if (impl->show_and_select_files_cancellable)
|
||||
g_cancellable_cancel (impl->show_and_select_files_cancellable);
|
||||
|
||||
impl->show_and_select_files_cancellable =
|
||||
_gtk_file_system_get_folder (impl->file_system, parent_file,
|
||||
"standard::is-hidden,standard::is-backup,standard::type,standard::name,standard::content-type",
|
||||
show_and_select_files_get_folder_cb, info);
|
||||
|
||||
profile_end ("end", NULL);
|
||||
return TRUE;
|
||||
return selected_a_file;
|
||||
}
|
||||
|
||||
/* Processes the pending operation when a folder is finished loading */
|
||||
@@ -6516,7 +6366,7 @@ pending_select_files_process (GtkFileChooserDefault *impl)
|
||||
|
||||
if (impl->pending_select_files)
|
||||
{
|
||||
show_and_select_files (impl, impl->current_folder, impl->pending_select_files);
|
||||
show_and_select_files (impl, impl->pending_select_files);
|
||||
pending_select_files_free (impl);
|
||||
browse_files_center_selected_row (impl);
|
||||
}
|
||||
@@ -7380,20 +7230,6 @@ gtk_file_chooser_default_set_current_name (GtkFileChooser *chooser,
|
||||
_gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), name);
|
||||
}
|
||||
|
||||
static void
|
||||
select_func (GtkFileSystemModel *model,
|
||||
GtkTreePath *path,
|
||||
GtkTreeIter *iter,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkFileChooserDefault *impl = user_data;
|
||||
GtkTreeSelection *selection;
|
||||
|
||||
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
|
||||
|
||||
gtk_tree_selection_select_iter (selection, iter);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_file_chooser_default_select_file (GtkFileChooser *chooser,
|
||||
GFile *file,
|
||||
@@ -7429,7 +7265,7 @@ gtk_file_chooser_default_select_file (GtkFileChooser *chooser,
|
||||
files.data = (gpointer) file;
|
||||
files.next = NULL;
|
||||
|
||||
result = show_and_select_files (impl, parent_file, &files);
|
||||
result = show_and_select_files (impl, &files);
|
||||
g_object_unref (parent_file);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -233,7 +233,6 @@ struct _GtkFileChooserDefault
|
||||
GSList *reload_icon_cancellables;
|
||||
GCancellable *file_list_drag_data_received_cancellable;
|
||||
GCancellable *update_current_folder_cancellable;
|
||||
GCancellable *show_and_select_files_cancellable;
|
||||
GCancellable *should_respond_get_info_cancellable;
|
||||
GCancellable *file_exists_get_info_cancellable;
|
||||
GCancellable *update_from_entry_cancellable;
|
||||
|
||||
@@ -968,11 +968,6 @@ gtk_file_system_model_got_files (GObject *object, GAsyncResult *res, gpointer da
|
||||
model->cancellable,
|
||||
gtk_file_system_model_closed_enumerator,
|
||||
NULL);
|
||||
if (error)
|
||||
g_error_free (error);
|
||||
else
|
||||
g_signal_emit (model, file_system_model_signals[FINISHED_LOADING], 0, NULL);
|
||||
|
||||
if (model->dir_thaw_source != 0)
|
||||
{
|
||||
g_source_remove (model->dir_thaw_source);
|
||||
@@ -980,6 +975,11 @@ gtk_file_system_model_got_files (GObject *object, GAsyncResult *res, gpointer da
|
||||
_gtk_file_system_model_thaw_updates (model);
|
||||
}
|
||||
|
||||
if (error)
|
||||
g_error_free (error);
|
||||
else
|
||||
g_signal_emit (model, file_system_model_signals[FINISHED_LOADING], 0, NULL);
|
||||
|
||||
g_object_unref (model);
|
||||
}
|
||||
else
|
||||
@@ -1315,6 +1315,17 @@ _gtk_file_system_model_set_show_files (GtkFileSystemModel *model,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* _gtk_file_system_model_get_cancellable:
|
||||
* @model: the model
|
||||
*
|
||||
* Gets the cancellable used by the @model. This is the cancellable used
|
||||
* internally by the @model that will be cancelled when @model is
|
||||
* disposed. So you can use it for operations that should be cancelled
|
||||
* when the model goes away.
|
||||
*
|
||||
* Returns: The cancellable used by @model
|
||||
**/
|
||||
GCancellable *
|
||||
_gtk_file_system_model_get_cancellable (GtkFileSystemModel *model)
|
||||
{
|
||||
@@ -1323,6 +1334,32 @@ _gtk_file_system_model_get_cancellable (GtkFileSystemModel *model)
|
||||
return model->cancellable;
|
||||
}
|
||||
|
||||
/**
|
||||
* _gtk_file_system_model_get_is_visible:
|
||||
* @model: the model
|
||||
* @iter: a valid iterator
|
||||
*
|
||||
* 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
|
||||
* being a hidden file.
|
||||
*
|
||||
* Returns: %TRUE if the iterator is visible
|
||||
**/
|
||||
gboolean
|
||||
_gtk_file_system_model_get_is_visible (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->visible;
|
||||
}
|
||||
|
||||
/**
|
||||
* _gtk_file_system_model_get_info:
|
||||
* @model: a #GtkFileSystemModel
|
||||
@@ -1347,6 +1384,7 @@ _gtk_file_system_model_get_info (GtkFileSystemModel *model,
|
||||
FileModelNode *node;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_FILE_SYSTEM_MODEL (model), NULL);
|
||||
g_return_val_if_fail (iter != NULL, NULL);
|
||||
|
||||
node = get_node (model, ITER_INDEX (iter));
|
||||
g_assert (node->info == NULL || G_IS_FILE_INFO (node->info));
|
||||
@@ -1447,6 +1485,20 @@ node_get_for_file (GtkFileSystemModel *model,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* _gtk_file_system_model_get_iter_for_file:
|
||||
* @model: the model
|
||||
* @iter: the iterator to be initialized
|
||||
* @file: the file to look up
|
||||
*
|
||||
* Initializes @iter to point to the row used for @file, if @file is part
|
||||
* of the model. Note that upon successful return, @iter may point to an
|
||||
* invisible row in the @model. Use
|
||||
* _gtk_file_system_model_get_is_visible() to make sure it is visible to
|
||||
* the tree view.
|
||||
*
|
||||
* Returns: %TRUE if file is part of the model and @iter was initialized
|
||||
**/
|
||||
gboolean
|
||||
_gtk_file_system_model_get_iter_for_file (GtkFileSystemModel *model,
|
||||
GtkTreeIter *iter,
|
||||
|
||||
@@ -53,6 +53,8 @@ GtkFileSystemModel *_gtk_file_system_model_new_for_directory(GFile *
|
||||
guint n_columns,
|
||||
...);
|
||||
GCancellable * _gtk_file_system_model_get_cancellable (GtkFileSystemModel *model);
|
||||
gboolean _gtk_file_system_model_get_is_visible (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,
|
||||
|
||||
Reference in New Issue
Block a user