[gtk/icontheme-api: 3/3] icontheme: Update the api



commit 66307f00f141ab84d38edfff2da80e7df430ce58
Author: Matthias Clasen <mclasen redhat com>
Date:   Tue Feb 18 00:56:37 2020 -0500

    icontheme: Update the api
    
    Add properties, and use string arrays instead of lists.
    
    Among other things, this renames gtk_icon_theme_list_icons
    to gtk_icon_theme_get_icon_names.
    
    Fixes: https://gitlab.gnome.org/GNOME/gtk/issues/2410

 demos/gtk-demo/fishbowl.c            |  22 +-
 docs/reference/gtk/gtk4-sections.txt |  11 +-
 gtk/gtkcssiconthemevalue.c           |   2 +-
 gtk/gtkicontheme.c                   | 519 ++++++++++++++++++++++++-----------
 gtk/gtkicontheme.h                   |  32 +--
 tests/testicontheme.c                |  17 +-
 testsuite/gtk/defaultvalue.c         |   4 +
 testsuite/gtk/icontheme.c            |  42 +--
 8 files changed, 421 insertions(+), 228 deletions(-)
---
diff --git a/demos/gtk-demo/fishbowl.c b/demos/gtk-demo/fishbowl.c
index 111d6a199e..36e45a77bf 100644
--- a/demos/gtk-demo/fishbowl.c
+++ b/demos/gtk-demo/fishbowl.c
@@ -22,29 +22,11 @@ gsize n_icon_names = 0;
 static void
 init_icon_names (GtkIconTheme *theme)
 {
-  GPtrArray *icons;
-  GList *l, *icon_list;
-
   if (icon_names)
     return;
 
-  icon_list = gtk_icon_theme_list_icons (theme);
-  icons = g_ptr_array_new ();
-
-  for (l = icon_list; l; l = l->next)
-    {
-      if (g_str_has_suffix (l->data, "symbolic"))
-        continue;
-
-      g_ptr_array_add (icons, g_strdup (l->data));
-    }
-
-  n_icon_names = icons->len;
-  g_ptr_array_add (icons, NULL); /* NULL-terminate the array */
-  icon_names = (char **) g_ptr_array_free (icons, FALSE);
-
-  /* don't free strings, we assigned them to the array */
-  g_list_free_full (icon_list, g_free);
+  icon_names = gtk_icon_theme_get_icon_names (theme);
+  n_icon_names = g_strv_length (icon_names);
 }
 
 static const char *
diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt
index f0b4e577d7..030fe98bce 100644
--- a/docs/reference/gtk/gtk4-sections.txt
+++ b/docs/reference/gtk/gtk4-sections.txt
@@ -4764,19 +4764,20 @@ GTK_TYPE_ICON_LOOKUP_FLAGS
 GtkIconThemeError
 gtk_icon_theme_new
 gtk_icon_theme_get_for_display
-gtk_icon_theme_set_display
 gtk_icon_theme_set_search_path
 gtk_icon_theme_get_search_path
-gtk_icon_theme_append_search_path
-gtk_icon_theme_prepend_search_path
+gtk_icon_theme_add_search_path
+gtk_icon_theme_set_resource_path
+gtk_icon_theme_get_resource_path
 gtk_icon_theme_add_resource_path
-gtk_icon_theme_set_custom_theme
+gtk_icon_theme_set_theme_name
+gtk_icon_theme_get_theme_name
 gtk_icon_theme_has_icon
 gtk_icon_theme_lookup_icon
 gtk_icon_theme_choose_icon_async
 gtk_icon_theme_choose_icon_finish
 gtk_icon_theme_lookup_by_gicon
-gtk_icon_theme_list_icons
+gtk_icon_theme_get_icon_names
 gtk_icon_theme_get_icon_sizes
 gtk_icon_paintable_new_for_file
 gtk_icon_paintable_get_file
diff --git a/gtk/gtkcssiconthemevalue.c b/gtk/gtkcssiconthemevalue.c
index 50d021f113..0708d84f77 100644
--- a/gtk/gtkcssiconthemevalue.c
+++ b/gtk/gtkcssiconthemevalue.c
@@ -156,7 +156,7 @@ gtk_css_icon_theme_value_parse (GtkCssParser *parser)
     return NULL;
 
   icontheme = gtk_icon_theme_new ();
-  gtk_icon_theme_set_custom_theme (icontheme, s);
+  gtk_icon_theme_set_theme_name (icontheme, s);
 
   result = gtk_css_icon_theme_value_new (icontheme);
 
diff --git a/gtk/gtkicontheme.c b/gtk/gtkicontheme.c
index 5c1f2dc22c..323feb7bb4 100644
--- a/gtk/gtkicontheme.c
+++ b/gtk/gtkicontheme.c
@@ -295,7 +295,7 @@ typedef struct _GtkIconThemeRef GtkIconThemeRef;
  * will contain information about current icon theme for
  * that display, but you can also create a new #GtkIconTheme
  * object and set the icon theme name explicitly using
- * gtk_icon_theme_set_custom_theme().
+ * gtk_icon_theme_set_theme_name().
  */
 struct _GtkIconTheme
 {
@@ -307,10 +307,9 @@ struct _GtkIconTheme
   GtkIconPaintable *lru_cache[LRU_CACHE_SIZE];  /* Protected by icon_cache lock */
   int lru_cache_current;                        /* Protected by icon_cache lock */
 
-  gchar *current_theme;
-  gchar **search_path;
-  gint search_path_len;
-  GList *resource_paths;
+  char *current_theme;
+  char **search_path;
+  char **resource_path;
 
   guint custom_theme         : 1;
   guint is_display_singleton : 1;
@@ -479,7 +478,9 @@ static GtkIconPaintable *icon_paintable_new               (const char       *ico
 static IconCacheFlag     suffix_from_name                 (const gchar      *name);
 static void              icon_ensure_texture__locked      (GtkIconPaintable *icon,
                                                            gboolean          in_thread);
-static void              unset_display                    (GtkIconTheme     *self);
+static void              gtk_icon_theme_unset_display     (GtkIconTheme     *self);
+static void              gtk_icon_theme_set_display       (GtkIconTheme     *self,
+                                                           GdkDisplay       *display);
 static void              update_current_theme__mainthread (GtkIconTheme     *self);
 static gboolean          ensure_valid_themes              (GtkIconTheme     *self,
                                                            gboolean          non_blocking);
@@ -851,19 +852,97 @@ gtk_icon_theme_get_for_display (GdkDisplay *display)
     {
       self = gtk_icon_theme_new ();
       self->is_display_singleton = TRUE;
-
       g_object_set_data (G_OBJECT (display), I_("gtk-icon-theme"), self);
 
       /* Call this after setting the user-data, because it recurses into gtk_icon_theme_get_for_display via 
the thememing machinery */
       gtk_icon_theme_set_display (self, display);
 
-      /* Queue early read of the default themes, we read the icon theme name in _set_display(). */
+      /* Queue early read of the default themes, we read the icon theme name in set_display(). */
       gtk_icon_theme_load_in_thread (self);
     }
 
   return self;
 }
 
+enum {
+  PROP_DISPLAY = 1,
+  PROP_ICON_NAMES,
+  PROP_SEARCH_PATH,
+  PROP_RESOURCE_PATH,
+  PROP_THEME_NAME,
+  LAST_PROP
+};
+
+static GParamSpec *props[LAST_PROP];
+
+static void
+gtk_icon_theme_get_property (GObject      *object,
+                             guint         prop_id,
+                             GValue       *value,
+                             GParamSpec   *pspec)
+{
+  GtkIconTheme *self = GTK_ICON_THEME (object);
+
+  switch (prop_id)
+    {
+    case PROP_DISPLAY:
+      g_value_set_object (value, self->display);
+      break;
+
+    case PROP_ICON_NAMES:
+      g_value_take_boxed (value, gtk_icon_theme_get_icon_names (self));
+      break;
+
+    case PROP_SEARCH_PATH:
+      g_value_set_boxed (value, self->search_path);
+      break;
+
+    case PROP_RESOURCE_PATH:
+      g_value_set_boxed (value, self->resource_path);
+      break;
+
+    case PROP_THEME_NAME:
+      g_value_take_string (value, gtk_icon_theme_get_theme_name (self));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gtk_icon_theme_set_property (GObject      *object,
+                             guint         prop_id,
+                             const GValue *value,
+                             GParamSpec   *pspec)
+{
+  GtkIconTheme *self = GTK_ICON_THEME (object);
+
+  switch (prop_id)
+    {
+    case PROP_DISPLAY:
+      gtk_icon_theme_set_display (self, g_value_get_object (value));
+      break;
+
+    case PROP_SEARCH_PATH:
+      gtk_icon_theme_set_search_path (self, g_value_get_boxed (value));
+      break;
+
+    case PROP_RESOURCE_PATH:
+      gtk_icon_theme_set_resource_path (self, g_value_get_boxed (value));
+      break;
+
+    case PROP_THEME_NAME:
+      gtk_icon_theme_set_theme_name (self, g_value_get_string (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
 static void
 gtk_icon_theme_class_init (GtkIconThemeClass *klass)
 {
@@ -871,6 +950,8 @@ gtk_icon_theme_class_init (GtkIconThemeClass *klass)
 
   gobject_class->finalize = gtk_icon_theme_finalize;
   gobject_class->dispose = gtk_icon_theme_dispose;
+  gobject_class->get_property = gtk_icon_theme_get_property;
+  gobject_class->set_property = gtk_icon_theme_set_property;
 
   /**
    * GtkIconTheme::changed:
@@ -887,6 +968,85 @@ gtk_icon_theme_class_init (GtkIconThemeClass *klass)
                                  NULL, NULL,
                                  NULL,
                                  G_TYPE_NONE, 0);
+
+  /**
+   * GtkIconTheme:display:
+   *
+   * The display that this icon theme object is attached to.
+   */ 
+  props[PROP_DISPLAY] =
+      g_param_spec_object ("display",
+                           P_("Display"),
+                           P_("Display"),
+                           GDK_TYPE_DISPLAY,
+                           G_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
+
+  /**
+   * GtkIconTheme:icon-names:
+   *
+   * The icon names that are supported by the icon theme.
+   */
+  props[PROP_ICON_NAMES] =
+      g_param_spec_boxed ("icon-names",
+                          P_("Supported icon names"),
+                          P_("Supported icon names"),
+                          G_TYPE_STRV,
+                          GTK_PARAM_READABLE);
+
+  /**
+   * GtkIconTheme:search-path:
+   *
+   * The search path for this icon theme.
+   *
+   * When looking for icons, GTK will search for a subdirectory of
+   * one or more of the directories in the search path with the same
+   * name as the icon theme containing an index.theme file. (Themes
+   * from multiple of the path elements are combined to allow themes
+   * to be extended by adding icons in the user’s home directory.)
+   */
+  props[PROP_SEARCH_PATH] =
+      g_param_spec_boxed ("search-path",
+                          P_("Search path"),
+                          P_("Search path"),
+                          G_TYPE_STRV,
+                          GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
+
+  /**
+   * GtkIconTheme:resource-path:
+   *
+   * Resource paths that will be looked at when looking for icons,
+   * similar to search paths.
+   *
+   * The resources are considered as part of the hicolor icon theme
+   * and must be located in subdirectories that are defined in the
+   * hicolor icon theme, such as `@path/16x16/actions/run.png`.
+   * Icons that are directly placed in the resource path instead
+   * of a subdirectory are also considered as ultimate fallback.
+   */
+  props[PROP_RESOURCE_PATH] =
+      g_param_spec_boxed ("resource-path",
+                          P_("Resource path"),
+                          P_("Resource path"),
+                          G_TYPE_STRV,
+                          GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
+
+  /**
+   * GtkIconTheme:theme-name:
+   *
+   * The name of the icon theme that is being used.
+   *
+   * Unless set to a different value, this will be the value of
+   * the #GtkSettings:gtk-icon-theme-name property of the #GtkSettings
+   * object associated to the display of the icontheme object. 
+   */
+  props[PROP_THEME_NAME] =
+      g_param_spec_string ("theme-name",
+                           P_("Theme name"),
+                           P_("Theme name"),
+                           NULL,
+                           GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
+
+  g_object_class_install_properties (gobject_class, LAST_PROP, props);
 }
 
 
@@ -912,7 +1072,7 @@ display_closed__mainthread_unlocked (GdkDisplay      *display,
           self->is_display_singleton = FALSE;
         }
 
-      unset_display (self);
+      gtk_icon_theme_unset_display (self);
       update_current_theme__mainthread (self);
 
       if (was_display_singleton)
@@ -976,7 +1136,7 @@ theme_changed__mainthread_unlocked (GtkSettings     *settings,
 }
 
 static void
-unset_display (GtkIconTheme *self)
+gtk_icon_theme_unset_display (GtkIconTheme *self)
 {
   if (self->display)
     {
@@ -989,18 +1149,11 @@ unset_display (GtkIconTheme *self)
 
       self->display = NULL;
       self->display_settings = NULL;
+
+      g_object_notify_by_pspec (G_OBJECT (self), props[PROP_DISPLAY]);
     }
 }
 
-/**
- * gtk_icon_theme_set_display:
- * @self: a #GtkIconTheme
- * @display: a #GdkDisplay
- *
- * Sets the display for an icon theme; the display is used
- * to track the user’s currently configured icon theme,
- * which might be different for different displays.
- */
 void
 gtk_icon_theme_set_display (GtkIconTheme *self,
                             GdkDisplay   *display)
@@ -1010,7 +1163,9 @@ gtk_icon_theme_set_display (GtkIconTheme *self,
 
   gtk_icon_theme_lock (self);
 
-  unset_display (self);
+  g_object_freeze_notify (G_OBJECT (self));
+
+  gtk_icon_theme_unset_display (self);
 
   if (display)
     {
@@ -1027,11 +1182,15 @@ gtk_icon_theme_set_display (GtkIconTheme *self,
                              gtk_icon_theme_ref_ref (self->ref),
                              (GClosureNotify)gtk_icon_theme_ref_unref,
                              0);
+
+      g_object_notify_by_pspec (G_OBJECT (self), props[PROP_DISPLAY]);
     }
 
   update_current_theme__mainthread (self);
 
   gtk_icon_theme_unlock (self);
+
+  g_object_thaw_notify (G_OBJECT (self));
 }
 
 /* Checks whether a loader for SVG files has been registered
@@ -1074,6 +1233,7 @@ gtk_icon_theme_init (GtkIconTheme *self)
 {
   const gchar * const *xdg_data_dirs;
   int i, j;
+  int len;
 
   self->ref = gtk_icon_theme_ref_new (self);
 
@@ -1085,9 +1245,9 @@ gtk_icon_theme_init (GtkIconTheme *self)
   xdg_data_dirs = g_get_system_data_dirs ();
   for (i = 0; xdg_data_dirs[i]; i++) ;
 
-  self->search_path_len = 2 * i + 2;
+  len = 2 * i + 3;
 
-  self->search_path = g_new (char *, self->search_path_len);
+  self->search_path = g_new (char *, len);
 
   i = 0;
   self->search_path[i++] = g_build_filename (g_get_user_data_dir (), "icons", NULL);
@@ -1099,7 +1259,11 @@ gtk_icon_theme_init (GtkIconTheme *self)
   for (j = 0; xdg_data_dirs[j]; j++)
     self->search_path[i++] = g_build_filename (xdg_data_dirs[j], "pixmaps", NULL);
 
-  self->resource_paths = g_list_append (NULL, g_strdup ("/org/gtk/libgtk/icons/"));
+  self->search_path[i] = NULL;
+
+  self->resource_path = g_new (char *, 2);
+  self->resource_path[0] = g_strdup ("/org/gtk/libgtk/icons/");
+  self->resource_path[1] = NULL;
 
   self->themes_valid = FALSE;
   self->themes = NULL;
@@ -1223,7 +1387,6 @@ static void
 gtk_icon_theme_finalize (GObject *object)
 {
   GtkIconTheme *self = GTK_ICON_THEME (object);
-  int i;
 
   /* We don't actually need to take the lock here, because by now
      there can be no other threads that own a ref to this object, but
@@ -1234,15 +1397,12 @@ gtk_icon_theme_finalize (GObject *object)
   if (self->theme_changed_idle)
     g_source_remove (self->theme_changed_idle);
 
-  unset_display (self);
+  gtk_icon_theme_unset_display (self);
 
   g_free (self->current_theme);
 
-  for (i = 0; i < self->search_path_len; i++)
-    g_free (self->search_path[i]);
-  g_free (self->search_path);
-
-  g_list_free_full (self->resource_paths, g_free);
+  g_strfreev (self->search_path);
+  g_strfreev (self->resource_path);
 
   blow_themes (self);
 
@@ -1254,12 +1414,11 @@ gtk_icon_theme_finalize (GObject *object)
 /**
  * gtk_icon_theme_set_search_path:
  * @self: a #GtkIconTheme
- * @path: (array length=n_elements) (element-type filename): array of
+ * @path: (element-type filename): NULL-terminated array of
  *     directories that are searched for icon themes
- * @n_elements: number of elements in @path.
  *
  * Sets the search path for the icon theme object. When looking
- * for an icon theme, GTK+ will search for a subdirectory of
+ * for an icon theme, GTK will search for a subdirectory of
  * one or more of the directories in @path with the same name
  * as the icon theme containing an index.theme file. (Themes from
  * multiple of the path elements are combined to allow themes to be
@@ -1274,69 +1433,54 @@ gtk_icon_theme_finalize (GObject *object)
  * rather than directly on the icon path.)
  */
 void
-gtk_icon_theme_set_search_path (GtkIconTheme *self,
-                                const gchar  *path[],
-                                gint          n_elements)
+gtk_icon_theme_set_search_path (GtkIconTheme       *self,
+                                const char * const *path)
 {
-  gint i;
+  char **search_path;
 
   g_return_if_fail (GTK_IS_ICON_THEME (self));
 
   gtk_icon_theme_lock (self);
 
-  for (i = 0; i < self->search_path_len; i++)
-    g_free (self->search_path[i]);
-
-  g_free (self->search_path);
-
-  self->search_path = g_new (gchar *, n_elements);
-  self->search_path_len = n_elements;
-
-  for (i = 0; i < self->search_path_len; i++)
-    self->search_path[i] = g_strdup (path[i]);
+  search_path = g_strdupv ((char **)path);
+  g_strfreev (self->search_path);
+  self->search_path = search_path;
 
   do_theme_change (self);
 
   gtk_icon_theme_unlock (self);
+
+  g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SEARCH_PATH]);
 }
 
 /**
  * gtk_icon_theme_get_search_path:
  * @self: a #GtkIconTheme
- * @path: (allow-none) (array length=n_elements) (element-type filename) (out):
- *     location to store a list of icon theme path directories or %NULL.
- *     The stored value should be freed with g_strfreev().
- * @n_elements: location to store number of elements in @path, or %NULL
  *
  * Gets the current search path. See gtk_icon_theme_set_search_path().
+ * 
+ * Returns: (element-type filename):
+ *     a list of icon theme path directories or %NULL.
+ *     The returned value should be freed with g_strfreev().
  */
-void
-gtk_icon_theme_get_search_path (GtkIconTheme  *self,
-                                gchar        **path[],
-                                gint          *n_elements)
+char **
+gtk_icon_theme_get_search_path (GtkIconTheme  *self)
 {
-  gint i;
+  char **paths;
 
-  g_return_if_fail (GTK_IS_ICON_THEME (self));
+  g_return_val_if_fail (GTK_IS_ICON_THEME (self), NULL);
 
   gtk_icon_theme_lock (self);
 
-  if (n_elements)
-    *n_elements = self->search_path_len;
-
-  if (path)
-    {
-      *path = g_new (gchar *, self->search_path_len + 1);
-      for (i = 0; i < self->search_path_len; i++)
-        (*path)[i] = g_strdup (self->search_path[i]);
-      (*path)[i] = NULL;
-    }
+  paths = g_strdupv (self->search_path);
 
   gtk_icon_theme_unlock (self);
+
+  return paths;
 }
 
 /**
- * gtk_icon_theme_append_search_path:
+ * gtk_icon_theme_add_search_path:
  * @self: a #GtkIconTheme
  * @path: (type filename): directory name to append to the icon path
  *
@@ -1344,54 +1488,87 @@ gtk_icon_theme_get_search_path (GtkIconTheme  *self,
  * See gtk_icon_theme_set_search_path().
  */
 void
-gtk_icon_theme_append_search_path (GtkIconTheme *self,
-                                   const gchar  *path)
+gtk_icon_theme_add_search_path (GtkIconTheme *self,
+                                const char   *path)
 {
+  char **paths;
+  int len;
+
   g_return_if_fail (GTK_IS_ICON_THEME (self));
   g_return_if_fail (path != NULL);
+ 
+  len = g_strv_length (self->search_path);
+  paths = g_new (char *, len + 2);
+  memcpy (paths, self->resource_path, sizeof (char *) * len);
+  paths[len] = (char *)path;
+  paths[len + 1] = NULL;
 
-  gtk_icon_theme_lock (self);
-
-  self->search_path_len++;
-
-  self->search_path = g_renew (gchar *, self->search_path, self->search_path_len);
-  self->search_path[self->search_path_len-1] = g_strdup (path);
-
-  do_theme_change (self);
+  gtk_icon_theme_set_search_path (self, (const char * const *)paths);
 
-  gtk_icon_theme_unlock (self);
+  g_free (paths);
 }
 
 /**
- * gtk_icon_theme_prepend_search_path:
+ * gtk_icon_theme_set_resource_path:
  * @self: a #GtkIconTheme
- * @path: (type filename): directory name to prepend to the icon path
+ * @path: NULL-terminated array of resource paths
+ *     that are searched for icons
  *
- * Prepends a directory to the search path.
- * See gtk_icon_theme_set_search_path().
+ * Sets the resource paths that will be looked at when
+ * looking for icons, similar to search paths.
+ *
+ * The resources are considered as part of the hicolor icon theme
+ * and must be located in subdirectories that are defined in the
+ * hicolor icon theme, such as `@path/16x16/actions/run.png`.
+ * Icons that are directly placed in the resource path instead
+ * of a subdirectory are also considered as ultimate fallback.
  */
 void
-gtk_icon_theme_prepend_search_path (GtkIconTheme *self,
-                                    const gchar  *path)
+gtk_icon_theme_set_resource_path (GtkIconTheme       *self,
+                                  const char * const *path)
 {
-  gint i;
+  char **search_path;
 
   g_return_if_fail (GTK_IS_ICON_THEME (self));
-  g_return_if_fail (path != NULL);
 
   gtk_icon_theme_lock (self);
 
-  self->search_path_len++;
-  self->search_path = g_renew (gchar *, self->search_path, self->search_path_len);
+  search_path = g_strdupv ((char **)path);
+  g_strfreev (self->resource_path);
+  self->resource_path = search_path;
 
-  for (i = self->search_path_len - 1; i > 0; i--)
-    self->search_path[i] = self->search_path[i - 1];
+  do_theme_change (self);
 
-  self->search_path[0] = g_strdup (path);
+  gtk_icon_theme_unlock (self);
 
-  do_theme_change (self);
+  g_object_notify_by_pspec (G_OBJECT (self), props[PROP_RESOURCE_PATH]);
+}
+
+/**
+ * gtk_icon_theme_get_resource_path:
+ * @self: a #GtkIconTheme
+ *
+ * Gets the current resource path.
+ *
+ * See gtk_icon_theme_set_resource_path().
+ * 
+ * Returns: A list of resource paths or %NULL.
+ *     The returned value should be freed with g_strfreev().
+ */
+char **
+gtk_icon_theme_get_resource_path (GtkIconTheme  *self)
+{
+  char **paths;
+
+  g_return_val_if_fail (GTK_IS_ICON_THEME (self), NULL);
+
+  gtk_icon_theme_lock (self);
+
+  paths = g_strdupv (self->resource_path);
 
   gtk_icon_theme_unlock (self);
+
+  return paths;
 }
 
 /**
@@ -1402,33 +1579,34 @@ gtk_icon_theme_prepend_search_path (GtkIconTheme *self,
  * Adds a resource path that will be looked at when looking
  * for icons, similar to search paths.
  *
+ * See gtk_icon_theme_set_resource_path().
+ *
  * This function should be used to make application-specific icons
  * available as part of the icon theme.
- *
- * The resources are considered as part of the hicolor icon theme
- * and must be located in subdirectories that are defined in the
- * hicolor icon theme, such as `@path/16x16/actions/run.png`.
- * Icons that are directly placed in the resource path instead
- * of a subdirectory are also considered as ultimate fallback.
  */
 void
 gtk_icon_theme_add_resource_path (GtkIconTheme *self,
-                                  const gchar  *path)
+                                  const char   *path)
 {
+  char **paths;
+  int len;
+
   g_return_if_fail (GTK_IS_ICON_THEME (self));
   g_return_if_fail (path != NULL);
+ 
+  len = g_strv_length (self->resource_path);
+  paths = g_new (char *, len + 2);
+  memcpy (paths, self->resource_path, sizeof (char *) * len);
+  paths[len] = (char *)path;
+  paths[len + 1] = NULL;
 
-  gtk_icon_theme_lock (self);
-
-  self->resource_paths = g_list_append (self->resource_paths, g_strdup (path));
+  gtk_icon_theme_set_resource_path (self, (const char * const *)paths);
 
-  do_theme_change (self);
-
-  gtk_icon_theme_unlock (self);
+  g_free (paths);
 }
 
 /**
- * gtk_icon_theme_set_custom_theme:
+ * gtk_icon_theme_set_theme_name:
  * @self: a #GtkIconTheme
  * @theme_name: (allow-none): name of icon theme to use instead of
  *   configured theme, or %NULL to unset a previously set custom theme
@@ -1438,11 +1616,10 @@ gtk_icon_theme_add_resource_path (GtkIconTheme *self,
  * on the icon theme objects returned from gtk_icon_theme_get_for_display().
  */
 void
-gtk_icon_theme_set_custom_theme (GtkIconTheme *self,
-                                 const gchar  *theme_name)
+gtk_icon_theme_set_theme_name (GtkIconTheme *self,
+                               const char   *theme_name)
 {
   g_return_if_fail (GTK_IS_ICON_THEME (self));
-
   g_return_if_fail (!self->is_display_singleton);
 
   gtk_icon_theme_lock (self);
@@ -1468,6 +1645,43 @@ gtk_icon_theme_set_custom_theme (GtkIconTheme *self,
     }
 
   gtk_icon_theme_unlock (self);
+
+  g_object_notify_by_pspec (G_OBJECT (self), props[PROP_THEME_NAME]);
+}
+
+/**
+ * gtk_icon_theme_get_theme_name:
+ * @self: a #GtkIconTheme
+ *
+ * Gets the current icon theme name.
+ *
+ * Returns (transfer full): the current icon theme name,
+ */
+char *
+gtk_icon_theme_get_theme_name (GtkIconTheme *self)
+{
+  char *theme_name;
+
+  g_return_val_if_fail (GTK_IS_ICON_THEME (self), NULL);
+
+  gtk_icon_theme_lock (self);
+
+  if (self->custom_theme)
+    theme_name = g_strdup (self->current_theme);
+  else
+    {
+      if (self->display)
+        {
+          GtkSettings *settings = gtk_settings_get_for_display (self->display);
+          g_object_get (settings, "gtk-icon-theme-name", &theme_name, NULL);
+        }
+      else
+        theme_name = NULL;
+    }
+
+  gtk_icon_theme_unlock (self);
+
+  return theme_name;
 }
 
 static const gchar builtin_hicolor_index[] =
@@ -1526,32 +1740,30 @@ insert_theme (GtkIconTheme *self,
         return;
     }
 
-  for (i = 0; i < self->search_path_len; i++)
+  for (i = 0; self->search_path[i]; i++)
     {
-      path = g_build_filename (self->search_path[i],
-                               theme_name,
-                               NULL);
+      path = g_build_filename (self->search_path[i], theme_name, NULL);
       dir_mtime = g_slice_new (IconThemeDirMtime);
       dir_mtime->cache = NULL;
       dir_mtime->dir = path;
-      if (g_stat (path, &stat_buf) == 0 && S_ISDIR (stat_buf.st_mode)) {
-        dir_mtime->mtime = stat_buf.st_mtime;
-        dir_mtime->exists = TRUE;
-      } else {
-        dir_mtime->mtime = 0;
-        dir_mtime->exists = FALSE;
-      }
+      if (g_stat (path, &stat_buf) == 0 && S_ISDIR (stat_buf.st_mode))
+        {
+          dir_mtime->mtime = stat_buf.st_mtime;
+          dir_mtime->exists = TRUE;
+        }
+      else
+        {
+          dir_mtime->mtime = 0;
+          dir_mtime->exists = FALSE;
+        }
 
       self->dir_mtimes = g_list_prepend (self->dir_mtimes, dir_mtime);
     }
 
   theme_file = NULL;
-  for (i = 0; i < self->search_path_len && !theme_file; i++)
+  for (i = 0; self->search_path[i] && !theme_file; i++)
     {
-      path = g_build_filename (self->search_path[i],
-                               theme_name,
-                               "index.theme",
-                               NULL);
+      path = g_build_filename (self->search_path[i], theme_name, "index.theme", NULL);
       if (g_file_test (path, G_FILE_TEST_IS_REGULAR))
         {
           theme_file = g_key_file_new ();
@@ -1733,7 +1945,7 @@ load_themes (GtkIconTheme *self)
   GTimeVal tv;
   IconThemeDirMtime *dir_mtime;
   GStatBuf stat_buf;
-  GList *d;
+  int j;
 
   if (self->current_theme)
     insert_theme (self, self->current_theme);
@@ -1744,7 +1956,7 @@ load_themes (GtkIconTheme *self)
   self->unthemed_icons = g_hash_table_new_full (g_str_hash, g_str_equal,
                                                 g_free, (GDestroyNotify)free_unthemed_icon);
 
-  for (base = 0; base < self->search_path_len; base++)
+  for (base = 0; self->search_path[base]; base++)
     {
       dir = self->search_path[base];
 
@@ -1776,12 +1988,12 @@ load_themes (GtkIconTheme *self)
     }
   self->dir_mtimes = g_list_reverse (self->dir_mtimes);
 
-  for (d = self->resource_paths; d; d = d->next)
+  for (j = 0; self->resource_path[j]; j++)
     {
       gchar **children;
       gint i;
 
-      dir = d->data;
+      dir = self->resource_path[j];
       children = g_resources_enumerate_children (dir, 0, NULL);
       if (!children)
         continue;
@@ -2462,32 +2674,25 @@ add_key_to_hash (gpointer key,
   g_hash_table_insert (hash, key, key);
 }
 
-static void
-add_key_to_list (gpointer key,
-                 gpointer value,
-                 gpointer user_data)
-{
-  GList **list = user_data;
-
-  *list = g_list_prepend (*list, g_strdup (key));
-}
-
 /**
- * gtk_icon_theme_list_icons:
+ * gtk_icon_theme_get_icon_names:
  * @self: a #GtkIconTheme
  *
- * Lists the icons in the current icon theme.
+ * Lists the names of icons in the current icon theme.
  *
- * Returns: (element-type utf8) (transfer full): a #GList list
+ * Returns: (element-type utf8) (transfer full): a string array
  *     holding the names of all the icons in the theme. You must
- *     first free each element in the list with g_free(), then
- *     free the list itself with g_list_free().
+ *     free the array using g_strfreev().
  */
-GList *
-gtk_icon_theme_list_icons (GtkIconTheme *self)
+char **
+gtk_icon_theme_get_icon_names (GtkIconTheme *self)
 {
   GHashTable *icons;
-  GList *list, *l;
+  GHashTableIter iter;
+  char **names;
+  char *key;
+  int i;
+  GList *l;
 
   gtk_icon_theme_lock (self);
 
@@ -2507,17 +2712,20 @@ gtk_icon_theme_list_icons (GtkIconTheme *self)
                         add_key_to_hash,
                         icons);
 
-  list = NULL;
+  names = g_new (char *, g_hash_table_size (icons) + 1);
+
+  i = 0;
+  g_hash_table_iter_init (&iter, icons);
+  while (g_hash_table_iter_next (&iter, (gpointer *)&key, NULL))
+    names[i++] = g_strdup (key);
 
-  g_hash_table_foreach (icons,
-                        add_key_to_list,
-                        &list);
+  names[i] = NULL;
 
   g_hash_table_destroy (icons);
 
   gtk_icon_theme_unlock (self);
 
-  return list;
+  return names;
 }
 
 static gboolean
@@ -3173,13 +3381,14 @@ theme_subdir_load (GtkIconTheme *self,
 
   if (strcmp (theme->name, FALLBACK_ICON_THEME) == 0)
     {
-      for (d = self->resource_paths; d; d = d->next)
+      int i;
+      for (i = 0; self->resource_path[i]; i++)
         {
           GHashTable *icons;
           gchar *full_dir;
 
           /* Force a trailing / here, to avoid extra copies in GResource */
-          full_dir = g_build_filename ((const gchar *)d->data, subdir, " ", NULL);
+          full_dir = g_build_filename (self->resource_path[i], subdir, " ", NULL);
           full_dir[strlen (full_dir) - 1] = '\0';
 
           icons = scan_resource_directory (self, full_dir, &theme->icons);
diff --git a/gtk/gtkicontheme.h b/gtk/gtkicontheme.h
index 86d22dc05c..d40a090827 100644
--- a/gtk/gtkicontheme.h
+++ b/gtk/gtkicontheme.h
@@ -85,32 +85,30 @@ GDK_AVAILABLE_IN_ALL
 GtkIconTheme    *gtk_icon_theme_new                  (void);
 GDK_AVAILABLE_IN_ALL
 GtkIconTheme    *gtk_icon_theme_get_for_display      (GdkDisplay                  *display);
-GDK_AVAILABLE_IN_ALL
-void             gtk_icon_theme_set_display          (GtkIconTheme                *self,
-                                                      GdkDisplay                  *display);
 
 GDK_AVAILABLE_IN_ALL
 void             gtk_icon_theme_set_search_path      (GtkIconTheme                *self,
-                                                      const gchar                 *path[],
-                                                      gint                         n_elements);
-GDK_AVAILABLE_IN_ALL
-void             gtk_icon_theme_get_search_path      (GtkIconTheme                *self,
-                                                      gchar                      **path[],
-                                                      gint                        *n_elements);
+                                                      const char * const          *path);
 GDK_AVAILABLE_IN_ALL
-void             gtk_icon_theme_append_search_path   (GtkIconTheme                *self,
-                                                      const gchar                 *path);
+char **          gtk_icon_theme_get_search_path      (GtkIconTheme                *self);
 GDK_AVAILABLE_IN_ALL
-void             gtk_icon_theme_prepend_search_path  (GtkIconTheme                *self,
-                                                      const gchar                 *path);
+void             gtk_icon_theme_add_search_path      (GtkIconTheme                *self,
+                                                      const char                  *path);
 
+GDK_AVAILABLE_IN_ALL
+void             gtk_icon_theme_set_resource_path    (GtkIconTheme                *self,
+                                                      const char * const          *path);
+GDK_AVAILABLE_IN_ALL
+char **          gtk_icon_theme_get_resource_path    (GtkIconTheme                *self);
 GDK_AVAILABLE_IN_ALL
 void             gtk_icon_theme_add_resource_path    (GtkIconTheme                *self,
-                                                      const gchar                 *path);
+                                                      const char                  *path);
 
 GDK_AVAILABLE_IN_ALL
-void             gtk_icon_theme_set_custom_theme     (GtkIconTheme                *self,
-                                                      const gchar                 *theme_name);
+void             gtk_icon_theme_set_theme_name       (GtkIconTheme                *self,
+                                                      const char                  *theme_name);
+GDK_AVAILABLE_IN_ALL
+char *           gtk_icon_theme_get_theme_name       (GtkIconTheme                *self);
 
 GDK_AVAILABLE_IN_ALL
 gboolean         gtk_icon_theme_has_icon             (GtkIconTheme                *self,
@@ -138,7 +136,7 @@ GtkIconPaintable *gtk_icon_paintable_new_for_file    (GFile
                                                       gint                         size,
                                                       gint                         scale);
 GDK_AVAILABLE_IN_ALL
-GList *       gtk_icon_theme_list_icons              (GtkIconTheme                *self);
+char **               gtk_icon_theme_get_icon_names  (GtkIconTheme                *self);
 
 GDK_AVAILABLE_IN_ALL
 GType                 gtk_icon_paintable_get_type         (void) G_GNUC_CONST;
diff --git a/tests/testicontheme.c b/tests/testicontheme.c
index cc9f988dca..5acd943d15 100644
--- a/tests/testicontheme.c
+++ b/tests/testicontheme.c
@@ -49,7 +49,6 @@ main (int argc, char *argv[])
   GtkIconTheme *icon_theme;
   GtkIconPaintable *icon;
   char *themename;
-  GList *list;
   int size = 48;
   int scale = 1;
   GtkIconLookupFlags flags;
@@ -76,7 +75,7 @@ main (int argc, char *argv[])
   
   icon_theme = gtk_icon_theme_new ();
   
-  gtk_icon_theme_set_custom_theme (icon_theme, themename);
+  gtk_icon_theme_set_theme_name (icon_theme, themename);
 
   if (strcmp (argv[1], "display") == 0)
     {
@@ -117,13 +116,13 @@ main (int argc, char *argv[])
     }
   else if (strcmp (argv[1], "list") == 0)
     {
-      list = gtk_icon_theme_list_icons (icon_theme);
-      
-      while (list)
-       {
-         g_print ("%s\n", (char *)list->data);
-         list = list->next;
-       }
+      char **icons;
+      int i;
+
+      icons = gtk_icon_theme_get_icon_names (icon_theme);
+      for (i = 0; icons[i]; i++)
+       g_print ("%s\n", icons[i]);
+      g_strfreev (icons);
     }
   else if (strcmp (argv[1], "lookup") == 0)
     {
diff --git a/testsuite/gtk/defaultvalue.c b/testsuite/gtk/defaultvalue.c
index ea64a5b5de..29536fe037 100644
--- a/testsuite/gtk/defaultvalue.c
+++ b/testsuite/gtk/defaultvalue.c
@@ -392,6 +392,10 @@ G_GNUC_END_IGNORE_DEPRECATIONS
           strcmp (pspec->name, "adjustment") == 0)
         continue;
 
+      /* All the icontheme properties depend on the environment */
+      if (g_type_is_a (type, GTK_TYPE_ICON_THEME))
+        continue;
+
       if (g_test_verbose ())
         {
           g_print ("Property %s:%s\n",
diff --git a/testsuite/gtk/icontheme.c b/testsuite/gtk/icontheme.c
index 3948828b93..a343c75735 100644
--- a/testsuite/gtk/icontheme.c
+++ b/testsuite/gtk/icontheme.c
@@ -8,7 +8,7 @@ static GtkIconTheme *
 get_test_icontheme (gboolean force_reload)
 {
   static GtkIconTheme *icon_theme = NULL;
-  const char *current_dir;
+  const char *current_dir[2];
 
   if (force_reload)
     g_clear_object (&icon_theme);
@@ -17,10 +17,10 @@ get_test_icontheme (gboolean force_reload)
     return icon_theme;
 
   icon_theme = gtk_icon_theme_new ();
-  gtk_icon_theme_set_custom_theme (icon_theme, "icons");
-  gtk_icon_theme_set_display (icon_theme, gdk_display_get_default ());
-  current_dir = g_test_get_dir (G_TEST_DIST);
-  gtk_icon_theme_set_search_path (icon_theme, &current_dir, 1);
+  gtk_icon_theme_set_theme_name (icon_theme, "icons");
+  current_dir[0] = g_test_get_dir (G_TEST_DIST);
+  current_dir[1] = NULL;
+  gtk_icon_theme_set_search_path (icon_theme, current_dir);
 
   return icon_theme;
 }
@@ -656,23 +656,23 @@ static void
 test_list (void)
 {
   GtkIconTheme *theme;
-  GList *icons;
+  char **icons;
 
   theme = get_test_icontheme (TRUE);
-  icons = gtk_icon_theme_list_icons (theme);
-
-  g_assert (g_list_find_custom (icons, "size-test", (GCompareFunc)g_strcmp0));
-  g_assert (g_list_find_custom (icons, "simple", (GCompareFunc)g_strcmp0));
-  g_assert (g_list_find_custom (icons, "twosize-fixed", (GCompareFunc)g_strcmp0));
-  g_assert (g_list_find_custom (icons, "twosize", (GCompareFunc)g_strcmp0));
-  g_assert (g_list_find_custom (icons, "only32-symbolic", (GCompareFunc)g_strcmp0));
-  g_assert (g_list_find_custom (icons, "everything", (GCompareFunc)g_strcmp0));
-  g_assert (g_list_find_custom (icons, "everything-rtl", (GCompareFunc)g_strcmp0));
-  g_assert (g_list_find_custom (icons, "everything-symbolic", (GCompareFunc)g_strcmp0));
-  g_assert (g_list_find_custom (icons, "everything-justregular", (GCompareFunc)g_strcmp0));
-  g_assert (g_list_find_custom (icons, "everything-justrtl-rtl", (GCompareFunc)g_strcmp0));
-  g_assert (g_list_find_custom (icons, "everything-symbolic-rtl", (GCompareFunc)g_strcmp0));
-  g_assert (g_list_find_custom (icons, "everything-justsymbolic-symbolic", (GCompareFunc)g_strcmp0));
+  icons = gtk_icon_theme_get_icon_names (theme);
+
+  g_assert (g_strv_contains ((const char * const *)icons, "size-test"));
+  g_assert (g_strv_contains ((const char * const *)icons, "simple"));
+  g_assert (g_strv_contains ((const char * const *)icons, "twosize-fixed"));
+  g_assert (g_strv_contains ((const char * const *)icons, "twosize"));
+  g_assert (g_strv_contains ((const char * const *)icons, "only32-symbolic"));
+  g_assert (g_strv_contains ((const char * const *)icons, "everything"));
+  g_assert (g_strv_contains ((const char * const *)icons, "everything-rtl"));
+  g_assert (g_strv_contains ((const char * const *)icons, "everything-symbolic"));
+  g_assert (g_strv_contains ((const char * const *)icons, "everything-justregular"));
+  g_assert (g_strv_contains ((const char * const *)icons, "everything-justrtl-rtl"));
+  g_assert (g_strv_contains ((const char * const *)icons, "everything-symbolic-rtl"));
+  g_assert (g_strv_contains ((const char * const *)icons, "everything-justsymbolic-symbolic"));
 
   g_assert (gtk_icon_theme_has_icon (theme, "size-test"));
   g_assert (gtk_icon_theme_has_icon (theme, "simple"));
@@ -687,7 +687,7 @@ test_list (void)
   g_assert (gtk_icon_theme_has_icon (theme, "everything-symbolic-rtl"));
   g_assert (gtk_icon_theme_has_icon (theme, "everything-justsymbolic-symbolic"));
 
-  g_list_free_full (icons, g_free);
+  g_strfreev (icons);
 }
 
 static void



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