128035cfca1b4628e31af30320df01663f7d4ace
[tweakr] / modules / tweakr-profile.c
1 /*
2  * vim:ts=4:sw=4:et:cindent:cino=(0
3  */ 
4
5 #include <config.h>
6 #include <glib.h>
7 #include <glib/gi18n-lib.h>
8
9 #include <gtk/gtk.h>
10 #include <hildon/hildon-picker-button.h>
11 #include <hildon/hildon-touch-selector.h>
12 #include <hildon/hildon-entry.h>
13 #include <hildon/hildon-defines.h>
14 #include <hildon/hildon-banner.h>
15 #include <hildon/hildon-pannable-area.h>
16
17 #include <gconf/gconf-client.h>
18
19 #include <libprofile.h>
20
21 #include "libtweakr-section/tweakr-section.h"
22 #include "libtweakr-section/tweakr-module.h"
23
24
25 #define TWEAKR_TYPE_PROFILE_SECTION \
26         (tweakr_profile_section_type)
27 #define TWEAKR_PROFILE_SECTION(obj) \
28         (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
29         TWEAKR_TYPE_PROFILE_SECTION, \
30         TweakrProfileSection))
31 #define TWEAKR_PROFILE_SECTION_CLASS(k) \
32         (G_TYPE_CHECK_CLASS_CAST((k), \
33         TWEAKR_TYPE_PROFILE_SECTION, \
34         TweakrProfileSectionClass))
35 #define TWEAKR_IS_PROFILE_SECTION(obj) \
36         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
37         TWEAKR_TYPE_PROFILE_SECTION))
38
39 #define GCONF_PATH "/system/tweakr"
40
41 typedef struct _TweakrProfileSection TweakrProfileSection;
42 typedef struct _TweakrProfileSectionClass
43                TweakrProfileSectionClass;
44
45 struct _TweakrProfileSection
46 {
47     TweakrSection parent_instance;
48
49     GtkWidget *preset_button;
50     GtkWidget *delete_button;
51     GtkWidget *delete_dialog;
52     GtkWidget *delete_box;
53     GConfClient *gconf;
54 };
55
56 struct _TweakrProfileSectionClass
57 {
58     TweakrSectionClass parent_class;
59 };
60
61
62 static GType tweakr_profile_section_get_type (GTypeModule *module);
63 static void tweakr_profile_section_class_init
64     (TweakrProfileSectionClass *class);
65 static void tweakr_profile_section_init
66     (TweakrProfileSection *section);
67 static void tweakr_profile_section_dispose (GObject *obj);
68
69 static gboolean _save (TweakrSection *section,
70                        gboolean *requires_restart);
71
72 static GType tweakr_profile_section_type = 0;
73 static TweakrSectionClass *
74     tweakr_profile_section_parent_class = NULL;
75
76
77 G_MODULE_EXPORT void
78 tweakr_module_load (TweakrModule *module)
79 {
80     tweakr_profile_section_get_type (G_TYPE_MODULE (module));
81 }
82
83 G_MODULE_EXPORT void
84 tweakr_module_unload (TweakrModule *module)
85 {
86 }
87
88 static GType
89 tweakr_profile_section_get_type (GTypeModule *module)
90 {
91     if (!tweakr_profile_section_type)
92     {
93         static const GTypeInfo section_info =
94         {
95             sizeof (TweakrProfileSectionClass),
96             (GBaseInitFunc) NULL,
97             (GBaseFinalizeFunc) NULL,
98             (GClassInitFunc) tweakr_profile_section_class_init,
99             NULL,           /* class_finalize */
100             NULL,           /* class_data     */
101             sizeof (TweakrProfileSection),
102             0,              /* n_preallocs    */
103             (GInstanceInitFunc) tweakr_profile_section_init
104         };
105
106         tweakr_profile_section_type =
107             g_type_module_register_type (module, TWEAKR_TYPE_SECTION,
108                                          "TweakrProfileSection",
109                                          &section_info, 0);
110     }
111
112     return tweakr_profile_section_type;
113 }
114
115 static void
116 tweakr_profile_section_class_init
117     (TweakrProfileSectionClass *klass)
118 {
119     GObjectClass *object_class = G_OBJECT_CLASS (klass);
120     TweakrSectionClass *section_class =
121         TWEAKR_SECTION_CLASS (klass);
122
123     tweakr_profile_section_parent_class =
124         g_type_class_peek_parent (klass);
125
126     section_class->name   = "_Profile";
127     section_class->save = _save;
128
129     object_class->dispose = tweakr_profile_section_dispose;
130 }
131
132 static void
133 _save_preset_clicked (HildonPickerButton *button,
134                       TweakrProfileSection *section)
135 {
136     GtkWindow *parent;
137     GtkWidget *dialog, *entry;
138     const gchar* text = NULL;
139
140     parent = GTK_WINDOW (gtk_widget_get_ancestor (tweakr_section_get_widget
141                                                   (TWEAKR_SECTION (section)),
142                                                   GTK_TYPE_WINDOW));
143     dialog = gtk_dialog_new_with_buttons
144         (_("Preset name"),
145          parent,
146          GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR,
147          GTK_STOCK_OK, GTK_RESPONSE_OK,
148          NULL);
149
150     entry = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT);
151     gtk_widget_show (entry);
152
153     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), entry,
154                         TRUE, TRUE, 0);
155     while (text == NULL || text [0] == '\0')
156     {
157         gint ret;
158
159         ret = gtk_dialog_run (GTK_DIALOG (dialog));
160         if (ret == GTK_RESPONSE_OK)
161         {
162             GtkWidget *banner;
163             profileval_t *values, *values_iter;
164             GConfClient *gconf;
165
166             text = hildon_entry_get_text (HILDON_ENTRY (entry));
167             if (text == NULL || text[0] == '\0')
168             {
169                 GtkWidget *banner;
170
171                 banner = hildon_banner_show_information
172                     (dialog, NULL, _("Enter the name first."));
173
174                 continue;
175             }
176
177             /* Save the settings to our own gconf directory. */
178
179             gconf = gconf_client_get_default ();
180             gconf_client_set_string (gconf, GCONF_PATH "/current-preset",
181                                      _("None"), NULL);
182             values = profile_get_values ("general");
183             for (values_iter = values;
184                  values_iter->pv_key != NULL;
185                  values_iter++)
186             {
187                 gchar key[128];
188
189                 g_snprintf (key, 128, "%s/%s/%s", GCONF_PATH, text,
190                             values_iter->pv_key);
191                 gconf_client_set_string (gconf, key, values_iter->pv_val,
192                                          NULL);
193             }
194             profile_free_values (values);
195             g_object_unref (gconf);
196
197             banner = hildon_banner_show_information
198                 (GTK_WIDGET (parent), NULL,
199                  _("Preset saved. Use the status menu to select it."));
200         }
201         else
202         {
203             gtk_widget_destroy (dialog);
204             break;
205         }
206         gtk_widget_destroy (dialog);
207     }
208 }
209
210 static GtkWidget *
211 _build_save_preset_button (TweakrProfileSection *section)
212 {
213     GtkWidget *button;
214
215     button = hildon_button_new (HILDON_SIZE_AUTO |
216                                 HILDON_SIZE_FINGER_HEIGHT,
217                                 HILDON_BUTTON_ARRANGEMENT_VERTICAL);
218     hildon_button_set_title (HILDON_BUTTON (button),
219                              _("Save current General profile to new preset"));
220     gtk_button_set_alignment (GTK_BUTTON (button), 0.0f, 0.5f);
221
222     g_signal_connect (G_OBJECT (button), "clicked",
223                       G_CALLBACK (_save_preset_clicked), section);
224
225     gtk_widget_show (button);
226     return button;
227 }
228
229 static void
230 _preset_clicked (HildonButton *button, TweakrProfileSection *section)
231 {
232     const gchar *path = g_object_get_data (G_OBJECT (button), "path");
233     gchar *basename;
234     gchar *current;
235
236     current = gconf_client_get_string (section->gconf,
237                                        GCONF_PATH "/current-preset",
238                                        NULL);
239     basename = g_path_get_basename (path);
240     if (g_strcmp0 (current, basename) == 0)
241     {
242         gconf_client_set_string (section->gconf,
243                                  GCONF_PATH "/current-preset", _("None"),
244                                  NULL);
245     }
246
247     gconf_client_recursive_unset (section->gconf, path, 0, NULL);
248     g_free (basename);
249     g_free (current);
250
251     gtk_dialog_response (GTK_DIALOG (section->delete_dialog),
252                          GTK_RESPONSE_OK);
253     hildon_banner_show_information (NULL, NULL,
254                                     _("Preset deleted."));
255 }
256
257 static void
258 _add_preset (gchar *preset, TweakrProfileSection *section)
259 {
260     GtkWidget *button;
261     gchar *basename;
262
263     basename = g_path_get_basename (preset);
264     button = hildon_button_new_with_text
265         (HILDON_SIZE_FINGER_HEIGHT, HILDON_BUTTON_ARRANGEMENT_VERTICAL,
266          basename, NULL);
267     gtk_button_set_alignment (GTK_BUTTON (button), 0.0f, 0.5f);
268     gtk_box_pack_start (GTK_BOX (section->delete_box), button, FALSE, FALSE,
269                         0);
270     g_object_set_data_full (G_OBJECT (button), "path", preset,
271                             (GDestroyNotify) g_free);
272     g_signal_connect (button, "clicked", G_CALLBACK (_preset_clicked),
273                       section);
274 }
275
276 static void
277 _delete_preset_clicked (HildonButton *b, TweakrProfileSection *section)
278 {
279     GtkWidget *panarea;
280     gint ret;
281     GSList *presets;
282     GtkWidget *parent;
283
284     parent = gtk_widget_get_ancestor (GTK_WIDGET (b), GTK_TYPE_WINDOW);
285
286     section->delete_dialog = gtk_dialog_new ();
287     gtk_window_set_modal (GTK_WINDOW (section->delete_dialog), TRUE);
288     gtk_window_set_title (GTK_WINDOW (section->delete_dialog),
289                           _("Select preset"));
290
291     panarea = hildon_pannable_area_new ();
292     section->delete_box = gtk_vbox_new (FALSE, 0);
293
294     hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (panarea),
295                                             section->delete_box);
296     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (section->delete_dialog)->vbox),
297                         panarea, TRUE, TRUE, 0);
298
299     if (section->gconf == NULL)
300     {
301         section->gconf = gconf_client_get_default ();
302     }
303     presets = gconf_client_all_dirs (section->gconf, GCONF_PATH, NULL);
304
305     g_object_set (G_OBJECT (panarea), "height-request",
306                   MIN (350, g_slist_length (presets) * 70), NULL);
307
308     g_slist_foreach (presets, (GFunc) _add_preset, section);
309
310     gtk_widget_show_all (GTK_DIALOG (section->delete_dialog)->vbox);
311     ret = gtk_dialog_run (GTK_DIALOG (section->delete_dialog));
312     gtk_widget_destroy (section->delete_dialog);
313
314     g_slist_free (presets);
315 }
316
317 static GtkWidget *
318 _build_delete_preset_button (TweakrProfileSection *section)
319 {
320     GtkWidget *button;
321
322     button = hildon_button_new (HILDON_SIZE_AUTO |
323                                 HILDON_SIZE_FINGER_HEIGHT,
324                                 HILDON_BUTTON_ARRANGEMENT_VERTICAL);
325     hildon_button_set_title (HILDON_BUTTON (button),
326                              _("Delete a profile preset"));
327     gtk_button_set_alignment (GTK_BUTTON (button), 0.0f, 0.5f);
328
329     g_signal_connect (G_OBJECT (button), "clicked",
330                       G_CALLBACK (_delete_preset_clicked), section);
331
332     gtk_widget_show (button);
333     return button;
334 }
335
336 static void
337 tweakr_profile_section_init (TweakrProfileSection *section)
338 {
339     TweakrSection *iface;
340
341     iface = TWEAKR_SECTION (section);
342     iface->name = _("Profile presets");
343     iface->widget = gtk_vbox_new (FALSE, 0);
344
345     section->preset_button = _build_save_preset_button (section);
346     section->delete_button = _build_delete_preset_button (section);
347
348     gtk_box_pack_start (GTK_BOX (iface->widget), section->preset_button,
349                         FALSE, FALSE, 0);
350     gtk_box_pack_start (GTK_BOX (iface->widget), section->delete_button,
351                         FALSE, FALSE, 0);
352 }
353
354 static void
355 tweakr_profile_section_dispose (GObject *obj)
356 {
357     TweakrProfileSection *section = TWEAKR_PROFILE_SECTION (obj);
358
359     if (section->gconf != NULL)
360     {
361         g_object_unref (section->gconf);
362         section->gconf = NULL;
363     }
364
365     G_OBJECT_CLASS (tweakr_profile_section_parent_class)->dispose (obj);
366 }
367
368 static gboolean _save (TweakrSection *section, gboolean *requires_restart)
369 {
370     return TRUE;
371 }
372