Libravatar: cache usage info label
authorRicardo Mones <ricardo@mones.org>
Sun, 28 Jun 2015 07:53:19 +0000 (09:53 +0200)
committerRicardo Mones <ricardo@mones.org>
Sun, 28 Jun 2015 07:53:19 +0000 (09:53 +0200)
src/plugins/libravatar/TODO
src/plugins/libravatar/libravatar_cache.c
src/plugins/libravatar/libravatar_cache.h
src/plugins/libravatar/libravatar_prefs.c

index f64281fc89e5e400ff052a3e8a76c581f83906dc..9149680ee79442e465dc67225c5584ab52fc5ff7 100644 (file)
@@ -6,7 +6,6 @@ Enhancements, possibilities and random ideas
 - Button for checking custom default URL is not 404 (!) check on apply (?)
 - Make it run in cache-less mode if cache dir cannot be created (??)
 - Only cache "mystery man" once for all hashes (what if changes) (?)
-- Cache information label (size on disk/# of avatars/missing cached) (?)
 - Empty avatar/missing cache button(s) (?)
 - Run network retrieval in a separate thread started at header capture
   hook (??)
index 975a6fd2e8205817eda2bada4312c397d1da5793..3c8c0bc2e1e1c01ac9dcf4de0c616ed3f1621f0f 100644 (file)
@@ -16,6 +16,8 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <sys/stat.h>
+
 #include "libravatar_cache.h"
 #include "utils.h"
 
@@ -49,3 +51,76 @@ gchar *libravatar_cache_init(const char *dirs[], gint start, gint end)
 
        return rootdir;
 }
+
+static void cache_stat_item(gpointer filename, gpointer data)
+{
+       struct stat             s;
+       const gchar             *fname = (const gchar *) filename;
+       AvatarCacheStats        *stats = (AvatarCacheStats *) data;
+
+       if (0 == g_stat(fname, &s)) {
+               if (S_ISDIR(s.st_mode) != 0) {
+                       stats->dirs++;
+               }
+               else if (S_ISREG(s.st_mode) != 0) {
+                       stats->files++;
+                       stats->bytes += s.st_size;
+               }
+               else {
+                       stats->others++;
+               }
+       }
+       else {
+               g_warning("cannot stat %s\n", fname);
+               stats->errors++;
+       }
+}
+
+static void cache_items_deep_first(const gchar *dir, GSList **items, guint *failed)
+{
+       struct dirent   *d;
+       DIR             *dp;
+
+       cm_return_if_fail(dir != NULL);
+
+       if ((dp = opendir(dir)) == NULL) {
+               g_warning("cannot open directory %s\n", dir);
+               (*failed)++;
+               return;
+       }
+       while ((d = readdir(dp)) != NULL) {
+               if (strcmp(d->d_name, ".") == 0 || strcmp(d->d_name, "..") == 0) {
+                       continue;
+               }
+               else {
+                       const gchar *fname = g_strconcat(dir, G_DIR_SEPARATOR_S,
+                                                  d->d_name, NULL);
+                       if (is_dir_exist(fname))
+                               cache_items_deep_first(fname, items, failed);
+                       *items = g_slist_append(*items, (gpointer) fname);
+               }
+       }
+       closedir(dp);
+}
+
+AvatarCacheStats *libravatar_cache_stats()
+{
+       gchar *rootdir;
+       AvatarCacheStats *stats;
+       GSList *items = NULL;
+       guint errors = 0;
+
+       stats = g_new0(AvatarCacheStats, 1);
+       cm_return_val_if_fail(stats != NULL, NULL);
+
+       rootdir = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
+                               LIBRAVATAR_CACHE_DIR, G_DIR_SEPARATOR_S,
+                               NULL);
+       cache_items_deep_first(rootdir, &items, &errors);
+       stats->errors += errors;
+       g_slist_foreach(items, (GFunc) cache_stat_item, (gpointer) stats);
+       slist_free_strings_full(items);
+       g_free(rootdir);
+
+       return stats;
+}
index 0bdec248991a33e08160fa21a6bca5a0f62a1da2..bebd4e5f04f2b648c2e1d70f5ec5e4a9d9860b4b 100644 (file)
 
 #define LIBRAVATAR_CACHE_DIR "avatarcache"
 
-gchar  *libravatar_cache_init          (const char *dirs[],
-                                        gint start,
-                                        gint end);
+typedef struct _AvatarCacheStats       AvatarCacheStats;
+
+gchar                  *libravatar_cache_init          (const char *dirs[],
+                                                        gint start,
+                                                        gint end);
+AvatarCacheStats       *libravatar_cache_stats         ();
+
+
+struct _AvatarCacheStats
+{
+       gint bytes;
+       gint files;
+       gint dirs;
+       gint others;
+       gint errors;
+};
 
 #endif
index 794a7dfb11f53f4a70c854a60fa53c28d1537ef1..766b838d6dc80e19566bcb59ebe9f078f2b63601 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "defs.h"
 #include "libravatar_prefs.h"
+#include "libravatar_cache.h"
 #include "prefs_common.h"
 #include "prefs_gtk.h"
 
@@ -128,10 +129,36 @@ static GtkWidget *labeled_spinner_box(gchar *label, GtkWidget *spinner, gchar *u
        return hbox;
 }
 
+static gchar *avatar_stats_label_markup(AvatarCacheStats *stats)
+{
+       if (stats == NULL)
+               return g_strdup(
+                       _("<span color=\"red\">Error reading cache stats</span>"));
+
+       if (stats->errors > 0)
+               return g_markup_printf_escaped(
+                       _("<span color=\"red\">Using %s in %d files, %d "
+                       "directories, %d others and %d errors</span>"),
+                       to_human_readable((goffset) stats->bytes),
+                       stats->files,
+                       stats->dirs,
+                       stats->others,
+                       stats->errors);
+
+       return g_strdup_printf(
+               _("Using %s in %d files, %d directories and %d others"),
+               to_human_readable((goffset) stats->bytes),
+               stats->files,
+               stats->dirs,
+               stats->others);
+}
+
 static GtkWidget *p_create_frame_cache(struct LibravatarPrefsPage *page)
 {
-       GtkWidget *vbox, *checkbox, *spinner, *hbox;
+       GtkWidget *vbox, *checkbox, *spinner, *hbox, *label;
        GtkAdjustment *adj;
+       AvatarCacheStats *stats;
+       gchar *markup;
 
        vbox =  gtk_vbox_new(FALSE, 6);
 
@@ -157,6 +184,17 @@ static GtkWidget *p_create_frame_cache(struct LibravatarPrefsPage *page)
        gtk_box_pack_start(GTK_BOX(vbox), checkbox, FALSE, FALSE, 0);
        gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
 
+       label = gtk_label_new(NULL);
+       gtk_widget_show(label);
+       stats = libravatar_cache_stats();
+       markup = avatar_stats_label_markup(stats);
+       if (stats != NULL)
+               g_free(stats);
+       gtk_label_set_markup(GTK_LABEL(label), markup);
+       g_free(markup);
+       gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+       gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
+
        return vbox;
 }
 
@@ -323,6 +361,7 @@ static GtkWidget *p_create_frame_network(struct LibravatarPrefsPage *page)
   ┌─Icon cache───────────────────────────────────────────┐
   │ [✔] Use cached icons                                 │
   │ Cache refresh interval [ 24 |⬘] hours                │
+  │ Using X KB in Y files and Z directories              │
   └──────────────────────────────────────────────────────┘
   ┌─Default missing icon mode────────────────────────────┐
   │ (•) None                                             │