From 89bf8af8784513cf95b31812a1c7fb68753b9b87 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 9 Jul 2020 01:29:20 -0400 Subject: [PATCH] filechooser: Make get_files return a list model Like the other list getters in this interface, make gtk_file_chooser_get_files() return a list model. --- gtk/gtkfilechooser.c | 31 +++++++--------- gtk/gtkfilechooser.h | 2 +- gtk/gtkfilechooserbutton.c | 16 +++++--- gtk/gtkfilechooserdialog.c | 6 +-- gtk/gtkfilechoosernative.c | 13 ++++++- gtk/gtkfilechooserprivate.h | 2 +- gtk/gtkfilechooserutils.c | 4 +- gtk/gtkfilechooserwidget.c | 55 +++++++++++++++++---------- tests/testfilechooser.c | 74 ++++++++++++++++--------------------- tests/testgtk.c | 14 ++++--- 10 files changed, 118 insertions(+), 99 deletions(-) diff --git a/gtk/gtkfilechooser.c b/gtk/gtkfilechooser.c index b77652bd1c..ff70023af9 100644 --- a/gtk/gtkfilechooser.c +++ b/gtk/gtkfilechooser.c @@ -508,16 +508,15 @@ gtk_file_chooser_unselect_file (GtkFileChooser *chooser, /** * gtk_file_chooser_get_files: * @chooser: a #GtkFileChooser - * - * Lists all the selected files and subfolders in the current folder of @chooser - * as #GFile. * - * Returns: (element-type GFile) (transfer full): a list - * containing a #GFile for each selected file and subfolder in the - * current folder. Free the returned list with g_slist_free(), and - * the files with g_object_unref(). - **/ -GSList * + * Lists all the selected files and subfolders in the current folder + * of @chooser as #GFile. + * + * Returns: (transfer full): a list model containing a #GFile for each + * selected file and subfolder in the current folder. Free the returned + * list with g_object_unref(). + */ +GListModel * gtk_file_chooser_get_files (GtkFileChooser *chooser) { g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL); @@ -597,19 +596,15 @@ gtk_file_chooser_set_file (GtkFileChooser *chooser, GFile * gtk_file_chooser_get_file (GtkFileChooser *chooser) { - GSList *list; + GListModel *list; GFile *result = NULL; - + g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL); list = gtk_file_chooser_get_files (chooser); - if (list) - { - result = list->data; - list = g_slist_delete_link (list, list); - - g_slist_free_full (list, g_object_unref); - } + if (g_list_model_get_n_items (list) > 0) + result = g_list_model_get_item (list, 0); + g_object_unref (list); return result; } diff --git a/gtk/gtkfilechooser.h b/gtk/gtkfilechooser.h index b3b5aec9b8..9fd20da3c9 100644 --- a/gtk/gtkfilechooser.h +++ b/gtk/gtkfilechooser.h @@ -123,7 +123,7 @@ gboolean gtk_file_chooser_set_file (GtkFileChooser GFile *file, GError **error); GDK_AVAILABLE_IN_ALL -GSList * gtk_file_chooser_get_files (GtkFileChooser *chooser); +GListModel * gtk_file_chooser_get_files (GtkFileChooser *chooser); GDK_AVAILABLE_IN_ALL gboolean gtk_file_chooser_set_current_folder (GtkFileChooser *chooser, GFile *file, diff --git a/gtk/gtkfilechooserbutton.c b/gtk/gtkfilechooserbutton.c index 97bd4eab90..c8d24fdb33 100644 --- a/gtk/gtkfilechooserbutton.c +++ b/gtk/gtkfilechooserbutton.c @@ -244,7 +244,7 @@ static gboolean gtk_file_chooser_button_select_file (GtkFileChooser *chooser, static void gtk_file_chooser_button_unselect_file (GtkFileChooser *chooser, GFile *file); static void gtk_file_chooser_button_unselect_all (GtkFileChooser *chooser); -static GSList *gtk_file_chooser_button_get_files (GtkFileChooser *chooser); +static GListModel *gtk_file_chooser_button_get_files (GtkFileChooser *chooser); static gboolean gtk_file_chooser_button_add_shortcut_folder (GtkFileChooser *chooser, GFile *file, GError **error); @@ -750,17 +750,23 @@ get_selected_file (GtkFileChooserButton *button) return NULL; } -static GSList * +static GListModel * gtk_file_chooser_button_get_files (GtkFileChooser *chooser) { GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (chooser); GFile *file; + GListStore *store; + + store = g_list_store_new (G_TYPE_FILE); file = get_selected_file (button); if (file) - return g_slist_prepend (NULL, file); - else - return NULL; + { + g_list_store_append (store, file); + g_object_unref (file); + } + + return G_LIST_MODEL (store); } static gboolean diff --git a/gtk/gtkfilechooserdialog.c b/gtk/gtkfilechooserdialog.c index 46ce76e4d7..dd22c08a7e 100644 --- a/gtk/gtkfilechooserdialog.c +++ b/gtk/gtkfilechooserdialog.c @@ -381,7 +381,7 @@ file_chooser_widget_selection_changed (GtkWidget *widget, { GtkFileChooserDialogPrivate *priv = gtk_file_chooser_dialog_get_instance_private (dialog); GtkWidget *button; - GSList *files; + GListModel *files; gboolean sensitive; button = get_accept_action_widget (GTK_DIALOG (dialog), FALSE); @@ -389,10 +389,10 @@ file_chooser_widget_selection_changed (GtkWidget *widget, return; files = gtk_file_chooser_get_files (GTK_FILE_CHOOSER (priv->widget)); - sensitive = (files != NULL); + sensitive = (g_list_model_get_n_items (files) > 0); gtk_widget_set_sensitive (button, sensitive); - g_slist_free_full (files, g_object_unref); + g_object_unref (files); } static void diff --git a/gtk/gtkfilechoosernative.c b/gtk/gtkfilechoosernative.c index 4eb46e4a4e..d4c6563d25 100644 --- a/gtk/gtkfilechoosernative.c +++ b/gtk/gtkfilechoosernative.c @@ -683,7 +683,7 @@ gtk_file_chooser_native_set_current_name (GtkFileChooser *chooser, g_clear_object (&self->current_file); } -static GSList * +static GListModel * gtk_file_chooser_native_get_files (GtkFileChooser *chooser) { GtkFileChooserNative *self = GTK_FILE_CHOOSER_NATIVE (chooser); @@ -693,7 +693,16 @@ gtk_file_chooser_native_get_files (GtkFileChooser *chooser) case MODE_PORTAL: case MODE_WIN32: case MODE_QUARTZ: - return g_slist_copy_deep (self->custom_files, (GCopyFunc)g_object_ref, NULL); + { + GListStore *store; + GSList *l; + + store = g_list_store_new (G_TYPE_FILE); + for (l = self->custom_files; l; l = l->next) + g_list_store_append (store, l->data); + + return G_LIST_MODEL (store); + } case MODE_FALLBACK: default: diff --git a/gtk/gtkfilechooserprivate.h b/gtk/gtkfilechooserprivate.h index a88fe367f7..092d785eb9 100644 --- a/gtk/gtkfilechooserprivate.h +++ b/gtk/gtkfilechooserprivate.h @@ -72,7 +72,7 @@ struct _GtkFileChooserIface GFile *file); void (*select_all) (GtkFileChooser *chooser); void (*unselect_all) (GtkFileChooser *chooser); - GSList * (*get_files) (GtkFileChooser *chooser); + GListModel * (*get_files) (GtkFileChooser *chooser); GtkFileSystem *(*get_file_system) (GtkFileChooser *chooser); void (*add_filter) (GtkFileChooser *chooser, GtkFileFilter *filter); diff --git a/gtk/gtkfilechooserutils.c b/gtk/gtkfilechooserutils.c index d41d9513cb..d05585c299 100644 --- a/gtk/gtkfilechooserutils.c +++ b/gtk/gtkfilechooserutils.c @@ -39,7 +39,7 @@ static void delegate_unselect_file (GtkFileChooser *choose GFile *file); static void delegate_select_all (GtkFileChooser *chooser); static void delegate_unselect_all (GtkFileChooser *chooser); -static GSList * delegate_get_files (GtkFileChooser *chooser); +static GListModel * delegate_get_files (GtkFileChooser *chooser); static GtkFileSystem *delegate_get_file_system (GtkFileChooser *chooser); static void delegate_add_filter (GtkFileChooser *chooser, GtkFileFilter *filter); @@ -221,7 +221,7 @@ delegate_unselect_all (GtkFileChooser *chooser) gtk_file_chooser_unselect_all (get_delegate (chooser)); } -static GSList * +static GListModel * delegate_get_files (GtkFileChooser *chooser) { return gtk_file_chooser_get_files (get_delegate (chooser)); diff --git a/gtk/gtkfilechooserwidget.c b/gtk/gtkfilechooserwidget.c index 3551463c23..9a6f3b31fe 100644 --- a/gtk/gtkfilechooserwidget.c +++ b/gtk/gtkfilechooserwidget.c @@ -479,7 +479,7 @@ static void gtk_file_chooser_widget_unselect_file (GtkF GFile *file); static void gtk_file_chooser_widget_select_all (GtkFileChooser *chooser); static void gtk_file_chooser_widget_unselect_all (GtkFileChooser *chooser); -static GSList * gtk_file_chooser_widget_get_files (GtkFileChooser *chooser); +static GListModel * gtk_file_chooser_widget_get_files (GtkFileChooser *chooser); static GtkFileSystem *gtk_file_chooser_widget_get_file_system (GtkFileChooser *chooser); static void gtk_file_chooser_widget_add_filter (GtkFileChooser *chooser, GtkFileFilter *filter); @@ -5408,7 +5408,7 @@ check_save_entry (GtkFileChooserWidget *impl, struct get_files_closure { GtkFileChooserWidget *impl; - GSList *result; + GListStore *result; GFile *file_from_entry; }; @@ -5425,10 +5425,25 @@ get_files_foreach (GtkTreeModel *model, file = _gtk_file_system_model_get_file (fs_model, iter); if (!info->file_from_entry || !g_file_equal (info->file_from_entry, file)) - info->result = g_slist_prepend (info->result, g_object_ref (file)); + g_list_store_append (info->result, file); } -static GSList * +static GListModel * +get_selected_files_as_model (GtkFileChooserWidget *impl) +{ + GListStore *store; + GSList *files, *l; + + store = g_list_store_new (G_TYPE_FILE); + files = get_selected_files (impl); + for (l = files; l; l = l->next) + g_list_store_append (store, l->data); + g_slist_free_full (files, g_object_unref); + + return G_LIST_MODEL (store); +} + +static GListModel * gtk_file_chooser_widget_get_files (GtkFileChooser *chooser) { GtkFileChooserWidget *impl = GTK_FILE_CHOOSER_WIDGET (chooser); @@ -5437,12 +5452,8 @@ gtk_file_chooser_widget_get_files (GtkFileChooser *chooser) GtkWidget *current_focus; gboolean file_list_seen; - info.impl = impl; - info.result = NULL; - info.file_from_entry = NULL; - if (impl->operation_mode == OPERATION_MODE_SEARCH) - return get_selected_files (impl); + return get_selected_files_as_model (impl); if (impl->operation_mode == OPERATION_MODE_RECENT) { @@ -5452,9 +5463,13 @@ gtk_file_chooser_widget_get_files (GtkFileChooser *chooser) goto file_entry; } else - return get_selected_files (impl); + return get_selected_files_as_model (impl); } + info.impl = impl; + info.result = g_list_store_new (G_TYPE_FILE); + info.file_from_entry = NULL; + toplevel = get_toplevel (GTK_WIDGET (impl)); if (toplevel) current_focus = gtk_root_get_focus (GTK_ROOT (toplevel)); @@ -5498,7 +5513,7 @@ gtk_file_chooser_widget_get_files (GtkFileChooser *chooser) return NULL; if (info.file_from_entry) - info.result = g_slist_prepend (info.result, info.file_from_entry); + g_list_store_append (info.result, info.file_from_entry); else if (!file_list_seen) goto file_list; else @@ -5530,10 +5545,10 @@ gtk_file_chooser_widget_get_files (GtkFileChooser *chooser) current_folder = gtk_file_chooser_get_current_folder (chooser); if (current_folder) - info.result = g_slist_prepend (info.result, current_folder); + g_list_store_append (info.result, current_folder); } - return g_slist_reverse (info.result); + return G_LIST_MODEL (info.result); } static GtkFileSystem * @@ -6143,18 +6158,18 @@ location_popup_on_paste_handler (GtkFileChooserWidget *impl) static void add_selection_to_recent_list (GtkFileChooserWidget *impl) { - GSList *files; - GSList *l; + GListModel *files; + guint i, n; files = gtk_file_chooser_widget_get_files (GTK_FILE_CHOOSER (impl)); - if (!impl->recent_manager) impl->recent_manager = gtk_recent_manager_get_default (); - for (l = files; l; l = l->next) + n = g_list_model_get_n_items (files); + for (i = 0; i < n; i++) { - GFile *file = l->data; + GFile *file = g_list_model_get_item (files, i); char *uri; uri = g_file_get_uri (file); @@ -6163,9 +6178,11 @@ add_selection_to_recent_list (GtkFileChooserWidget *impl) gtk_recent_manager_add_item (impl->recent_manager, uri); g_free (uri); } + + g_object_unref (file); } - g_slist_free_full (files, g_object_unref); + g_object_unref (files); } static gboolean diff --git a/tests/testfilechooser.c b/tests/testfilechooser.c index eace90337c..d5eef8aeda 100644 --- a/tests/testfilechooser.c +++ b/tests/testfilechooser.c @@ -63,19 +63,21 @@ print_current_folder (GtkFileChooser *chooser) static void print_selected (GtkFileChooser *chooser) { - GSList *uris = gtk_file_chooser_get_files (chooser); - GSList *tmp_list; + GListModel *files = gtk_file_chooser_get_files (chooser); + guint i, n; g_print ("Selection changed :\n"); - for (tmp_list = uris; tmp_list; tmp_list = tmp_list->next) + n = g_list_model_get_n_items (files); + for (i = 0; i < n; i++) { - GFile *file = tmp_list->data; + GFile *file = g_list_model_get_item (files, i); char *uri = g_file_get_uri (file); g_print (" %s\n", uri ? uri : "(null)"); g_free (uri); + g_object_unref (files); } g_print ("\n"); - g_slist_free_full (uris, g_object_unref); + g_object_unref (files); } static void @@ -87,28 +89,23 @@ response_cb (GtkDialog *dialog, if (response_id == GTK_RESPONSE_OK) { - GSList *list; + GListModel *files; + guint i, n; - list = gtk_file_chooser_get_files (GTK_FILE_CHOOSER (dialog)); + files = gtk_file_chooser_get_files (GTK_FILE_CHOOSER (dialog)); + n = g_list_model_get_n_items (files); - if (list) - { - GSList *l; + g_print ("Selected files:\n"); + for (i = 0; i < n; i++) + { + GFile *file = g_list_model_get_item (files, i); + char *uri = g_file_get_uri (file); + g_print (" %s\n", uri ? uri : "(null)"); + g_free (uri); + g_object_unref (file); + } - g_print ("Selected files:\n"); - - for (l = list; l; l = l->next) - { - GFile *file = l->data; - char *uri = g_file_get_uri (file); - g_print (" %s\n", uri ? uri : "(null)"); - g_free (uri); - } - - g_slist_free_full (list, g_object_unref); - } - else - g_print ("No selected files\n"); + g_object_unref (files); } else g_print ("Dialog was closed\n"); @@ -208,33 +205,24 @@ static void get_selection_cb (GtkButton *button, GtkFileChooser *chooser) { - GSList *selection; + GListModel *selection; + guint i, n; selection = gtk_file_chooser_get_files (chooser); + n = g_list_model_get_n_items (selection); g_print ("Selection: "); - if (selection == NULL) - g_print ("empty\n"); - else + for (i = 0; i < n; i++) { - GSList *l; - - for (l = selection; l; l = l->next) - { - GFile *file = l->data; - char *uri = g_file_get_uri (file); - - g_print ("%s\n", uri); - - g_free (uri); - - if (l->next) - g_print (" "); - } + GFile *file = g_list_model_get_item (selection, i); + char *uri = g_file_get_uri (file); + g_print ("%s\n", uri); + g_free (uri); + g_object_unref (file); } - g_slist_free_full (selection, g_object_unref); + g_object_unref (selection); } static void diff --git a/tests/testgtk.c b/tests/testgtk.c index 50db5c8111..acb14b7615 100644 --- a/tests/testgtk.c +++ b/tests/testgtk.c @@ -5507,22 +5507,26 @@ native_response (GtkNativeDialog *self, { static int count = 0; char *res; - GSList *uris, *l; GString *s; char *response; GtkFileFilter *filter; + GListModel *files; + guint i, n; - uris = gtk_file_chooser_get_files (GTK_FILE_CHOOSER (self)); + files = gtk_file_chooser_get_files (GTK_FILE_CHOOSER (self)); filter = gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (self)); s = g_string_new (""); - for (l = uris; l != NULL; l = l->next) + n = g_list_model_get_n_items (files); + for (i = 0; i < n; i++) { - char *uri = g_file_get_uri (l->data); + GFile *file = g_list_model_get_item (files, i); + char *uri = g_file_get_uri (file); g_string_prepend (s, uri); g_string_prepend (s, "\n"); g_free (uri); + g_object_unref (file); } - g_slist_free_full (uris, g_object_unref); + g_object_unref (files); switch (response_id) {