[Xfce4-commits] <xfce4-weather-plugin:master> Icons: Remember icons that can not be read.

Harald Judt noreply at xfce.org
Mon Jan 14 18:08:04 CET 2013


Updating branch refs/heads/master
         to 9a632ce7b1901e873f0836dcdb68305865da91c7 (commit)
       from cd743dd183588997bcec972cac4f48d679550cb6 (commit)

commit 9a632ce7b1901e873f0836dcdb68305865da91c7
Author: Harald Judt <h.judt at gmx.at>
Date:   Mon Jan 14 02:15:48 2013 +0100

    Icons: Remember icons that can not be read.
    
    This should prevent unnecessary checking for the presence of files and
    reduce disk access somewhat.

 panel-plugin/weather-icon.c |  173 ++++++++++++++++++++++++++++++++++---------
 panel-plugin/weather-icon.h |    1 +
 2 files changed, 139 insertions(+), 35 deletions(-)

diff --git a/panel-plugin/weather-icon.c b/panel-plugin/weather-icon.c
index f9c429f..064a1f1 100644
--- a/panel-plugin/weather-icon.c
+++ b/panel-plugin/weather-icon.c
@@ -34,18 +34,100 @@
 #define ICON_DIR_SMALL "22"
 #define ICON_DIR_MEDIUM "48"
 #define ICON_DIR_BIG "128"
-#define NODATA "NODATA"
+
+
+static gboolean
+icon_missing(const icon_theme *theme,
+             const gchar *sizedir,
+             const gchar *symbol_name,
+             const gchar *suffix)
+{
+    gchar *missing, *icon;
+    gint i;
+
+    icon = g_strconcat(sizedir, G_DIR_SEPARATOR_S, symbol_name, suffix, NULL);
+    for (i = 0; i < theme->missing_icons->len; i++) {
+        missing = g_array_index(theme->missing_icons, gchar *, i);
+        if (G_UNLIKELY(missing == NULL))
+            continue;
+        if (!strcmp(missing, icon)) {
+            g_free(icon);
+            return TRUE;
+        }
+    }
+    g_free(icon);
+    return FALSE;
+}
+
+
+static void
+remember_missing_icon(const icon_theme *theme,
+                      const gchar *sizedir,
+                      const gchar *symbol_name,
+                      const gchar *suffix)
+{
+    gchar *icon;
+
+    icon = g_strconcat(sizedir, G_DIR_SEPARATOR_S, symbol_name, suffix, NULL);
+    g_array_append_val(theme->missing_icons, icon);
+    weather_debug("Remembered missing icon %s.", icon);
+}
+
+
+static const gchar *
+get_icon_sizedir(const gint size)
+{
+    const gchar *sizedir;
+
+    if (size < 24)
+        sizedir = ICON_DIR_SMALL;
+    else if (size < 49)
+        sizedir = ICON_DIR_MEDIUM;
+    else
+        sizedir = ICON_DIR_BIG;
+    return sizedir;
+}
+
+
+static gchar *
+make_icon_filename(const icon_theme *theme,
+                   const gchar *sizedir,
+                   const gchar *symbol_name,
+                   const gchar *suffix)
+{
+    gchar *filename, *symlow;
+
+    symlow = g_ascii_strdown(symbol_name, -1);
+    filename = g_strconcat(theme->dir, G_DIR_SEPARATOR_S, sizedir,
+                           G_DIR_SEPARATOR_S, symlow, suffix, ".png", NULL);
+    g_free(symlow);
+    return filename;
+}
+
+
+static gchar *
+make_fallback_icon_filename(const gchar *sizedir)
+{
+    gchar *filename, *symlow;
+
+    symlow = g_ascii_strdown(symbol_names[SYMBOL_NODATA], -1);
+    filename = g_strconcat(THEMESDIR, G_DIR_SEPARATOR_S, DEFAULT_W_THEME,
+                           G_DIR_SEPARATOR_S, sizedir, G_DIR_SEPARATOR_S,
+                           symlow, ".png", NULL);
+    g_free(symlow);
+    return filename;
+}
 
 
 GdkPixbuf *
 get_icon(const icon_theme *theme,
-         const gchar *number,
+         const gchar *symbol_name,
          const gint size,
          const gboolean night)
 {
     GdkPixbuf *image = NULL;
-    const gchar* dir;
-    gchar *filename, *suffix = "";
+    const gchar *sizedir;
+    gchar *filename = NULL, *suffix = "";
 
     g_assert(theme != NULL);
     if (G_UNLIKELY(!theme)) {
@@ -53,47 +135,44 @@ get_icon(const icon_theme *theme,
         return NULL;
     }
 
-    /* Try to use optimal size */
-    if (size < 24)
-        dir = ICON_DIR_SMALL;
-    else if (size < 49)
-        dir = ICON_DIR_MEDIUM;
-    else
-        dir = ICON_DIR_BIG;
+    /* choose icons from directory best matching the requested size */
+    sizedir = get_icon_sizedir(size);
 
-    if (number == NULL || strlen(number) == 0)
-        number = NODATA;
+    if (symbol_name == NULL || strlen(symbol_name) == 0)
+        symbol_name = symbol_names[SYMBOL_NODATA];
     else if (night)
         suffix = "-night";
 
-    filename = g_strconcat(theme->dir, G_DIR_SEPARATOR_S,
-                           dir, G_DIR_SEPARATOR_S,
-                           g_ascii_strdown(number, -1),
-                           suffix, ".png", NULL);
-
-    image = gdk_pixbuf_new_from_file_at_scale(filename, size, size, TRUE, NULL);
+    /* check whether icon has been verified to be missing before */
+    if (!icon_missing(theme, sizedir, symbol_name, suffix)) {
+        filename = make_icon_filename(theme, sizedir, symbol_name, suffix);
+        image = gdk_pixbuf_new_from_file_at_scale(filename, size, size, TRUE, NULL);
+    }
 
-    if (G_UNLIKELY(!image)) {
-        weather_debug("Unable to open image: %s", filename);
-        if (number && strcmp(number, NODATA)) {
+    if (image == NULL) {
+        /* remember failure for future lookups */
+        if (filename) {
+            weather_debug("Unable to open image: %s", filename);
+            remember_missing_icon(theme, sizedir, symbol_name, suffix);
             g_free(filename);
+            filename = NULL;
+        }
 
-            /* maybe there is no night icon, so fallback to using day icon */
+        if (strcmp(symbol_name, symbol_names[SYMBOL_NODATA]))
             if (night)
-                return get_icon(theme, number, size, FALSE);
+                /* maybe there is no night icon, so fallback to using day icon... */
+                return get_icon(theme, symbol_name, size, FALSE);
             else
+                /* ... or use NODATA if we tried that already */
                 return get_icon(theme, NULL, size, FALSE);
-        } else {
-            /* last fallback: get NODATA icon from standard theme */
-            g_free(filename);
-            filename = g_strconcat(THEMESDIR, G_DIR_SEPARATOR_S,
-                                   DEFAULT_W_THEME, G_DIR_SEPARATOR_S,
-                                   dir, G_DIR_SEPARATOR_S,
-                                   g_ascii_strdown(NODATA, -1), ".png", NULL);
+        else {
+            /* last chance: get NODATA icon from standard theme */
+            filename = make_fallback_icon_filename(sizedir);
             image = gdk_pixbuf_new_from_file_at_scale(filename, size, size,
                                                       TRUE, NULL);
-            if (G_UNLIKELY(!image))
-                g_warning("Failed to open image: %s", filename);
+            if (G_UNLIKELY(image == NULL))
+                g_warning("Failed to open fallback icon from standard theme: %s",
+                          filename);
         }
     }
     g_free(filename);
@@ -103,6 +182,22 @@ get_icon(const icon_theme *theme,
 
 
 /*
+ * Create a new icon theme struct, initializing caches to undefined.
+ */
+static icon_theme *
+make_icon_theme(void)
+{
+    icon_theme *theme = g_slice_new0(icon_theme);
+
+    g_assert(theme != NULL);
+    if (theme == NULL)
+        return NULL;
+    theme->missing_icons = g_array_new(FALSE, TRUE, sizeof(gchar *));
+    return theme;
+}
+
+
+/*
  * Load icon theme info from theme info file given a directory.
  */
 icon_theme *
@@ -127,7 +222,7 @@ icon_theme_load_info(const gchar *dir)
         if (!rc)
             return NULL;
 
-        if ((theme = g_slice_new0(icon_theme)) == NULL) {
+        if ((theme = make_icon_theme()) == NULL) {
             xfce_rc_close(rc);
             return NULL;
         }
@@ -293,7 +388,7 @@ icon_theme_copy(icon_theme *src)
     if (G_UNLIKELY(src == NULL))
         return NULL;
 
-    dst = g_slice_new0(icon_theme);
+    dst = make_icon_theme();
     if (G_UNLIKELY(dst == NULL))
         return NULL;
 
@@ -314,6 +409,9 @@ icon_theme_copy(icon_theme *src)
 void
 icon_theme_free(icon_theme *theme)
 {
+    gchar *missing;
+    guint i;
+
     g_assert(theme != NULL);
     if (G_UNLIKELY(theme == NULL))
         return;
@@ -322,5 +420,10 @@ icon_theme_free(icon_theme *theme)
     g_free(theme->author);
     g_free(theme->description);
     g_free(theme->license);
+    for (i = 0; i < theme->missing_icons->len; i++) {
+        missing = g_array_index(theme->missing_icons, gchar *, i);
+        g_free(missing);
+    }
+    g_array_free(theme->missing_icons, FALSE);
     g_slice_free(icon_theme, theme);
 }
diff --git a/panel-plugin/weather-icon.h b/panel-plugin/weather-icon.h
index 4178b85..b5a39a2 100644
--- a/panel-plugin/weather-icon.h
+++ b/panel-plugin/weather-icon.h
@@ -82,6 +82,7 @@ typedef struct {
     gchar *author;
     gchar *description;
     gchar *license;
+    GArray *missing_icons;
 } icon_theme;
 
 


More information about the Xfce4-commits mailing list