[gtk/file-chooser-api-cleanups] filechooser: Add gtk_file_chooser_get_shortcuts



commit e87b930f9745dcb9902d42a9224d2a6ed6038d32
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Jul 4 22:08:33 2020 -0400

    filechooser: Add gtk_file_chooser_get_shortcuts
    
    Replace gtk_file_chooser_list_shortcuts with a new
    api that returns a list model.
    
    Update all callers.

 gtk/gtkfilechooser.c            |   6 +--
 gtk/gtkfilechooser.h            |  10 ++--
 gtk/gtkfilechoosernativewin32.c |  26 ++++++----
 gtk/gtkfilechooserprivate.h     |   2 +-
 gtk/gtkfilechooserutils.c       |  10 ++--
 gtk/gtkfilechooserwidget.c      |  26 +++++-----
 gtk/gtkplacessidebar.c          | 103 ++++++++++++++++++----------------------
 gtk/gtkplacessidebarprivate.h   |   2 +-
 8 files changed, 92 insertions(+), 93 deletions(-)
---
diff --git a/gtk/gtkfilechooser.c b/gtk/gtkfilechooser.c
index 93dbf91549..251dda43b5 100644
--- a/gtk/gtkfilechooser.c
+++ b/gtk/gtkfilechooser.c
@@ -760,12 +760,12 @@ gtk_file_chooser_get_filter (GtkFileChooser *chooser)
  * Returns: (nullable) (element-type Gio.File) (transfer full): A list
  * of folder filenames, or %NULL if there are no shortcut folders.
  */
-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 71713a49ff..74cb80deb7 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);
@@ -134,7 +134,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;
@@ -263,10 +263,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 1c2d2619ed..fb1653dbae 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;
@@ -3429,25 +3429,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;
 }
@@ -5629,12 +5631,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.
+ *
+ * You should not modify the returned list model. Future changes to
+ * @sidebar may or may not affect the returned model.
  *
- * Returns: (element-type GFile) (transfer full):
- *     A #GSList of #GFile of the locations that have been added as
+ * 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
- * |[<!-- language="C" -->
- * 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);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]