Libravatar: cache usage info label
[claws.git] / src / plugins / libravatar / libravatar_prefs.c
index c14948d2ce1a4c5523d3768a022415565dc32703..766b838d6dc80e19566bcb59ebe9f078f2b63601 100644 (file)
@@ -1,7 +1,6 @@
 /*
  * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2014 Hiroyuki Yamamoto and the Claws Mail Team
- * Copyright (C) 2014 Ricardo Mones
+ * Copyright (C) 2014-2015 Ricardo Mones and the Claws Mail Team
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 
 #include "defs.h"
 #include "libravatar_prefs.h"
+#include "libravatar_cache.h"
 #include "prefs_common.h"
 #include "prefs_gtk.h"
 
 #define PREFS_BLOCK_NAME "Libravatar"
 #define NUM_DEF_BUTTONS 7
+#define CUSTOM_URL_BUTTON_INDEX 6
 /* cache interval goes from 1 hour to 30 days */
 #define INTERVAL_MIN_H 1.0
 #define INTERVAL_MAX_H 720.0
+/* timeout interval goes from 0 seconds (= use general timeout value)
+   to (general timeout value - 1) seconds */
+#define TIMEOUT_MIN_S 0.0
 
 LibravatarPrefs libravatarprefs;
+GHashTable *libravatarmisses;
 
 struct LibravatarPrefsPage
 {
@@ -52,6 +57,10 @@ struct LibravatarPrefsPage
        GtkWidget *defm_radio[NUM_DEF_BUTTONS];
        GtkWidget *defm_url_text;
        GtkWidget *allow_redirects_check;
+#if (defined USE_GNUTLS && GLIB_CHECK_VERSION(2,22,0))
+       GtkWidget *allow_federated_check;
+#endif
+       GtkWidget *timeout;
 };
 
 struct LibravatarPrefsPage libravatarprefs_page;
@@ -75,6 +84,14 @@ static PrefParam param[] = {
        { "allow_redirects", "TRUE",
          &libravatarprefs.allow_redirects,
           P_BOOL, NULL, NULL, NULL },
+#if (defined USE_GNUTLS && GLIB_CHECK_VERSION(2,22,0))
+       { "allow_federated", "TRUE",
+         &libravatarprefs.allow_federated,
+          P_BOOL, NULL, NULL, NULL },
+#endif
+       { "timeout", "0",
+         &libravatarprefs.timeout,
+          P_INT, NULL, NULL, NULL },
        {NULL, NULL, NULL, P_OTHER, NULL, NULL, NULL}
 };
 
@@ -93,10 +110,55 @@ static void cache_icons_check_toggled_cb(GtkToggleButton *button, gpointer data)
                                 gtk_toggle_button_get_active(button));
 }
 
+static GtkWidget *labeled_spinner_box(gchar *label, GtkWidget *spinner, gchar *units, gchar *hint)
+{
+       GtkWidget *lbl, *lbla, *hbox;
+
+       lbl = gtk_label_new(label);
+       gtk_widget_show(lbl);
+       lbla = gtk_label_new(units);
+       gtk_widget_show(lbla);
+       hbox = gtk_hbox_new(FALSE, 6);
+       if (hint != NULL) {
+               CLAWS_SET_TIP(spinner, hint);
+       }
+       gtk_box_pack_start(GTK_BOX(hbox), lbl, FALSE, FALSE, 0);
+       gtk_box_pack_start(GTK_BOX(hbox), spinner, FALSE, FALSE, 0);
+       gtk_box_pack_start(GTK_BOX(hbox), lbla, FALSE, FALSE, 0);
+
+       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, *lbl, *lbla, *spinner, *hbox;
+       GtkWidget *vbox, *checkbox, *spinner, *hbox, *label;
        GtkAdjustment *adj;
+       AvatarCacheStats *stats;
+       gchar *markup;
 
        vbox =  gtk_vbox_new(FALSE, 6);
 
@@ -109,10 +171,6 @@ static GtkWidget *p_create_frame_cache(struct LibravatarPrefsPage *page)
                         G_CALLBACK(cache_icons_check_toggled_cb), NULL);
        page->cache_icons_check = checkbox;
 
-       lbl = gtk_label_new(_("Cache refresh interval"));
-       gtk_widget_show(lbl);
-       lbla = gtk_label_new(_("hours"));
-       gtk_widget_show(lbla);
        adj = (GtkAdjustment *) gtk_adjustment_new(
                                        libravatarprefs.cache_interval,
                                        INTERVAL_MIN_H, INTERVAL_MAX_H, 1.0,
@@ -120,32 +178,50 @@ static GtkWidget *p_create_frame_cache(struct LibravatarPrefsPage *page)
        spinner = gtk_spin_button_new(adj, 1.0, 0);
        gtk_widget_show(spinner);
        gtk_widget_set_sensitive(spinner, libravatarprefs.cache_icons);
-       hbox = gtk_hbox_new(FALSE, 6);
-       gtk_box_pack_start(GTK_BOX(hbox), lbl, FALSE, FALSE, 0);
-       gtk_box_pack_start(GTK_BOX(hbox), spinner, FALSE, FALSE, 0);
-       gtk_box_pack_start(GTK_BOX(hbox), lbla, FALSE, FALSE, 0);
+       hbox = labeled_spinner_box(_("Cache refresh interval"), spinner, _("hours"), NULL);
        page->cache_interval_spin = spinner;
 
        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;
 }
 
 static void default_mode_radio_button_cb(GtkToggleButton *button, gpointer data)
 {
+       guint mode;
        gboolean is_url;
 
-       if (gtk_toggle_button_get_active(button) == TRUE) {
-               is_url = (*((guint *)data) == DEF_MODE_URL)? TRUE: FALSE;
-               gtk_widget_set_sensitive(libravatarprefs_page.defm_url_text, is_url);
-               if (is_url) /* custom URL requires following redirects */
-                       gtk_toggle_button_set_active(
-                               GTK_TOGGLE_BUTTON(libravatarprefs_page.allow_redirects_check),
-                               TRUE);
+       if (gtk_toggle_button_get_active(button) != TRUE)
+               return;
+
+       mode = *((guint *)data);
+       is_url = (mode == DEF_MODE_URL)? TRUE: FALSE;
+
+       gtk_widget_set_sensitive(libravatarprefs_page.defm_url_text, is_url);
+       if (is_url) /* custom URL requires following redirects */
+               gtk_toggle_button_set_active(
+                       GTK_TOGGLE_BUTTON(libravatarprefs_page.allow_redirects_check),
+                       TRUE);
+
+       if (mode == DEF_MODE_NONE) {
+               prefs_common_get_prefs()->enable_avatars = AVATARS_ENABLE_BOTH;
+       } else {
                /* don't waste time with headers that won't be displayed */
-               prefs_common.enable_avatars = (*((guint *)data) == DEF_MODE_NONE)
-                                               ? AVATARS_ENABLE_BOTH: AVATARS_DISABLE;
+               prefs_common_get_prefs()->enable_avatars = AVATARS_DISABLE;
+               /* empty missing cache when switching to generated */
+               g_hash_table_remove_all(libravatarmisses);
        }
 }
 
@@ -161,9 +237,9 @@ static const guint radio_value[] = {
 
 static GtkWidget *p_create_frame_missing(struct LibravatarPrefsPage *page)
 {
-       GtkWidget *vbox, *radio[NUM_DEF_BUTTONS], *hbox, *label, *entry;
+       GtkWidget *vbox, *radio[NUM_DEF_BUTTONS], *hbox, *entry;
        gboolean enable = FALSE;
-       int i;
+       int i, e = 0;
        gchar *radio_label[] = {
                _("None"),
                _("Mystery man"),
@@ -186,11 +262,32 @@ static GtkWidget *p_create_frame_missing(struct LibravatarPrefsPage *page)
        vbox =  gtk_vbox_new(FALSE, 6);
 
        for (i = 0; i < NUM_DEF_BUTTONS; ++i) {
-               enable = (!enable && libravatarprefs.default_mode == radio_value[i])? TRUE: FALSE;
+               enable = (libravatarprefs.default_mode == radio_value[i])? TRUE: FALSE;
+               e += enable? 1: 0;
                radio[i] = gtk_radio_button_new_with_label_from_widget(
                                (i > 0)? GTK_RADIO_BUTTON(radio[i - 1]): NULL, radio_label[i]);
                gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio[i]), enable);
-               gtk_box_pack_start(GTK_BOX(vbox), radio[i], FALSE, FALSE, 0);
+               if (i == CUSTOM_URL_BUTTON_INDEX) {
+                       /* set related entry next to radio button */
+                       entry = gtk_entry_new_with_max_length(MAX_URL_LENGTH);
+                       CLAWS_SET_TIP(entry, _("Enter the URL you want to be "
+                               "redirected when no user icon is available. "
+                               "Leave an empty URL to use the default "
+                               "libravatar orange icon."));
+                       gtk_widget_show(entry);
+                       gtk_entry_set_text(GTK_ENTRY(entry),
+                               libravatarprefs.default_mode_url);
+                       hbox = gtk_hbox_new(FALSE, 6);
+                       gtk_box_pack_start(GTK_BOX(hbox), radio[i], FALSE, FALSE, 0);
+                       gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
+                       gtk_widget_set_sensitive(entry,
+                               (libravatarprefs.default_mode == DEF_MODE_URL)
+                               ? TRUE: FALSE);
+                       page->defm_url_text = entry;
+                       gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+               } else {
+                       gtk_box_pack_start(GTK_BOX(vbox), radio[i], FALSE, FALSE, 0);
+               }
                g_signal_connect(radio[i], "toggled",
                                 G_CALLBACK(default_mode_radio_button_cb),
                                 (gpointer) &(radio_value[i]));
@@ -198,47 +295,64 @@ static GtkWidget *p_create_frame_missing(struct LibravatarPrefsPage *page)
                gtk_widget_show(radio[i]);
                page->defm_radio[i] = radio[i];
        }
-       if (!enable) { /* unknown value, go default */
+       if (e == 0) { /* unknown value, go default */
                gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio[0]), TRUE);
                libravatarprefs.default_mode = DEF_MODE_NONE;
        }
        /* don't waste time with headers that won't be displayed */
-       prefs_common.enable_avatars = (libravatarprefs.default_mode == DEF_MODE_NONE)
-                                               ? AVATARS_ENABLE_BOTH: AVATARS_DISABLE;
+       prefs_common_get_prefs()->enable_avatars =
+               (libravatarprefs.default_mode == DEF_MODE_NONE)
+               ? AVATARS_ENABLE_BOTH: AVATARS_DISABLE;
 
-       label = gtk_label_new(_("URL:"));
-       gtk_widget_show(label);
-       entry = gtk_entry_new_with_max_length(MAX_URL_LENGTH);
-       gtk_widget_show(entry);
-       gtk_entry_set_text(GTK_ENTRY(entry), libravatarprefs.default_mode_url);
 
-       hbox = gtk_hbox_new(FALSE, 6);
-       gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-       gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
-       gtk_widget_set_sensitive(entry,
-               (libravatarprefs.default_mode == DEF_MODE_URL)? TRUE: FALSE);
-       page->defm_url_text = entry;
-
-       gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
 
        return vbox;
 }
 
 static GtkWidget *p_create_frame_network(struct LibravatarPrefsPage *page)
 {
-       GtkWidget *vbox, *checkbox;
+       GtkWidget *vbox, *chk_redirects, *spinner, *hbox;
+       GtkAdjustment *adj;
+#if (defined USE_GNUTLS && GLIB_CHECK_VERSION(2,22,0))
+       GtkWidget *chk_federated;
+#endif
 
        vbox =  gtk_vbox_new(FALSE, 6);
 
-       checkbox = create_checkbox(_("_Allow redirects to other sites"),
+       chk_redirects = create_checkbox(_("_Allow redirects to other sites"),
                                   _("Follow redirect responses received from "
                                     "libravatar server to other avatar "
                                     "services like gravatar.com"));
-       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbox),
+       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chk_redirects),
                                     libravatarprefs.allow_redirects);
-       page->allow_redirects_check = checkbox;
+       page->allow_redirects_check = chk_redirects;
+       gtk_box_pack_start(GTK_BOX(vbox), chk_redirects, FALSE, FALSE, 0);
+
+#if (defined USE_GNUTLS && GLIB_CHECK_VERSION(2,22,0))
+       chk_federated = create_checkbox(_("_Enable federated servers"),
+                               _("Try to get avatar from sender's domain "
+                                 "libravatar server"));
+       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chk_federated),
+                                    libravatarprefs.allow_federated);
+       page->allow_federated_check = chk_federated;
+       gtk_box_pack_start(GTK_BOX(vbox), chk_federated, FALSE, FALSE, 0);
+#endif
 
-       gtk_box_pack_start(GTK_BOX(vbox), checkbox, FALSE, FALSE, 0);
+       adj = (GtkAdjustment *) gtk_adjustment_new(
+                                       libravatarprefs.timeout,
+                                       TIMEOUT_MIN_S,
+                                       (prefs_common_get_prefs()->io_timeout_secs > 0)
+                                       ? (prefs_common_get_prefs()->io_timeout_secs - 1)
+                                       : 0,
+                                       1.0, 0.0, 0.0);
+       spinner = gtk_spin_button_new(adj, 1.0, 0);
+       gtk_widget_show(spinner);
+       hbox = labeled_spinner_box(_("Request timeout"), spinner, _("seconds"),
+               _("Set to 0 to use global socket I/O timeout. "
+                  "Maximum value must be also less than global socket "
+                  "I/O timeout."));
+       page->timeout = spinner;
+       gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
 
        return vbox;
 }
@@ -247,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                                             │
@@ -255,11 +370,12 @@ static GtkWidget *p_create_frame_network(struct LibravatarPrefsPage *page)
   │ ( ) MonsterID                                        │
   │ ( ) Wavatar                                          │
   │ ( ) Retro                                            │
-  │ ( ) Custom URL                                       │
-  │     URL: [_________________________________________] │
+  │ ( ) Custom URL [___________________________________] │
   └──────────────────────────────────────────────────────┘
   ┌─Network──────────────────────────────────────────────┐
   │ [✔] Allow redirects                                  │
+  │ [✔] Federated servers                                │
+  │ Timeout [ 10 |⬘] seconds                             │
   └──────────────────────────────────────────────────────┘
  */
 static void libravatar_prefs_create_widget_func(PrefsPage * _page,
@@ -311,7 +427,7 @@ static void libravatar_save_config(void)
                return;
 
        if (prefs_write_param(param, pfile->fp) < 0) {
-               g_warning("Failed to write Libravatar configuration to file\n");
+               g_warning("failed to write Libravatar configuration to file");
                prefs_file_close_revert(pfile);
                return;
        }
@@ -349,6 +465,14 @@ static void libravatar_prefs_save_func(PrefsPage * _page)
        /* redirects */
        libravatarprefs.allow_redirects = gtk_toggle_button_get_active(
                GTK_TOGGLE_BUTTON(page->allow_redirects_check));
+       /* federation */
+#if (defined USE_GNUTLS && GLIB_CHECK_VERSION(2,22,0))
+       libravatarprefs.allow_federated = gtk_toggle_button_get_active(
+               GTK_TOGGLE_BUTTON(page->allow_federated_check));
+#endif
+       /* timeout */
+       libravatarprefs.timeout = gtk_spin_button_get_value_as_int(
+               GTK_SPIN_BUTTON(page->timeout));
 
        libravatar_save_config();
 }
@@ -371,6 +495,7 @@ void libravatar_prefs_init(void)
        libravatarprefs_page.page.create_widget = libravatar_prefs_create_widget_func;
        libravatarprefs_page.page.destroy_widget = libravatar_prefs_destroy_widget_func;
        libravatarprefs_page.page.save_page = libravatar_prefs_save_func;
+       libravatarprefs_page.page.weight = 40.0;
 
        prefs_gtk_register_page((PrefsPage *) &libravatarprefs_page);
 }