[gimp] libgimpwidgets: be smarter when changing icon themes, and have fallbacks



commit 69f87bcc84304456b5305ff416b8bad5491e550d
Author: Michael Natterer <mitch gimp org>
Date:   Sat Dec 12 19:32:11 2015 +0100

    libgimpwidgets: be smarter when changing icon themes, and have fallbacks
    
    Add gimp_stock_set_icon_theme() which can be called at any time, also
    before gimp_stock_init(), in which case we avoid setting the configured
    icon theme twice on startup. Call it from libgimp/gimpui.c and
    from app/gui/icon-themes.c so the app and plug-ins use the same
    icon theme.

 app/gui/gui.c                  |    7 ++-
 app/gui/icon-themes.c          |   21 +------
 libgimp/gimpui.c               |    5 ++
 libgimpwidgets/gimpstock.c     |  148 ++++++++++++++++++++++++++++++++++++++--
 libgimpwidgets/gimpstock.h     |    4 +-
 libgimpwidgets/gimpwidgets.def |    1 +
 6 files changed, 158 insertions(+), 28 deletions(-)
---
diff --git a/app/gui/gui.c b/app/gui/gui.c
index e2f4441..317290b 100644
--- a/app/gui/gui.c
+++ b/app/gui/gui.c
@@ -221,6 +221,11 @@ gui_init (Gimp     *gimp,
   gui_unique_init (gimp);
   gimp_language_store_parser_init ();
 
+  /*  initialize icon themes before gimp_widgets_init() so we avoid
+   *  setting the configured theme twice
+   */
+  icon_themes_init (gimp);
+
   gimp_widgets_init (gui_help_func,
                      gui_get_foreground_func,
                      gui_get_background_func,
@@ -235,8 +240,6 @@ gui_init (Gimp     *gimp,
 
   themes_init (gimp);
 
-  icon_themes_init (gimp);
-
   initial_monitor = gimp_get_monitor_at_pointer (&initial_screen);
   gtk_widget_set_default_colormap (gdk_screen_get_rgb_colormap (initial_screen));
 
diff --git a/app/gui/icon-themes.c b/app/gui/icon-themes.c
index 481e7a0..33cb5f4 100644
--- a/app/gui/icon-themes.c
+++ b/app/gui/icon-themes.c
@@ -208,10 +208,6 @@ static void
 icons_apply_theme (Gimp        *gimp,
                    const gchar *icon_theme_name)
 {
-  GtkIconTheme  *icon_theme;
-  gchar        **paths;
-  gint           n_paths;
-
   g_return_if_fail (GIMP_IS_GIMP (gimp));
 
   if (! icon_theme_name)
@@ -220,22 +216,7 @@ icons_apply_theme (Gimp        *gimp,
   if (gimp->be_verbose)
     g_print ("Loading icon theme '%s'\n", icon_theme_name);
 
-  icon_theme = gtk_icon_theme_get_default ();
-
-  gtk_icon_theme_get_search_path (icon_theme, &paths, &n_paths);
-
-  if (paths)
-    {
-      GFile *icon_theme_dir = icon_themes_get_theme_dir (gimp, icon_theme_name);
-
-      g_free (paths[0]);
-      paths[0] = g_file_get_path (icon_theme_dir);
-
-      gtk_icon_theme_set_search_path (icon_theme,
-                                      (const gchar **) paths, n_paths);
-
-      g_strfreev (paths);
-    }
+  gimp_stock_set_icon_theme (icon_themes_get_theme_dir (gimp, icon_theme_name));
 }
 
 static void
diff --git a/libgimp/gimpui.c b/libgimp/gimpui.c
index 3be7fd7..1533f86 100644
--- a/libgimp/gimpui.c
+++ b/libgimp/gimpui.c
@@ -96,6 +96,7 @@ gimp_ui_init (const gchar *prog_name,
   GdkScreen   *screen;
   const gchar *display_name;
   gchar       *themerc;
+  GFile       *icon_theme;
 
   g_return_if_fail (prog_name != NULL);
 
@@ -137,6 +138,10 @@ gimp_ui_init (const gchar *prog_name,
   screen = gdk_screen_get_default ();
   gtk_widget_set_default_colormap (gdk_screen_get_rgb_colormap (screen));
 
+  icon_theme = g_file_new_for_path (gimp_get_icon_theme_dir ());
+  gimp_stock_set_icon_theme (icon_theme);
+  g_object_unref (icon_theme);
+
   gimp_widgets_init (gimp_ui_help_func,
                      gimp_context_get_foreground,
                      gimp_context_get_background,
diff --git a/libgimpwidgets/gimpstock.c b/libgimpwidgets/gimpstock.c
index 4271cc2..625699e 100644
--- a/libgimpwidgets/gimpstock.c
+++ b/libgimpwidgets/gimpstock.c
@@ -346,6 +346,131 @@ register_bidi_stock_icon (GtkIconFactory *factory,
 }
 
 
+static GFile *icon_theme_path         = NULL;
+static GFile *default_icon_theme_path = NULL;
+
+
+static void
+gimp_stock_change_icon_theme (GFile *path)
+{
+  if (! default_icon_theme_path)
+    default_icon_theme_path = gimp_data_directory_file ("icons", "Default",
+                                                        NULL);
+
+  if (! g_file_equal (path, icon_theme_path))
+    {
+      GtkIconTheme *icon_theme = gtk_icon_theme_get_default ();
+
+      if (g_file_equal (icon_theme_path, default_icon_theme_path))
+        {
+          /*  if the current icon theme is the default theme, simply
+           *  prepend the new theme's path
+           */
+          gchar *path_str = g_file_get_path (path);
+
+          gtk_icon_theme_prepend_search_path (icon_theme, path_str);
+          g_free (path_str);
+        }
+      else
+        {
+          /*  if the current theme is not the default theme, we need
+           *  to deal with the search path's first element
+           */
+          gchar **paths;
+          gint    n_paths;
+
+          gtk_icon_theme_get_search_path (icon_theme, &paths, &n_paths);
+
+          if (g_file_equal (path, default_icon_theme_path))
+            {
+              /*  when switching to the default theme, remove the
+               *  first search path element, the default theme will
+               *  still be in the search path as fallback
+               */
+              gtk_icon_theme_set_search_path (icon_theme,
+                                              (const gchar **) paths + 1,
+                                              n_paths - 1);
+            }
+          else
+            {
+              /*  when switching between two non-default themes, replace
+               *  the first element of the search path with the new
+               *  theme's path
+               */
+              g_free (paths[0]);
+              paths[0] = g_file_get_path (path);
+
+              gtk_icon_theme_set_search_path (icon_theme,
+                                              (const gchar **) paths, n_paths);
+            }
+
+          g_strfreev (paths);
+        }
+
+      g_object_unref (icon_theme_path);
+      icon_theme_path = g_object_ref (path);
+    }
+}
+
+void
+gimp_stock_set_icon_theme (GFile *path)
+{
+  g_return_if_fail (path == NULL || G_IS_FILE (path));
+
+  if (path)
+    path = g_object_ref (path);
+  else
+    path = gimp_data_directory_file (gimp_data_directory (), "icons", "Default",
+                                     NULL);
+
+  if (! g_file_query_exists (path, NULL))
+    {
+      g_warning ("Icon theme path does not exist: %s",
+                 gimp_file_get_utf8_name (path));
+    }
+  else
+    {
+      GFile *hicolor = g_file_get_child (path, "hicolor");
+
+      if (! g_file_query_exists (hicolor, NULL))
+        {
+          g_warning ("Icon theme path has no 'hicolor' subdirectory: %s",
+                     gimp_file_get_utf8_name (path));
+        }
+      else
+        {
+          GFile *index = g_file_get_child (hicolor, "index.theme");
+
+          if (! g_file_query_exists (index, NULL))
+            {
+              g_warning ("Icon theme path has no 'hicolor/index.theme': %s",
+                         gimp_file_get_utf8_name (path));
+            }
+          else
+            {
+              /*  the path points to what looks like a valid icon theme  */
+
+              if (icon_theme_path)
+                {
+                  /*  this is an icon theme change  */
+                  gimp_stock_change_icon_theme (path);
+                }
+              else
+                {
+                  /*  this is the first call upon initialization  */
+                  icon_theme_path = g_object_ref (path);
+                }
+            }
+
+          g_object_unref (index);
+        }
+
+      g_object_unref (hicolor);
+    }
+
+  g_object_unref (path);
+}
+
 /**
  * gimp_stock_init:
  *
@@ -361,7 +486,6 @@ gimp_stock_init (void)
 
   GdkPixbuf *pixbuf;
   GError    *error = NULL;
-  gchar     *icon_theme;
   gchar     *icons_dir;
   gint       i;
 
@@ -398,15 +522,29 @@ gimp_stock_init (void)
   gtk_stock_add_static (gimp_compat_stock_items,
                         G_N_ELEMENTS (gimp_compat_stock_items));
 
-  icon_theme = g_strdup ("Default"); /* FIXME */
-  icons_dir = g_build_filename (gimp_data_directory (), "icons", icon_theme,
-                                NULL);
-  g_free (icon_theme);
+  /*  always prepend the default icon theme, it's never removed from
+   *  the path again and acts as fallback for missing icons in other
+   *  themes.
+   */
+  if (! default_icon_theme_path)
+    default_icon_theme_path = gimp_data_directory_file ("icons", "Default",
+                                                        NULL);
 
+  icons_dir = g_file_get_path (default_icon_theme_path);
   gtk_icon_theme_prepend_search_path (gtk_icon_theme_get_default (),
                                       icons_dir);
   g_free (icons_dir);
 
+  /*  if an icon theme was chosen before init(), change to it  */
+  if (icon_theme_path &&
+      ! g_file_equal (icon_theme_path, default_icon_theme_path))
+    {
+      icons_dir = g_file_get_path (icon_theme_path);
+      gtk_icon_theme_prepend_search_path (gtk_icon_theme_get_default (),
+                                          icons_dir);
+      g_free (icons_dir);
+    }
+
   pixbuf = gdk_pixbuf_new_from_resource ("/org/gimp/icons/64/gimp-wilber-eek.png",
                                          &error);
 
diff --git a/libgimpwidgets/gimpstock.h b/libgimpwidgets/gimpstock.h
index f0703a3..1d48021 100644
--- a/libgimpwidgets/gimpstock.h
+++ b/libgimpwidgets/gimpstock.h
@@ -296,7 +296,9 @@ G_BEGIN_DECLS
 #define GIMP_STOCK_CONVERT_PRECISION        GIMP_STOCK_CONVERT_RGB
 
 
-void   gimp_stock_init (void);
+void   gimp_stock_init           (void);
+
+void   gimp_stock_set_icon_theme (GFile *path);
 
 
 G_END_DECLS
diff --git a/libgimpwidgets/gimpwidgets.def b/libgimpwidgets/gimpwidgets.def
index 983efb0..e356879 100644
--- a/libgimpwidgets/gimpwidgets.def
+++ b/libgimpwidgets/gimpwidgets.def
@@ -373,6 +373,7 @@ EXPORTS
        gimp_spin_button_new
        gimp_standard_help_func
        gimp_stock_init
+       gimp_stock_set_icon_theme
        gimp_string_combo_box_get_active
        gimp_string_combo_box_get_type
        gimp_string_combo_box_new


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