* Full implementation of the Global settings dialogs UI with all the notifications...
[modest] / src / widgets / modest-global-settings-dialog.c
1 /* Copyright (c) 2006, Nokia Corporation
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Nokia Corporation nor the names of its
14  *   contributors may be used to endorse or promote products derived from
15  *   this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include <glib/gi18n.h>
31 #include <gtk/gtknotebook.h>
32 #include <gtk/gtkstock.h>
33 #include <gtk/gtklabel.h>
34 #include <gtk/gtktogglebutton.h>
35 #include "widgets/modest-global-settings-dialog.h"
36 #include "widgets/modest-global-settings-dialog-priv.h"
37 #include "modest-defs.h"
38 #include "modest-conf.h"
39 #include "modest-runtime.h"
40 #include "modest-ui-constants.h"
41 #include "modest-tny-msg.h"
42 #include "modest-platform.h"
43 #include "widgets/modest-combo-box.h"
44 #ifdef MODEST_PLATFORM_MAEMO
45 #ifdef MODEST_HILDON_VERSION_0
46 #include <hildon-widgets/hildon-number-editor.h>
47 #else
48 #include <hildon/hildon-number-editor.h>
49 #endif /*MODEST_HILDON_VERSION_0*/
50 #endif
51 /* include other impl specific header files */
52
53 #define RETURN_FALSE_ON_ERROR(error) if (error) { g_clear_error (&error); return FALSE; }
54
55 /* 'private'/'protected' functions */
56 static void modest_global_settings_dialog_class_init (ModestGlobalSettingsDialogClass *klass);
57 static void modest_global_settings_dialog_init       (ModestGlobalSettingsDialog *obj);
58 static void modest_global_settings_dialog_finalize   (GObject *obj);
59
60 static void on_response (GtkDialog *dialog,
61                          gint arg1,
62                          gpointer user_data);
63 static void get_current_settings (ModestGlobalSettingsDialogPrivate *priv, 
64                                   ModestGlobalSettingsState *state);
65
66 /* list my signals  */
67 enum {
68         /* MY_SIGNAL_1, */
69         /* MY_SIGNAL_2, */
70         LAST_SIGNAL
71 };
72
73 /* globals */
74 static GtkDialogClass *parent_class = NULL;
75
76 /* uncomment the following if you have defined any signals */
77 /* static guint signals[LAST_SIGNAL] = {0}; */
78
79 GType
80 modest_global_settings_dialog_get_type (void)
81 {
82         static GType my_type = 0;
83         if (!my_type) {
84                 static const GTypeInfo my_info = {
85                         sizeof(ModestGlobalSettingsDialogClass),
86                         NULL,           /* base init */
87                         NULL,           /* base finalize */
88                         (GClassInitFunc) modest_global_settings_dialog_class_init,
89                         NULL,           /* class finalize */
90                         NULL,           /* class data */
91                         sizeof(ModestGlobalSettingsDialog),
92                         1,              /* n_preallocs */
93                         (GInstanceInitFunc) modest_global_settings_dialog_init,
94                         NULL
95                 };
96                 my_type = g_type_register_static (GTK_TYPE_DIALOG,
97                                                   "ModestGlobalSettingsDialog",
98                                                   &my_info, 0);
99         }
100         return my_type;
101 }
102
103 static void
104 modest_global_settings_dialog_class_init (ModestGlobalSettingsDialogClass *klass)
105 {
106         GObjectClass *gobject_class;
107         gobject_class = (GObjectClass*) klass;
108
109         parent_class            = g_type_class_peek_parent (klass);
110         gobject_class->finalize = modest_global_settings_dialog_finalize;
111
112         g_type_class_add_private (gobject_class, sizeof(ModestGlobalSettingsDialogPrivate));
113 }
114
115 static void
116 modest_global_settings_dialog_init (ModestGlobalSettingsDialog *self)
117 {
118         ModestGlobalSettingsDialogPrivate *priv;
119 /*      GdkGeometry *geometry; */
120
121         priv = MODEST_GLOBAL_SETTINGS_DIALOG_GET_PRIVATE (self);
122
123         priv->notebook = gtk_notebook_new ();
124         priv->changed = FALSE;
125
126         /* Add the buttons: */
127         gtk_dialog_add_button (GTK_DIALOG (self), GTK_STOCK_OK, GTK_RESPONSE_OK);
128         gtk_dialog_add_button (GTK_DIALOG (self), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
129     
130         /* Connect to the dialog's response signal: */
131         g_signal_connect (G_OBJECT (self), "response", G_CALLBACK (on_response), self);
132
133         /* Set title */
134         gtk_window_set_title (GTK_WINDOW (self), _("mcen_ti_options"));
135
136         /* Set geometry */
137 /*      geometry = g_malloc0(sizeof (GdkGeometry)); */
138 /*      geometry->max_width = MODEST_DIALOG_WINDOW_MAX_WIDTH; */
139 /*      geometry->min_width = MODEST_DIALOG_WINDOW_MIN_WIDTH; */
140 /*      geometry->max_height = MODEST_DIALOG_WINDOW_MAX_HEIGHT; */
141 /*      geometry->min_height = MODEST_DIALOG_WINDOW_MIN_HEIGHT; */
142 /*      gtk_window_set_geometry_hints (GTK_WINDOW (self), */
143 /*                                     GTK_WIDGET (self), */
144 /*                                     geometry, */
145 /*                                     GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE); */
146         gtk_widget_set_size_request (GTK_WIDGET (self), 
147                                      MODEST_DIALOG_WINDOW_MAX_WIDTH, 
148                                      MODEST_DIALOG_WINDOW_MAX_HEIGHT);
149 }
150
151 static void
152 modest_global_settings_dialog_finalize (GObject *obj)
153 {
154 /*      free/unref instance resources here */
155         G_OBJECT_CLASS(parent_class)->finalize (obj);
156 }
157
158 /*
159  * Creates a pair list (number,string) and adds it to the given list
160  */
161 static void
162 add_to_modest_pair_list (const gint num, const gchar *str, GSList **list)
163 {
164         gint *number;
165         ModestPair *pair;
166
167         number = g_malloc0 (sizeof (gint));
168         *number = num;
169         pair = modest_pair_new (number, g_strdup (str), FALSE);
170         *list = g_slist_prepend (*list, pair);
171 }
172
173 /*
174  * Gets a list of pairs 
175  */
176 ModestPairList *
177 _modest_global_settings_dialog_get_connected_via (void)
178 {
179         GSList *list = NULL;
180
181         add_to_modest_pair_list (MODEST_CONNECTED_VIA_WLAN, 
182                                  _("mcen_va_options_connectiontype_wlan"), 
183                                  &list);
184         add_to_modest_pair_list (MODEST_CONNECTED_VIA_ANY, 
185                                  _("mcen_va_options_connectiontype_all"), 
186                                  &list);
187
188         return (ModestPairList *) g_slist_reverse (list);
189 }
190
191 /*
192  * Gets a list of pairs of update intervals
193  */
194 ModestPairList *
195 _modest_global_settings_dialog_get_update_interval (void)
196 {
197         GSList *list = NULL;
198
199         add_to_modest_pair_list (MODEST_UPDATE_INTERVAL_5_MIN, 
200                                  _("mcen_va_options_updateinterval_5min"), 
201                                  &list);
202         add_to_modest_pair_list (MODEST_UPDATE_INTERVAL_10_MIN, 
203                                  _("mcen_va_options_updateinterval_10min"), 
204                                  &list);
205         add_to_modest_pair_list (MODEST_UPDATE_INTERVAL_15_MIN, 
206                                  _("mcen_va_options_updateinterval_15min"), 
207                                  &list);
208         add_to_modest_pair_list (MODEST_UPDATE_INTERVAL_30_MIN, 
209                                  _("mcen_va_options_updateinterval_30min"), 
210                                  &list);
211         add_to_modest_pair_list (MODEST_UPDATE_INTERVAL_1_HOUR, 
212                                  _("mcen_va_options_updateinterval_1h"), 
213                                  &list);
214         add_to_modest_pair_list (MODEST_UPDATE_INTERVAL_2_HOUR, 
215                                  _("mcen_va_options_updateinterval_2h"), 
216                                  &list);
217
218         return (ModestPairList *) g_slist_reverse (list);
219 }
220
221 /*
222  * Gets a list of pairs 
223  */
224 ModestPairList *
225 _modest_global_settings_dialog_get_msg_formats (void)
226 {
227         GSList *list = NULL;
228
229         add_to_modest_pair_list (MODEST_FILE_FORMAT_FORMATTED_TEXT, 
230                                  _("mcen_va_options_messageformat_html"), 
231                                  &list);
232         add_to_modest_pair_list (MODEST_FILE_FORMAT_PLAIN_TEXT, 
233                                  _("mcen_va_options_messageformat_plain"), 
234                                  &list);
235
236         return (ModestPairList *) g_slist_reverse (list);
237 }
238
239 void   
240 _modest_global_settings_dialog_load_conf (ModestGlobalSettingsDialogPrivate *priv)
241 {
242         ModestConf *conf;
243         gboolean checked;
244         gint combo_id, value;
245         GError *error = NULL;
246
247         conf = modest_runtime_get_conf ();
248
249         /* Autoupdate */
250         checked = modest_conf_get_bool (conf, MODEST_CONF_AUTO_UPDATE, &error);
251         if (error) {
252                 g_clear_error (&error);
253                 error = NULL;
254                 checked = FALSE;
255         }
256         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->auto_update), checked);
257         priv->initial_state.auto_update = checked;
258
259         /* Connected by */
260         combo_id = modest_conf_get_int (conf, MODEST_CONF_UPDATE_WHEN_CONNECTED_BY, &error);
261         if (error) {
262                 g_error_free (error);
263                 error = NULL;
264                 combo_id = MODEST_CONNECTED_VIA_WLAN;
265         }
266         modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->connect_via), 
267                                         (gpointer) &combo_id);
268         priv->initial_state.connect_via = combo_id;
269
270         /* Emit toggled to update the visibility of connect_by caption */
271         gtk_toggle_button_toggled (GTK_TOGGLE_BUTTON (priv->auto_update));
272
273         /* Update interval */
274         combo_id = modest_conf_get_int (conf, MODEST_CONF_UPDATE_INTERVAL, &error);
275         if (error) {
276                 g_error_free (error);
277                 error = NULL;
278                 combo_id = MODEST_UPDATE_INTERVAL_15_MIN;
279         }
280         modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->update_interval), 
281                                         (gpointer) &combo_id);
282         priv->initial_state.update_interval = combo_id;
283
284         /* Size limit */
285         value  = modest_conf_get_int (conf, MODEST_CONF_MSG_SIZE_LIMIT, &error);
286         if (error) {
287                 g_error_free (error);
288                 error = NULL;
289                 value = 1000;
290         }
291         /* It's better to do this in the subclasses, but it's just one
292            line, so we'll leave it here for the moment */
293 #ifdef MODEST_PLATFORM_MAEMO
294         hildon_number_editor_set_value (HILDON_NUMBER_EDITOR (priv->size_limit), value);
295 #else
296         gtk_spin_button_set_value (GTK_SPIN_BUTTON (priv->size_limit, value));
297 #endif
298         priv->initial_state.size_limit = value;
299
300         /* Play sound */
301         checked = modest_conf_get_bool (conf, MODEST_CONF_PLAY_SOUND_MSG_ARRIVE, &error);
302         if (error) {
303                 g_error_free (error);
304                 error = NULL;
305                 checked = FALSE;
306         }
307         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->play_sound), checked);
308         priv->initial_state.play_sound = checked;
309
310         /* Msg format */
311         combo_id = modest_conf_get_int (conf, MODEST_CONF_PREFER_FORMATTED_TEXT, &error);
312         if (error) {
313                 g_error_free (error);
314                 error = NULL;
315                 combo_id = MODEST_FILE_FORMAT_FORMATTED_TEXT;
316         }
317         modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->msg_format), 
318                                         (gpointer) &combo_id);
319         priv->initial_state.msg_format = combo_id;
320
321         /* Include reply */
322         value = modest_conf_get_int (conf, MODEST_CONF_REPLY_TYPE, &error);
323         if (error) {
324                 g_error_free (error);
325                 error = NULL;
326                 value = MODEST_TNY_MSG_REPLY_TYPE_QUOTE;
327         }
328         if (value == MODEST_TNY_MSG_REPLY_TYPE_QUOTE)
329                 checked = TRUE;
330         else
331                 checked = FALSE;
332         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->include_reply), checked);
333         priv->initial_state.include_reply = checked;
334 }
335
336 static void 
337 get_current_settings (ModestGlobalSettingsDialogPrivate *priv, 
338                       ModestGlobalSettingsState *state) 
339 {
340         gint *id;
341
342         /* Get values from UI */
343         state->auto_update = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->auto_update));
344         id = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->connect_via));
345         state->connect_via = *id;
346 #ifdef MODEST_PLATFORM_MAEMO
347         state->size_limit = hildon_number_editor_get_value (HILDON_NUMBER_EDITOR (priv->size_limit));
348 #else
349         state->size_limit = gtk_spin_button_set_value (GTK_SPIN_BUTTON (priv->size_limit));
350 #endif
351         id = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->update_interval));
352         state->update_interval = *id;
353         state->play_sound = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->play_sound));
354         id = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->msg_format));
355         state->msg_format = *id;
356         state->include_reply = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->include_reply));
357 }
358
359 gboolean
360 _modest_global_settings_dialog_save_conf (ModestGlobalSettingsDialogPrivate *priv)
361 {
362         ModestConf *conf;
363         ModestGlobalSettingsState current_state;
364         GError *error = NULL;
365
366         conf = modest_runtime_get_conf ();
367
368         get_current_settings (priv, &current_state);
369
370         /* Save configuration */
371         modest_conf_set_bool (conf, MODEST_CONF_AUTO_UPDATE, current_state.auto_update, &error);
372         RETURN_FALSE_ON_ERROR(error);
373         modest_conf_set_int (conf, MODEST_CONF_UPDATE_WHEN_CONNECTED_BY, current_state.connect_via, NULL);
374         RETURN_FALSE_ON_ERROR(error);
375         modest_conf_set_int (conf, MODEST_CONF_UPDATE_INTERVAL, current_state.update_interval, NULL);
376         RETURN_FALSE_ON_ERROR(error);
377         modest_conf_set_int (conf, MODEST_CONF_MSG_SIZE_LIMIT, current_state.size_limit, NULL);
378         RETURN_FALSE_ON_ERROR(error);
379         modest_conf_set_bool (conf, MODEST_CONF_PLAY_SOUND_MSG_ARRIVE, current_state.play_sound, NULL);
380         RETURN_FALSE_ON_ERROR(error);
381         modest_conf_set_int (conf, MODEST_CONF_PREFER_FORMATTED_TEXT, current_state.msg_format, NULL);
382         RETURN_FALSE_ON_ERROR(error);
383         modest_conf_set_int (conf, MODEST_CONF_REPLY_TYPE,
384                              (current_state.include_reply) ? MODEST_TNY_MSG_REPLY_TYPE_QUOTE : 
385                              MODEST_TNY_MSG_REPLY_TYPE_CITE, NULL);
386         RETURN_FALSE_ON_ERROR(error);
387
388         return TRUE;
389 }
390
391 static gboolean
392 settings_changed (ModestGlobalSettingsState initial_state,
393                   ModestGlobalSettingsState current_state)
394 {
395         if (initial_state.auto_update != current_state.auto_update ||
396             initial_state.connect_via != current_state.connect_via ||
397             initial_state.update_interval != current_state.update_interval ||
398             initial_state.size_limit != current_state.size_limit ||
399             initial_state.play_sound != current_state.play_sound ||
400             initial_state.msg_format != current_state.msg_format ||
401             initial_state.include_reply != current_state.include_reply)
402                 return TRUE;
403         else
404                 return FALSE;
405 }
406
407 static void
408 on_response (GtkDialog *dialog,
409              gint arg1,
410              gpointer user_data)
411 {
412         ModestGlobalSettingsDialogPrivate *priv;
413         ModestGlobalSettingsState current_state;
414         gboolean changed;
415
416         priv = MODEST_GLOBAL_SETTINGS_DIALOG_GET_PRIVATE (user_data);
417
418         get_current_settings (priv, &current_state);
419         changed = settings_changed (priv->initial_state, current_state);
420
421         if (arg1 == GTK_RESPONSE_OK) {
422                 if (changed) {
423                         gboolean saved;
424
425                         saved = _modest_global_settings_dialog_save_conf (priv);
426                         if (saved)
427                                 modest_platform_run_information_dialog (GTK_WINDOW (user_data),
428                                                                         _("mcen_ib_advsetup_settings_saved"));
429                         else
430                                 modest_platform_run_information_dialog (GTK_WINDOW (user_data),
431                                                                         _("mail_ib_setting_failed"));
432                 }
433         } else {
434                 if (changed) {
435                         gint response;
436                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (user_data), 
437                                                                             _("imum_nc_wizard_confirm_lose_changes"));
438                         /* Do not close if the user Cancels */
439                         if (response == GTK_RESPONSE_CANCEL)
440                                 g_signal_stop_emission_by_name (dialog, "response");
441                 }
442         }
443 }