~mterry/indicator-datetime/fix-show-clock

« back to all changes in this revision

Viewing changes to src/datetime-prefs.c

  • Committer: David Barth
  • Date: 2011-02-25 17:01:20 UTC
  • mfrom: (28.6.40 clock-prefs)
  • Revision ID: david.barth@canonical.com-20110225170120-10376wecmiat132u
merging in mterry's branch with the new preferences dialog

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; coding: utf-8; indent-tabs-mode: nil; tab-width: 2 -*-
 
2
 
 
3
A dialog for setting time and date preferences.
 
4
 
 
5
Copyright 2011 Canonical Ltd.
 
6
 
 
7
Authors:
 
8
    Ted Gould <ted@canonical.com>
 
9
    Michael Terry <michael.terry@canonical.com>
 
10
 
 
11
This program is free software: you can redistribute it and/or modify it 
 
12
under the terms of the GNU General Public License version 3, as published 
 
13
by the Free Software Foundation.
 
14
 
 
15
This program is distributed in the hope that it will be useful, but 
 
16
WITHOUT ANY WARRANTY; without even the implied warranties of 
 
17
MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR 
 
18
PURPOSE.  See the GNU General Public License for more details.
 
19
 
 
20
You should have received a copy of the GNU General Public License along 
 
21
with this program.  If not, see <http://www.gnu.org/licenses/>.
 
22
*/
 
23
 
 
24
#ifdef HAVE_CONFIG_H
 
25
#include "config.h"
 
26
#endif
 
27
 
 
28
#include <stdlib.h>
 
29
#include <libintl.h>
 
30
#include <locale.h>
 
31
#include <langinfo.h>
 
32
#include <glib/gi18n-lib.h>
 
33
#include <gtk/gtk.h>
 
34
#include <unique/unique.h>
 
35
#include <polkitgtk/polkitgtk.h>
 
36
 
 
37
#include "settings-shared.h"
 
38
#include "utils.h"
 
39
#include "datetime-prefs-locations.h"
 
40
#include "timezone-completion.h"
 
41
#include "cc-timezone-map.h"
 
42
 
 
43
#define DATETIME_DIALOG_UI_FILE PKGDATADIR "/datetime-dialog.ui"
 
44
 
 
45
GDBusProxy * proxy = NULL;
 
46
GtkWidget * auto_radio = NULL;
 
47
GtkWidget * tz_entry = NULL;
 
48
CcTimezoneMap * tzmap = NULL;
 
49
 
 
50
/* Turns the boolean property into a string gsettings */
 
51
static GVariant *
 
52
bind_hours_set (const GValue * value, const GVariantType * type, gpointer user_data)
 
53
{
 
54
  const gchar * output = NULL;
 
55
  gboolean is_12hour_button = (gboolean)GPOINTER_TO_INT(user_data);
 
56
 
 
57
  if (g_value_get_boolean(value)) {
 
58
    /* Only do anything if we're setting active = true */
 
59
    output = is_12hour_button ? "12-hour" : "24-hour";
 
60
  } else {
 
61
    return NULL;
 
62
  }
 
63
 
 
64
  return g_variant_new_string (output);
 
65
}
 
66
 
 
67
/* Turns a string gsettings into a boolean property */
 
68
static gboolean
 
69
bind_hours_get (GValue * value, GVariant * variant, gpointer user_data)
 
70
{
 
71
  const gchar * str = g_variant_get_string(variant, NULL);
 
72
  gboolean output = FALSE;
 
73
  gboolean is_12hour_button = (gboolean)GPOINTER_TO_INT(user_data);
 
74
 
 
75
  if (g_strcmp0(str, "locale-default") == 0) {
 
76
    output = (is_12hour_button == is_locale_12h ());
 
77
  } else if (g_strcmp0(str, "12-hour") == 0) {
 
78
    output = is_12hour_button;
 
79
  } else if (g_strcmp0(str, "24-hour") == 0) {
 
80
    output = !is_12hour_button;
 
81
  } else {
 
82
    return FALSE;
 
83
  }
 
84
 
 
85
  g_value_set_boolean (value, output);
 
86
  return TRUE;
 
87
}
 
88
 
 
89
static void
 
90
widget_dependency_cb (GtkWidget * parent, GParamSpec *pspec, GtkWidget * dependent)
 
91
{
 
92
  gboolean active, sensitive;
 
93
  g_object_get (G_OBJECT (parent),
 
94
                "active", &active,
 
95
                "sensitive", &sensitive, NULL);
 
96
  gtk_widget_set_sensitive (dependent, active && sensitive);
 
97
}
 
98
 
 
99
static void
 
100
add_widget_dependency (GtkWidget * parent, GtkWidget * dependent)
 
101
{
 
102
  g_signal_connect (parent, "notify::active", G_CALLBACK(widget_dependency_cb),
 
103
                    dependent);
 
104
  g_signal_connect (parent, "notify::sensitive", G_CALLBACK(widget_dependency_cb),
 
105
                    dependent);
 
106
  widget_dependency_cb (parent, NULL, dependent);
 
107
}
 
108
 
 
109
static void
 
110
polkit_dependency_cb (GtkWidget * parent, GParamSpec *pspec, GtkWidget * dependent)
 
111
{
 
112
  gboolean authorized, sensitive;
 
113
  g_object_get (G_OBJECT (parent),
 
114
                "is-authorized", &authorized,
 
115
                "sensitive", &sensitive, NULL);
 
116
  gtk_widget_set_sensitive (dependent, authorized && sensitive);
 
117
}
 
118
 
 
119
static void
 
120
add_polkit_dependency (GtkWidget * parent, GtkWidget * dependent)
 
121
{
 
122
  g_signal_connect (parent, "notify::is-authorized", G_CALLBACK(polkit_dependency_cb),
 
123
                    dependent);
 
124
  g_signal_connect (parent, "notify::sensitive", G_CALLBACK(polkit_dependency_cb),
 
125
                    dependent);
 
126
  polkit_dependency_cb (parent, NULL, dependent);
 
127
}
 
128
 
 
129
static void
 
130
dbus_set_answered (GObject *object, GAsyncResult *res, gpointer command)
 
131
{
 
132
  GError * error = NULL;
 
133
  GVariant * answers = g_dbus_proxy_call_finish (proxy, res, &error);
 
134
 
 
135
  if (error != NULL) {
 
136
    g_warning("Could not set '%s' for SettingsDaemon: %s", (gchar *)command, error->message);
 
137
    g_error_free(error);
 
138
    return;
 
139
  }
 
140
 
 
141
  g_variant_unref (answers);
 
142
}
 
143
 
 
144
static void
 
145
toggle_ntp (GtkWidget * radio, GParamSpec * pspec, gpointer user_data)
 
146
{
 
147
  gboolean active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (radio));
 
148
 
 
149
  g_dbus_proxy_call (proxy, "SetUsingNtp", g_variant_new ("(b)", active),
 
150
                     G_DBUS_CALL_FLAGS_NONE, -1, NULL, dbus_set_answered, "using_ntp");
 
151
}
 
152
 
 
153
static void
 
154
ntp_query_answered (GObject *object, GAsyncResult *res, gpointer user_data)
 
155
{
 
156
  GError * error = NULL;
 
157
  GVariant * answers = g_dbus_proxy_call_finish (proxy, res, &error);
 
158
 
 
159
  if (error != NULL) {
 
160
    g_warning("Could not query DBus proxy for SettingsDaemon: %s", error->message);
 
161
    g_error_free(error);
 
162
    return;
 
163
  }
 
164
 
 
165
  gboolean can_use_ntp, is_using_ntp;
 
166
  g_variant_get (answers, "(bb)", &can_use_ntp, &is_using_ntp);
 
167
 
 
168
  gtk_widget_set_sensitive (GTK_WIDGET (auto_radio), can_use_ntp);
 
169
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (auto_radio), is_using_ntp);
 
170
 
 
171
  g_signal_connect (auto_radio, "notify::active", G_CALLBACK (toggle_ntp), NULL);
 
172
 
 
173
  g_variant_unref (answers);
 
174
}
 
175
 
 
176
static void
 
177
sync_entry (const gchar * location)
 
178
{
 
179
  gchar * name;
 
180
  split_settings_location (location, NULL, &name);
 
181
  gtk_entry_set_text (GTK_ENTRY (tz_entry), name);
 
182
  g_free (name);
 
183
}
 
184
 
 
185
static void
 
186
tz_changed (CcTimezoneMap * map, TzLocation * location)
 
187
{
 
188
  if (location == NULL)
 
189
    return;
 
190
 
 
191
  gchar * file = g_build_filename ("/usr/share/zoneinfo", location->zone, NULL);
 
192
  g_dbus_proxy_call (proxy, "SetTimezone", g_variant_new ("(s)", file),
 
193
                     G_DBUS_CALL_FLAGS_NONE, -1, NULL, dbus_set_answered, "timezone");
 
194
  g_free (file);
 
195
 
 
196
  sync_entry (location->zone);
 
197
}
 
198
 
 
199
static void
 
200
tz_query_answered (GObject *object, GAsyncResult *res, gpointer user_data)
 
201
{
 
202
  GError * error = NULL;
 
203
  GVariant * answers = g_dbus_proxy_call_finish (proxy, res, &error);
 
204
 
 
205
  if (error != NULL) {
 
206
    g_warning("Could not query DBus proxy for SettingsDaemon: %s", error->message);
 
207
    g_error_free(error);
 
208
    return;
 
209
  }
 
210
 
 
211
  const gchar * timezone;
 
212
  g_variant_get (answers, "(&s)", &timezone);
 
213
 
 
214
  cc_timezone_map_set_timezone (tzmap, timezone);
 
215
 
 
216
  sync_entry (timezone);
 
217
  g_signal_connect (tzmap, "location-changed", G_CALLBACK (tz_changed), NULL);
 
218
 
 
219
  g_variant_unref (answers);
 
220
}
 
221
 
 
222
void proxy_ready (GObject *object, GAsyncResult *res, gpointer user_data)
 
223
{
 
224
  GError * error = NULL;
 
225
 
 
226
  proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
 
227
 
 
228
  if (error != NULL) {
 
229
    g_critical("Could not grab DBus proxy for SettingsDaemon: %s", error->message);
 
230
    g_error_free(error);
 
231
    return;
 
232
  }
 
233
 
 
234
  /* And now, do initial proxy configuration */
 
235
  g_dbus_proxy_call (proxy, "GetUsingNtp", NULL, G_DBUS_CALL_FLAGS_NONE, -1,
 
236
                     NULL, ntp_query_answered, auto_radio);
 
237
  g_dbus_proxy_call (proxy, "GetTimezone", NULL, G_DBUS_CALL_FLAGS_NONE, -1,
 
238
                     NULL, tz_query_answered, NULL);
 
239
}
 
240
 
 
241
static int
 
242
input_time_text (GtkWidget * spinner, gdouble *value, gpointer user_data)
 
243
{
 
244
  gboolean is_time = (gboolean)GPOINTER_TO_INT (g_object_get_data (G_OBJECT (spinner), "is-time"));
 
245
  const gchar * text = gtk_entry_get_text (GTK_ENTRY (spinner));
 
246
 
 
247
  GDateTime * now = g_date_time_new_now_local ();
 
248
  gint year, month, day, hour, minute, second;
 
249
  year = g_date_time_get_year (now);
 
250
  month = g_date_time_get_month (now);
 
251
  day = g_date_time_get_day_of_month (now);
 
252
  hour = g_date_time_get_hour (now);
 
253
  minute = g_date_time_get_minute (now);
 
254
  second = g_date_time_get_second (now);
 
255
  g_date_time_unref (now);
 
256
 
 
257
  /* Parse this string as if it were in the output format */
 
258
  gint scanned = 0;
 
259
  gboolean passed = TRUE, skip = FALSE;
 
260
  if (is_time) {
 
261
    gint hour_in, minute_in, second_in;
 
262
 
 
263
    if (is_locale_12h ()) { // TODO: make this look-at/watch gsettings?
 
264
      char ampm[51];
 
265
 
 
266
      scanned = sscanf (text, "%u:%u:%u %50s", &hour_in, &minute_in, &second_in, ampm);
 
267
      passed = (scanned == 4);
 
268
 
 
269
      if (passed) {
 
270
        const char *pm_str = nl_langinfo (PM_STR);
 
271
        if (g_ascii_strcasecmp (pm_str, ampm) == 0) {
 
272
          hour_in += 12;
 
273
        }
 
274
      }
 
275
    } else {
 
276
      scanned = sscanf (text, "%u:%u:%u", &hour_in, &minute_in, &second_in);
 
277
      passed = (scanned == 3);
 
278
    }
 
279
 
 
280
    if (passed && (hour_in > 23 || minute_in > 59 || second_in > 59)) {
 
281
      passed = FALSE;
 
282
    }
 
283
    if (passed && hour == hour_in && minute == minute_in && second == second_in) {
 
284
      skip = TRUE; // no change
 
285
    } else {
 
286
      hour = hour_in;
 
287
      minute = minute_in;
 
288
      second = second_in;
 
289
    }
 
290
  }
 
291
  else {
 
292
    gint year_in, month_in, day_in;
 
293
 
 
294
    scanned = sscanf (text, "%u-%u-%u", &year_in, &month_in, &day_in);
 
295
 
 
296
    if (scanned != 3 || year_in < 1 || year_in > 9999 ||
 
297
        month_in < 1 || month_in > 12 || day_in < 1 || day_in > 31) {
 
298
      passed = FALSE;
 
299
    }
 
300
    if (passed && year == year_in && month == month_in && day == day_in) {
 
301
      skip = TRUE; // no change
 
302
    } else {
 
303
      year = year_in;
 
304
      month = month_in;
 
305
      day = day_in;
 
306
    }
 
307
  }
 
308
 
 
309
  if (!passed) {
 
310
    g_warning ("Could not understand %s", text);
 
311
    return TRUE;
 
312
  }
 
313
 
 
314
  if (skip) {
 
315
    return TRUE;
 
316
  }
 
317
 
 
318
  GDateTime * datetime = g_date_time_new_local (year, month, day, hour, minute, second);
 
319
 
 
320
  g_dbus_proxy_call (proxy, "SetTime", g_variant_new ("(x)", g_date_time_to_unix (datetime)),
 
321
                     G_DBUS_CALL_FLAGS_NONE, -1, NULL, dbus_set_answered, "time");
 
322
 
 
323
  return TRUE;
 
324
}
 
325
 
 
326
static gboolean
 
327
format_time_text (GtkWidget * spinner, gpointer user_data)
 
328
{
 
329
  if (gtk_widget_has_focus (spinner)) {
 
330
    /* Don't do anything if we have focus, user is likely editing us */
 
331
    return TRUE;
 
332
  }
 
333
 
 
334
  GDateTime * datetime = (GDateTime *)g_object_get_data (G_OBJECT (spinner), "datetime");
 
335
  gboolean is_time = (gboolean)GPOINTER_TO_INT (g_object_get_data (G_OBJECT (spinner), "is-time"));
 
336
 
 
337
  const gchar * format;
 
338
  if (is_time) {
 
339
    if (is_locale_12h ()) { // TODO: make this look-at/watch gsettings?
 
340
      format = "%I:%M:%S %p";
 
341
    } else {
 
342
      format = "%H:%M:%S";
 
343
    }
 
344
  }
 
345
  else {
 
346
    format = "%Y-%m-%d";
 
347
  }
 
348
 
 
349
  gchar * formatted = g_date_time_format (datetime, format);
 
350
  gtk_entry_set_text (GTK_ENTRY (spinner), formatted);
 
351
 
 
352
  return TRUE;
 
353
}
 
354
 
 
355
static gboolean
 
356
update_spinner (GtkWidget * spinner)
 
357
{
 
358
  /* Add datetime object to spinner, which will hold the real time value, rather
 
359
     then using the value of the spinner itself. */
 
360
  GDateTime * datetime = g_date_time_new_now_local ();
 
361
  g_object_set_data_full (G_OBJECT (spinner), "datetime", datetime, (GDestroyNotify)g_date_time_unref);
 
362
 
 
363
  format_time_text (spinner, NULL);
 
364
 
 
365
  return TRUE;
 
366
}
 
367
 
 
368
static void
 
369
setup_time_spinner (GtkWidget * spinner, GtkWidget * other, gboolean is_time)
 
370
{
 
371
  /* Set up spinner to have reasonable behavior */
 
372
  gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinner), FALSE);
 
373
  g_signal_connect (spinner, "input", G_CALLBACK (input_time_text), other);
 
374
  g_signal_connect (spinner, "output", G_CALLBACK (format_time_text), other);
 
375
  g_object_set_data (G_OBJECT (spinner), "is-time", GINT_TO_POINTER (is_time));
 
376
 
 
377
  /* 2 seconds is what the indicator itself uses */
 
378
  guint time_id = g_timeout_add_seconds (2, (GSourceFunc)update_spinner, spinner);
 
379
  g_signal_connect_swapped (spinner, "destroy", G_CALLBACK (g_source_remove), GINT_TO_POINTER (time_id));
 
380
 
 
381
  update_spinner (spinner);
 
382
}
 
383
 
 
384
static void
 
385
show_locations (GtkWidget * button, GtkWidget * dlg)
 
386
{
 
387
  GtkWidget * locationsDlg = datetime_setup_locations_dialog (GTK_WINDOW (dlg), tzmap);
 
388
  gtk_widget_show_all (locationsDlg);
 
389
}
 
390
 
 
391
static gboolean
 
392
timezone_selected (GtkEntryCompletion * widget, GtkTreeModel * model,
 
393
                   GtkTreeIter * iter, gpointer user_data)
 
394
{
 
395
  GValue value = {0};
 
396
  const gchar * strval;
 
397
 
 
398
  gtk_tree_model_get_value (model, iter, TIMEZONE_COMPLETION_ZONE, &value);
 
399
  strval = g_value_get_string (&value);
 
400
 
 
401
  if (strval != NULL && strval[0] != 0) {
 
402
    cc_timezone_map_set_timezone (tzmap, strval);
 
403
  }
 
404
  else {
 
405
    GValue lon_value = {0}, lat_value = {0};
 
406
    const gchar * strlon, * strlat;
 
407
    gdouble lon = 0.0, lat = 0.0;
 
408
 
 
409
    gtk_tree_model_get_value (model, iter, TIMEZONE_COMPLETION_LONGITUDE, &lon_value);
 
410
    strlon = g_value_get_string (&lon_value);
 
411
    if (strlon != NULL && strlon[0] != 0) {
 
412
      lon = strtod(strlon, NULL);
 
413
    }
 
414
 
 
415
    gtk_tree_model_get_value (model, iter, TIMEZONE_COMPLETION_LATITUDE, &lat_value);
 
416
    strlat = g_value_get_string (&lat_value);
 
417
    if (strlat != NULL && strlat[0] != 0) {
 
418
      lat = strtod(strlat, NULL);
 
419
    }
 
420
 
 
421
    cc_timezone_map_set_coords (tzmap, lon, lat);
 
422
  }
 
423
 
 
424
  g_value_unset (&value);
 
425
 
 
426
  return FALSE; // Do normal action too
 
427
}
 
428
 
 
429
static GtkWidget *
 
430
create_dialog (void)
 
431
{
 
432
  GError * error = NULL;
 
433
 
 
434
  GtkBuilder * builder = gtk_builder_new ();
 
435
  gtk_builder_add_from_file (builder, DATETIME_DIALOG_UI_FILE, &error);
 
436
  if (error != NULL) {
 
437
    /* We have to abort, we can't continue without the ui file */
 
438
    g_error ("Could not load ui file %s: %s", DATETIME_DIALOG_UI_FILE, error->message);
 
439
    g_error_free (error);
 
440
    return NULL;
 
441
  }
 
442
 
 
443
  gtk_builder_set_translation_domain (builder, GETTEXT_PACKAGE);
 
444
 
 
445
  GSettings * conf = g_settings_new (SETTINGS_INTERFACE);
 
446
 
 
447
#define WIG(name) GTK_WIDGET (gtk_builder_get_object (builder, name))
 
448
 
 
449
  /* Add policykit button */
 
450
  GtkWidget * polkit_button = polkit_lock_button_new ("org.gnome.settingsdaemon.datetimemechanism.configure");
 
451
  polkit_lock_button_set_unlock_text (POLKIT_LOCK_BUTTON (polkit_button), _("Unlock to change these settings"));
 
452
  polkit_lock_button_set_lock_text (POLKIT_LOCK_BUTTON (polkit_button), _("Lock to prevent further changes"));
 
453
  gtk_box_pack_start (GTK_BOX (WIG ("timeDateBox")), polkit_button, FALSE, TRUE, 0);
 
454
 
 
455
  /* Add map */
 
456
  tzmap = cc_timezone_map_new ();
 
457
  gtk_container_add (GTK_CONTAINER (WIG ("mapBox")), GTK_WIDGET (tzmap));
 
458
  /* Fufill the CC by Attribution license requirements for the Geonames lookup */
 
459
  cc_timezone_map_set_watermark (tzmap, "Geonames.org");
 
460
 
 
461
  /* And completion entry */
 
462
  TimezoneCompletion * completion = timezone_completion_new ();
 
463
  gtk_entry_set_completion (GTK_ENTRY (WIG ("timezoneEntry")),
 
464
                            GTK_ENTRY_COMPLETION (completion));
 
465
  timezone_completion_watch_entry (completion, GTK_ENTRY (WIG ("timezoneEntry")));
 
466
  g_signal_connect (completion, "match-selected", G_CALLBACK (timezone_selected), NULL);
 
467
 
 
468
  /* Set up settings bindings */
 
469
  g_settings_bind (conf, SETTINGS_SHOW_CLOCK_S, WIG ("showClockCheck"),
 
470
                   "active", G_SETTINGS_BIND_DEFAULT);
 
471
  g_settings_bind (conf, SETTINGS_SHOW_DAY_S, WIG ("showWeekdayCheck"),
 
472
                   "active", G_SETTINGS_BIND_DEFAULT);
 
473
  g_settings_bind (conf, SETTINGS_SHOW_DATE_S, WIG ("showDateTimeCheck"),
 
474
                   "active", G_SETTINGS_BIND_DEFAULT);
 
475
  g_settings_bind (conf, SETTINGS_SHOW_SECONDS_S, WIG ("showSecondsCheck"),
 
476
                   "active", G_SETTINGS_BIND_DEFAULT);
 
477
  g_settings_bind_with_mapping (conf, SETTINGS_TIME_FORMAT_S,
 
478
                                WIG ("show12HourRadio"), "active",
 
479
                                G_SETTINGS_BIND_DEFAULT,
 
480
                                bind_hours_get, bind_hours_set,
 
481
                                GINT_TO_POINTER(TRUE), NULL);
 
482
  g_settings_bind_with_mapping (conf, SETTINGS_TIME_FORMAT_S,
 
483
                                WIG ("show24HourRadio"), "active",
 
484
                                G_SETTINGS_BIND_DEFAULT,
 
485
                                bind_hours_get, bind_hours_set,
 
486
                                GINT_TO_POINTER(FALSE), NULL);
 
487
  g_settings_bind (conf, SETTINGS_SHOW_CALENDAR_S, WIG ("showCalendarCheck"),
 
488
                   "active", G_SETTINGS_BIND_DEFAULT);
 
489
  g_settings_bind (conf, SETTINGS_SHOW_WEEK_NUMBERS_S, WIG ("includeWeekNumbersCheck"),
 
490
                   "active", G_SETTINGS_BIND_DEFAULT);
 
491
  g_settings_bind (conf, SETTINGS_SHOW_EVENTS_S, WIG ("showEventsCheck"),
 
492
                   "active", G_SETTINGS_BIND_DEFAULT);
 
493
  g_settings_bind (conf, SETTINGS_SHOW_LOCATIONS_S, WIG ("showLocationsCheck"),
 
494
                   "active", G_SETTINGS_BIND_DEFAULT);
 
495
 
 
496
  /* Set up sensitivities */
 
497
  add_widget_dependency (WIG ("showCalendarCheck"), WIG ("calendarOptions"));
 
498
  add_widget_dependency (WIG ("showClockCheck"), WIG ("clockOptions"));
 
499
  add_widget_dependency (WIG ("showLocationsCheck"), WIG ("locationsButton"));
 
500
  add_widget_dependency (WIG ("manualTimeRadio"), WIG ("manualOptions"));
 
501
  add_polkit_dependency (polkit_button, WIG ("timeDateOptions"));
 
502
 
 
503
  /* Hacky proxy test for whether evolution-data-server is installed */
 
504
  gchar * evo_path = g_find_program_in_path ("evolution");
 
505
  gtk_widget_set_sensitive (WIG ("showEventsCheck"), (evo_path != NULL));
 
506
  g_free (evo_path);
 
507
 
 
508
  setup_time_spinner (WIG ("timeSpinner"), WIG ("dateSpinner"), TRUE);
 
509
  setup_time_spinner (WIG ("dateSpinner"), WIG ("timeSpinner"), FALSE);
 
510
 
 
511
  GtkWidget * dlg = WIG ("timeDateDialog");
 
512
  auto_radio = WIG ("automaticTimeRadio");
 
513
  tz_entry = WIG ("timezoneEntry");
 
514
 
 
515
  g_signal_connect (WIG ("locationsButton"), "clicked", G_CALLBACK (show_locations), dlg);
 
516
 
 
517
  /* Grab proxy for settings daemon */
 
518
  g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL,
 
519
                            "org.gnome.SettingsDaemon.DateTimeMechanism",
 
520
                            "/",                            
 
521
                            "org.gnome.SettingsDaemon.DateTimeMechanism",
 
522
                            NULL, proxy_ready, NULL);
 
523
 
 
524
#undef WIG
 
525
 
 
526
  g_object_unref (conf);
 
527
  g_object_unref (builder);
 
528
 
 
529
  return dlg;
 
530
}
 
531
 
 
532
static UniqueResponse
 
533
message_received (UniqueApp * app, gint command, UniqueMessageData *message_data,
 
534
                  guint time, gpointer user_data)
 
535
{
 
536
  if (command == UNIQUE_ACTIVATE) {
 
537
    gtk_window_present_with_time (GTK_WINDOW (user_data), time);
 
538
    return UNIQUE_RESPONSE_OK;
 
539
  }
 
540
  return UNIQUE_RESPONSE_PASSTHROUGH;
 
541
}
 
542
 
 
543
int
 
544
main (int argc, char ** argv)
 
545
{
 
546
  g_type_init ();
 
547
 
 
548
  /* Setting up i18n and gettext.  Apparently, we need
 
549
     all of these. */
 
550
  setlocale (LC_ALL, "");
 
551
  bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
 
552
  textdomain (GETTEXT_PACKAGE);
 
553
 
 
554
  gtk_init (&argc, &argv);
 
555
 
 
556
  UniqueApp * app = unique_app_new ("com.canonical.indicator.datetime.preferences", NULL);
 
557
 
 
558
  if (unique_app_is_running (app)) {
 
559
    unique_app_send_message (app, UNIQUE_ACTIVATE, NULL);
 
560
  } else {
 
561
    // We're first instance.  Yay!
 
562
    GtkWidget * dlg = create_dialog ();
 
563
 
 
564
    g_signal_connect (app, "message-received", G_CALLBACK(message_received), dlg);
 
565
    unique_app_watch_window (app, GTK_WINDOW (dlg));
 
566
 
 
567
    gtk_widget_show_all (dlg);
 
568
    g_signal_connect (dlg, "response", G_CALLBACK(gtk_main_quit), NULL);
 
569
    gtk_main ();
 
570
  }
 
571
 
 
572
  return 0;
 
573
}
 
574