diff --git a/gtk/gtkfilechooser.c b/gtk/gtkfilechooser.c index 0ce214feec..0c42fb8f7b 100644 --- a/gtk/gtkfilechooser.c +++ b/gtk/gtkfilechooser.c @@ -767,21 +767,23 @@ gtk_file_chooser_get_filter (GtkFileChooser *chooser) } /** - * gtk_file_chooser_list_shortcut_folders: + * gtk_file_chooser_get_shortcut_folders: * @chooser: a #GtkFileChooser * * Queries the list of shortcut folders in the file chooser, as set by * gtk_file_chooser_add_shortcut_folder(). * - * Returns: (nullable) (element-type Gio.File) (transfer full): A list - * of folder filenames, or %NULL if there are no shortcut folders. + * You should not modify the returned list model. Future changes to + * @chooser may or may not affect the returned model. + * + * Returns: (transfer full): A list model of #GFiles */ -GSList * -gtk_file_chooser_list_shortcut_folders (GtkFileChooser *chooser) +GListModel * +gtk_file_chooser_get_shortcut_folders (GtkFileChooser *chooser) { g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL); - return GTK_FILE_CHOOSER_GET_IFACE (chooser)->list_shortcut_folders (chooser); + return GTK_FILE_CHOOSER_GET_IFACE (chooser)->get_shortcut_folders (chooser); } /** diff --git a/gtk/gtkfilechooser.h b/gtk/gtkfilechooser.h index 1f3381b993..f37aea031e 100644 --- a/gtk/gtkfilechooser.h +++ b/gtk/gtkfilechooser.h @@ -164,14 +164,14 @@ GtkFileFilter *gtk_file_chooser_get_filter (GtkFileChooser *chooser); GDK_AVAILABLE_IN_ALL gboolean gtk_file_chooser_add_shortcut_folder (GtkFileChooser *chooser, - GFile *folder, - GError **error); + GFile *folder, + GError **error); GDK_AVAILABLE_IN_ALL gboolean gtk_file_chooser_remove_shortcut_folder (GtkFileChooser *chooser, - GFile *folder, - GError **error); + GFile *folder, + GError **error); GDK_AVAILABLE_IN_ALL -GSList *gtk_file_chooser_list_shortcut_folders (GtkFileChooser *chooser); +GListModel *gtk_file_chooser_get_shortcut_folders (GtkFileChooser *chooser); GDK_AVAILABLE_IN_ALL void gtk_file_chooser_add_choice (GtkFileChooser *chooser, diff --git a/gtk/gtkfilechoosernativewin32.c b/gtk/gtkfilechoosernativewin32.c index 722f324ae8..66157ccd69 100644 --- a/gtk/gtkfilechoosernativewin32.c +++ b/gtk/gtkfilechoosernativewin32.c @@ -66,7 +66,7 @@ typedef struct { char *cancel_label; char *title; - GSList *shortcut_files; + GListModel *shortcut_files; GArray *choices_selections; GFile *current_folder; @@ -330,7 +330,7 @@ filechooser_win32_thread_data_free (FilechooserWin32ThreadData *data) g_array_free (data->choices_selections, TRUE); data->choices_selections = NULL; } - g_slist_free_full (data->shortcut_files, g_object_unref); + g_object_unref (data->shortcut_files); g_slist_free_full (data->files, g_object_unref); if (data->self) g_object_unref (data->self); @@ -465,7 +465,7 @@ filechooser_win32_thread (gpointer _data) IFileDialog2 *pfd2 = NULL; DWORD flags; DWORD cookie; - GSList *l; + guint j, n_items; CoInitializeEx (NULL, COINIT_APARTMENTTHREADED); @@ -531,9 +531,11 @@ filechooser_win32_thread (gpointer _data) g_free (label); } - for (l = data->shortcut_files; l != NULL; l = l->next) + n_items = g_list_model_get_n_items (data->shortcut_files); + for (j = 0; j < n_items; j++) { - IShellItem *item = get_shell_item_for_file (l->data); + GFile *file = g_list_model_get_item (data->shortcut_files, j); + IShellItem *item = get_shell_item_for_file (file); if (item) { hr = IFileDialog_AddPlace (pfd, item, FDAP_BOTTOM); @@ -541,6 +543,7 @@ filechooser_win32_thread (gpointer _data) g_warning_hr ("Can't add dialog shortcut", hr); IShellItem_Release (item); } + g_object_unref (file); } if (data->current_file) @@ -594,17 +597,16 @@ filechooser_win32_thread (gpointer _data) if (data->self->current_filter) { GListModel *filters; - guint n_items, i; guint current_filter_index = GTK_INVALID_LIST_POSITION; filters = gtk_file_chooser_get_filters (GTK_FILE_CHOOSER (data->self)); n_items = g_list_model_get_n_items (filters); - for (i = 0; i < n_items; i++) + for (j = 0; j < n_items; j++) { - gpointer item = g_list_model_get_item (filters, i); + gpointer item = g_list_model_get_item (filters, j); if (item == data->self->current_filter) { - current_filter_index = i; + current_filter_index = j; g_object_unref (item); break; } @@ -634,6 +636,8 @@ filechooser_win32_thread (gpointer _data) hr = IFileDialog_QueryInterface (pfd, &IID_IFileDialogCustomize, (LPVOID *) &pfdc); if (SUCCEEDED (hr)) { + GSList *l; + for (l = data->self->choices; l; l = l->next, dialog_control_id++) { GtkFileChooserNativeChoice *choice = (GtkFileChooserNativeChoice*) l->data; @@ -759,6 +763,8 @@ filechooser_win32_thread (gpointer _data) hr = IFileDialog_QueryInterface (pfd, &IID_IFileDialogCustomize, (LPVOID *) &pfdc); if (SUCCEEDED (hr)) { + GSList *l; + for (l = data->self->choices; l; l = l->next) { GtkFileChooserNativeChoice *choice = (GtkFileChooserNativeChoice*) l->data; @@ -915,7 +921,7 @@ gtk_file_chooser_native_win32_show (GtkFileChooserNative *self) data->self = g_object_ref (self); data->shortcut_files = - gtk_file_chooser_list_shortcut_folders (GTK_FILE_CHOOSER (self->dialog)); + gtk_file_chooser_get_shortcut_folders (GTK_FILE_CHOOSER (self->dialog)); data->accept_label = translate_mnemonics (self->accept_label); data->cancel_label = translate_mnemonics (self->cancel_label); diff --git a/gtk/gtkfilechooserprivate.h b/gtk/gtkfilechooserprivate.h index d0f2b53910..85e86c8905 100644 --- a/gtk/gtkfilechooserprivate.h +++ b/gtk/gtkfilechooserprivate.h @@ -85,7 +85,7 @@ struct _GtkFileChooserIface gboolean (*remove_shortcut_folder) (GtkFileChooser *chooser, GFile *file, GError **error); - GSList * (*list_shortcut_folders) (GtkFileChooser *chooser); + GListModel * (*get_shortcut_folders) (GtkFileChooser *chooser); /* Signals */ diff --git a/gtk/gtkfilechooserutils.c b/gtk/gtkfilechooserutils.c index 91da4cfd36..e3fb636731 100644 --- a/gtk/gtkfilechooserutils.c +++ b/gtk/gtkfilechooserutils.c @@ -52,7 +52,7 @@ static gboolean delegate_add_shortcut_folder (GtkFileChooser *choose static gboolean delegate_remove_shortcut_folder (GtkFileChooser *chooser, GFile *file, GError **error); -static GSList * delegate_list_shortcut_folders (GtkFileChooser *chooser); +static GListModel * delegate_get_shortcut_folders (GtkFileChooser *chooser); static void delegate_notify (GObject *object, GParamSpec *pspec, gpointer data); @@ -137,7 +137,7 @@ _gtk_file_chooser_delegate_iface_init (GtkFileChooserIface *iface) iface->get_filters = delegate_get_filters; iface->add_shortcut_folder = delegate_add_shortcut_folder; iface->remove_shortcut_folder = delegate_remove_shortcut_folder; - iface->list_shortcut_folders = delegate_list_shortcut_folders; + iface->get_shortcut_folders = delegate_get_shortcut_folders; iface->add_choice = delegate_add_choice; iface->remove_choice = delegate_remove_choice; iface->set_choice = delegate_set_choice; @@ -266,10 +266,10 @@ delegate_remove_shortcut_folder (GtkFileChooser *chooser, return gtk_file_chooser_remove_shortcut_folder (get_delegate (chooser), file, error); } -static GSList * -delegate_list_shortcut_folders (GtkFileChooser *chooser) +static GListModel * +delegate_get_shortcut_folders (GtkFileChooser *chooser) { - return gtk_file_chooser_list_shortcut_folders (get_delegate (chooser)); + return gtk_file_chooser_get_shortcut_folders (get_delegate (chooser)); } static gboolean diff --git a/gtk/gtkfilechooserwidget.c b/gtk/gtkfilechooserwidget.c index 48991021a8..e9fb6cbcab 100644 --- a/gtk/gtkfilechooserwidget.c +++ b/gtk/gtkfilechooserwidget.c @@ -492,7 +492,7 @@ static gboolean gtk_file_chooser_widget_add_shortcut_folder (GtkFileCho static gboolean gtk_file_chooser_widget_remove_shortcut_folder (GtkFileChooser *chooser, GFile *file, GError **error); -static GSList * gtk_file_chooser_widget_list_shortcut_folders (GtkFileChooser *chooser); +static GListModel * gtk_file_chooser_widget_get_shortcut_folders (GtkFileChooser *chooser); static gboolean gtk_file_chooser_widget_should_respond (GtkFileChooserEmbed *chooser_embed); static void gtk_file_chooser_widget_initial_focus (GtkFileChooserEmbed *chooser_embed); @@ -622,7 +622,7 @@ gtk_file_chooser_widget_iface_init (GtkFileChooserIface *iface) iface->get_filters = gtk_file_chooser_widget_get_filters; iface->add_shortcut_folder = gtk_file_chooser_widget_add_shortcut_folder; iface->remove_shortcut_folder = gtk_file_chooser_widget_remove_shortcut_folder; - iface->list_shortcut_folders = gtk_file_chooser_widget_list_shortcut_folders; + iface->get_shortcut_folders = gtk_file_chooser_widget_get_shortcut_folders; iface->add_choice = gtk_file_chooser_widget_add_choice; iface->remove_choice = gtk_file_chooser_widget_remove_choice; iface->set_choice = gtk_file_chooser_widget_set_choice; @@ -3433,25 +3433,27 @@ set_startup_mode (GtkFileChooserWidget *impl) static gboolean shortcut_exists (GtkFileChooserWidget *impl, GFile *needle) { - GSList *haystack; - GSList *l; + GListModel *haystack; + guint n, i; gboolean exists; exists = FALSE; - haystack = gtk_places_sidebar_list_shortcuts (GTK_PLACES_SIDEBAR (impl->places_sidebar)); - for (l = haystack; l; l = l->next) + haystack = gtk_places_sidebar_get_shortcuts (GTK_PLACES_SIDEBAR (impl->places_sidebar)); + n = g_list_model_get_n_items (haystack); + for (i = 0; i < n; i++) { - GFile *hay; + GFile *hay = g_list_model_get_item (haystack, i); - hay = G_FILE (l->data); if (g_file_equal (hay, needle)) { + g_object_unref (hay); exists = TRUE; break; } + g_object_unref (hay); } - g_slist_free_full (haystack, g_object_unref); + g_object_unref (haystack); return exists; } @@ -5637,12 +5639,12 @@ gtk_file_chooser_widget_remove_shortcut_folder (GtkFileChooser *chooser, return TRUE; } -static GSList * -gtk_file_chooser_widget_list_shortcut_folders (GtkFileChooser *chooser) +static GListModel * +gtk_file_chooser_widget_get_shortcut_folders (GtkFileChooser *chooser) { GtkFileChooserWidget *impl = GTK_FILE_CHOOSER_WIDGET (chooser); - return gtk_places_sidebar_list_shortcuts (GTK_PLACES_SIDEBAR (impl->places_sidebar)); + return gtk_places_sidebar_get_shortcuts (GTK_PLACES_SIDEBAR (impl->places_sidebar)); } struct switch_folder_closure { diff --git a/gtk/gtkplacessidebar.c b/gtk/gtkplacessidebar.c index 3fa3cc5c3e..1131668f58 100644 --- a/gtk/gtkplacessidebar.c +++ b/gtk/gtkplacessidebar.c @@ -162,7 +162,7 @@ struct _GtkPlacesSidebar { GtkWidget *popover; GtkSidebarRow *context_row; - GSList *shortcuts; + GListStore *shortcuts; GDBusProxy *hostnamed_proxy; GCancellable *hostnamed_cancellable; @@ -709,15 +709,25 @@ file_is_shown (GtkPlacesSidebar *sidebar, return found; } +typedef struct +{ + GtkPlacesSidebar *sidebar; + guint position; +} ShortcutData; + static void on_app_shortcuts_query_complete (GObject *source, GAsyncResult *result, gpointer data) { - GtkPlacesSidebar *sidebar = data; + ShortcutData *sdata = data; + GtkPlacesSidebar *sidebar = sdata->sidebar; + guint pos = sdata->position; GFile *file = G_FILE (source); GFileInfo *info; + g_free (sdata); + info = g_file_query_info_finish (file, result, NULL); if (info) @@ -726,20 +736,12 @@ on_app_shortcuts_query_complete (GObject *source, gchar *tooltip; const gchar *name; GIcon *start_icon; - int pos = 0; name = g_file_info_get_display_name (info); start_icon = g_file_info_get_symbolic_icon (info); uri = g_file_get_uri (file); tooltip = g_file_get_parse_name (file); - /* XXX: we could avoid this by using an ancillary closure - * with the index coming from add_application_shortcuts(), - * but in terms of algorithmic overhead, the application - * shortcuts is not going to be really big - */ - pos = g_slist_index (sidebar->shortcuts, file); - add_place (sidebar, PLACES_BUILT_IN, SECTION_COMPUTER, name, start_icon, NULL, uri, @@ -757,11 +759,13 @@ on_app_shortcuts_query_complete (GObject *source, static void add_application_shortcuts (GtkPlacesSidebar *sidebar) { - GSList *l; + guint i, n; - for (l = sidebar->shortcuts; l; l = l->next) + n = g_list_model_get_n_items (G_LIST_MODEL (sidebar->shortcuts)); + for (i = 0; i < n; i++) { - GFile *file = l->data; + GFile *file = g_list_model_get_item (G_LIST_MODEL (sidebar->shortcuts), i); + ShortcutData *data; if (!should_show_file (sidebar, file)) continue; @@ -769,13 +773,16 @@ add_application_shortcuts (GtkPlacesSidebar *sidebar) if (file_is_shown (sidebar, file)) continue; + data = g_new (ShortcutData, 1); + data->sidebar = sidebar; + data->position = i; g_file_query_info_async (file, "standard::display-name,standard::symbolic-icon", G_FILE_QUERY_INFO_NONE, G_PRIORITY_DEFAULT, sidebar->cancellable, on_app_shortcuts_query_complete, - sidebar); + data); } } @@ -3748,6 +3755,8 @@ gtk_places_sidebar_init (GtkPlacesSidebar *sidebar) sidebar->show_recent = TRUE; sidebar->show_desktop = TRUE; + sidebar->shortcuts = g_list_store_new (G_TYPE_FILE); + create_volume_monitor (sidebar); sidebar->open_flags = GTK_PLACES_OPEN_NORMAL; @@ -4018,9 +4027,7 @@ gtk_places_sidebar_dispose (GObject *object) g_clear_object (&sidebar->current_location); g_clear_pointer (&sidebar->rename_uri, g_free); - - g_slist_free_full (sidebar->shortcuts, g_object_unref); - sidebar->shortcuts = NULL; + g_clear_object (&sidebar->shortcuts); #ifdef HAVE_CLOUDPROVIDERS for (l = cloud_providers_collector_get_providers (sidebar->cloud_manager); @@ -4782,24 +4789,6 @@ gtk_places_sidebar_get_show_trash (GtkPlacesSidebar *sidebar) return sidebar->show_trash; } -static GSList * -find_shortcut_link (GtkPlacesSidebar *sidebar, - GFile *location) -{ - GSList *l; - - for (l = sidebar->shortcuts; l; l = l->next) - { - GFile *shortcut; - - shortcut = G_FILE (l->data); - if (g_file_equal (shortcut, location)) - return l; - } - - return NULL; -} - /* * gtk_places_sidebar_add_shortcut: * @sidebar: a places sidebar @@ -4823,8 +4812,7 @@ gtk_places_sidebar_add_shortcut (GtkPlacesSidebar *sidebar, g_return_if_fail (GTK_IS_PLACES_SIDEBAR (sidebar)); g_return_if_fail (G_IS_FILE (location)); - g_object_ref (location); - sidebar->shortcuts = g_slist_append (sidebar->shortcuts, location); + g_list_store_append (sidebar->shortcuts, location); update_places (sidebar); } @@ -4842,43 +4830,46 @@ void gtk_places_sidebar_remove_shortcut (GtkPlacesSidebar *sidebar, GFile *location) { - GSList *link; - GFile *shortcut; + guint i, n; g_return_if_fail (GTK_IS_PLACES_SIDEBAR (sidebar)); g_return_if_fail (G_IS_FILE (location)); - link = find_shortcut_link (sidebar, location); - if (!link) - return; + n = g_list_model_get_n_items (G_LIST_MODEL (sidebar->shortcuts)); + for (i = 0; i < n; i++) + { + GFile *shortcut = g_list_model_get_item (G_LIST_MODEL (sidebar->shortcuts), i); - shortcut = G_FILE (link->data); - g_object_unref (shortcut); + if (shortcut == location) + { + g_list_store_remove (sidebar->shortcuts, i); + g_object_unref (shortcut); + update_places (sidebar); + return; + } - sidebar->shortcuts = g_slist_delete_link (sidebar->shortcuts, link); - update_places (sidebar); + g_object_unref (shortcut); + } } /* * gtk_places_sidebar_list_shortcuts: * @sidebar: a places sidebar * - * Gets the list of shortcuts. + * Gets the list of shortcuts, as a list model containing #GFile objects. * - * Returns: (element-type GFile) (transfer full): - * A #GSList of #GFile of the locations that have been added as + * You should not modify the returned list model. Future changes to + * @sidebar may or may not affect the returned model. + * + * Returns: (transfer full): a list model of #GFiles that have been added as * application-specific shortcuts with gtk_places_sidebar_add_shortcut(). - * To free this list, you can use - * |[ - * g_slist_free_full (list, (GDestroyNotify) g_object_unref); - * ]| */ -GSList * -gtk_places_sidebar_list_shortcuts (GtkPlacesSidebar *sidebar) +GListModel * +gtk_places_sidebar_get_shortcuts (GtkPlacesSidebar *sidebar) { g_return_val_if_fail (GTK_IS_PLACES_SIDEBAR (sidebar), NULL); - return g_slist_copy_deep (sidebar->shortcuts, (GCopyFunc) g_object_ref, NULL); + return G_LIST_MODEL (g_object_ref (sidebar->shortcuts)); } /* diff --git a/gtk/gtkplacessidebarprivate.h b/gtk/gtkplacessidebarprivate.h index ec0b35b325..a3b011b612 100644 --- a/gtk/gtkplacessidebarprivate.h +++ b/gtk/gtkplacessidebarprivate.h @@ -92,7 +92,7 @@ void gtk_places_sidebar_add_shortcut (GtkPlacesSideb GFile *location); void gtk_places_sidebar_remove_shortcut (GtkPlacesSidebar *sidebar, GFile *location); -GSList * gtk_places_sidebar_list_shortcuts (GtkPlacesSidebar *sidebar); +GListModel * gtk_places_sidebar_get_shortcuts (GtkPlacesSidebar *sidebar); GFile * gtk_places_sidebar_get_nth_bookmark (GtkPlacesSidebar *sidebar, gint n);