~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: 2010-03-17 09:02:44 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20100317090244-ni0ye04mva2hxe10
Tags: 0.3.0-1
* New upstream release
* debian/control:
  + No change bump of Standards-Version to 3.8.4
  + Update build-deps:
    - Drop libglade, libpanel-applet, libgnomevfs2, libgnome{2,ui}
    - Add libxml2-dev and libunique-dev, intltool
* debian/patches/01_update-alarms-eta,patch:
  + Dropped, applied upstream
* debian/(alarm-clock-applet.1, alarm-clock-applet.manpages):
  + Add manpage for alarm-clock-applet, now that the binary is moved to
    /usr/bin.

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
 
}