~ubuntu-branches/ubuntu/oneiric/alarm-clock-applet/oneiric

« back to all changes in this revision

Viewing changes to src/edit-alarm.c

  • Committer: Bazaar Package Importer
  • Author(s): Chow Loong Jin
  • Date: 2009-05-30 23:24:27 UTC
  • Revision ID: james.westby@ubuntu.com-20090530232427-88on1j2ily4ajxdz
Tags: upstream-0.2.6
ImportĀ upstreamĀ versionĀ 0.2.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * edit-alarm.c -- Alarm settings dialog
 
3
 * 
 
4
 * Copyright (C) 2007-2008 Johannes H. Jensen <joh@pseudoberries.com>
 
5
 * 
 
6
 * This program is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the GNU General Public License
 
8
 * as published by the Free Software Foundation; either version 2
 
9
 * of the License, or (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, write to the Free Software
 
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
19
 * 
 
20
 * Authors:
 
21
 *              Johannes H. Jensen <joh@pseudoberries.com>
 
22
 */
 
23
 
 
24
#include "edit-alarm.h"
 
25
#include "alarm-applet.h"
 
26
#include "alarm.h"
 
27
#include "player.h"
 
28
 
 
29
#include <glib.h>
 
30
#include <glib-object.h>
 
31
#include <gtk/gtk.h>
 
32
 
 
33
static void
 
34
alarm_settings_update_time (AlarmSettingsDialog *dialog);
 
35
 
 
36
static void
 
37
time_changed_cb (GtkSpinButton *spinbutton, gpointer data);
 
38
 
 
39
static void
 
40
sound_combo_changed_cb (GtkComboBox *combo, AlarmSettingsDialog *dialog);
 
41
 
 
42
static void
 
43
app_combo_changed_cb (GtkComboBox *combo, AlarmSettingsDialog *dialog);
 
44
 
 
45
 
 
46
 
 
47
#define REPEAT_LABEL    _("<b>T_rigger alarm:</b> %s")
 
48
 
 
49
 
 
50
/*
 
51
 * Utility functions
 
52
 */
 
53
 
 
54
static GtkWidget *
 
55
create_img_label (const gchar *label_text, const gchar *icon_name)
 
56
{
 
57
        gchar *tmp;
 
58
        
 
59
        tmp = g_strdup_printf ("<b>%s</b>", label_text);
 
60
        
 
61
        GdkPixbuf *icon;
 
62
        GtkWidget *img, *label, *spacer;        // TODO: Ugly with spacer
 
63
        GtkWidget *hbox;
 
64
        
 
65
        icon = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
 
66
                                                                         icon_name,
 
67
                                                                         24,
 
68
                                                                         0, NULL);
 
69
        img = gtk_image_new_from_pixbuf(icon);
 
70
        label = g_object_new (GTK_TYPE_LABEL,
 
71
                                                  "label", tmp,
 
72
                                                  "use-markup", TRUE,
 
73
                                                  "xalign", 0.0,
 
74
                                                  NULL);
 
75
        
 
76
        hbox = g_object_new (GTK_TYPE_HBOX, "spacing", 6, NULL);
 
77
        
 
78
        spacer = g_object_new (GTK_TYPE_LABEL, "label", "", NULL);
 
79
        gtk_box_pack_start_defaults (GTK_BOX (hbox), spacer);
 
80
        
 
81
        gtk_box_pack_start(GTK_BOX (hbox), img, FALSE, FALSE, 0);
 
82
        gtk_box_pack_start(GTK_BOX (hbox), label, FALSE, FALSE, 0);
 
83
        
 
84
        spacer = g_object_new (GTK_TYPE_LABEL, "label", "", NULL);
 
85
        gtk_box_pack_start_defaults (GTK_BOX (hbox), spacer);
 
86
        
 
87
        g_free (tmp);
 
88
        
 
89
        return hbox;
 
90
}
 
91
 
 
92
 
 
93
 
 
94
 
 
95
 
 
96
/*
 
97
 * Utility functions for updating various parts of the settings dialog.
 
98
 */
 
99
 
 
100
static void
 
101
alarm_settings_update_type (AlarmSettingsDialog *dialog)
 
102
{
 
103
        if (dialog->alarm->type == ALARM_TYPE_CLOCK) {
 
104
                gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->clock_toggle), TRUE);
 
105
                gtk_widget_set_sensitive(dialog->repeat_expand, TRUE);
 
106
        } else {
 
107
                gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->timer_toggle), TRUE);
 
108
                gtk_widget_set_sensitive(dialog->repeat_expand, FALSE);
 
109
        }
 
110
}
 
111
 
 
112
static void
 
113
alarm_settings_update_time (AlarmSettingsDialog *dialog)
 
114
{
 
115
        struct tm *tm;
 
116
        
 
117
        tm = alarm_get_time(dialog->alarm);
 
118
        
 
119
        gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->hour_spin), tm->tm_hour);
 
120
        gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->min_spin), tm->tm_min);
 
121
        gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->sec_spin), tm->tm_sec);
 
122
}
 
123
 
 
124
static void
 
125
alarm_settings_update_repeat (AlarmSettingsDialog *dialog)
 
126
{
 
127
        AlarmRepeat r;
 
128
        gint i;
 
129
        gboolean check;
 
130
        gchar *label;
 
131
        
 
132
        /*
 
133
         * Update check boxes
 
134
         */
 
135
        for (r = ALARM_REPEAT_SUN, i = 0; r <= ALARM_REPEAT_SAT; r = 1 << ++i) {
 
136
                check = (dialog->alarm->repeat & r) != 0;
 
137
                
 
138
                // Activate the appropriate widget
 
139
                g_object_set (dialog->repeat_check[i], "active", check, NULL);
 
140
        }
 
141
        
 
142
        
 
143
        /*
 
144
         * Update fancy expander label
 
145
         */
 
146
        
 
147
        if (dialog->alarm->repeat == ALARM_REPEAT_NONE) {
 
148
                // NO REPEAT
 
149
                label = g_strdup_printf (REPEAT_LABEL, _("Once"));
 
150
                
 
151
        } else if (dialog->alarm->repeat == ALARM_REPEAT_WEEKDAYS) {
 
152
                // REPEAT WEEKDAYS
 
153
                label = g_strdup_printf (REPEAT_LABEL, _("Weekdays"));
 
154
                
 
155
        } else if (dialog->alarm->repeat == ALARM_REPEAT_WEEKENDS) {
 
156
                // REPEAT WEEKENDS
 
157
                label = g_strdup_printf (REPEAT_LABEL, _("Weekends"));
 
158
                
 
159
        } else if (dialog->alarm->repeat == ALARM_REPEAT_ALL) {
 
160
                // REPEAT WEEK
 
161
                label = g_strdup_printf (REPEAT_LABEL, _("Every day"));
 
162
                
 
163
        } else {
 
164
                // CUSTOM
 
165
                label = g_strdup_printf (REPEAT_LABEL, _("Custom"));
 
166
        }
 
167
        
 
168
        g_object_set (dialog->repeat_label, "label", label, NULL);
 
169
        
 
170
        g_free (label);
 
171
}
 
172
 
 
173
static void
 
174
alarm_settings_update_snooze (AlarmSettingsDialog *dialog)
 
175
{
 
176
        g_object_set (dialog->snooze_spin, "value", (gdouble)dialog->alarm->snooze, NULL);
 
177
        
 
178
        g_object_set (dialog->snooze_check, "active", dialog->alarm->snooze > 0, NULL);
 
179
}
 
180
 
 
181
static void
 
182
alarm_settings_update_notify_type (AlarmSettingsDialog *dialog)
 
183
{
 
184
        // Enable selected
 
185
        switch (dialog->alarm->notify_type) {
 
186
        case ALARM_NOTIFY_COMMAND:
 
187
                g_object_set (dialog->notify_app_radio, "active", TRUE, NULL);
 
188
                g_object_set (dialog->notify_app_box, "sensitive", TRUE, NULL);
 
189
                
 
190
                // Disable others
 
191
                g_object_set (dialog->notify_sound_box, "sensitive", FALSE, NULL);
 
192
                
 
193
                if (dialog->player && dialog->player->state == MEDIA_PLAYER_PLAYING) {
 
194
                        // Stop preview player
 
195
                        media_player_stop (dialog->player);
 
196
                }
 
197
                
 
198
                break;
 
199
        default:
 
200
                // NOTIFY_SOUND
 
201
                g_object_set (dialog->notify_sound_radio, "active", TRUE, NULL);
 
202
                g_object_set (dialog->notify_sound_box, "sensitive", TRUE, NULL);
 
203
                
 
204
                // Disable others
 
205
                g_object_set (dialog->notify_app_box, "sensitive", FALSE, NULL);
 
206
                break;
 
207
        }
 
208
}
 
209
 
 
210
static void
 
211
alarm_settings_update_sound (AlarmSettingsDialog *dialog)
 
212
{
 
213
        AlarmListEntry *item;
 
214
        GList *l;
 
215
        guint pos, len, combo_len;
 
216
        gint sound_pos = -1;
 
217
        
 
218
        g_debug ("alarm_settings_update_sound (%p): sound_combo: %p, applet: %p, sounds: %p", dialog, dialog->notify_sound_combo, dialog->applet, dialog->applet->sounds);
 
219
        
 
220
        /* Fill sounds list */
 
221
        fill_combo_box (GTK_COMBO_BOX (dialog->notify_sound_combo),
 
222
                                        dialog->applet->sounds, _("Select sound file..."));
 
223
        
 
224
        // Look for the selected sound file
 
225
        for (l = dialog->applet->sounds, pos = 0; l != NULL; l = l->next, pos++) {
 
226
                item = (AlarmListEntry *)l->data;
 
227
                if (strcmp (item->data, dialog->alarm->sound_file) == 0) {
 
228
                        // Match!
 
229
                        sound_pos = pos;
 
230
                        gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->notify_sound_combo), pos);
 
231
                        break;
 
232
                }
 
233
        }
 
234
}
 
235
 
 
236
static void
 
237
alarm_settings_update_app (AlarmSettingsDialog *dialog)
 
238
{
 
239
        AlarmListEntry *item;
 
240
        GList *l;
 
241
        guint pos, len, combo_len;
 
242
        gboolean custom = FALSE;
 
243
        
 
244
        g_debug ("alarm_settings_update_app (%p): app_combo: %p, applet: %p, apps: %p", dialog, dialog->notify_app_combo, dialog->applet, dialog->applet->apps);
 
245
        g_debug ("alarm_settings_update_app setting entry to %s", dialog->alarm->command);
 
246
        
 
247
        /* Fill apps list */
 
248
        fill_combo_box (GTK_COMBO_BOX (dialog->notify_app_combo),
 
249
                                        dialog->applet->apps, _("Custom command..."));
 
250
        
 
251
        // Look for the selected command
 
252
        len = g_list_length (dialog->applet->apps);
 
253
        for (l = dialog->applet->apps, pos = 0; l != NULL; l = l->next, pos++) {
 
254
                item = (AlarmListEntry *)l->data;
 
255
                if (strcmp (item->data, dialog->alarm->command) == 0) {
 
256
                        // Match!
 
257
                        break;
 
258
                }
 
259
        }
 
260
        
 
261
        /* Only change sensitivity of the command entry if user
 
262
         * isn't typing a custom command there already. */ 
 
263
        if (pos >= len) {
 
264
                // Custom command
 
265
                pos += 1;
 
266
                custom = TRUE;
 
267
        }
 
268
        
 
269
        g_debug ("CMD ENTRY HAS FOCUS? %d", GTK_WIDGET_HAS_FOCUS (dialog->notify_app_command_entry));
 
270
        
 
271
        if (!GTK_WIDGET_HAS_FOCUS (dialog->notify_app_command_entry))
 
272
                g_object_set (dialog->notify_app_command_entry, "sensitive", custom, NULL);
 
273
        
 
274
        gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->notify_app_combo), pos);
 
275
}
 
276
 
 
277
static void
 
278
alarm_settings_update (AlarmSettingsDialog *dialog)
 
279
{
 
280
        Alarm *alarm = ALARM (dialog->alarm);
 
281
        
 
282
        g_object_set (dialog->label_entry, "text", alarm->message, NULL);
 
283
        g_object_set (dialog->notify_sound_loop_check, "active", alarm->sound_loop, NULL);
 
284
        g_object_set (dialog->notify_app_command_entry, "text", dialog->alarm->command, NULL);
 
285
        g_object_set (dialog->notify_bubble_check, "active", alarm->notify_bubble, NULL);
 
286
        
 
287
        alarm_settings_update_type (dialog);
 
288
        alarm_settings_update_time (dialog);
 
289
        alarm_settings_update_repeat (dialog);
 
290
        alarm_settings_update_snooze (dialog);
 
291
        alarm_settings_update_notify_type (dialog);
 
292
        alarm_settings_update_sound (dialog);
 
293
        alarm_settings_update_app (dialog);
 
294
}
 
295
 
 
296
 
 
297
 
 
298
 
 
299
 
 
300
 
 
301
/*
 
302
 * Alarm object callbacks
 
303
 */
 
304
 
 
305
static void
 
306
alarm_type_changed (GObject *object, 
 
307
                                        GParamSpec *param,
 
308
                                        gpointer data)
 
309
{
 
310
        AlarmSettingsDialog *dialog = (AlarmSettingsDialog *)data;
 
311
        
 
312
        alarm_settings_update_type (dialog);
 
313
}
 
314
 
 
315
static void
 
316
alarm_time_changed (GObject *object, 
 
317
                                        GParamSpec *param,
 
318
                                        gpointer data)
 
319
{
 
320
        AlarmSettingsDialog *dialog = (AlarmSettingsDialog *)data;
 
321
        
 
322
        /* Only interesting if alarm is a CLOCK */
 
323
        if (dialog->alarm->type != ALARM_TYPE_CLOCK)
 
324
                return;
 
325
        
 
326
        alarm_settings_update_time (dialog);
 
327
}
 
328
 
 
329
static void
 
330
alarm_repeat_changed (GObject *object, 
 
331
                                          GParamSpec *param,
 
332
                                          gpointer data)
 
333
{
 
334
        AlarmSettingsDialog *dialog = (AlarmSettingsDialog *)data;
 
335
        
 
336
        alarm_settings_update_repeat (dialog);
 
337
}
 
338
 
 
339
static void
 
340
alarm_snooze_changed (GObject *object, 
 
341
                                          GParamSpec *param,
 
342
                                          gpointer data)
 
343
{
 
344
        AlarmSettingsDialog *dialog = (AlarmSettingsDialog *)data;
 
345
        
 
346
        alarm_settings_update_snooze (dialog);
 
347
}
 
348
 
 
349
static void
 
350
alarm_timer_changed (GObject *object, 
 
351
                                         GParamSpec *param,
 
352
                                         gpointer data)
 
353
{
 
354
        AlarmSettingsDialog *dialog = (AlarmSettingsDialog *)data;
 
355
        
 
356
        /* Only interesting if alarm is a TIMER */
 
357
        if (dialog->alarm->type != ALARM_TYPE_TIMER)
 
358
                return;
 
359
        
 
360
        alarm_settings_update_time (dialog);
 
361
}
 
362
 
 
363
static void
 
364
alarm_notify_type_changed (GObject *object, 
 
365
                                                   GParamSpec *param,
 
366
                                                   gpointer data)
 
367
{
 
368
        AlarmSettingsDialog *dialog = (AlarmSettingsDialog *)data;
 
369
        
 
370
        alarm_settings_update_notify_type (dialog);
 
371
}
 
372
 
 
373
static void
 
374
alarm_settings_sound_file_changed (GObject *object, 
 
375
                                                                   GParamSpec *param,
 
376
                                                                   gpointer data)
 
377
{
 
378
        AlarmSettingsDialog *dialog = (AlarmSettingsDialog *)data;
 
379
        
 
380
        g_debug ("alarm_settings_sound_file_changed (%p)", data);
 
381
        
 
382
        // Block sound combo signals to prevent infinite loop
 
383
        // because the "changed" signal will be emitted when we
 
384
        // change the combo box tree model.
 
385
        g_signal_handlers_block_matched (dialog->notify_sound_combo, 
 
386
                                                                         G_SIGNAL_MATCH_FUNC, 
 
387
                                                                         0, 0, NULL, sound_combo_changed_cb, NULL);
 
388
        
 
389
        // Update UI
 
390
        alarm_settings_update_sound (dialog);
 
391
        
 
392
        // Unblock combo signals
 
393
        g_signal_handlers_unblock_matched (dialog->notify_sound_combo, 
 
394
                                                                           G_SIGNAL_MATCH_FUNC,
 
395
                                                                           0, 0, NULL, sound_combo_changed_cb, NULL);
 
396
}
 
397
 
 
398
static void
 
399
alarm_sound_repeat_changed (GObject *object, 
 
400
                                                        GParamSpec *param,
 
401
                                                        gpointer data)
 
402
{
 
403
        AlarmSettingsDialog *dialog = (AlarmSettingsDialog *)data;
 
404
        
 
405
        g_debug ("alarm_sound_repeat_changed to: %d", dialog->alarm->sound_loop);
 
406
}
 
407
 
 
408
static void
 
409
alarm_settings_command_changed (GObject *object, 
 
410
                                                                GParamSpec *param,
 
411
                                                                gpointer data)
 
412
{
 
413
        AlarmSettingsDialog *dialog = (AlarmSettingsDialog *)data;
 
414
        
 
415
        g_debug ("alarm_settings_command_changed (%p)", data);
 
416
        
 
417
        // Block sound combo signals to prevent infinite loop
 
418
        // because the "changed" signal will be emitted when we
 
419
        // change the combo box tree model.
 
420
        g_signal_handlers_block_matched (dialog->notify_app_combo, 
 
421
                                                                         G_SIGNAL_MATCH_FUNC, 
 
422
                                                                         0, 0, NULL, app_combo_changed_cb, NULL);
 
423
        
 
424
        // Update UI
 
425
        alarm_settings_update_app (dialog);
 
426
        
 
427
        // Unblock combo signals
 
428
        g_signal_handlers_unblock_matched (dialog->notify_app_combo, 
 
429
                                                                           G_SIGNAL_MATCH_FUNC,
 
430
                                                                           0, 0, NULL, app_combo_changed_cb, NULL);
 
431
}
 
432
 
 
433
 
 
434
/*
 
435
 * GUI utils
 
436
 */
 
437
 
 
438
static void
 
439
open_sound_file_chooser (AlarmSettingsDialog *dialog)
 
440
{
 
441
        GtkWidget *chooser;
 
442
        
 
443
        chooser = gtk_file_chooser_dialog_new (_("Select sound file..."),
 
444
                                                                                   GTK_WINDOW (dialog->dialog),
 
445
                                                                                   GTK_FILE_CHOOSER_ACTION_OPEN,
 
446
                                                                                   GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
 
447
                                                                                   GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
 
448
                                                                                   NULL);
 
449
        
 
450
        gtk_file_chooser_set_uri (GTK_FILE_CHOOSER (chooser), dialog->alarm->sound_file);
 
451
        
 
452
        if (gtk_dialog_run (GTK_DIALOG (chooser)) == GTK_RESPONSE_ACCEPT) {
 
453
                gchar *uri;
 
454
                
 
455
                uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (chooser));
 
456
                
 
457
                g_debug ("RESPONSE ACCEPT: %s", uri);
 
458
                
 
459
                g_object_set (dialog->alarm, "sound_file", uri, NULL);
 
460
                
 
461
                g_free (uri);
 
462
        } else {
 
463
                g_debug ("RESPONSE CANCEL");
 
464
                alarm_settings_update_sound (dialog);
 
465
        }
 
466
        
 
467
        gtk_widget_destroy (chooser);
 
468
}
 
469
 
 
470
 
 
471
 
 
472
/*
 
473
 * GUI callbacks
 
474
 */
 
475
 
 
476
static void
 
477
type_toggle_cb (GtkToggleButton *toggle, gpointer data)
 
478
{
 
479
        AlarmSettingsDialog *dialog = (AlarmSettingsDialog *)data;
 
480
        GtkWidget *toggle2 = (GTK_WIDGET (toggle) == dialog->clock_toggle) ? dialog->timer_toggle : dialog->clock_toggle;
 
481
        gboolean toggled = gtk_toggle_button_get_active(toggle);
 
482
        
 
483
        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle2), !toggled);
 
484
        
 
485
        if (GTK_WIDGET (toggle) == dialog->clock_toggle && toggled) {
 
486
                g_object_set (dialog->alarm, "type", ALARM_TYPE_CLOCK, NULL);
 
487
        } else {
 
488
                g_object_set (dialog->alarm, "type", ALARM_TYPE_TIMER, NULL);
 
489
        }
 
490
        
 
491
        time_changed_cb (GTK_SPIN_BUTTON (dialog->hour_spin), dialog);
 
492
}
 
493
 
 
494
static void
 
495
time_changed_cb (GtkSpinButton *spinbutton, gpointer data)
 
496
{
 
497
        AlarmSettingsDialog *dialog = (AlarmSettingsDialog *)data;
 
498
        guint hour, min, sec;
 
499
        
 
500
        hour = gtk_spin_button_get_value (GTK_SPIN_BUTTON (dialog->hour_spin));
 
501
        min = gtk_spin_button_get_value (GTK_SPIN_BUTTON (dialog->min_spin));
 
502
        sec = gtk_spin_button_get_value (GTK_SPIN_BUTTON (dialog->sec_spin));
 
503
        
 
504
        alarm_set_time (dialog->alarm, hour, min, sec);
 
505
}
 
506
 
 
507
static void
 
508
repeat_changed_cb (GtkToggleButton *togglebutton,
 
509
                                   gpointer         data)
 
510
{
 
511
        AlarmSettingsDialog *dialog = (AlarmSettingsDialog *)data;
 
512
        
 
513
        const gchar *name;
 
514
        AlarmRepeat rep, new_rep;
 
515
        gboolean active;
 
516
 
 
517
        /* The check buttons have the same name as the 3 letter
 
518
         * string representation of the day.
 
519
         */
 
520
        name   = gtk_widget_get_name (GTK_WIDGET (togglebutton));
 
521
        rep    = alarm_repeat_from_string (name);
 
522
        active = gtk_toggle_button_get_active (togglebutton);
 
523
        
 
524
        if (active)
 
525
                // Add rep
 
526
                new_rep = dialog->alarm->repeat | rep;
 
527
        else
 
528
                // Remove rep
 
529
                new_rep = dialog->alarm->repeat & ~rep;
 
530
        
 
531
        g_object_set (dialog->alarm, "repeat", new_rep, NULL);
 
532
}
 
533
 
 
534
static void
 
535
snooze_changed_cb (GtkSpinButton *spinbutton, gpointer data)
 
536
{
 
537
        AlarmSettingsDialog *dialog = (AlarmSettingsDialog *)data;
 
538
        
 
539
        g_object_set (dialog->alarm, "snooze", (gint)gtk_spin_button_get_value (GTK_SPIN_BUTTON (dialog->snooze_spin)), NULL);
 
540
}
 
541
 
 
542
static void
 
543
snooze_check_changed_cb (GtkToggleButton *togglebutton, gpointer data)
 
544
{
 
545
        AlarmSettingsDialog *dialog = (AlarmSettingsDialog *)data;
 
546
        
 
547
        if (gtk_toggle_button_get_active (togglebutton) && dialog->alarm->snooze == 0) {
 
548
                g_object_set (dialog->alarm, "snooze", ALARM_DEF_SNOOZE, NULL);
 
549
        } else if (!gtk_toggle_button_get_active (togglebutton) && dialog->alarm->snooze > 0) {
 
550
                g_object_set (dialog->alarm, "snooze", 0, NULL);
 
551
        }
 
552
}
 
553
 
 
554
static void
 
555
notify_type_changed_cb (GtkToggleButton *togglebutton,
 
556
                                                AlarmSettingsDialog *dialog)
 
557
{
 
558
        const gchar *name = gtk_widget_get_name (GTK_WIDGET (togglebutton));
 
559
        gboolean value    = gtk_toggle_button_get_active (togglebutton);
 
560
        
 
561
        if (!value) {
 
562
                // Not checked, not interested
 
563
                return;
 
564
        }
 
565
        
 
566
        g_debug ("notify_type_changed: %s", name);
 
567
        
 
568
        if (strcmp (name, "app-radio") == 0) {
 
569
                g_object_set (dialog->alarm, "notify_type", ALARM_NOTIFY_COMMAND, NULL);
 
570
        } else {
 
571
                g_object_set (dialog->alarm, "notify_type", ALARM_NOTIFY_SOUND, NULL);
 
572
        }
 
573
        
 
574
        alarm_settings_update_notify_type (dialog);
 
575
}
 
576
 
 
577
static void
 
578
sound_combo_changed_cb (GtkComboBox *combo,
 
579
                                                AlarmSettingsDialog *dialog)
 
580
{
 
581
        g_debug ("SOUND Combo_changed");
 
582
        
 
583
        GtkTreeModel *model;
 
584
        AlarmListEntry *item;
 
585
        guint current_index, len, combo_len;
 
586
        
 
587
        model = gtk_combo_box_get_model (GTK_COMBO_BOX (dialog->notify_sound_combo));
 
588
        combo_len = gtk_tree_model_iter_n_children (model, NULL);
 
589
        current_index = gtk_combo_box_get_active (combo);
 
590
        len = g_list_length (dialog->applet->sounds);
 
591
        
 
592
        g_debug ("Current index: %d, n sounds: %d", current_index, len);
 
593
        
 
594
        if (current_index < 0)
 
595
                // None selected
 
596
                return;
 
597
        
 
598
        if (current_index >= len) {
 
599
                // Select sound file
 
600
                g_debug ("Open SOUND file chooser...");
 
601
                open_sound_file_chooser (dialog);
 
602
                return;
 
603
        }
 
604
        
 
605
        // Valid file selected, update alarm
 
606
        item = (AlarmListEntry *) g_list_nth_data (dialog->applet->sounds, current_index);
 
607
        g_object_set (dialog->alarm, "sound_file", item->data, NULL);
 
608
}
 
609
 
 
610
static void
 
611
app_combo_changed_cb (GtkComboBox *combo,
 
612
                                          AlarmSettingsDialog *dialog)
 
613
{
 
614
        g_debug ("APP Combo_changed");
 
615
        
 
616
        if (GTK_WIDGET_HAS_FOCUS (dialog->notify_app_command_entry)) {
 
617
                g_debug (" ---- Skipping because command_entry has focus!");
 
618
                return;
 
619
        }
 
620
        
 
621
        GtkTreeModel *model;
 
622
        AlarmListEntry *item;
 
623
        guint current_index, len, combo_len;
 
624
        
 
625
        model = gtk_combo_box_get_model (GTK_COMBO_BOX (dialog->notify_app_combo));
 
626
        combo_len = gtk_tree_model_iter_n_children (model, NULL);
 
627
        current_index = gtk_combo_box_get_active (combo);
 
628
        len = g_list_length (dialog->applet->apps);
 
629
        
 
630
        if (current_index < 0)
 
631
                // None selected
 
632
                return;
 
633
        
 
634
        if (current_index >= len) {
 
635
                // Custom command
 
636
                g_debug ("CUSTOM command selected...");
 
637
                
 
638
                g_object_set (dialog->notify_app_command_entry, "sensitive", TRUE, NULL);
 
639
                gtk_widget_grab_focus (dialog->notify_app_command_entry);
 
640
                return;
 
641
        }
 
642
        
 
643
        g_object_set (dialog->notify_app_command_entry, "sensitive", FALSE, NULL);
 
644
        
 
645
        
 
646
        item = (AlarmListEntry *) g_list_nth_data (dialog->applet->apps, current_index);
 
647
        g_object_set (dialog->alarm, "command", item->data, NULL);
 
648
}
 
649
 
 
650
 
 
651
 
 
652
/*
 
653
 * Preview player {{
 
654
 */
 
655
 
 
656
static void
 
657
preview_player_state_cb (MediaPlayer *player, MediaPlayerState state, AlarmSettingsDialog *dialog)
 
658
{
 
659
        const gchar *stock;
 
660
        
 
661
        if (state == MEDIA_PLAYER_PLAYING) {
 
662
                stock = "gtk-media-stop";
 
663
        } else {
 
664
                stock = "gtk-media-play";
 
665
                
 
666
                g_debug ("AlarmSettingsDialog: Freeing media player %p", player);
 
667
                
 
668
                media_player_free (player);
 
669
                dialog->player = NULL;
 
670
        }
 
671
        
 
672
        // Set stock
 
673
        gtk_button_set_label (GTK_BUTTON (dialog->notify_sound_preview), stock);
 
674
}
 
675
 
 
676
void
 
677
preview_sound_cb (GtkButton *button,
 
678
                                  AlarmSettingsDialog *dialog)
 
679
{
 
680
        if (dialog->player && dialog->player->state == MEDIA_PLAYER_PLAYING) {
 
681
                // Stop preview player
 
682
                media_player_stop (dialog->player);
 
683
        } else {
 
684
                // Start preview player
 
685
                if (dialog->player == NULL)
 
686
                        dialog->player = media_player_new (dialog->alarm->sound_file,
 
687
                                                                                           dialog->alarm->sound_loop,
 
688
                                                                                           preview_player_state_cb, dialog,
 
689
                                                                                           media_player_error_cb, dialog->dialog);
 
690
        
 
691
                g_debug ("AlarmSettingsDialog: preview_start...");
 
692
                media_player_start (dialog->player);
 
693
        }
 
694
}
 
695
 
 
696
/*
 
697
 * }} Preview player
 
698
 */
 
699
 
 
700
 
 
701
void
 
702
alarm_settings_dialog_close (AlarmSettingsDialog *dialog)
 
703
{
 
704
        g_hash_table_remove (dialog->applet->edit_alarm_dialogs, dialog->alarm->id);
 
705
        
 
706
        gtk_widget_destroy (GTK_WIDGET (dialog->dialog));
 
707
        
 
708
        if (dialog->player) {
 
709
                if (dialog->player->state == MEDIA_PLAYER_STOPPED) {
 
710
                        media_player_free (dialog->player);
 
711
                } else {
 
712
                        media_player_stop (dialog->player);
 
713
                }
 
714
        }
 
715
        
 
716
        /* Remove alarm notify handlers! This would otherwise cause segfaults as
 
717
         * the callbacks would look for a non-existant dialog struct.
 
718
         */
 
719
        g_signal_handlers_disconnect_matched (dialog->alarm, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, dialog);
 
720
        
 
721
        // TODO: Why does this cause segfaults once the UI is reused?
 
722
        Alarm *a = dialog->alarm;
 
723
        g_debug ("FREE AlarmSettingsDialog %p alarm is %p", dialog, a);
 
724
        g_free (dialog);
 
725
        g_debug ("\talarm is %p", a);
 
726
}
 
727
 
 
728
static void
 
729
alarm_settings_dialog_response_cb (GtkDialog *dialog,
 
730
                                                                   gint rid,
 
731
                                                                   AlarmSettingsDialog *settings_dialog)
 
732
{
 
733
        alarm_settings_dialog_close (settings_dialog);
 
734
}
 
735
 
 
736
 
 
737
 
 
738
 
 
739
 
 
740
/*
 
741
 * Dialog creation
 
742
 * 
 
743
 * TODO: A bug exists which somehow causes some widgets to become NULL
 
744
 *               and thus crashes the program. Investigate further.
 
745
 */
 
746
 
 
747
static AlarmSettingsDialog *
 
748
alarm_settings_dialog_new (Alarm *alarm, AlarmApplet *applet)
 
749
{
 
750
        AlarmSettingsDialog *dialog;
 
751
        GtkWidget *clock_content, *timer_content, *snooze_label;
 
752
        AlarmRepeat r;
 
753
        gint i;
 
754
        
 
755
        GladeXML *ui = glade_xml_new (ALARM_UI_XML, "edit-alarm", NULL);
 
756
        
 
757
        /* Init */
 
758
        dialog = g_new0 (AlarmSettingsDialog, 1);
 
759
        
 
760
        dialog->applet = applet;
 
761
        dialog->alarm  = alarm;
 
762
        dialog->player = NULL;
 
763
        dialog->dialog = glade_xml_get_widget (ui, "edit-alarm");
 
764
        
 
765
        g_debug ("NEW AlarmSettingsDialog %p for alarm #%d", dialog, alarm->id);
 
766
        g_debug ("\talarm is %p");
 
767
        
 
768
        /* Response from dialog */
 
769
        g_signal_connect (dialog->dialog, "response", 
 
770
                                          G_CALLBACK (alarm_settings_dialog_response_cb), dialog);      
 
771
        
 
772
        /*
 
773
         * TYPE TOGGLE BUTTONS
 
774
         */
 
775
        dialog->clock_toggle = glade_xml_get_widget (ui, "toggle-clock");
 
776
        clock_content = create_img_label ("Alarm Clock", "alarm-clock");
 
777
        
 
778
        dialog->timer_toggle = glade_xml_get_widget (ui, "toggle-timer");
 
779
        timer_content = create_img_label ("Timer", "alarm-timer");
 
780
        
 
781
        gtk_container_add (GTK_CONTAINER (dialog->clock_toggle), clock_content);
 
782
        gtk_widget_show_all (GTK_WIDGET (dialog->clock_toggle));
 
783
        
 
784
        gtk_container_add (GTK_CONTAINER (dialog->timer_toggle), timer_content);
 
785
        gtk_widget_show_all (GTK_WIDGET (dialog->timer_toggle));
 
786
        
 
787
        /*
 
788
         * GENERAL SETTINGS
 
789
         */
 
790
        dialog->label_entry = glade_xml_get_widget (ui, "label-entry");
 
791
        gtk_widget_grab_focus (dialog->label_entry);
 
792
        
 
793
        dialog->hour_spin = glade_xml_get_widget (ui, "hour-spin");
 
794
        dialog->min_spin = glade_xml_get_widget (ui, "minute-spin");
 
795
        dialog->sec_spin = glade_xml_get_widget (ui, "second-spin");
 
796
        
 
797
        /*
 
798
         * REPEAT SETTINGS
 
799
         */
 
800
        dialog->repeat_expand = glade_xml_get_widget (ui, "repeat-expand");
 
801
        dialog->repeat_label  = glade_xml_get_widget (ui, "repeat-label");
 
802
        
 
803
        /* The check buttons have the same name as the 3 letter
 
804
         * string representation of the day.
 
805
         */
 
806
        for (r = ALARM_REPEAT_SUN, i = 0; r <= ALARM_REPEAT_SAT; r = 1 << ++i) {
 
807
                dialog->repeat_check[i] = glade_xml_get_widget (ui, alarm_repeat_to_string (r));
 
808
        }
 
809
        
 
810
        /*
 
811
         * SNOOZE SETTINGS
 
812
         */
 
813
        dialog->snooze_check = glade_xml_get_widget (ui, "snooze-check");
 
814
        dialog->snooze_spin  = glade_xml_get_widget (ui, "snooze-spin");
 
815
        
 
816
        snooze_label = gtk_bin_get_child (GTK_BIN (dialog->snooze_check));
 
817
        g_object_set (G_OBJECT (snooze_label), "use-markup", TRUE, NULL);
 
818
        
 
819
        /*
 
820
         * NOTIFY SETTINGS
 
821
         */
 
822
        dialog->notify_sound_radio       = glade_xml_get_widget (ui, "sound-radio");
 
823
        dialog->notify_sound_box         = glade_xml_get_widget (ui, "sound-box");
 
824
        dialog->notify_sound_combo       = glade_xml_get_widget (ui, "sound-combo");
 
825
        dialog->notify_sound_preview     = glade_xml_get_widget (ui, "sound-play");
 
826
        dialog->notify_sound_loop_check  = glade_xml_get_widget (ui, "sound-loop-check");
 
827
        dialog->notify_app_radio         = glade_xml_get_widget (ui, "app-radio");
 
828
        dialog->notify_app_box           = glade_xml_get_widget (ui, "app-box");
 
829
        dialog->notify_app_combo         = glade_xml_get_widget (ui, "app-combo");
 
830
        dialog->notify_app_command_box   = glade_xml_get_widget (ui, "app-command-box");
 
831
        dialog->notify_app_command_entry = glade_xml_get_widget (ui, "app-command-entry");
 
832
        dialog->notify_bubble_check      = glade_xml_get_widget (ui, "notify-bubble-check");
 
833
        
 
834
        
 
835
        /*
 
836
         * Load apps list
 
837
         */
 
838
        alarm_applet_apps_load (applet);
 
839
        
 
840
        /*
 
841
         * Populate widgets
 
842
         */
 
843
        alarm_settings_update (dialog);
 
844
        
 
845
        /* Got libnotify? */
 
846
#ifndef HAVE_LIBNOTIFY
 
847
        g_object_set (dialog->notify_bubble_check, "sensitive", FALSE, NULL);
 
848
        gtk_widget_set_tooltip_text (GTK_WIDGET (dialog->notify_bubble_check), _("This feature requires libnotify to be installed"));
 
849
#endif
 
850
        
 
851
        /*
 
852
         * Bind widgets
 
853
         */
 
854
        alarm_bind (alarm, "message", dialog->label_entry, "text");
 
855
        alarm_bind (alarm, "sound-repeat", dialog->notify_sound_loop_check, "active");
 
856
        alarm_bind (alarm, "command", dialog->notify_app_command_entry, "text");
 
857
        alarm_bind (alarm, "notify-bubble", dialog->notify_bubble_check, "active");
 
858
        
 
859
        /*
 
860
         * Special widgets require special attention!
 
861
         */
 
862
        
 
863
        /* type */
 
864
        g_signal_connect (alarm, "notify::type", G_CALLBACK (alarm_type_changed), dialog);
 
865
        g_signal_connect (dialog->clock_toggle, "toggled", G_CALLBACK (type_toggle_cb), dialog);
 
866
        g_signal_connect (dialog->timer_toggle, "toggled", G_CALLBACK (type_toggle_cb), dialog);
 
867
        
 
868
        /* time/timer */
 
869
        g_signal_connect (alarm, "notify::time", G_CALLBACK (alarm_time_changed), dialog);
 
870
        g_signal_connect (alarm, "notify::timer", G_CALLBACK (alarm_timer_changed), dialog);
 
871
        
 
872
        g_signal_connect (dialog->hour_spin, "value-changed", G_CALLBACK (time_changed_cb), dialog);
 
873
        g_signal_connect (dialog->min_spin, "value-changed", G_CALLBACK (time_changed_cb), dialog);
 
874
        g_signal_connect (dialog->sec_spin, "value-changed", G_CALLBACK (time_changed_cb), dialog);
 
875
        
 
876
        /* repeat */
 
877
        g_signal_connect (alarm, "notify::repeat", G_CALLBACK (alarm_repeat_changed), dialog);
 
878
        for (i = 0; i < 7; i++)
 
879
                g_signal_connect (dialog->repeat_check[i], "toggled", G_CALLBACK (repeat_changed_cb), dialog);
 
880
        
 
881
        /* snooze */
 
882
        g_signal_connect (alarm, "notify::snooze", G_CALLBACK (alarm_snooze_changed), dialog);
 
883
        
 
884
        g_signal_connect (dialog->snooze_spin, "value-changed", G_CALLBACK (snooze_changed_cb), dialog);
 
885
        g_signal_connect (dialog->snooze_check, "toggled", G_CALLBACK (snooze_check_changed_cb), dialog);
 
886
        
 
887
        /* notify type */
 
888
        g_signal_connect (alarm, "notify::notify-type", G_CALLBACK (alarm_notify_type_changed), dialog);
 
889
        g_signal_connect (dialog->notify_sound_radio, "toggled", G_CALLBACK (notify_type_changed_cb), dialog);
 
890
        g_signal_connect (dialog->notify_app_radio, "toggled", G_CALLBACK (notify_type_changed_cb), dialog);
 
891
        
 
892
        /* sound file */
 
893
        g_signal_connect (alarm, "notify::sound-file", 
 
894
                                          G_CALLBACK (alarm_settings_sound_file_changed), dialog);
 
895
        g_signal_connect (dialog->notify_sound_combo, "changed",
 
896
                                          G_CALLBACK (sound_combo_changed_cb), dialog);
 
897
        
 
898
        g_signal_connect (dialog->notify_sound_preview, "clicked",
 
899
                                          G_CALLBACK (preview_sound_cb), dialog);
 
900
        
 
901
        /* app / command */
 
902
        g_signal_connect (alarm, "notify::command",
 
903
                                          G_CALLBACK (alarm_settings_command_changed), dialog);
 
904
        
 
905
        g_signal_connect (dialog->notify_app_combo, "changed",
 
906
                                          G_CALLBACK (app_combo_changed_cb), dialog);
 
907
        
 
908
        /*g_signal_connect (dialog->notify_app_command_entry, "changed",
 
909
                                          G_CALLBACK (app_command_changed_cb), dialog);*/
 
910
        
 
911
        g_object_unref (ui);
 
912
        
 
913
        return dialog;
 
914
}
 
915
 
 
916
void
 
917
display_edit_alarm_dialog (AlarmApplet *applet, Alarm *alarm)
 
918
{
 
919
        AlarmSettingsDialog *dialog;
 
920
        
 
921
        // Check if a dialog is already open for this alarm
 
922
        dialog = (AlarmSettingsDialog *)g_hash_table_lookup (applet->edit_alarm_dialogs, alarm->id);
 
923
        
 
924
        if (dialog) {
 
925
                // Already open
 
926
                gtk_window_present (GTK_WINDOW (dialog->dialog));
 
927
                return;
 
928
        }
 
929
        
 
930
        dialog = alarm_settings_dialog_new (alarm, applet);
 
931
        g_hash_table_insert (applet->edit_alarm_dialogs, alarm->id, dialog);
 
932
}