[gtk+/multiroot-filechooser-2-20] Use a boxed G_TYPE_STRV for the 'root-uris' property, not a pointer to a list



commit 33026141792469d54d599bc23f1590bb9747cf82
Author: Federico Mena Quintero <federico novell com>
Date:   Mon Sep 6 15:07:42 2010 -0500

    Use a boxed G_TYPE_STRV for the 'root-uris' property, not a pointer to a list
    
    That should be friendlier to language bindings, and it makes our memory management correct.
    
    Signed-off-by: Federico Mena Quintero <federico novell com>

 gtk/gtkfilechooser.c        |   57 +++++++++++++++++++++++--------
 gtk/gtkfilechooser.h        |    4 +-
 gtk/gtkfilechooserbutton.c  |   27 +++++----------
 gtk/gtkfilechooserdefault.c |   76 +++++++++++++++++++++++++++++++++++--------
 gtk/gtkfilechooserentry.c   |    2 +-
 gtk/gtkfilechooserprivate.h |    3 +-
 gtk/gtkpathbar.c            |    2 +-
 7 files changed, 118 insertions(+), 53 deletions(-)
---
diff --git a/gtk/gtkfilechooser.c b/gtk/gtkfilechooser.c
index 5c6669c..8b124e0 100644
--- a/gtk/gtkfilechooser.c
+++ b/gtk/gtkfilechooser.c
@@ -864,9 +864,10 @@ gtk_file_chooser_class_init (gpointer g_iface)
    * Since: 2.18
    */
   g_object_interface_install_property (g_iface,
-				       g_param_spec_pointer ("root-uris",
+				       g_param_spec_boxed ("root-uris",
 							   P_("Root URIs"),
 							   P_("The URIs, if any, to use as the root for all access in the file chooser."),
+							   G_TYPE_STRV,
 							   GTK_PARAM_READWRITE));
 }
 
@@ -988,7 +989,7 @@ gtk_file_chooser_get_local_only (GtkFileChooser *chooser)
 /**
  * gtk_file_chooser_set_root_uris:
  * @chooser: a #GtkFileChooser
- * @root_uri: The root URI, or %NULL to allow access to everything.
+ * @root_uris: A %NULL-terminated array of strings with the root URIs, or %NULL to allow access to everything.
  *
  * Sets the URIs that will be the roots of the file chooser. The file
  * chooser will not display or allow access to files outside of these URIs.
@@ -1010,7 +1011,7 @@ gtk_file_chooser_get_local_only (GtkFileChooser *chooser)
  **/
 void
 gtk_file_chooser_set_root_uris (GtkFileChooser *chooser,
-			        GSList         *root_uris)
+			        const gchar   **root_uris)
 {
   g_return_if_fail (GTK_IS_FILE_CHOOSER (chooser));
 
@@ -1037,14 +1038,16 @@ gtk_file_chooser_set_root_uris (GtkFileChooser *chooser,
  *
  * See gtk_file_chooser_set_root_uris()
  *
- * Return value: The root URIs, or %NULL.
+ * Return value: A %NULL-terminated array of strings with the URIs of the roots,
+ * or simply %NULL if there are no roots set for the @chooser.  You should free
+ * this array with g_strfreev().
  *
  * Since: 2.18
  **/
-GSList *
+gchar **
 gtk_file_chooser_get_root_uris (GtkFileChooser *chooser)
 {
-  GSList *root_uris;
+  gchar **root_uris;
 
   g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL);
 
@@ -2885,16 +2888,16 @@ uri_has_prefix (const char *uri, const char *prefix)
 }
 
 gboolean
-_gtk_file_chooser_uri_has_prefix (const char *uri, GSList *prefixes)
+_gtk_file_chooser_uri_is_in_roots_list (const char *uri, GSList *roots)
 {
   GSList *l;
 
   g_return_val_if_fail (uri != NULL, FALSE);
 
-  if (prefixes == NULL)
-    return TRUE; /* No prefix means all URIs are good */
+  if (roots == NULL)
+    return TRUE; /* No roots means all URIs are good */
 
-  for (l = prefixes; l != NULL; l = l->next)
+  for (l = roots; l; l = l->next)
     {
       const char *prefix = l->data;
 
@@ -2905,18 +2908,36 @@ _gtk_file_chooser_uri_has_prefix (const char *uri, GSList *prefixes)
   return FALSE;
 }
 
+static gboolean
+uri_is_in_roots_strv (const char *uri, gchar **roots)
+{
+  gchar **r;
+
+  if (!roots)
+    return TRUE; /* No roots means all URIs are good */
+
+  for (r = roots; *r; r++)
+    if (uri_has_prefix (uri, *r))
+      return TRUE;
+
+  return FALSE;
+}
+
 gboolean
 _gtk_file_chooser_is_uri_in_roots (GtkFileChooser *chooser,
 				   const char     *uri)
 {
-  GSList *root_uris;
+  gchar **root_uris;
+  gboolean is_in_roots;
 
   g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), FALSE);
   g_return_val_if_fail (uri != NULL, FALSE);
 
   root_uris = gtk_file_chooser_get_root_uris (chooser);
+  is_in_roots = uri_is_in_roots_strv (uri, root_uris);
+  g_strfreev (root_uris);
 
-  return _gtk_file_chooser_uri_has_prefix (uri, root_uris);
+  return is_in_roots;
 }
 
 gboolean
@@ -2939,12 +2960,16 @@ _gtk_file_chooser_is_file_in_roots (GtkFileChooser *chooser,
 GSList *
 _gtk_file_chooser_get_visible_roots (GtkFileChooser *chooser)
 {
-  GSList *l, *results = NULL;
+  GSList *results = NULL;
   GtkFileSystem *file_system = _gtk_file_chooser_get_file_system (chooser);
+  gchar **root_uris;
+  gchar **r;
 
-  for (l = gtk_file_chooser_get_root_uris (chooser); l != NULL; l = l->next)
+  root_uris = gtk_file_chooser_get_root_uris (chooser);
+
+  for (r = root_uris; r && *r; r++)
     {
-      GFile *file = g_file_new_for_uri ((char *)l->data);
+      GFile *file = g_file_new_for_uri (*r);
       gboolean skip = FALSE;
       GtkFileSystemVolume *volume;
       GFileInfo *file_info;
@@ -3011,6 +3036,8 @@ _gtk_file_chooser_get_visible_roots (GtkFileChooser *chooser)
       results = g_slist_append (results, file);
     }
 
+  g_strfreev (root_uris);
+
   return results;
 }
 
diff --git a/gtk/gtkfilechooser.h b/gtk/gtkfilechooser.h
index 63ec0a1..47dff02 100644
--- a/gtk/gtkfilechooser.h
+++ b/gtk/gtkfilechooser.h
@@ -124,8 +124,8 @@ void                 gtk_file_chooser_set_local_only      (GtkFileChooser
 							   gboolean              local_only);
 gboolean             gtk_file_chooser_get_local_only      (GtkFileChooser       *chooser);
 void                 gtk_file_chooser_set_root_uris       (GtkFileChooser       *chooser,
-							   GSList               *root_uris);
-GSList              *gtk_file_chooser_get_root_uris       (GtkFileChooser       *chooser);
+							   const gchar         **root_uris);
+gchar              **gtk_file_chooser_get_root_uris       (GtkFileChooser       *chooser);
 void                 gtk_file_chooser_set_select_multiple (GtkFileChooser       *chooser,
 							   gboolean              select_multiple);
 gboolean             gtk_file_chooser_get_select_multiple (GtkFileChooser       *chooser);
diff --git a/gtk/gtkfilechooserbutton.c b/gtk/gtkfilechooserbutton.c
index 83369cb..178e68b 100644
--- a/gtk/gtkfilechooserbutton.c
+++ b/gtk/gtkfilechooserbutton.c
@@ -924,11 +924,12 @@ gtk_file_chooser_button_set_property (GObject      *object,
 
       if (!_gtk_file_chooser_is_file_in_roots (filechooser, gtk_file_chooser_get_current_folder_file (filechooser)))
         {
-          GSList *root_uris = gtk_file_chooser_get_root_uris (filechooser);
+	  char **root_uris = gtk_file_chooser_get_root_uris (filechooser);
 
-          GFile *file = g_file_new_for_uri (root_uris == NULL
+          GFile *file = g_file_new_for_uri ((root_uris == NULL || *root_uris == NULL)
                                             ? "file:///"
-                                            : (char *)root_uris->data);
+                                            : root_uris[0]);
+	  g_strfreev (root_uris);
 
           gtk_file_chooser_set_current_folder_file (filechooser, file, NULL);
           model_update_current_folder (button, file);
@@ -1885,7 +1886,6 @@ model_add_volumes (GtkFileChooserButton *button,
   GtkListStore *store;
   gint pos;
   gboolean local_only;
-  GSList *root_uris;
   GtkFileSystem *file_system;
   GtkFileChooser *filechooser;
   GSList *l;
@@ -1897,7 +1897,6 @@ model_add_volumes (GtkFileChooserButton *button,
   pos = model_get_type_position (button, ROW_TYPE_VOLUME);
   filechooser = GTK_FILE_CHOOSER (button->priv->dialog);
   local_only = gtk_file_chooser_get_local_only (filechooser);
-  root_uris = gtk_file_chooser_get_root_uris (filechooser);
   file_system = button->priv->fs;
 
   for (l = volumes; l; l = l->next)
@@ -1918,9 +1917,8 @@ model_add_volumes (GtkFileChooserButton *button,
           _gtk_file_system_volume_is_mounted (volume) &&
           !g_file_is_native (base_file))
         skip = TRUE;
-      else if (root_uris != NULL &&
-               (base_file == NULL ||
-                !_gtk_file_chooser_is_file_in_roots (filechooser, base_file)))
+      else if (base_file == NULL ||
+	       !_gtk_file_chooser_is_file_in_roots (filechooser, base_file))
         skip = TRUE;
 
       if (base_file != NULL)
@@ -2200,13 +2198,11 @@ model_remove_rows (GtkFileChooserButton *button,
 
 /* Filter Model */
 static inline gboolean
-test_if_file_is_visible (GtkFileSystem *fs,
+test_if_file_is_visible (GtkFileChooserButton *button,
 			 GFile         *file,
 			 gboolean       local_only,
-			 GSList        *root_uris,
 			 gboolean       is_folder)
 {
-  char *uri;
   gboolean result;
 
   if (!file)
@@ -2215,9 +2211,7 @@ test_if_file_is_visible (GtkFileSystem *fs,
   if (local_only && !g_file_is_native (file))
     return FALSE;
 
-  uri = g_file_get_uri (file);
-  result = _gtk_file_chooser_uri_has_prefix (uri, root_uris);
-  g_free (uri);
+  result = _gtk_file_chooser_is_file_in_roots (GTK_FILE_CHOOSER (button), file);
 
   if (!result)
     return FALSE;
@@ -2238,12 +2232,10 @@ filter_model_visible_func (GtkTreeModel *model,
   gchar type;
   gpointer data;
   gboolean local_only, retval, is_folder;
-  GSList *root_uris;
 
   type = ROW_TYPE_INVALID;
   data = NULL;
   local_only = gtk_file_chooser_get_local_only (GTK_FILE_CHOOSER (priv->dialog));
-  root_uris = gtk_file_chooser_get_root_uris (GTK_FILE_CHOOSER (priv->dialog));
 
   gtk_tree_model_get (model, iter,
 		      TYPE_COLUMN, &type,
@@ -2259,8 +2251,7 @@ filter_model_visible_func (GtkTreeModel *model,
     case ROW_TYPE_SPECIAL:
     case ROW_TYPE_SHORTCUT:
     case ROW_TYPE_BOOKMARK:
-      retval = test_if_file_is_visible (priv->fs, data, local_only, root_uris,
-										is_folder);
+      retval = test_if_file_is_visible (button, data, local_only, is_folder);
       break;
     case ROW_TYPE_VOLUME:
       {
diff --git a/gtk/gtkfilechooserdefault.c b/gtk/gtkfilechooserdefault.c
index a5e8eac..1235f65 100644
--- a/gtk/gtkfilechooserdefault.c
+++ b/gtk/gtkfilechooserdefault.c
@@ -1976,6 +1976,7 @@ shortcuts_append_roots (GtkFileChooserDefault *impl)
 
       shortcuts_insert_file (impl, start_row + n, SHORTCUT_TYPE_FILE,
                              NULL, file, NULL, FALSE, SHORTCUTS_ROOTS);
+      g_object_unref (file);
       n++;
     }
 
@@ -5449,22 +5450,34 @@ set_extra_widget (GtkFileChooserDefault *impl,
     gtk_widget_hide (impl->extra_align);
 }
 
+static GSList *
+strv_to_slist (const gchar **strv)
+{
+  const gchar **s;
+  GSList *list;
+
+  list = NULL;
+  for (s = strv; s && *s; s++)
+    list = g_slist_prepend (list, g_strdup (*s));
+
+  list = g_slist_reverse (list);
+
+  return list;
+}
+
 static void
 set_root_uris (GtkFileChooserDefault *impl,
-               GSList                *root_uris)
+               const gchar          **root_uris)
 {
   GtkTreeIter iter;
   GFile *list_selected = NULL;
   ShortcutType shortcut_type = -1;
   gboolean local_only;
 
-  if (root_uris == impl->root_uris)
-    return;
-
   g_slist_foreach (impl->root_uris, (GFunc)g_free, NULL);
   g_slist_free (impl->root_uris);
 
-  impl->root_uris = root_uris;
+  impl->root_uris = strv_to_slist (root_uris);
 
   local_only = gtk_file_chooser_get_local_only (GTK_FILE_CHOOSER (impl));
 
@@ -5769,11 +5782,11 @@ gtk_file_chooser_default_set_property (GObject      *object,
       break;
 
     case GTK_FILE_CHOOSER_PROP_LOCAL_ONLY:
-      set_root_uris (impl,
-                     g_value_get_boolean (value)
-                     ? g_slist_append (NULL, g_strdup ("file://"))
-                     : NULL);
-      break;
+      {
+	const char *local_only_uris[] = { "file:///", NULL };
+	set_root_uris (impl, g_value_get_boolean (value) ? local_only_uris : NULL);
+	break;
+      }
 
     case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET:
       set_preview_widget (impl, g_value_get_object (value));
@@ -5839,7 +5852,7 @@ gtk_file_chooser_default_set_property (GObject      *object,
       break;
 
     case GTK_FILE_CHOOSER_PROP_ROOT_URIS:
-      set_root_uris (impl, (GSList *)g_value_get_pointer (value));
+      set_root_uris (impl, (const gchar **) g_value_get_boxed (value));
       break;
 
     default:
@@ -5848,6 +5861,36 @@ gtk_file_chooser_default_set_property (GObject      *object,
     }
 }
 
+static gchar **
+slist_to_strv (GSList *list)
+{
+  int n;
+  gchar **strv;
+  int i;
+  GSList *l;
+
+  n = g_slist_length (list);
+
+  if (n == 0)
+    return NULL;
+
+  strv = g_new (char *, n + 1);
+
+  i = 0;
+  for (l = list; l; l = l->next)
+    {
+      gchar *s;
+
+      s = l->data;
+      strv[i] = g_strdup (s);
+      i++;
+    }
+
+  strv[i] = NULL;
+
+  return strv;
+}
+
 static void
 gtk_file_chooser_default_get_property (GObject    *object,
 				       guint       prop_id,
@@ -5921,8 +5964,13 @@ gtk_file_chooser_default_get_property (GObject    *object,
       break;
 
     case GTK_FILE_CHOOSER_PROP_ROOT_URIS:
-      g_value_set_pointer (value, impl->root_uris);
-      break;
+      {
+	char **strv;
+
+	strv = slist_to_strv (impl->root_uris);
+	g_value_set_boxed (value, strv);
+	g_strfreev (strv);
+      }
 
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -9672,7 +9720,7 @@ recent_idle_load (gpointer data)
           GtkRecentInfo *info = walk->data;
           const char *uri = gtk_recent_info_get_uri (info);
 
-          if (_gtk_file_chooser_is_uri_in_roots (GTK_FILE_CHOOSER (impl), uri))
+          if (_gtk_file_chooser_uri_is_in_roots_list (uri, impl->root_uris))
             {
               /* We'll sort this later, so prepend for efficiency. */
               load_data->items = g_list_prepend(load_data->items, info);
diff --git a/gtk/gtkfilechooserentry.c b/gtk/gtkfilechooserentry.c
index bc7eaf9..f52615f 100644
--- a/gtk/gtkfilechooserentry.c
+++ b/gtk/gtkfilechooserentry.c
@@ -454,7 +454,7 @@ is_file_in_roots (GtkFileChooserEntry *chooser_entry,
 		  GFile               *file)
 {
   char *uri = g_file_get_uri (file);
-  gboolean result = _gtk_file_chooser_uri_has_prefix (uri, chooser_entry->root_uris);
+  gboolean result = _gtk_file_chooser_uri_is_in_roots_list (uri, chooser_entry->root_uris);
   g_free (uri);
 
   return result;
diff --git a/gtk/gtkfilechooserprivate.h b/gtk/gtkfilechooserprivate.h
index 7ab7583..9b55e66 100644
--- a/gtk/gtkfilechooserprivate.h
+++ b/gtk/gtkfilechooserprivate.h
@@ -112,8 +112,7 @@ gboolean       _gtk_file_chooser_is_file_in_roots (GtkFileChooser *chooser,
 						   GFile          *file);
 GSList *       _gtk_file_chooser_get_visible_roots (GtkFileChooser *chooser);
 
-gboolean       _gtk_file_chooser_uri_has_prefix (const char   *uri,
-                                                 GSList *prefixes);
+gboolean       _gtk_file_chooser_uri_is_in_roots_list (const char *uri, GSList *roots);
 
 /* GtkFileChooserDialog private */
 
diff --git a/gtk/gtkpathbar.c b/gtk/gtkpathbar.c
index 6c3bdcf..24af3da 100644
--- a/gtk/gtkpathbar.c
+++ b/gtk/gtkpathbar.c
@@ -1666,7 +1666,7 @@ is_file_in_roots (GtkPathBar *path_bar,
 		  GFile      *file)
 {
   char *uri = g_file_get_uri (file);
-  gboolean result = _gtk_file_chooser_uri_has_prefix (uri, path_bar->root_uris);
+  gboolean result = _gtk_file_chooser_uri_is_in_roots_list (uri, path_bar->root_uris);
   g_free(uri);
 
   return result;



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