New libravatar plugin
[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
46 struct LibravatarPrefsPage
47 {
48         PrefsPage page;
49
50         GtkWidget *cache_interval_spin;
51         GtkWidget *cache_icons_check;
52         GtkWidget *defm_radio[NUM_DEF_BUTTONS];
53         GtkWidget *defm_url_text;
54         GtkWidget *allow_redirects_check;
55 };
56
57 struct LibravatarPrefsPage libravatarprefs_page;
58
59 static PrefParam param[] = {
60         { "base_url", "http://cdn.libravatar.org/avatar",
61           &libravatarprefs.base_url,
62           P_STRING, NULL, NULL, NULL },
63         { "cache_interval", "24",
64           &libravatarprefs.cache_interval,
65           P_INT, NULL, NULL, NULL },
66         { "cache_icons", "TRUE",
67           &libravatarprefs.cache_icons,
68           P_BOOL, NULL, NULL, NULL },
69         { "default_mode", "0",
70           &libravatarprefs.default_mode,
71           P_INT, NULL, NULL, NULL },
72         { "default_mode_url", "",
73           &libravatarprefs.default_mode_url,
74           P_STRING, NULL, NULL, NULL },
75         { "allow_redirects", "TRUE",
76           &libravatarprefs.allow_redirects,
77           P_BOOL, NULL, NULL, NULL },
78         {NULL, NULL, NULL, P_OTHER, NULL, NULL, NULL}
79 };
80
81 static GtkWidget *create_checkbox(gchar *label, gchar *hint)
82 {
83         GtkWidget *cb = gtk_check_button_new_with_mnemonic(label);
84         CLAWS_SET_TIP(cb, hint);
85         gtk_widget_show(cb);
86
87         return cb;
88 }
89
90 static void cache_icons_check_toggled_cb(GtkToggleButton *button, gpointer data)
91 {
92         gtk_widget_set_sensitive(libravatarprefs_page.cache_interval_spin,
93                                  gtk_toggle_button_get_active(button));
94 }
95
96 static GtkWidget *p_create_frame_cache(struct LibravatarPrefsPage *page)
97 {
98         GtkWidget *vbox, *checkbox, *lbl, *lbla, *spinner, *hbox;
99         GtkAdjustment *adj;
100
101         vbox =  gtk_vbox_new(FALSE, 6);
102
103         checkbox = create_checkbox(_("_Use cached icons"),
104                                    _("Keep icons on disk for reusing instead "
105                                      "of making another network request"));
106         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbox),
107                                      libravatarprefs.cache_icons);
108         g_signal_connect(checkbox, "toggled",
109                          G_CALLBACK(cache_icons_check_toggled_cb), NULL);
110         page->cache_icons_check = checkbox;
111
112         lbl = gtk_label_new(_("Cache refresh interval"));
113         gtk_widget_show(lbl);
114         lbla = gtk_label_new(_("hours"));
115         gtk_widget_show(lbla);
116         adj = (GtkAdjustment *) gtk_adjustment_new(
117                                         libravatarprefs.cache_interval,
118                                         INTERVAL_MIN_H, INTERVAL_MAX_H, 1.0,
119                                         0.0, 0.0);
120         spinner = gtk_spin_button_new(adj, 1.0, 0);
121         gtk_widget_show(spinner);
122         gtk_widget_set_sensitive(spinner, libravatarprefs.cache_icons);
123         hbox = gtk_hbox_new(FALSE, 6);
124         gtk_box_pack_start(GTK_BOX(hbox), lbl, FALSE, FALSE, 0);
125         gtk_box_pack_start(GTK_BOX(hbox), spinner, FALSE, FALSE, 0);
126         gtk_box_pack_start(GTK_BOX(hbox), lbla, FALSE, FALSE, 0);
127         page->cache_interval_spin = spinner;
128
129         gtk_box_pack_start(GTK_BOX(vbox), checkbox, FALSE, FALSE, 0);
130         gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
131
132         return vbox;
133 }
134
135 static void default_mode_radio_button_cb(GtkToggleButton *button, gpointer data)
136 {
137         gboolean is_url;
138
139         if (gtk_toggle_button_get_active(button) == TRUE) {
140                 is_url = (*((guint *)data) == DEF_MODE_URL)? TRUE: FALSE;
141                 gtk_widget_set_sensitive(libravatarprefs_page.defm_url_text, is_url);
142                 if (is_url) /* custom URL requires following redirects */
143                         gtk_toggle_button_set_active(
144                                 GTK_TOGGLE_BUTTON(libravatarprefs_page.allow_redirects_check),
145                                 TRUE);
146                 /* don't waste time with headers that won't be displayed */
147                 prefs_common.enable_avatars = (*((guint *)data) == DEF_MODE_NONE)
148                                                 ? AVATARS_ENABLE_BOTH: AVATARS_DISABLE;
149         }
150 }
151
152 static const guint radio_value[] = {
153         DEF_MODE_NONE,
154         DEF_MODE_MM,
155         DEF_MODE_IDENTICON,
156         DEF_MODE_MONSTERID,
157         DEF_MODE_WAVATAR,
158         DEF_MODE_RETRO,
159         DEF_MODE_URL
160 };
161
162 static GtkWidget *p_create_frame_missing(struct LibravatarPrefsPage *page)
163 {
164         GtkWidget *vbox, *radio[NUM_DEF_BUTTONS], *hbox, *label, *entry;
165         gboolean enable = FALSE;
166         int i;
167         gchar *radio_label[] = {
168                 _("None"),
169                 _("Mystery man"),
170                 _("Identicon"),
171                 _("MonsterID"),
172                 _("Wavatar"),
173                 _("Retro"),
174                 _("Custom URL")
175         };
176         gchar *radio_hint[] = {
177                 _("A blank image"),
178                 _("The unobtrusive low-contrast greyish silhouette"),
179                 _("A generated geometric pattern"),
180                 _("A generated full-body monster"),
181                 _("A generated almost unique face"),
182                 _("A generated 8-bit arcade-style pixelated image"),
183                 _("Redirect to a user provided URL")
184         };
185
186         vbox =  gtk_vbox_new(FALSE, 6);
187
188         for (i = 0; i < NUM_DEF_BUTTONS; ++i) {
189                 enable = (!enable && libravatarprefs.default_mode == radio_value[i])? TRUE: FALSE;
190                 radio[i] = gtk_radio_button_new_with_label_from_widget(
191                                 (i > 0)? GTK_RADIO_BUTTON(radio[i - 1]): NULL, radio_label[i]);
192                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio[i]), enable);
193                 gtk_box_pack_start(GTK_BOX(vbox), radio[i], FALSE, FALSE, 0);
194                 g_signal_connect(radio[i], "toggled",
195                                  G_CALLBACK(default_mode_radio_button_cb),
196                                  (gpointer) &(radio_value[i]));
197                 CLAWS_SET_TIP(radio[i], radio_hint[i]);
198                 gtk_widget_show(radio[i]);
199                 page->defm_radio[i] = radio[i];
200         }
201         if (!enable) { /* unknown value, go default */
202                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio[0]), TRUE);
203                 libravatarprefs.default_mode = DEF_MODE_NONE;
204         }
205         /* don't waste time with headers that won't be displayed */
206         prefs_common.enable_avatars = (libravatarprefs.default_mode == DEF_MODE_NONE)
207                                                 ? AVATARS_ENABLE_BOTH: AVATARS_DISABLE;
208
209         label = gtk_label_new(_("URL:"));
210         gtk_widget_show(label);
211         entry = gtk_entry_new_with_max_length(MAX_URL_LENGTH);
212         gtk_widget_show(entry);
213         gtk_entry_set_text(GTK_ENTRY(entry), libravatarprefs.default_mode_url);
214
215         hbox = gtk_hbox_new(FALSE, 6);
216         gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
217         gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
218         gtk_widget_set_sensitive(entry,
219                 (libravatarprefs.default_mode == DEF_MODE_URL)? TRUE: FALSE);
220         page->defm_url_text = entry;
221
222         gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
223
224         return vbox;
225 }
226
227 static GtkWidget *p_create_frame_network(struct LibravatarPrefsPage *page)
228 {
229         GtkWidget *vbox, *checkbox;
230
231         vbox =  gtk_vbox_new(FALSE, 6);
232
233         checkbox = create_checkbox(_("_Allow redirects to other sites"),
234                                    _("Follow redirect responses received from "
235                                      "libravatar server to other avatar "
236                                      "services like gravatar.com"));
237         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbox),
238                                      libravatarprefs.allow_redirects);
239         page->allow_redirects_check = checkbox;
240
241         gtk_box_pack_start(GTK_BOX(vbox), checkbox, FALSE, FALSE, 0);
242
243         return vbox;
244 }
245
246 /*
247   ┌─Icon cache───────────────────────────────────────────┐
248   │ [✔] Use cached icons                                 │
249   │ Cache refresh interval [ 24 |⬘] hours                │
250   └──────────────────────────────────────────────────────┘
251   ┌─Default missing icon mode────────────────────────────┐
252   │ (•) None                                             │
253   │ ( ) Mystery man                                      │
254   │ ( ) Identicon                                        │
255   │ ( ) MonsterID                                        │
256   │ ( ) Wavatar                                          │
257   │ ( ) Retro                                            │
258   │ ( ) Custom URL                                       │
259   │     URL: [_________________________________________] │
260   └──────────────────────────────────────────────────────┘
261   ┌─Network──────────────────────────────────────────────┐
262   │ [✔] Allow redirects                                  │
263   └──────────────────────────────────────────────────────┘
264  */
265 static void libravatar_prefs_create_widget_func(PrefsPage * _page,
266                                                 GtkWindow * window,
267                                                 gpointer data)
268 {
269         struct LibravatarPrefsPage *page = (struct LibravatarPrefsPage *) _page;
270         GtkWidget *vbox, *vbox1, *vbox2, *vbox3, *frame;
271
272         vbox1 = p_create_frame_cache(page);
273         vbox2 = p_create_frame_missing(page);
274         vbox3 = p_create_frame_network(page);
275
276         vbox = gtk_vbox_new(FALSE, 6);
277         gtk_container_set_border_width(GTK_CONTAINER(vbox), VBOX_BORDER);
278
279         PACK_FRAME (vbox, frame, _("Icon cache"));
280         gtk_container_set_border_width(GTK_CONTAINER(vbox1), 6);
281         gtk_container_add(GTK_CONTAINER(frame), vbox1);
282
283         PACK_FRAME (vbox, frame, _("Default missing icon mode"));
284         gtk_container_set_border_width(GTK_CONTAINER(vbox2), 6);
285         gtk_container_add(GTK_CONTAINER(frame), vbox2);
286
287         PACK_FRAME (vbox, frame, _("Network"));
288         gtk_container_set_border_width(GTK_CONTAINER(vbox3), 6);
289         gtk_container_add(GTK_CONTAINER(frame), vbox3);
290
291         gtk_widget_show_all(vbox);
292         page->page.widget = vbox;
293 }
294
295 static void libravatar_prefs_destroy_widget_func(PrefsPage *_page)
296 {
297         /* nothing */
298 }
299
300 static void libravatar_save_config(void)
301 {
302         PrefFile *pfile;
303         gchar *rcpath;
304
305         debug_print("Saving Libravatar Page\n");
306
307         rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, COMMON_RC, NULL);
308         pfile = prefs_write_open(rcpath);
309         g_free(rcpath);
310         if (!pfile || (prefs_set_block_label(pfile, PREFS_BLOCK_NAME) < 0))
311                 return;
312
313         if (prefs_write_param(param, pfile->fp) < 0) {
314                 g_warning("Failed to write Libravatar configuration to file\n");
315                 prefs_file_close_revert(pfile);
316                 return;
317         }
318         if (fprintf(pfile->fp, "\n") < 0) {
319                 FILE_OP_ERROR(rcpath, "fprintf");
320                 prefs_file_close_revert(pfile);
321         } else
322                 prefs_file_close(pfile);
323 }
324
325 static void libravatar_prefs_save_func(PrefsPage * _page)
326 {
327         struct LibravatarPrefsPage *page = (struct LibravatarPrefsPage *) _page;
328         int i;
329
330         /* cache */
331         libravatarprefs.cache_icons = gtk_toggle_button_get_active(
332                 GTK_TOGGLE_BUTTON(page->cache_icons_check));
333         /* cache interval */
334         libravatarprefs.cache_interval = gtk_spin_button_get_value_as_int(
335                 GTK_SPIN_BUTTON(page->cache_interval_spin));
336         /* default mode */
337         for (i = 0; i < NUM_DEF_BUTTONS; ++i) {
338                 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->defm_radio[i]))) {
339                         libravatarprefs.default_mode = radio_value[i];
340                         break;
341                 }
342         }
343         /* custom url */
344         if (libravatarprefs.default_mode_url != NULL) {
345                 g_free(libravatarprefs.default_mode_url);
346         }
347         libravatarprefs.default_mode_url = gtk_editable_get_chars(
348                 GTK_EDITABLE(page->defm_url_text), 0, -1);
349         /* redirects */
350         libravatarprefs.allow_redirects = gtk_toggle_button_get_active(
351                 GTK_TOGGLE_BUTTON(page->allow_redirects_check));
352
353         libravatar_save_config();
354 }
355
356 void libravatar_prefs_init(void)
357 {
358         static gchar *path[3];
359         gchar *rcpath;
360
361         path[0] = _("Plugins");
362         path[1] = _("Libravatar");
363         path[2] = NULL;
364
365         prefs_set_default(param);
366         rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, COMMON_RC, NULL);
367         prefs_read_config(param, PREFS_BLOCK_NAME, rcpath, NULL);
368         g_free(rcpath);
369
370         libravatarprefs_page.page.path = path;
371         libravatarprefs_page.page.create_widget = libravatar_prefs_create_widget_func;
372         libravatarprefs_page.page.destroy_widget = libravatar_prefs_destroy_widget_func;
373         libravatarprefs_page.page.save_page = libravatar_prefs_save_func;
374
375         prefs_gtk_register_page((PrefsPage *) &libravatarprefs_page);
376 }
377
378 void libravatar_prefs_done(void)
379 {
380         prefs_gtk_unregister_page((PrefsPage *) &libravatarprefs_page);
381 }
382