[gtk+/wip/gbsneto/other-locations] file chooser: Fix multi-selection
- From: Georges Basile Stavracas Neto <gbsneto src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/gbsneto/other-locations] file chooser: Fix multi-selection
- Date: Sat, 11 Jul 2015 14:29:49 +0000 (UTC)
commit ae657f7f6bde4ee9d40090c24af52ed8cedbb19a
Author: Matthias Clasen <mclasen redhat com>
Date: Wed Jul 8 21:31:40 2015 -0400
file chooser: Fix multi-selection
Even if we only ever hit the code with a singleton selection,
calling gtk_tree_selection_get_selected is not ok if the tree
selection mode allows multi-selection. Replace all calls to
gtk_tree_selection_get_selected in the file chooser code with
callback loops iterating over the selection. This problem
was introduced with the recently added rename and delete
menuitems.
gtk/gtkfilechooserwidget.c | 240 +++++++++++++++++++++++---------------------
1 files changed, 125 insertions(+), 115 deletions(-)
---
diff --git a/gtk/gtkfilechooserwidget.c b/gtk/gtkfilechooserwidget.c
index c0f6ae7..1df2ecc 100644
--- a/gtk/gtkfilechooserwidget.c
+++ b/gtk/gtkfilechooserwidget.c
@@ -565,12 +565,14 @@ static void location_switch_to_path_bar (GtkFileChooserWidget *impl);
static void stop_loading_and_clear_list_model (GtkFileChooserWidget *impl,
gboolean remove_from_treeview);
+static GSList *get_selected_files (GtkFileChooserWidget *impl);
+static GSList *get_selected_infos (GtkFileChooserWidget *impl);
+
static void search_setup_widgets (GtkFileChooserWidget *impl);
static void search_stop_searching (GtkFileChooserWidget *impl,
gboolean remove_query);
static void search_clear_model (GtkFileChooserWidget *impl,
gboolean remove_from_treeview);
-static GSList *search_get_selected_files (GtkFileChooserWidget *impl);
static void search_entry_activate_cb (GtkFileChooserWidget *impl);
static void search_entry_stop_cb (GtkFileChooserWidget *impl);
static void settings_load (GtkFileChooserWidget *impl);
@@ -584,7 +586,6 @@ static void recent_stop_loading (GtkFileChooserWidget *impl);
static void recent_clear_model (GtkFileChooserWidget *impl,
gboolean remove_from_treeview);
static gboolean recent_should_respond (GtkFileChooserWidget *impl);
-static GSList * recent_get_selected_files (GtkFileChooserWidget *impl);
static void set_file_system_backend (GtkFileChooserWidget *impl);
static void unset_file_system_backend (GtkFileChooserWidget *impl);
@@ -1502,54 +1503,63 @@ G_GNUC_END_IGNORE_DEPRECATIONS
}
static void
+delete_selected_cb (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ GtkFileChooserWidget *impl = data;
+ GFile *file;
+ GFileInfo *info;
+ GError *error = NULL;
+
+ file = _gtk_file_system_model_get_file (GTK_FILE_SYSTEM_MODEL (model), iter);
+ info = _gtk_file_system_model_get_info (GTK_FILE_SYSTEM_MODEL (model), iter);
+
+ if (confirm_delete (impl, info))
+ {
+ if (!g_file_delete (file, NULL, &error))
+ error_deleting_file (impl, file, error);
+ }
+}
+
+static void
delete_file_cb (GtkMenuItem *item,
GtkFileChooserWidget *impl)
{
GtkFileChooserWidgetPrivate *priv = impl->priv;
GtkTreeSelection *selection;
- GtkTreeModel *model;
- GtkTreeIter iter;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
+ gtk_tree_selection_selected_foreach (selection, delete_selected_cb, impl);
+}
- if (gtk_tree_selection_get_selected (selection, &model, &iter))
- {
- GFile *file;
- GFileInfo *info;
- GError *error = NULL;
+static void
+trash_selected_cb (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ GtkFileChooserWidget *impl = data;
+ GFile *file;
+ GError *error = NULL;
- file = _gtk_file_system_model_get_file (GTK_FILE_SYSTEM_MODEL (model), &iter);
- info = _gtk_file_system_model_get_info (GTK_FILE_SYSTEM_MODEL (model), &iter);
+ file = _gtk_file_system_model_get_file (GTK_FILE_SYSTEM_MODEL (model), iter);
- if (confirm_delete (impl, info))
- {
- if (!g_file_delete (file, NULL, &error))
- error_deleting_file (impl, file, error);
- }
- }
+ if (!g_file_trash (file, NULL, &error))
+ error_trashing_file (impl, file, error);
}
+
static void
trash_file_cb (GtkMenuItem *item,
GtkFileChooserWidget *impl)
{
GtkFileChooserWidgetPrivate *priv = impl->priv;
GtkTreeSelection *selection;
- GtkTreeModel *model;
- GtkTreeIter iter;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
-
- if (gtk_tree_selection_get_selected (selection, &model, &iter))
- {
- GFile *file;
- GError *error = NULL;
-
- file = _gtk_file_system_model_get_file (GTK_FILE_SYSTEM_MODEL (model), &iter);
-
- if (!g_file_trash (file, NULL, &error))
- error_trashing_file (impl, file, error);
- }
+ gtk_tree_selection_selected_foreach (selection, trash_selected_cb, impl);
}
static void
@@ -1611,43 +1621,47 @@ rename_file_rename_clicked (GtkButton *button,
}
static void
-rename_file_cb (GtkMenuItem *item,
- GtkFileChooserWidget *impl)
+rename_selected_cb (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer data)
{
+ GtkFileChooserWidget *impl = data;
GtkFileChooserWidgetPrivate *priv = impl->priv;
- GtkTreeSelection *selection;
- GtkTreeModel *model;
- GtkTreeIter iter;
- GtkTreePath *path;
GdkRectangle rect;
gchar *filename;
- /* insensitive until we change the name */
- gtk_widget_set_sensitive (priv->rename_file_rename_button, FALSE);
+ gtk_tree_model_get (model, iter,
+ MODEL_COL_FILE, &priv->rename_file_source_file,
+ -1);
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
+ gtk_tree_view_get_cell_area (GTK_TREE_VIEW (priv->browse_files_tree_view),
+ path, priv->list_name_column, &rect);
- if (gtk_tree_selection_get_selected (selection, &model, &iter))
- {
- gtk_tree_model_get (model, &iter,
- MODEL_COL_FILE, &priv->rename_file_source_file,
- -1);
+ gtk_tree_view_convert_tree_to_widget_coords (GTK_TREE_VIEW (priv->browse_files_tree_view),
+ rect.x, rect.y, &rect.x, &rect.y);
- path = gtk_tree_model_get_path (model, &iter);
- gtk_tree_view_get_cell_area (GTK_TREE_VIEW (priv->browse_files_tree_view),
- path, priv->list_name_column, &rect);
+ filename = g_file_get_basename (priv->rename_file_source_file);
+ gtk_entry_set_text (GTK_ENTRY(priv->rename_file_name_entry), filename);
+ g_free (filename);
- gtk_tree_view_convert_tree_to_widget_coords (GTK_TREE_VIEW (priv->browse_files_tree_view),
- rect.x, rect.y, &rect.x, &rect.y);
+ gtk_popover_set_pointing_to (GTK_POPOVER (priv->rename_file_popover), &rect);
+ gtk_widget_show (priv->rename_file_popover);
+ gtk_widget_grab_focus (priv->rename_file_popover);
+}
- filename = g_file_get_basename (priv->rename_file_source_file);
- gtk_entry_set_text (GTK_ENTRY(priv->rename_file_name_entry), filename);
- g_free (filename);
+static void
+rename_file_cb (GtkMenuItem *item,
+ GtkFileChooserWidget *impl)
+{
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
+ GtkTreeSelection *selection;
- gtk_popover_set_pointing_to (GTK_POPOVER (priv->rename_file_popover), &rect);
- gtk_widget_show (priv->rename_file_popover);
- gtk_widget_grab_focus (priv->rename_file_popover);
- }
+ /* insensitive until we change the name */
+ gtk_widget_set_sensitive (priv->rename_file_rename_button, FALSE);
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
+ gtk_tree_selection_selected_foreach (selection, rename_selected_cb, impl);
}
/* callback used to set data to clipboard */
@@ -1703,8 +1717,7 @@ copy_file_clear_cb (GtkClipboard *clipboard,
{
GSList *selected_files = data;
- g_slist_foreach (selected_files, (GFunc) g_object_unref, NULL);
- g_slist_free (selected_files);
+ g_slist_free_full (selected_files, g_object_unref);
}
/* Callback used when the "Copy file’s location" menu item is activated */
@@ -1714,7 +1727,7 @@ copy_file_location_cb (GtkMenuItem *item,
{
GSList *selected_files = NULL;
- selected_files = search_get_selected_files (impl);
+ selected_files = get_selected_files (impl);
if (selected_files)
{
@@ -1748,7 +1761,7 @@ visit_file_cb (GtkMenuItem *item,
{
GSList *files;
- files = search_get_selected_files (impl);
+ files = get_selected_files (impl);
/* Sigh, just use the first one */
if (files)
@@ -1769,7 +1782,7 @@ open_folder_cb (GtkMenuItem *item,
{
GSList *files;
- files = search_get_selected_files (impl);
+ files = get_selected_files (impl);
/* Sigh, just use the first one */
if (files)
@@ -2103,16 +2116,16 @@ check_file_list_menu_sensitivity (GtkFileChooserWidget *impl)
{
if (num_selected == 1)
{
- GtkTreeSelection *selection;
- GtkTreeModel *model;
- GtkTreeIter iter;
+ GSList *infos;
GFileInfo *info;
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
- gtk_tree_selection_get_selected (selection, &model, &iter);
- info = _gtk_file_system_model_get_info (GTK_FILE_SYSTEM_MODEL (model), &iter);
+ infos = get_selected_infos (impl);
+ info = G_FILE_INFO (infos->data);
+
gtk_widget_set_sensitive (priv->rename_file_item,
g_file_info_get_attribute_boolean (info,
G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME));
+
+ g_slist_free_full (infos, g_object_unref);
}
else
gtk_widget_set_sensitive (priv->rename_file_item, FALSE);
@@ -2122,14 +2135,12 @@ check_file_list_menu_sensitivity (GtkFileChooserWidget *impl)
{
if (num_selected == 1)
{
- GtkTreeSelection *selection;
- GtkTreeModel *model;
- GtkTreeIter iter;
+ GSList *infos;
GFileInfo *info;
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
- gtk_tree_selection_get_selected (selection, &model, &iter);
- info = _gtk_file_system_model_get_info (GTK_FILE_SYSTEM_MODEL (model), &iter);
+ infos = get_selected_infos (impl);
+ info = G_FILE_INFO (infos->data);
+
if (g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH))
{
gtk_widget_set_sensitive (priv->trash_file_item, TRUE);
@@ -2148,6 +2159,8 @@ check_file_list_menu_sensitivity (GtkFileChooserWidget *impl)
gtk_widget_set_visible (priv->delete_file_item, FALSE);
gtk_widget_set_visible (priv->trash_file_item, TRUE);
}
+
+ g_slist_free_full (infos, g_object_unref);
}
else
{
@@ -5732,7 +5745,7 @@ gtk_file_chooser_widget_get_files (GtkFileChooser *chooser)
info.file_from_entry = NULL;
if (priv->operation_mode == OPERATION_MODE_SEARCH)
- return search_get_selected_files (impl);
+ return get_selected_files (impl);
if (priv->operation_mode == OPERATION_MODE_RECENT)
{
@@ -5742,7 +5755,7 @@ gtk_file_chooser_widget_get_files (GtkFileChooser *chooser)
goto file_entry;
}
else
- return recent_get_selected_files (impl);
+ return get_selected_files (impl);
}
toplevel = get_toplevel (GTK_WIDGET (impl));
@@ -6868,12 +6881,11 @@ gtk_file_chooser_widget_initial_focus (GtkFileChooserEmbed *chooser_embed)
gtk_widget_grab_focus (widget);
}
-/* Callback used from gtk_tree_selection_selected_foreach(); gets the selected GFiles */
static void
-search_selected_foreach_get_file_cb (GtkTreeModel *model,
- GtkTreePath *path,
- GtkTreeIter *iter,
- gpointer data)
+selected_foreach_get_file_cb (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer data)
{
GSList **list;
GFile *file;
@@ -6887,9 +6899,39 @@ search_selected_foreach_get_file_cb (GtkTreeModel *model,
*list = g_slist_prepend (*list, file);
}
-/* Constructs a list of the selected paths in search mode */
static GSList *
-search_get_selected_files (GtkFileChooserWidget *impl)
+get_selected_files (GtkFileChooserWidget *impl)
+{
+ GtkFileChooserWidgetPrivate *priv = impl->priv;
+ GSList *result;
+ GtkTreeSelection *selection;
+
+ result = NULL;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
+ gtk_tree_selection_selected_foreach (selection, selected_foreach_get_file_cb, &result);
+ result = g_slist_reverse (result);
+
+ return result;
+}
+
+static void
+selected_foreach_get_info_cb (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ GSList **list;
+ GFileInfo *info;
+
+ list = data;
+
+ info = _gtk_file_system_model_get_info (GTK_FILE_SYSTEM_MODEL (model), iter);
+ *list = g_slist_prepend (*list, g_object_ref (info));
+}
+
+static GSList *
+get_selected_infos (GtkFileChooserWidget *impl)
{
GtkFileChooserWidgetPrivate *priv = impl->priv;
GSList *result;
@@ -6898,7 +6940,7 @@ search_get_selected_files (GtkFileChooserWidget *impl)
result = NULL;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
- gtk_tree_selection_selected_foreach (selection, search_selected_foreach_get_file_cb, &result);
+ gtk_tree_selection_selected_foreach (selection, selected_foreach_get_info_cb, &result);
result = g_slist_reverse (result);
return result;
@@ -7390,38 +7432,6 @@ recent_start_loading (GtkFileChooserWidget *impl)
g_source_set_name_by_id (priv->load_recent_id, "[gtk+] recent_idle_load");
}
-static void
-recent_selected_foreach_get_file_cb (GtkTreeModel *model,
- GtkTreePath *path,
- GtkTreeIter *iter,
- gpointer data)
-{
- GSList **list;
- GFile *file;
-
- list = data;
-
- gtk_tree_model_get (model, iter, MODEL_COL_FILE, &file, -1);
- *list = g_slist_prepend (*list, file);
-}
-
-/* Constructs a list of the selected paths in recent files mode */
-static GSList *
-recent_get_selected_files (GtkFileChooserWidget *impl)
-{
- GtkFileChooserWidgetPrivate *priv = impl->priv;
- GSList *result;
- GtkTreeSelection *selection;
-
- result = NULL;
-
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
- gtk_tree_selection_selected_foreach (selection, recent_selected_foreach_get_file_cb, &result);
- result = g_slist_reverse (result);
-
- return result;
-}
-
/* Called from ::should_respond(). We return whether there are selected
* files in the recent files list.
*/
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]