Libravatar: clean cache button
authorRicardo Mones <ricardo@mones.org>
Sun, 28 Jun 2015 07:54:04 +0000 (09:54 +0200)
committerRicardo Mones <ricardo@mones.org>
Sun, 28 Jun 2015 07:54:04 +0000 (09:54 +0200)
src/plugins/libravatar/TODO
src/plugins/libravatar/libravatar_cache.c
src/plugins/libravatar/libravatar_cache.h
src/plugins/libravatar/libravatar_prefs.c

index 9149680ee79442e465dc67225c5584ab52fc5ff7..61667a6d888f1c1dc7793e952d3661ef258388d0 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) (?)
-- Empty avatar/missing cache button(s) (?)
 - Run network retrieval in a separate thread started at header capture
   hook (??)
 - Alternate proxy support (send avatar requests through a proxy which
index 3c8c0bc2e1e1c01ac9dcf4de0c616ed3f1621f0f..df378f90f4d0a0c5f6897bd49d5330fc737b9887 100644 (file)
@@ -124,3 +124,43 @@ AvatarCacheStats *libravatar_cache_stats()
 
        return stats;
 }
+
+static void cache_delete_item(gpointer filename, gpointer errors)
+{
+       const gchar *fname = (const gchar *) filename;
+       AvatarCleanupResult *acr = (AvatarCleanupResult *) errors;
+
+       if (!is_dir_exist(fname)) {
+               if (claws_unlink(fname) < 0) {
+                       g_warning("couldn't delete file %s\n", fname);
+                       (acr->e_unlink)++;
+               }
+               else {
+                       (acr->removed)++;
+               }
+       }
+}
+
+AvatarCleanupResult *libravatar_cache_clean()
+{
+       gchar *rootdir;
+       AvatarCleanupResult *acr;
+       GSList *items = NULL;
+       guint errors = 0;
+
+       acr = g_new0(AvatarCleanupResult, 1);
+       cm_return_val_if_fail(acr != 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);
+       acr->e_stat = (gint) errors;
+
+       g_slist_foreach(items, (GFunc) cache_delete_item, (gpointer) acr);
+
+       slist_free_strings_full(items);
+       g_free(rootdir);
+
+       return acr;
+}
index bebd4e5f04f2b648c2e1d70f5ec5e4a9d9860b4b..2d97e9c368f71a30a5329044baecfd0d0d6b3fdc 100644 (file)
 #define LIBRAVATAR_CACHE_DIR "avatarcache"
 
 typedef struct _AvatarCacheStats       AvatarCacheStats;
+typedef struct _AvatarCleanupResult    AvatarCleanupResult;
 
 gchar                  *libravatar_cache_init          (const char *dirs[],
                                                         gint start,
                                                         gint end);
 AvatarCacheStats       *libravatar_cache_stats         ();
-
+AvatarCleanupResult    *libravatar_cache_clean         ();
 
 struct _AvatarCacheStats
 {
@@ -40,4 +41,11 @@ struct _AvatarCacheStats
        gint errors;
 };
 
+struct _AvatarCleanupResult
+{
+       guint removed;
+       guint e_stat;
+       guint e_unlink;
+};
+
 #endif
index 766b838d6dc80e19566bcb59ebe9f078f2b63601..9e0e6c9995f8cf740754c9f79fed36c81dc9f5de 100644 (file)
@@ -34,6 +34,7 @@
 #include "libravatar_cache.h"
 #include "prefs_common.h"
 #include "prefs_gtk.h"
+#include "alertpanel.h"
 
 #define PREFS_BLOCK_NAME "Libravatar"
 #define NUM_DEF_BUTTONS 7
@@ -153,9 +154,56 @@ static gchar *avatar_stats_label_markup(AvatarCacheStats *stats)
                stats->others);
 }
 
+static void cache_clean_button_clicked_cb(GtkButton *button, gpointer data)
+{
+       GtkLabel *label = (GtkLabel *) data;
+       gint val = 0;
+       AvatarCleanupResult *acr;
+       guint misses;
+
+       val = alertpanel_full(_("Clear icon cache"),
+                       _("Are you sure you want to remove all cached avatar icons?"),
+                       GTK_STOCK_NO, GTK_STOCK_YES, NULL, FALSE,
+                       NULL, ALERT_WARNING, G_ALERTDEFAULT);
+       if (val != G_ALERTALTERNATE)
+               return;
+
+       debug_print("cleaning missing cache");
+       misses = g_hash_table_size(libravatarmisses);
+       g_hash_table_remove_all(libravatarmisses);
+
+       debug_print("cleaning disk cache");
+       acr = libravatar_cache_clean();
+       if (acr == NULL) {
+               alertpanel_error(_("Not enough memory for operation"));
+               return;
+       }
+
+       if (acr->e_stat == 0 && acr->e_unlink == 0) {
+               alertpanel_notice(_("Icon cache successfully cleared:\n"
+                       "• %u missing entries removed.\n"
+                       "• %u files removed."),
+                       misses, acr->removed);
+               gtk_label_set_markup(label,
+                       _("<span color=\"#006400\">Icon cache succesfully cleared!</span>"));
+       }
+       else {
+               alertpanel_warning(_("Errors clearing icon cache:\n"
+                       "• %u missing entries removed.\n"
+                       "• %u files removed.\n"
+                       "• %u files failed to be read.\n"
+                       "• %u files couldn't be removed."),
+                       misses, acr->removed, acr->e_stat, acr->e_unlink);
+               gtk_label_set_markup(label,
+                       _("<span color=\"red\">Error clearing icon cache.</span>"));
+       }
+       gtk_widget_set_sensitive(GTK_WIDGET(button), FALSE);
+       g_free(acr);
+}
+
 static GtkWidget *p_create_frame_cache(struct LibravatarPrefsPage *page)
 {
-       GtkWidget *vbox, *checkbox, *spinner, *hbox, *label;
+       GtkWidget *vbox, *checkbox, *spinner, *hbox, *label, *button;
        GtkAdjustment *adj;
        AvatarCacheStats *stats;
        gchar *markup;
@@ -188,12 +236,24 @@ static GtkWidget *p_create_frame_cache(struct LibravatarPrefsPage *page)
        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);
+
+       button = gtk_button_new_from_stock(GTK_STOCK_CLEAR);
+       gtk_widget_show(button);
+       g_signal_connect(button, "clicked",
+               G_CALLBACK(cache_clean_button_clicked_cb), label);
+       gtk_widget_set_sensitive(button, (stats != NULL && stats->bytes > 0));
+
+       hbox = gtk_hbox_new(FALSE, 6);
+       gtk_widget_show(hbox);
+       gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+       gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
+       gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+
+       if (stats != NULL)
+               g_free(stats);
 
        return vbox;
 }
@@ -361,7 +421,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              │
+  │ Using X KB in Y files and Z directories [Clear]      │
   └──────────────────────────────────────────────────────┘
   ┌─Default missing icon mode────────────────────────────┐
   │ (•) None                                             │