Merge branch 'master' of ssh+git://git.claws-mail.org/home/git/claws
[claws.git] / src / plugins / libravatar / libravatar_prefs.c
1 /*
2  * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 1999-2014 Hiroyuki Yamamoto and the Claws Mail Team
4  * Copyright (C) 2014 Ricardo Mones
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #  include "config.h"
22 #include "claws-features.h"
23 #endif
24
25 #include <glib.h>
26 #include <glib/gi18n.h>
27
28 #include "libravatar.h"
29
30 #include <gtk/gtk.h>
31 #include <gtk/filesel.h>
32
33 #include "defs.h"
34 #include "libravatar_prefs.h"
35 #include "prefs_common.h"
36 #include "prefs_gtk.h"
37
38 #define PREFS_BLOCK_NAME "Libravatar"
39 #define NUM_DEF_BUTTONS 7
40 /* cache interval goes from 1 hour to 30 days */
41 #define INTERVAL_MIN_H 1.0
42 #define INTERVAL_MAX_H 720.0
43
44 LibravatarPrefs libravatarprefs;
45 GHashTable *libravatarmisses;
46
47 struct LibravatarPrefsPage
48 {
49         PrefsPage page;
50
51         GtkWidget *cache_interval_spin;
52         GtkWidget *cache_icons_check;
53         GtkWidget *defm_radio[NUM_DEF_BUTTONS];
54         GtkWidget *defm_url_text;
55         GtkWidget *allow_redirects_check;
56 #if (defined USE_GNUTLS && GLIB_CHECK_VERSION(2,22,0))
57         GtkWidget *allow_federated_check;
58 #endif
59 };
60
61 struct LibravatarPrefsPage libravatarprefs_page;
62
63 static PrefParam param[] = {
64         { "base_url", "http://cdn.libravatar.org/avatar",
65           &libravatarprefs.base_url,
66           P_STRING, NULL, NULL, NULL },
67         { "cache_interval", "24",
68           &libravatarprefs.cache_interval,
69           P_INT, NULL, NULL, NULL },
70         { "cache_icons", "TRUE",
71           &libravatarprefs.cache_icons,
72           P_BOOL, NULL, NULL, NULL },
73         { "default_mode", "0",
74           &libravatarprefs.default_mode,
75           P_INT, NULL, NULL, NULL },
76         { "default_mode_url", "",
77           &libravatarprefs.default_mode_url,
78           P_STRING, NULL, NULL, NULL },
79         { "allow_redirects", "TRUE",
80           &libravatarprefs.allow_redirects,
81           P_BOOL, NULL, NULL, NULL },
82 #if (defined USE_GNUTLS && GLIB_CHECK_VERSION(2,22,0))
83         { "allow_federated", "TRUE",
84           &libravatarprefs.allow_federated,
85           P_BOOL, NULL, NULL, NULL },
86 #endif
87         {NULL, NULL, NULL, P_OTHER, NULL, NULL, NULL}
88 };
89
90 static GtkWidget *create_checkbox(gchar *label, gchar *hint)
91 {
92         GtkWidget *cb = gtk_check_button_new_with_mnemonic(label);
93         CLAWS_SET_TIP(cb, hint);
94         gtk_widget_show(cb);
95
96         return cb;
97 }
98
99 static void cache_icons_check_toggled_cb(GtkToggleButton *button, gpointer data)
100 {
101         gtk_widget_set_sensitive(libravatarprefs_page.cache_interval_spin,
102                                  gtk_toggle_button_get_active(button));
103 }
104
105 static GtkWidget *p_create_frame_cache(struct LibravatarPrefsPage *page)
106 {
107         GtkWidget *vbox, *checkbox, *lbl, *lbla, *spinner, *hbox;
108         GtkAdjustment *adj;
109
110         vbox =  gtk_vbox_new(FALSE, 6);
111
112         checkbox = create_checkbox(_("_Use cached icons"),
113                                    _("Keep icons on disk for reusing instead "
114                                      "of making another network request"));
115         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbox),
116                                      libravatarprefs.cache_icons);
117         g_signal_connect(checkbox, "toggled",
118                          G_CALLBACK(cache_icons_check_toggled_cb), NULL);
119         page->cache_icons_check = checkbox;
120
121         lbl = gtk_label_new(_("Cache refresh interval"));
122         gtk_widget_show(lbl);
123         lbla = gtk_label_new(_("hours"));
124         gtk_widget_show(lbla);
125         adj = (GtkAdjustment *) gtk_adjustment_new(
126                                         libravatarprefs.cache_interval,
127                                         INTERVAL_MIN_H, INTERVAL_MAX_H, 1.0,
128                                         0.0, 0.0);
129         spinner = gtk_spin_button_new(adj, 1.0, 0);
130         gtk_widget_show(spinner);
131         gtk_widget_set_sensitive(spinner, libravatarprefs.cache_icons);
132         hbox = gtk_hbox_new(FALSE, 6);
133         gtk_box_pack_start(GTK_BOX(hbox), lbl, FALSE, FALSE, 0);
134         gtk_box_pack_start(GTK_BOX(hbox), spinner, FALSE, FALSE, 0);
135         gtk_box_pack_start(GTK_BOX(hbox), lbla, FALSE, FALSE, 0);
136         page->cache_interval_spin = spinner;
137
138         gtk_box_pack_start(GTK_BOX(vbox), checkbox, FALSE, FALSE, 0);
139         gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
140
141         return vbox;
142 }
143
144 static void default_mode_radio_button_cb(GtkToggleButton *button, gpointer data)
145 {
146         guint mode;
147         gboolean is_url;
148
149         if (gtk_toggle_button_get_active(button) != TRUE)
150                 return;
151
152         mode = *((guint *)data);
153         is_url = (mode == DEF_MODE_URL)? TRUE: FALSE;
154
155         gtk_widget_set_sensitive(libravatarprefs_page.defm_url_text, is_url);
156         if (is_url) /* custom URL requires following redirects */
157                 gtk_toggle_button_set_active(
158                         GTK_TOGGLE_BUTTON(libravatarprefs_page.allow_redirects_check),
159                         TRUE);
160
161         if (mode == DEF_MODE_NONE) {
162                 prefs_common.enable_avatars = AVATARS_ENABLE_BOTH;
163         } else {
164                 /* don't waste time with headers that won't be displayed */
165                 prefs_common.enable_avatars = AVATARS_DISABLE;
166                 /* empty missing cache when switching to generated */
167                 g_hash_table_remove_all(libravatarmisses);
168         }
169 }
170
171 static const guint radio_value[] = {
172         DEF_MODE_NONE,
173         DEF_MODE_MM,
174         DEF_MODE_IDENTICON,
175         DEF_MODE_MONSTERID,
176         DEF_MODE_WAVATAR,
177         DEF_MODE_RETRO,
178         DEF_MODE_URL
179 };
180
181 static GtkWidget *p_create_frame_missing(struct LibravatarPrefsPage *page)
182 {
183         GtkWidget *vbox, *radio[NUM_DEF_BUTTONS], *hbox, *label, *entry;
184         gboolean enable = FALSE;
185         int i, e = 0;
186         gchar *radio_label[] = {
187                 _("None"),
188                 _("Mystery man"),
189                 _("Identicon"),
190                 _("MonsterID"),
191                 _("Wavatar"),
192                 _("Retro"),
193                 _("Custom URL")
194         };
195         gchar *radio_hint[] = {
196                 _("A blank image"),
197                 _("The unobtrusive low-contrast greyish silhouette"),
198                 _("A generated geometric pattern"),
199                 _("A generated full-body monster"),
200                 _("A generated almost unique face"),
201                 _("A generated 8-bit arcade-style pixelated image"),
202                 _("Redirect to a user provided URL")
203         };
204
205         vbox =  gtk_vbox_new(FALSE, 6);
206
207         for (i = 0; i < NUM_DEF_BUTTONS; ++i) {
208                 enable = (libravatarprefs.default_mode == radio_value[i])? TRUE: FALSE;
209                 e += enable? 1: 0;
210                 radio[i] = gtk_radio_button_new_with_label_from_widget(
211                                 (i > 0)? GTK_RADIO_BUTTON(radio[i - 1]): NULL, radio_label[i]);
212                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio[i]), enable);
213                 gtk_box_pack_start(GTK_BOX(vbox), radio[i], FALSE, FALSE, 0);
214                 g_signal_connect(radio[i], "toggled",
215                                  G_CALLBACK(default_mode_radio_button_cb),
216                                  (gpointer) &(radio_value[i]));
217                 CLAWS_SET_TIP(radio[i], radio_hint[i]);
218                 gtk_widget_show(radio[i]);
219                 page->defm_radio[i] = radio[i];
220         }
221         if (e == 0) { /* unknown value, go default */
222                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio[0]), TRUE);
223                 libravatarprefs.default_mode = DEF_MODE_NONE;
224         }
225         /* don't waste time with headers that won't be displayed */
226         prefs_common.enable_avatars = (libravatarprefs.default_mode == DEF_MODE_NONE)
227                                                 ? AVATARS_ENABLE_BOTH: AVATARS_DISABLE;
228
229         label = gtk_label_new(_("URL:"));
230         gtk_widget_show(label);
231         entry = gtk_entry_new_with_max_length(MAX_URL_LENGTH);
232         gtk_widget_show(entry);
233         gtk_entry_set_text(GTK_ENTRY(entry), libravatarprefs.default_mode_url);
234
235         hbox = gtk_hbox_new(FALSE, 6);
236         gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
237         gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
238         gtk_widget_set_sensitive(entry,
239                 (libravatarprefs.default_mode == DEF_MODE_URL)? TRUE: FALSE);
240         page->defm_url_text = entry;
241
242         gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
243
244         return vbox;
245 }
246
247 static GtkWidget *p_create_frame_network(struct LibravatarPrefsPage *page)
248 {
249         GtkWidget *vbox, *chk_redirects;
250 #if (defined USE_GNUTLS && GLIB_CHECK_VERSION(2,22,0))
251         GtkWidget *chk_federated;
252 #endif
253
254         vbox =  gtk_vbox_new(FALSE, 6);
255
256         chk_redirects = create_checkbox(_("_Allow redirects to other sites"),
257                                    _("Follow redirect responses received from "
258                                      "libravatar server to other avatar "
259                                      "services like gravatar.com"));
260         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chk_redirects),
261                                      libravatarprefs.allow_redirects);
262         page->allow_redirects_check = chk_redirects;
263         gtk_box_pack_start(GTK_BOX(vbox), chk_redirects, FALSE, FALSE, 0);
264
265 #if (defined USE_GNUTLS && GLIB_CHECK_VERSION(2,22,0))
266         chk_federated = create_checkbox(_("_Enable federated servers"),
267                                 _("Try to get avatar from sender's domain "
268                                   "libravatar server"));
269         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chk_federated),
270                                      libravatarprefs.allow_federated);
271         page->allow_federated_check = chk_federated;
272         gtk_box_pack_start(GTK_BOX(vbox), chk_federated, FALSE, FALSE, 0);
273 #endif
274
275         return vbox;
276 }
277
278 /*
279   ┌─Icon cache───────────────────────────────────────────┐
280   │ [✔] Use cached icons                                 │
281   │ Cache refresh interval [ 24 |⬘] hours                │
282   └──────────────────────────────────────────────────────┘
283   ┌─Default missing icon mode────────────────────────────┐
284   │ (•) None                                             │
285   │ ( ) Mystery man                                      │
286   │ ( ) Identicon                                        │
287   │ ( ) MonsterID                                        │
288   │ ( ) Wavatar                                          │
289   │ ( ) Retro                                            │
290   │ ( ) Custom URL                                       │
291   │     URL: [_________________________________________] │
292   └──────────────────────────────────────────────────────┘
293   ┌─Network──────────────────────────────────────────────┐
294   │ [✔] Allow redirects                                  │
295   │ [✔] Federated servers                                │
296   └──────────────────────────────────────────────────────┘
297  */
298 static void libravatar_prefs_create_widget_func(PrefsPage * _page,
299                                                 GtkWindow * window,
300                                                 gpointer data)
301 {
302         struct LibravatarPrefsPage *page = (struct LibravatarPrefsPage *) _page;
303         GtkWidget *vbox, *vbox1, *vbox2, *vbox3, *frame;
304
305         vbox1 = p_create_frame_cache(page);
306         vbox2 = p_create_frame_missing(page);
307         vbox3 = p_create_frame_network(page);
308
309         vbox = gtk_vbox_new(FALSE, 6);
310         gtk_container_set_border_width(GTK_CONTAINER(vbox), VBOX_BORDER);
311
312         PACK_FRAME (vbox, frame, _("Icon cache"));
313         gtk_container_set_border_width(GTK_CONTAINER(vbox1), 6);
314         gtk_container_add(GTK_CONTAINER(frame), vbox1);
315
316         PACK_FRAME (vbox, frame, _("Default missing icon mode"));
317         gtk_container_set_border_width(GTK_CONTAINER(vbox2), 6);
318         gtk_container_add(GTK_CONTAINER(frame), vbox2);
319
320         PACK_FRAME (vbox, frame, _("Network"));
321         gtk_container_set_border_width(GTK_CONTAINER(vbox3), 6);
322         gtk_container_add(GTK_CONTAINER(frame), vbox3);
323
324         gtk_widget_show_all(vbox);
325         page->page.widget = vbox;
326 }
327
328 static void libravatar_prefs_destroy_widget_func(PrefsPage *_page)
329 {
330         /* nothing */
331 }
332
333 static void libravatar_save_config(void)
334 {
335         PrefFile *pfile;
336         gchar *rcpath;
337
338         debug_print("Saving Libravatar Page\n");
339
340         rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, COMMON_RC, NULL);
341         pfile = prefs_write_open(rcpath);
342         g_free(rcpath);
343         if (!pfile || (prefs_set_block_label(pfile, PREFS_BLOCK_NAME) < 0))
344                 return;
345
346         if (prefs_write_param(param, pfile->fp) < 0) {
347                 g_warning("Failed to write Libravatar configuration to file\n");
348                 prefs_file_close_revert(pfile);
349                 return;
350         }
351         if (fprintf(pfile->fp, "\n") < 0) {
352                 FILE_OP_ERROR(rcpath, "fprintf");
353                 prefs_file_close_revert(pfile);
354         } else
355                 prefs_file_close(pfile);
356 }
357
358 static void libravatar_prefs_save_func(PrefsPage * _page)
359 {
360         struct LibravatarPrefsPage *page = (struct LibravatarPrefsPage *) _page;
361         int i;
362
363         /* cache */
364         libravatarprefs.cache_icons = gtk_toggle_button_get_active(
365                 GTK_TOGGLE_BUTTON(page->cache_icons_check));
366         /* cache interval */
367         libravatarprefs.cache_interval = gtk_spin_button_get_value_as_int(
368                 GTK_SPIN_BUTTON(page->cache_interval_spin));
369         /* default mode */
370         for (i = 0; i < NUM_DEF_BUTTONS; ++i) {
371                 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->defm_radio[i]))) {
372                         libravatarprefs.default_mode = radio_value[i];
373                         break;
374                 }
375         }
376         /* custom url */
377         if (libravatarprefs.default_mode_url != NULL) {
378                 g_free(libravatarprefs.default_mode_url);
379         }
380         libravatarprefs.default_mode_url = gtk_editable_get_chars(
381                 GTK_EDITABLE(page->defm_url_text), 0, -1);
382         /* redirects */
383         libravatarprefs.allow_redirects = gtk_toggle_button_get_active(
384                 GTK_TOGGLE_BUTTON(page->allow_redirects_check));
385         /* federation */
386 #if (defined USE_GNUTLS && GLIB_CHECK_VERSION(2,22,0))
387         libravatarprefs.allow_federated = gtk_toggle_button_get_active(
388                 GTK_TOGGLE_BUTTON(page->allow_federated_check));
389 #endif
390
391         libravatar_save_config();
392 }
393
394 void libravatar_prefs_init(void)
395 {
396         static gchar *path[3];
397         gchar *rcpath;
398
399         path[0] = _("Plugins");
400         path[1] = _("Libravatar");
401         path[2] = NULL;
402
403         prefs_set_default(param);
404         rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, COMMON_RC, NULL);
405         prefs_read_config(param, PREFS_BLOCK_NAME, rcpath, NULL);
406         g_free(rcpath);
407
408         libravatarprefs_page.page.path = path;
409         libravatarprefs_page.page.create_widget = libravatar_prefs_create_widget_func;
410         libravatarprefs_page.page.destroy_widget = libravatar_prefs_destroy_widget_func;
411         libravatarprefs_page.page.save_page = libravatar_prefs_save_func;
412
413         prefs_gtk_register_page((PrefsPage *) &libravatarprefs_page);
414 }
415
416 void libravatar_prefs_done(void)
417 {
418         prefs_gtk_unregister_page((PrefsPage *) &libravatarprefs_page);
419 }
420