Merge lp:~ted/indicator-datetime/upstart-job into lp:~indicator-applet-developers/indicator-datetime/trunk.13.10

Proposed by Ted Gould
Status: Superseded
Proposed branch: lp:~ted/indicator-datetime/upstart-job
Merge into: lp:~indicator-applet-developers/indicator-datetime/trunk.13.10
Diff against target: 1793 lines (+1169/-185) (has conflicts)
17 files modified
.bzrignore (+2/-0)
data/Makefile.am (+24/-11)
data/com.canonical.indicator.datetime (+3/-0)
data/indicator-datetime.conf.in (+8/-0)
data/indicator-datetime.desktop.in (+9/-0)
data/indicator-datetime.service.in (+0/-3)
debian/indicator-datetime.install (+2/-1)
src/Makefile.am (+4/-0)
src/clock-live.c (+281/-0)
src/clock-live.h (+73/-0)
src/clock.c (+110/-0)
src/clock.h (+76/-0)
src/datetime-prefs-locations.c (+3/-1)
src/main.c (+38/-1)
src/service.c (+515/-166)
src/service.h (+21/-0)
src/timezone.h (+0/-2)
Path conflict: <deleted> / tests/planner-mock.c
Path conflict: <deleted> / tests/planner-mock.h
Text conflict in src/main.c
Text conflict in src/service.c
Text conflict in src/service.h
To merge this branch: bzr merge lp:~ted/indicator-datetime/upstart-job
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Indicator Applet Developers Pending
Review via email: mp+182463@code.launchpad.net

This proposal has been superseded by a proposal from 2013-10-29.

Commit message

Upstart Job

Description of the change

Upstart Job

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Sebastien Bacher (seb128) wrote :

Thanks for the work, similar to https://code.launchpad.net/~ted/indicator-session/upstart-job/+merge/166373 ... why do we need to export the env and do we need that to land this cycle?

253. By Ted Gould

Dropping debugging for system-wide support

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
254. By Ted Gould

Merge trunk

255. By Ted Gould

Add in support for XDG Autostart

256. By Ted Gould

Install the autostart file

257. By Ted Gould

Ignore generated files

258. By Ted Gould

Merge trunk

259. By Ted Gould

Autostart directory

Unmerged revisions

259. By Ted Gould

Autostart directory

258. By Ted Gould

Merge trunk

257. By Ted Gould

Ignore generated files

256. By Ted Gould

Install the autostart file

255. By Ted Gould

Add in support for XDG Autostart

254. By Ted Gould

Merge trunk

253. By Ted Gould

Dropping debugging for system-wide support

252. By Ted Gould

Adding into the package

251. By Ted Gould

Adding the upstart job configuration

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2012-02-17 22:06:39 +0000
3+++ .bzrignore 2013-10-29 00:19:32 +0000
4@@ -15,3 +15,5 @@
5 build-aux
6 data/com.canonical.indicator.datetime.gschema.valid
7 src/libdatetime_la-utils.lo
8+data/indicator-datetime.conf
9+data/indicator-datetime.desktop
10
11=== modified file 'data/Makefile.am'
12--- data/Makefile.am 2013-06-28 21:41:31 +0000
13+++ data/Makefile.am 2013-10-29 00:19:32 +0000
14@@ -18,17 +18,30 @@
15 EXTRA_DIST += $(gsettings_SCHEMAS)
16
17 #
18-# the dbus service file
19-#
20-
21-dbus_servicesdir = $(datadir)/dbus-1/services
22-dbus_services_DATA = indicator-datetime.service
23-dbus_services_in = $(dbus_services_DATA:.service=.service.in)
24-$(dbus_services_DATA): $(dbus_services_in)
25- $(AM_V_GEN) $(SED) -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
26-BUILT_SOURCES += $(dbus_services_DATA)
27-CLEANFILES += $(dbus_services_DATA)
28-EXTRA_DIST += $(dbus_services_in)
29+# the upstart job file
30+#
31+
32+upstart_jobsdir = $(datadir)/upstart/sessions
33+upstart_jobs_DATA = indicator-datetime.conf
34+upstart_jobs_in = $(upstart_jobs_DATA:.conf=.conf.in)
35+$(upstart_jobs_DATA): $(upstart_jobs_in)
36+ $(AM_V_GEN) $(SED) -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
37+BUILT_SOURCES += $(upstart_jobs_DATA)
38+CLEANFILES += $(upstart_jobs_DATA)
39+EXTRA_DIST += $(upstart_jobs_in)
40+
41+#
42+# the xdg autostart job file
43+#
44+
45+xdg_autostartdir = /etc/xdg/autostart
46+xdg_autostart_DATA = indicator-datetime.desktop
47+xdg_autostart_in = $(xdg_autostart_DATA:.desktop=.desktop.in)
48+$(xdg_autostart_DATA): $(xdg_autostart_in)
49+ $(AM_V_GEN) $(SED) -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
50+BUILT_SOURCES += $(xdg_autostart_DATA)
51+CLEANFILES += $(xdg_autostart_DATA)
52+EXTRA_DIST += $(xdg_autostart_in)
53
54 #
55 # the gnome-control-center panel
56
57=== modified file 'data/com.canonical.indicator.datetime'
58--- data/com.canonical.indicator.datetime 2013-07-25 18:08:34 +0000
59+++ data/com.canonical.indicator.datetime 2013-10-29 00:19:32 +0000
60@@ -12,3 +12,6 @@
61 [phone]
62 ObjectPath=/com/canonical/indicator/datetime/phone
63
64+[phone_greeter]
65+ObjectPath=/com/canonical/indicator/datetime/desktop_greeter
66+
67
68=== added file 'data/indicator-datetime.conf.in'
69--- data/indicator-datetime.conf.in 1970-01-01 00:00:00 +0000
70+++ data/indicator-datetime.conf.in 2013-10-29 00:19:32 +0000
71@@ -0,0 +1,8 @@
72+description "Indicator Date & Time Backend"
73+
74+start on indicators-loaded or indicator-services-start
75+stop on desktop-end or indicator-services-end
76+
77+respawn
78+
79+exec @libexecdir@/indicator-datetime-service
80
81=== added file 'data/indicator-datetime.desktop.in'
82--- data/indicator-datetime.desktop.in 1970-01-01 00:00:00 +0000
83+++ data/indicator-datetime.desktop.in 2013-10-29 00:19:32 +0000
84@@ -0,0 +1,9 @@
85+[Desktop Entry]
86+Type=Application
87+Name=Indicator Date & Time
88+Exec=@libexecdir@/indicator-datetime-service
89+NotShowIn=Unity;
90+NoDisplay=true
91+StartupNotify=false
92+Terminal=false
93+
94
95=== removed file 'data/indicator-datetime.service.in'
96--- data/indicator-datetime.service.in 2011-01-17 17:41:28 +0000
97+++ data/indicator-datetime.service.in 1970-01-01 00:00:00 +0000
98@@ -1,3 +0,0 @@
99-[D-BUS Service]
100-Name=com.canonical.indicator.datetime
101-Exec=@libexecdir@/indicator-datetime-service
102
103=== modified file 'debian/indicator-datetime.install'
104--- debian/indicator-datetime.install 2013-08-27 14:52:26 +0000
105+++ debian/indicator-datetime.install 2013-10-29 00:19:32 +0000
106@@ -1,5 +1,6 @@
107 usr/share/glib-2.0/schemas/*
108-usr/share/dbus-1/services/*
109+usr/share/upstart/sessions/*
110 usr/share/unity/indicators/*
111 usr/lib/*/indicator-datetime-service
112 usr/share/locale/*
113+etc/xdg/autostart/*
114
115=== modified file 'src/Makefile.am'
116--- src/Makefile.am 2013-10-22 22:01:47 +0000
117+++ src/Makefile.am 2013-10-29 00:19:32 +0000
118@@ -18,6 +18,10 @@
119 $(SHARED_CFLAGS)
120
121 libindicator_datetime_service_a_SOURCES = \
122+ clock.c \
123+ clock.h \
124+ clock-live.c \
125+ clock-live.h \
126 planner.c \
127 planner.h \
128 planner-eds.c \
129
130=== added file 'src/clock-live.c'
131--- src/clock-live.c 1970-01-01 00:00:00 +0000
132+++ src/clock-live.c 2013-10-29 00:19:32 +0000
133@@ -0,0 +1,281 @@
134+/*
135+ * Copyright 2013 Canonical Ltd.
136+ *
137+ * Authors:
138+ * Charles Kerr <charles.kerr@canonical.com>
139+ *
140+ * This program is free software: you can redistribute it and/or modify it
141+ * under the terms of the GNU General Public License version 3, as published
142+ * by the Free Software Foundation.
143+ *
144+ * This program is distributed in the hope that it will be useful, but
145+ * WITHOUT ANY WARRANTY; without even the implied warranties of
146+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
147+ * PURPOSE. See the GNU General Public License for more details.
148+ *
149+ * You should have received a copy of the GNU General Public License along
150+ * with this program. If not, see <http://www.gnu.org/licenses/>.
151+ */
152+
153+#include <glib.h>
154+#include <gio/gio.h>
155+
156+#include "config.h"
157+
158+#include "clock-live.h"
159+#include "settings-shared.h"
160+#include "timezone-file.h"
161+#include "timezone-geoclue.h"
162+
163+/***
164+**** private struct
165+***/
166+
167+struct _IndicatorDatetimeClockLivePriv
168+{
169+ GSettings * settings;
170+
171+ GSList * timezones; /* IndicatorDatetimeTimezone */
172+ gchar ** timezones_strv;
173+ GTimeZone * localtime_zone;
174+};
175+
176+typedef IndicatorDatetimeClockLivePriv priv_t;
177+
178+/***
179+**** GObject boilerplate
180+***/
181+
182+static void indicator_datetime_clock_interface_init (
183+ IndicatorDatetimeClockInterface * iface);
184+
185+G_DEFINE_TYPE_WITH_CODE (
186+ IndicatorDatetimeClockLive,
187+ indicator_datetime_clock_live,
188+ G_TYPE_OBJECT,
189+ G_IMPLEMENT_INTERFACE (INDICATOR_TYPE_DATETIME_CLOCK,
190+ indicator_datetime_clock_interface_init));
191+
192+/***
193+**** Timezones
194+***/
195+
196+static void
197+on_current_timezone_changed (IndicatorDatetimeClockLive * self)
198+{
199+ priv_t * p = self->priv;
200+
201+ /* Invalidate the timezone information.
202+ These fields will be lazily regenerated by rebuild_timezones() */
203+ g_clear_pointer (&p->timezones_strv, g_strfreev);
204+ g_clear_pointer (&p->localtime_zone, g_time_zone_unref);
205+
206+ indicator_datetime_clock_emit_changed (INDICATOR_DATETIME_CLOCK (self));
207+}
208+
209+static void
210+set_detect_location_enabled (IndicatorDatetimeClockLive * self, gboolean enabled)
211+{
212+ GSList * l;
213+ priv_t * p = self->priv;
214+ gboolean changed = FALSE;
215+
216+ /* clear out the old timezone objects */
217+ if (p->timezones != NULL)
218+ {
219+ for (l=p->timezones; l!=NULL; l=l->next)
220+ {
221+ g_signal_handlers_disconnect_by_func (l->data, on_current_timezone_changed, self);
222+ g_object_unref (l->data);
223+ }
224+
225+ g_slist_free (p->timezones);
226+ p->timezones = NULL;
227+ changed = TRUE;
228+ }
229+
230+ /* maybe add new timezone objects */
231+ if (enabled)
232+ {
233+ p->timezones = g_slist_append (p->timezones, indicator_datetime_timezone_geoclue_new ());
234+ p->timezones = g_slist_append (p->timezones, indicator_datetime_timezone_file_new (TIMEZONE_FILE));
235+
236+ for (l=p->timezones; l!=NULL; l=l->next)
237+ {
238+ g_signal_connect_swapped (l->data, "notify::timezone",
239+ G_CALLBACK(on_current_timezone_changed), self);
240+ }
241+
242+ changed = TRUE;
243+ }
244+
245+ if (changed)
246+ on_current_timezone_changed (self);
247+}
248+
249+/* When the 'auto-detect timezone' boolean setting changes,
250+ start or stop watching geoclue and /etc/timezone */
251+static void
252+on_detect_location_changed (IndicatorDatetimeClockLive * self)
253+{
254+ const gboolean enabled = g_settings_get_boolean (self->priv->settings, SETTINGS_SHOW_DETECTED_S);
255+ set_detect_location_enabled (self, enabled);
256+}
257+
258+/***
259+**** IndicatorDatetimeClock virtual functions
260+***/
261+
262+static void
263+rebuild_timezones (IndicatorDatetimeClockLive * self)
264+{
265+ priv_t * p;
266+ GHashTable * hash;
267+ GSList * l;
268+ int i;
269+ GHashTableIter iter;
270+ gpointer key;
271+
272+ p = self->priv;
273+
274+ /* Build a hashtable of timezone strings.
275+ This will weed out duplicates. */
276+ hash = g_hash_table_new (g_str_hash, g_str_equal);
277+ for (l=p->timezones; l!=NULL; l=l->next)
278+ {
279+ const gchar * tz = indicator_datetime_timezone_get_timezone (l->data);
280+ if (tz && *tz)
281+ g_hash_table_add (hash, (gpointer) tz);
282+ }
283+
284+ /* rebuild p->timezone_strv */
285+ g_strfreev (p->timezones_strv);
286+ p->timezones_strv = g_new0 (gchar*, g_hash_table_size(hash) + 1);
287+ i = 0;
288+ g_hash_table_iter_init (&iter, hash);
289+ while (g_hash_table_iter_next (&iter, &key, NULL))
290+ p->timezones_strv[i++] = g_strdup (key);
291+
292+ /* rebuild localtime_zone */
293+ g_clear_pointer (&p->localtime_zone, g_time_zone_unref);
294+ p->localtime_zone = g_time_zone_new (p->timezones_strv ? p->timezones_strv[0] : NULL);
295+
296+ /* cleanup */
297+ g_hash_table_unref (hash);
298+}
299+
300+static const gchar **
301+my_get_timezones (IndicatorDatetimeClock * clock)
302+{
303+ IndicatorDatetimeClockLive * self = INDICATOR_DATETIME_CLOCK_LIVE (clock);
304+ priv_t * p = self->priv;
305+
306+ if (G_UNLIKELY (p->timezones_strv == NULL))
307+ rebuild_timezones (self);
308+
309+ return (const gchar **) p->timezones_strv;
310+}
311+
312+static GDateTime *
313+my_get_localtime (IndicatorDatetimeClock * clock)
314+{
315+ IndicatorDatetimeClockLive * self = INDICATOR_DATETIME_CLOCK_LIVE (clock);
316+ priv_t * p = self->priv;
317+
318+ if (G_UNLIKELY (p->localtime_zone == NULL))
319+ rebuild_timezones (self);
320+
321+ return g_date_time_new_now (p->localtime_zone);
322+}
323+
324+/***
325+**** GObject virtual functions
326+***/
327+
328+static void
329+my_dispose (GObject * o)
330+{
331+ IndicatorDatetimeClockLive * self;
332+ priv_t * p;
333+
334+ self = INDICATOR_DATETIME_CLOCK_LIVE(o);
335+ p = self->priv;
336+
337+ if (p->settings != NULL)
338+ {
339+ g_signal_handlers_disconnect_by_data (p->settings, self);
340+ g_clear_object (&p->settings);
341+ }
342+
343+ set_detect_location_enabled (self, FALSE);
344+
345+ G_OBJECT_CLASS (indicator_datetime_clock_live_parent_class)->dispose (o);
346+}
347+
348+static void
349+my_finalize (GObject * o)
350+{
351+ IndicatorDatetimeClockLive * self;
352+ priv_t * p;
353+
354+ self = INDICATOR_DATETIME_CLOCK_LIVE(o);
355+ p = self->priv;
356+
357+ g_clear_pointer (&p->localtime_zone, g_time_zone_unref);
358+ g_strfreev (p->timezones_strv);
359+
360+ G_OBJECT_CLASS (indicator_datetime_clock_live_parent_class)->dispose (o);
361+}
362+
363+/***
364+**** Instantiation
365+***/
366+
367+static void
368+indicator_datetime_clock_live_class_init (IndicatorDatetimeClockLiveClass * klass)
369+{
370+ GObjectClass * object_class = G_OBJECT_CLASS (klass);
371+
372+ object_class->dispose = my_dispose;
373+ object_class->finalize = my_finalize;
374+
375+ g_type_class_add_private (klass,
376+ sizeof (IndicatorDatetimeClockLivePriv));
377+}
378+
379+static void
380+indicator_datetime_clock_interface_init (IndicatorDatetimeClockInterface * iface)
381+{
382+ iface->get_localtime = my_get_localtime;
383+ iface->get_timezones = my_get_timezones;
384+}
385+
386+static void
387+indicator_datetime_clock_live_init (IndicatorDatetimeClockLive * self)
388+{
389+ IndicatorDatetimeClockLivePriv * p;
390+
391+ p = G_TYPE_INSTANCE_GET_PRIVATE (self,
392+ INDICATOR_TYPE_DATETIME_CLOCK_LIVE,
393+ IndicatorDatetimeClockLivePriv);
394+ self->priv = p;
395+
396+ p->settings = g_settings_new (SETTINGS_INTERFACE);
397+ g_signal_connect (p->settings, "changed::" SETTINGS_SHOW_DETECTED_S,
398+ G_CALLBACK(on_detect_location_changed), self);
399+
400+
401+ on_detect_location_changed (self);
402+}
403+
404+/***
405+**** Public API
406+***/
407+
408+IndicatorDatetimeClock *
409+indicator_datetime_clock_live_new (void)
410+{
411+ gpointer o = g_object_new (INDICATOR_TYPE_DATETIME_CLOCK_LIVE, NULL);
412+
413+ return INDICATOR_DATETIME_CLOCK (o);
414+}
415
416=== added file 'src/clock-live.h'
417--- src/clock-live.h 1970-01-01 00:00:00 +0000
418+++ src/clock-live.h 2013-10-29 00:19:32 +0000
419@@ -0,0 +1,73 @@
420+/*
421+ * Copyright 2013 Canonical Ltd.
422+ *
423+ * Authors:
424+ * Charles Kerr <charles.kerr@canonical.com>
425+ *
426+ * This program is free software: you can redistribute it and/or modify it
427+ * under the terms of the GNU General Public License version 3, as published
428+ * by the Free Software Foundation.
429+ *
430+ * This program is distributed in the hope that it will be useful, but
431+ * WITHOUT ANY WARRANTY; without even the implied warranties of
432+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
433+ * PURPOSE. See the GNU General Public License for more details.
434+ *
435+ * You should have received a copy of the GNU General Public License along
436+ * with this program. If not, see <http://www.gnu.org/licenses/>.
437+ */
438+
439+#ifndef __INDICATOR_DATETIME_CLOCK_LIVE__H__
440+#define __INDICATOR_DATETIME_CLOCK_LIVE__H__
441+
442+#include <glib-object.h> /* parent class */
443+
444+#include "clock.h"
445+
446+G_BEGIN_DECLS
447+
448+#define INDICATOR_TYPE_DATETIME_CLOCK_LIVE \
449+ (indicator_datetime_clock_live_get_type())
450+
451+#define INDICATOR_DATETIME_CLOCK_LIVE(o) \
452+ (G_TYPE_CHECK_INSTANCE_CAST ((o), \
453+ INDICATOR_TYPE_DATETIME_CLOCK_LIVE, \
454+ IndicatorDatetimeClockLive))
455+
456+#define INDICATOR_DATETIME_CLOCK_LIVE_GET_CLASS(o) \
457+ (G_TYPE_INSTANCE_GET_CLASS ((o), \
458+ INDICATOR_TYPE_DATETIME_CLOCK_LIVE, \
459+ IndicatorDatetimeClockLiveClass))
460+
461+#define INDICATOR_IS_DATETIME_CLOCK_LIVE(o) \
462+ (G_TYPE_CHECK_INSTANCE_TYPE ((o), \
463+ INDICATOR_TYPE_DATETIME_CLOCK_LIVE))
464+
465+typedef struct _IndicatorDatetimeClockLive
466+ IndicatorDatetimeClockLive;
467+typedef struct _IndicatorDatetimeClockLivePriv
468+ IndicatorDatetimeClockLivePriv;
469+typedef struct _IndicatorDatetimeClockLiveClass
470+ IndicatorDatetimeClockLiveClass;
471+
472+/**
473+ * An IndicatorDatetimeClock which gives live clock times
474+ * from timezones determined by geoclue and /etc/timezone
475+ */
476+struct _IndicatorDatetimeClockLive
477+{
478+ GObject parent_instance;
479+
480+ IndicatorDatetimeClockLivePriv * priv;
481+};
482+
483+struct _IndicatorDatetimeClockLiveClass
484+{
485+ GObjectClass parent_class;
486+};
487+
488+IndicatorDatetimeClock * indicator_datetime_clock_live_new (void);
489+
490+G_END_DECLS
491+
492+#endif /* __INDICATOR_DATETIME_CLOCK_LIVE__H__ */
493
494=== added file 'src/clock.c'
495--- src/clock.c 1970-01-01 00:00:00 +0000
496+++ src/clock.c 2013-10-29 00:19:32 +0000
497@@ -0,0 +1,110 @@
498+/*
499+ * Copyright 2013 Canonical Ltd.
500+ *
501+ * Authors:
502+ * Charles Kerr <charles.kerr@canonical.com>
503+ *
504+ * This program is free software: you can redistribute it and/or modify it
505+ * under the terms of the GNU General Public License version 3, as published
506+ * by the Free Software Foundation.
507+ *
508+ * This program is distributed in the hope that it will be useful, but
509+ * WITHOUT ANY WARRANTY; without even the implied warranties of
510+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
511+ * PURPOSE. See the GNU General Public License for more details.
512+ *
513+ * You should have received a copy of the GNU General Public License along
514+ * with this program. If not, see <http://www.gnu.org/licenses/>.
515+ */
516+
517+#include "clock.h"
518+
519+enum
520+{
521+ SIGNAL_CHANGED,
522+ SIGNAL_LAST
523+};
524+
525+static guint signals[SIGNAL_LAST] = { 0 };
526+
527+G_DEFINE_INTERFACE (IndicatorDatetimeClock,
528+ indicator_datetime_clock,
529+ G_TYPE_OBJECT);
530+
531+static void
532+indicator_datetime_clock_default_init (IndicatorDatetimeClockInterface * klass)
533+{
534+ signals[SIGNAL_CHANGED] = g_signal_new (
535+ "changed",
536+ G_TYPE_FROM_CLASS(klass),
537+ G_SIGNAL_RUN_LAST,
538+ G_STRUCT_OFFSET (IndicatorDatetimeClockInterface, changed),
539+ NULL, NULL,
540+ g_cclosure_marshal_VOID__VOID,
541+ G_TYPE_NONE, 0);
542+}
543+
544+/***
545+**** PUBLIC API
546+***/
547+
548+/**
549+ * Get a strv of timezones.
550+ *
551+ * Return value: (element-type char*)
552+ * (transfer full):
553+ * array of timezone strings
554+ */
555+const gchar **
556+indicator_datetime_clock_get_timezones (IndicatorDatetimeClock * self)
557+{
558+ const gchar ** timezones;
559+ IndicatorDatetimeClockInterface * iface;
560+
561+ g_return_val_if_fail (INDICATOR_IS_DATETIME_CLOCK(self), NULL);
562+ iface = INDICATOR_DATETIME_CLOCK_GET_INTERFACE(self);
563+
564+ if (iface->get_timezones != NULL)
565+ timezones = iface->get_timezones (self);
566+ else
567+ timezones = NULL;
568+
569+ return timezones;
570+}
571+
572+/**
573+ * Get the current time.
574+ *
575+ * Return value: (element-type GDateTime*)
576+ * (transfer full):
577+ * the current time.
578+ */
579+GDateTime *
580+indicator_datetime_clock_get_localtime (IndicatorDatetimeClock * self)
581+{
582+ GDateTime * now;
583+ IndicatorDatetimeClockInterface * iface;
584+
585+ g_return_val_if_fail (INDICATOR_IS_DATETIME_CLOCK(self), NULL);
586+ iface = INDICATOR_DATETIME_CLOCK_GET_INTERFACE(self);
587+
588+ if (iface->get_localtime != NULL)
589+ now = iface->get_localtime (self);
590+ else
591+ now = NULL;
592+
593+ return now;
594+}
595+
596+/**
597+ * Emits the "changed" signal.
598+ *
599+ * This should only be called by subclasses.
600+ */
601+void
602+indicator_datetime_clock_emit_changed (IndicatorDatetimeClock * self)
603+{
604+ g_return_if_fail (INDICATOR_IS_DATETIME_CLOCK (self));
605+
606+ g_signal_emit (self, signals[SIGNAL_CHANGED], 0, NULL);
607+}
608
609=== added file 'src/clock.h'
610--- src/clock.h 1970-01-01 00:00:00 +0000
611+++ src/clock.h 2013-10-29 00:19:32 +0000
612@@ -0,0 +1,76 @@
613+/*
614+ * Copyright 2013 Canonical Ltd.
615+ *
616+ * Authors:
617+ * Charles Kerr <charles.kerr@canonical.com>
618+ *
619+ * This program is free software: you can redistribute it and/or modify it
620+ * under the terms of the GNU General Public License version 3, as published
621+ * by the Free Software Foundation.
622+ *
623+ * This program is distributed in the hope that it will be useful, but
624+ * WITHOUT ANY WARRANTY; without even the implied warranties of
625+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
626+ * PURPOSE. See the GNU General Public License for more details.
627+ *
628+ * You should have received a copy of the GNU General Public License along
629+ * with this program. If not, see <http://www.gnu.org/licenses/>.
630+ */
631+
632+#ifndef __INDICATOR_DATETIME_CLOCK__H__
633+#define __INDICATOR_DATETIME_CLOCK__H__
634+
635+#include <glib-object.h>
636+
637+G_BEGIN_DECLS
638+
639+#define INDICATOR_TYPE_DATETIME_CLOCK \
640+ (indicator_datetime_clock_get_type ())
641+
642+#define INDICATOR_DATETIME_CLOCK(obj) \
643+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
644+ INDICATOR_TYPE_DATETIME_CLOCK, \
645+ IndicatorDatetimeClock))
646+
647+#define INDICATOR_IS_DATETIME_CLOCK(obj) \
648+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INDICATOR_TYPE_DATETIME_CLOCK))
649+
650+#define INDICATOR_DATETIME_CLOCK_GET_INTERFACE(inst) \
651+ (G_TYPE_INSTANCE_GET_INTERFACE ((inst), \
652+ INDICATOR_TYPE_DATETIME_CLOCK, \
653+ IndicatorDatetimeClockInterface))
654+
655+typedef struct _IndicatorDatetimeClock
656+ IndicatorDatetimeClock;
657+
658+typedef struct _IndicatorDatetimeClockInterface
659+ IndicatorDatetimeClockInterface;
660+
661+struct _IndicatorDatetimeClockInterface
662+{
663+ GTypeInterface parent_iface;
664+
665+ /* signals */
666+ void (*changed) (IndicatorDatetimeClock * self);
667+
668+ /* virtual functions */
669+ const gchar** (*get_timezones) (IndicatorDatetimeClock * self);
670+ GDateTime* (*get_localtime) (IndicatorDatetimeClock * self);
671+};
672+
673+GType indicator_datetime_clock_get_type (void);
674+
675+/***
676+****
677+***/
678+
679+const gchar ** indicator_datetime_clock_get_timezones (IndicatorDatetimeClock * clock);
680+
681+GDateTime * indicator_datetime_clock_get_localtime (IndicatorDatetimeClock * clock);
682+
683+void indicator_datetime_clock_emit_changed (IndicatorDatetimeClock * clock);
684+
685+
686+G_END_DECLS
687+
688+#endif /* __INDICATOR_DATETIME_CLOCK__H__ */
689
690=== modified file 'src/datetime-prefs-locations.c'
691--- src/datetime-prefs-locations.c 2013-09-07 12:10:53 +0000
692+++ src/datetime-prefs-locations.c 2013-10-29 00:19:32 +0000
693@@ -96,7 +96,9 @@
694 COL_ZONE, &zone,
695 COL_VISIBLE_NAME, &name,
696 -1);
697- list = g_slist_prepend (list, time_location_new (zone, name, pos++, now));
698+
699+ if (zone && name)
700+ list = g_slist_prepend (list, time_location_new (zone, name, pos++, now));
701
702 g_free (name);
703 g_free (zone);
704
705=== modified file 'src/main.c'
706--- src/main.c 2013-10-22 22:01:47 +0000
707+++ src/main.c 2013-10-29 00:19:32 +0000
708@@ -25,6 +25,11 @@
709 #include <glib/gi18n.h>
710 #include <gio/gio.h>
711
712+<<<<<<< TREE
713+=======
714+#include "clock-live.h"
715+#include "planner-eds.h"
716+>>>>>>> MERGE-SOURCE
717 #include "service.h"
718
719 /***
720@@ -35,13 +40,23 @@
721 on_name_lost (gpointer instance G_GNUC_UNUSED, gpointer loop)
722 {
723 g_message ("exiting: service couldn't acquire or lost ownership of busname");
724- g_main_loop_quit ((GMainLoop*)loop);
725+<<<<<<< TREE
726+ g_main_loop_quit ((GMainLoop*)loop);
727+=======
728+
729+ g_main_loop_quit ((GMainLoop*)loop);
730+>>>>>>> MERGE-SOURCE
731 }
732
733 int
734 main (int argc G_GNUC_UNUSED, char ** argv G_GNUC_UNUSED)
735 {
736+<<<<<<< TREE
737 GMainLoop * loop;
738+=======
739+ IndicatorDatetimeClock * clock;
740+ IndicatorDatetimePlanner * planner;
741+>>>>>>> MERGE-SOURCE
742 IndicatorDatetimeService * service;
743
744 /* Work around a deadlock in glib's type initialization. It can be
745@@ -55,15 +70,37 @@
746 bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
747 textdomain (GETTEXT_PACKAGE);
748
749+<<<<<<< TREE
750+=======
751+ /* init libnotify */
752+ if (!notify_init ("indicator-datetime-service"))
753+ g_critical ("libnotify initialization failed");
754+
755+ /* create the service */
756+ clock = indicator_datetime_clock_live_new ();
757+ planner = indicator_datetime_planner_eds_new ();
758+ service = indicator_datetime_service_new (clock, planner);
759+
760+>>>>>>> MERGE-SOURCE
761 /* run */
762+<<<<<<< TREE
763 service = indicator_datetime_service_new ();
764+=======
765+>>>>>>> MERGE-SOURCE
766 loop = g_main_loop_new (NULL, FALSE);
767 g_signal_connect (service, INDICATOR_DATETIME_SERVICE_SIGNAL_NAME_LOST,
768 G_CALLBACK(on_name_lost), loop);
769 g_main_loop_run (loop);
770+ g_main_loop_unref (loop);
771
772 /* cleanup */
773+<<<<<<< TREE
774 g_clear_object (&service);
775 g_main_loop_unref (loop);
776+=======
777+ g_object_unref (service);
778+ g_object_unref (planner);
779+ g_object_unref (clock);
780+>>>>>>> MERGE-SOURCE
781 return 0;
782 }
783
784=== modified file 'src/service.c'
785--- src/service.c 2013-10-22 22:01:47 +0000
786+++ src/service.c 2013-10-29 00:19:32 +0000
787@@ -28,9 +28,12 @@
788 #include <url-dispatcher.h>
789
790 #include "dbus-shared.h"
791+<<<<<<< TREE
792 #include "planner-eds.h"
793 #include "timezone-file.h"
794 #include "timezone-geoclue.h"
795+=======
796+>>>>>>> MERGE-SOURCE
797 #include "service.h"
798 #include "settings-shared.h"
799 #include "utils.h"
800@@ -53,6 +56,19 @@
801
802 enum
803 {
804+<<<<<<< TREE
805+=======
806+ PROP_0,
807+ PROP_CLOCK,
808+ PROP_PLANNER,
809+ PROP_LAST
810+};
811+
812+static GParamSpec * properties[PROP_LAST] = { 0 };
813+
814+enum
815+{
816+>>>>>>> MERGE-SOURCE
817 SECTION_HEADER = (1<<0),
818 SECTION_CALENDAR = (1<<1),
819 SECTION_APPOINTMENTS = (1<<2),
820@@ -92,16 +108,14 @@
821
822 GSettings * settings;
823
824- IndicatorDatetimeTimezone * tz_file;
825- IndicatorDatetimeTimezone * tz_geoclue;
826+ IndicatorDatetimeClock * clock;
827 IndicatorDatetimePlanner * planner;
828
829- /* cached GTimeZone for use by indicator_datetime_service_get_localtime() */
830- GTimeZone * internal_timezone;
831-
832 /* the clock app's icon filename */
833 gchar * clock_app_icon_filename;
834
835+ gchar * header_label_format_string;
836+
837 /* Whether or not we've tried to load the clock app's icon.
838 This way we don't keep trying to reload it on the desktop */
839 gboolean clock_app_icon_initialized;
840@@ -140,6 +154,13 @@
841 /* appointments over the next few weeks.
842 Used when building SECTION_APPOINTMENTS */
843 GSList * upcoming_appointments;
844+
845+ /* variant cache */
846+ GVariant * desktop_title_variant;
847+ GVariant * phone_title_variant;
848+ GVariant * visible_true_variant;
849+ GVariant * visible_false_variant;
850+ GVariant * alarm_icon_variant;
851 };
852
853 typedef IndicatorDatetimeServicePrivate priv_t;
854@@ -158,6 +179,12 @@
855 }
856 }
857
858+static inline GDateTime *
859+indicator_datetime_service_get_localtime (IndicatorDatetimeService * self)
860+{
861+ return indicator_datetime_clock_get_localtime (self->priv->clock);
862+}
863+
864 /***
865 ****
866 ***/
867@@ -168,6 +195,8 @@
868 static inline void
869 rebuild_header_soon (IndicatorDatetimeService * self)
870 {
871+ g_clear_pointer (&self->priv->header_label_format_string, g_free);
872+
873 rebuild_soon (self, SECTION_HEADER);
874 }
875
876@@ -350,7 +379,7 @@
877 return G_SOURCE_REMOVE;
878 }
879
880-static char * get_header_label_format_string (IndicatorDatetimeService *);
881+static const char * get_header_label_format_string (IndicatorDatetimeService *);
882
883 static void
884 start_header_timer (IndicatorDatetimeService * self)
885@@ -364,11 +393,10 @@
886
887 if (g_settings_get_boolean (self->priv->settings, SETTINGS_SHOW_CLOCK_S))
888 {
889- char * fmt = get_header_label_format_string (self);
890+ const char * fmt = get_header_label_format_string (self);
891 header_shows_seconds = fmt && (strstr(fmt,"%s") || strstr(fmt,"%S") ||
892 strstr(fmt,"%T") || strstr(fmt,"%X") ||
893 strstr(fmt,"%c"));
894- g_free (fmt);
895 }
896
897 if (header_shows_seconds)
898@@ -388,6 +416,7 @@
899 g_date_time_unref (now);
900 }
901
902+<<<<<<< TREE
903 static void
904 update_internal_timezone (IndicatorDatetimeService * self)
905 {
906@@ -405,6 +434,199 @@
907 p->internal_timezone = g_time_zone_new (id);
908 }
909
910+=======
911+/***
912+**** ALARMS
913+***/
914+
915+static void set_alarm_timer (IndicatorDatetimeService * self);
916+
917+static gboolean
918+appointment_has_alarm_url (const struct IndicatorDatetimeAppt * appt)
919+{
920+ return (appt->has_alarms) &&
921+ (appt->url != NULL) &&
922+ (g_str_has_prefix (appt->url, "alarm:///"));
923+}
924+
925+static gboolean
926+datetimes_have_the_same_minute (GDateTime * a G_GNUC_UNUSED, GDateTime * b G_GNUC_UNUSED)
927+{
928+ int ay, am, ad;
929+ int by, bm, bd;
930+
931+ g_date_time_get_ymd (a, &ay, &am, &ad);
932+ g_date_time_get_ymd (b, &by, &bm, &bd);
933+
934+ return (ay == by) &&
935+ (am == bm) &&
936+ (ad == bd) &&
937+ (g_date_time_get_hour (a) == g_date_time_get_hour (b)) &&
938+ (g_date_time_get_minute (a) == g_date_time_get_minute (b));
939+}
940+
941+static void
942+dispatch_alarm_url (const struct IndicatorDatetimeAppt * appt)
943+{
944+ gchar * str;
945+
946+ g_return_if_fail (appt != NULL);
947+ g_return_if_fail (appointment_has_alarm_url (appt));
948+
949+ str = g_date_time_format (appt->begin, "%F %T");
950+ g_debug ("dispatching url \"%s\" for appointment \"%s\", which begins at %s",
951+ appt->url, appt->summary, str);
952+ g_free (str);
953+
954+ url_dispatch_send (appt->url, NULL, NULL);
955+}
956+
957+static void
958+on_snap_decided (NotifyNotification * notification G_GNUC_UNUSED,
959+ char * action,
960+ gpointer gurl)
961+{
962+ g_debug ("%s: %s", G_STRFUNC, action);
963+
964+ if (!g_strcmp0 (action, "show"))
965+ {
966+ const gchar * url = gurl;
967+ g_debug ("dispatching url '%s'", url);
968+ url_dispatch_send (url, NULL, NULL);
969+ }
970+}
971+
972+static void
973+show_snap_decision_for_alarm (const struct IndicatorDatetimeAppt * appt)
974+{
975+ gchar * title;
976+ const gchar * body;
977+ const gchar * icon_name;
978+ NotifyNotification * nn;
979+ GError * error;
980+
981+ title = g_date_time_format (appt->begin,
982+ get_terse_time_format_string (appt->begin));
983+ body = appt->summary;
984+ icon_name = ALARM_CLOCK_ICON_NAME;
985+ g_debug ("creating a snap decision with title '%s', body '%s', icon '%s'",
986+ title, body, icon_name);
987+
988+ nn = notify_notification_new (title, body, icon_name);
989+ notify_notification_set_hint_string (nn,
990+ "x-canonical-snap-decisions",
991+ "true");
992+ notify_notification_set_hint_string (nn,
993+ "x-canonical-private-button-tint",
994+ "true");
995+ notify_notification_add_action (nn, "show", _("Show"),
996+ on_snap_decided, g_strdup(appt->url), g_free);
997+ notify_notification_add_action (nn, "dismiss", _("Dismiss"),
998+ on_snap_decided, NULL, NULL);
999+
1000+ error = NULL;
1001+ notify_notification_show (nn, &error);
1002+ if (error != NULL)
1003+ {
1004+ g_warning ("Unable to show alarm '%s' popup: %s", body, error->message);
1005+ g_error_free (error);
1006+ dispatch_alarm_url (appt);
1007+ }
1008+
1009+ g_free (title);
1010+}
1011+
1012+static void update_appointment_lists (IndicatorDatetimeService * self);
1013+
1014+static gboolean
1015+on_alarm_timer (gpointer gself)
1016+{
1017+ IndicatorDatetimeService * self = INDICATOR_DATETIME_SERVICE (gself);
1018+ GDateTime * now;
1019+ GSList * l;
1020+
1021+ /* If there are any alarms at the current time, show a snap decision */
1022+ now = indicator_datetime_service_get_localtime (self);
1023+ for (l=self->priv->upcoming_appointments; l!=NULL; l=l->next)
1024+ {
1025+ const struct IndicatorDatetimeAppt * appt = l->data;
1026+
1027+ if (appointment_has_alarm_url (appt))
1028+ if (datetimes_have_the_same_minute (now, appt->begin))
1029+ show_snap_decision_for_alarm (appt);
1030+ }
1031+ g_date_time_unref (now);
1032+
1033+ /* rebuild the alarm list asynchronously.
1034+ set_upcoming_appointments() will update the alarm timer when this
1035+ async call is done, so no need to restart the timer here... */
1036+ update_appointment_lists (self);
1037+
1038+ return G_SOURCE_REMOVE;
1039+}
1040+
1041+/* if there are upcoming alarms, set the alarm timer to the nearest one.
1042+ otherwise, unset the alarm timer. */
1043+static void
1044+set_alarm_timer (IndicatorDatetimeService * self)
1045+{
1046+ priv_t * p;
1047+ GDateTime * now;
1048+ GDateTime * alarm_time;
1049+ GSList * l;
1050+
1051+ p = self->priv;
1052+ indicator_clear_timer (&p->alarm_timer);
1053+
1054+ now = indicator_datetime_service_get_localtime (self);
1055+
1056+ /* find the time of the next alarm on our calendar */
1057+ alarm_time = NULL;
1058+ for (l=p->upcoming_appointments; l!=NULL; l=l->next)
1059+ {
1060+ const struct IndicatorDatetimeAppt * appt = l->data;
1061+
1062+ if (appointment_has_alarm_url (appt))
1063+ if (g_date_time_compare (appt->begin, now) > 0)
1064+ if (!alarm_time || g_date_time_compare (alarm_time, appt->begin) > 0)
1065+ alarm_time = appt->begin;
1066+ }
1067+
1068+ /* if there's an upcoming alarm, set a timer to wake up at that time */
1069+ if (alarm_time != NULL)
1070+ {
1071+ GTimeSpan interval_msec;
1072+ gchar * str;
1073+ GDateTime * then;
1074+
1075+ interval_msec = g_date_time_difference (alarm_time, now);
1076+ interval_msec += G_USEC_PER_SEC; /* fire a moment after alarm_time */
1077+ interval_msec /= 1000; /* convert from usec to msec */
1078+
1079+ str = g_date_time_format (alarm_time, "%F %T");
1080+ g_debug ("%s is the next alarm time", str);
1081+ g_free (str);
1082+ then = g_date_time_add_seconds (now, interval_msec/1000);
1083+ str = g_date_time_format (then, "%F %T");
1084+ g_debug ("%s is when we'll wake up for it", str);
1085+ g_free (str);
1086+ g_date_time_unref (then);
1087+
1088+ p->alarm_timer = g_timeout_add_full (G_PRIORITY_HIGH,
1089+ (guint) interval_msec,
1090+ on_alarm_timer,
1091+ self,
1092+ NULL);
1093+ }
1094+
1095+ g_date_time_unref (now);
1096+}
1097+
1098+/***
1099+****
1100+***/
1101+
1102+>>>>>>> MERGE-SOURCE
1103 /**
1104 * General purpose handler for rebuilding sections and restarting their timers
1105 * when time jumps for whatever reason:
1106@@ -423,7 +645,6 @@
1107 1. rebuild the necessary states / menuitems when time jumps
1108 2. restart the timers so their new wait interval is correct */
1109
1110- update_internal_timezone (self);
1111 on_header_timer (self);
1112 on_timezone_timer (self);
1113 }
1114@@ -455,38 +676,46 @@
1115 ****
1116 ***/
1117
1118-static gchar *
1119+static const gchar *
1120 get_header_label_format_string (IndicatorDatetimeService * self)
1121 {
1122- char * fmt;
1123- GSettings * s = self->priv->settings;
1124- const TimeFormatMode mode = g_settings_get_enum (s, SETTINGS_TIME_FORMAT_S);
1125-
1126- if (mode == TIME_FORMAT_MODE_CUSTOM)
1127- {
1128- fmt = g_settings_get_string (s, SETTINGS_CUSTOM_TIME_FORMAT_S);
1129- }
1130- else
1131- {
1132- gboolean show_day = g_settings_get_boolean (s, SETTINGS_SHOW_DAY_S);
1133- gboolean show_date = g_settings_get_boolean (s, SETTINGS_SHOW_DATE_S);
1134- fmt = generate_full_format_string (show_day, show_date, s);
1135- }
1136-
1137- return fmt;
1138+ priv_t * p = self->priv;
1139+
1140+ if (p->header_label_format_string == NULL)
1141+ {
1142+ char * fmt;
1143+ GSettings * s = p->settings;
1144+ const TimeFormatMode mode = g_settings_get_enum (s, SETTINGS_TIME_FORMAT_S);
1145+
1146+ if (mode == TIME_FORMAT_MODE_CUSTOM)
1147+ {
1148+ fmt = g_settings_get_string (s, SETTINGS_CUSTOM_TIME_FORMAT_S);
1149+ }
1150+ else
1151+ {
1152+ gboolean show_day = g_settings_get_boolean (s, SETTINGS_SHOW_DAY_S);
1153+ gboolean show_date = g_settings_get_boolean (s, SETTINGS_SHOW_DATE_S);
1154+ fmt = generate_full_format_string (show_day, show_date, s);
1155+ }
1156+
1157+ p->header_label_format_string = fmt;
1158+ }
1159+
1160+ return p->header_label_format_string;
1161 }
1162
1163 static GVariant *
1164 create_desktop_header_state (IndicatorDatetimeService * self)
1165 {
1166+ priv_t * p = self->priv;
1167 GVariantBuilder b;
1168- gchar * fmt;
1169+ const gchar * fmt;
1170 gchar * str;
1171 gboolean visible;
1172 GDateTime * now;
1173- const gchar * title = _("Date and Time");
1174+ GVariant * label_variant;
1175
1176- visible = g_settings_get_boolean (self->priv->settings, SETTINGS_SHOW_CLOCK_S);
1177+ visible = g_settings_get_boolean (p->settings, SETTINGS_SHOW_CLOCK_S);
1178
1179 /* build the time string for the label & a11y */
1180 fmt = get_header_label_format_string (self);
1181@@ -498,15 +727,15 @@
1182 g_warning ("%s", str);
1183 }
1184
1185+ label_variant = g_variant_new_take_string (str);
1186 g_variant_builder_init (&b, G_VARIANT_TYPE_VARDICT);
1187- g_variant_builder_add (&b, "{sv}", "accessible-desc", g_variant_new_string (str));
1188- g_variant_builder_add (&b, "{sv}", "label", g_variant_new_take_string (str));
1189- g_variant_builder_add (&b, "{sv}", "title", g_variant_new_string (title));
1190- g_variant_builder_add (&b, "{sv}", "visible", g_variant_new_boolean (visible));
1191+ g_variant_builder_add (&b, "{sv}", "accessible-desc", label_variant);
1192+ g_variant_builder_add (&b, "{sv}", "label", label_variant);
1193+ g_variant_builder_add_value (&b, p->desktop_title_variant);
1194+ g_variant_builder_add_value (&b, visible ? p->visible_true_variant : p->visible_false_variant);
1195
1196 /* cleanup */
1197 g_date_time_unref (now);
1198- g_free (fmt);
1199 return g_variant_builder_end (&b);
1200 }
1201
1202@@ -516,43 +745,37 @@
1203 static GVariant *
1204 create_phone_header_state (IndicatorDatetimeService * self)
1205 {
1206+ priv_t * p = self->priv;
1207+ const gboolean has_alarms = service_has_alarms (self);
1208 GVariantBuilder b;
1209 GDateTime * now;
1210 const gchar * fmt;
1211- gchar * label;
1212- gboolean has_alarms;
1213- gchar * a11y;
1214- const gchar * title = _("Upcoming");
1215
1216 g_variant_builder_init (&b, G_VARIANT_TYPE_VARDICT);
1217-
1218- /* label */
1219+ g_variant_builder_add_value (&b, p->phone_title_variant);
1220+ g_variant_builder_add_value (&b, p->visible_true_variant);
1221+
1222+ /* icon */
1223+ if (has_alarms)
1224+ g_variant_builder_add_value (&b, p->alarm_icon_variant);
1225+
1226+ /* label, a11y */
1227 now = indicator_datetime_service_get_localtime (self);
1228 fmt = get_terse_header_time_format_string ();
1229- label = g_date_time_format (now, fmt);
1230-
1231- /* icon */
1232- if ((has_alarms = service_has_alarms (self)))
1233- {
1234- GIcon * icon;
1235- icon = g_themed_icon_new_with_default_fallbacks (ALARM_CLOCK_ICON_NAME);
1236- g_variant_builder_add (&b, "{sv}", "icon", g_icon_serialize (icon));
1237- g_object_unref (icon);
1238- }
1239-
1240- /* a11y */
1241 if (has_alarms)
1242- a11y = g_strdup_printf (_("%s (has alarms)"), label);
1243+ {
1244+ gchar * label = g_date_time_format (now, fmt);
1245+ gchar * a11y = g_strdup_printf (_("%s (has alarms)"), label);
1246+ g_variant_builder_add (&b, "{sv}", "label", g_variant_new_take_string (label));
1247+ g_variant_builder_add (&b, "{sv}", "accessible-desc", g_variant_new_take_string (a11y));
1248+ }
1249 else
1250- a11y = g_strdup (label);
1251- g_variant_builder_add (&b, "{sv}", "accessible-desc",
1252- g_variant_new_take_string (a11y));
1253-
1254- g_variant_builder_add (&b, "{sv}", "visible", g_variant_new_boolean (TRUE));
1255- g_variant_builder_add (&b, "{sv}", "label", g_variant_new_take_string (label));
1256- g_variant_builder_add (&b, "{sv}", "title", g_variant_new_string (title));
1257-
1258- /* cleanup */
1259+ {
1260+ GVariant * v = g_variant_new_take_string (g_date_time_format (now, fmt));
1261+ g_variant_builder_add (&b, "{sv}", "label", v);
1262+ g_variant_builder_add (&b, "{sv}", "accessible-desc", v);
1263+ }
1264+
1265 g_date_time_unref (now);
1266 return g_variant_builder_end (&b);
1267 }
1268@@ -879,61 +1102,6 @@
1269 ****
1270 ***/
1271
1272-static void
1273-on_current_timezone_changed (IndicatorDatetimeService * self)
1274-{
1275- on_local_time_jumped (self);
1276-}
1277-
1278-/* When the 'auto-detect timezone' boolean setting changes,
1279- start or stop watching geoclue and /etc/timezone */
1280-static void
1281-set_detect_location_enabled (IndicatorDatetimeService * self, gboolean enabled)
1282-{
1283- gboolean changed = FALSE;
1284- priv_t * p = self->priv;
1285-
1286- /* geoclue */
1287-
1288- if (!p->tz_geoclue && enabled)
1289- {
1290- p->tz_geoclue = indicator_datetime_timezone_geoclue_new ();
1291- g_signal_connect_swapped (p->tz_geoclue, "notify::timezone",
1292- G_CALLBACK(on_current_timezone_changed),
1293- self);
1294- changed = TRUE;
1295- }
1296- else if (p->tz_geoclue && !enabled)
1297- {
1298- g_signal_handlers_disconnect_by_func (p->tz_geoclue,
1299- on_current_timezone_changed,
1300- self);
1301- g_clear_object (&p->tz_geoclue);
1302- changed = TRUE;
1303- }
1304-
1305- /* timezone file */
1306-
1307- if (!p->tz_file && enabled)
1308- {
1309- p->tz_file = indicator_datetime_timezone_file_new (TIMEZONE_FILE);
1310- g_signal_connect_swapped (p->tz_file, "notify::timezone",
1311- G_CALLBACK(on_current_timezone_changed),
1312- self);
1313- changed = TRUE;
1314- }
1315- else if (p->tz_file && !enabled)
1316- {
1317- g_signal_handlers_disconnect_by_func (p->tz_file,
1318- on_current_timezone_changed,
1319- self);
1320- g_clear_object (&p->tz_file);
1321- changed = TRUE;
1322- }
1323-
1324- if (changed)
1325- on_current_timezone_changed (self);
1326-}
1327
1328 /* A temp struct used by create_locations_section()
1329 for pruning duplicates and sorting. */
1330@@ -1019,44 +1187,30 @@
1331 GSList * l;
1332 GSList * locations = NULL;
1333 gchar ** user_locations;
1334- gboolean visible;
1335- IndicatorDatetimeTimezone * detected_timezones[2];
1336+ const gchar ** detected_timezones;
1337 priv_t * p = self->priv;
1338 GDateTime * now = indicator_datetime_service_get_localtime (self);
1339
1340- set_detect_location_enabled (self,
1341- g_settings_get_boolean (p->settings, SETTINGS_SHOW_DETECTED_S));
1342-
1343 menu = g_menu_new ();
1344
1345 /***
1346- **** Build a list of locations to add: use geo_timezone,
1347- **** current_timezone, and SETTINGS_LOCATIONS_S, but omit duplicates.
1348+ **** Build a list of locations to add, omitting duplicates
1349 ***/
1350
1351- /* maybe add the auto-detected timezones */
1352- detected_timezones[0] = p->tz_geoclue;
1353- detected_timezones[1] = p->tz_file;
1354- visible = g_settings_get_boolean (p->settings, SETTINGS_SHOW_DETECTED_S);
1355- for (i=0; i<G_N_ELEMENTS(detected_timezones); i++)
1356+ detected_timezones = indicator_datetime_clock_get_timezones (p->clock);
1357+ for (i=0; detected_timezones && detected_timezones[i]; i++)
1358 {
1359- if (detected_timezones[i] != NULL)
1360- {
1361- const char * tz = indicator_datetime_timezone_get_timezone (detected_timezones[i]);
1362- if (tz && *tz)
1363- {
1364- gchar * name = get_current_zone_name (tz, p->settings);
1365- locations = locations_add (locations, tz, name, visible);
1366- g_free (name);
1367- }
1368- }
1369+ const char * tz = detected_timezones[i];
1370+ gchar * name = get_current_zone_name (tz, p->settings);
1371+ locations = locations_add (locations, tz, name, TRUE);
1372+ g_free (name);
1373 }
1374
1375 /* maybe add the user-specified locations */
1376 user_locations = g_settings_get_strv (p->settings, SETTINGS_LOCATIONS_S);
1377 if (user_locations != NULL)
1378 {
1379- visible = g_settings_get_boolean (p->settings, SETTINGS_SHOW_LOCATIONS_S);
1380+ const gboolean visible = g_settings_get_boolean (p->settings, SETTINGS_SHOW_LOCATIONS_S);
1381
1382 for (i=0; user_locations[i] != NULL; i++)
1383 {
1384@@ -1485,6 +1639,9 @@
1385 struct ProfileMenuInfo * desktop = &p->menus[PROFILE_DESKTOP];
1386 struct ProfileMenuInfo * greeter = &p->menus[PROFILE_GREETER];
1387
1388+ if (p->actions == NULL)
1389+ return;
1390+
1391 if (sections & SECTION_HEADER)
1392 {
1393 g_simple_action_set_state (p->desktop_header_action,
1394@@ -1825,6 +1982,56 @@
1395 ***/
1396
1397 static void
1398+<<<<<<< TREE
1399+=======
1400+my_get_property (GObject * o,
1401+ guint property_id,
1402+ GValue * value,
1403+ GParamSpec * pspec)
1404+{
1405+ IndicatorDatetimeService * self = INDICATOR_DATETIME_SERVICE (o);
1406+
1407+ switch (property_id)
1408+ {
1409+ case PROP_CLOCK:
1410+ g_value_set_object (value, self->priv->clock);
1411+ break;
1412+
1413+ case PROP_PLANNER:
1414+ g_value_set_object (value, self->priv->planner);
1415+ break;
1416+
1417+ default:
1418+ G_OBJECT_WARN_INVALID_PROPERTY_ID (o, property_id, pspec);
1419+ }
1420+}
1421+
1422+static void
1423+my_set_property (GObject * o,
1424+ guint property_id,
1425+ const GValue * value,
1426+ GParamSpec * pspec)
1427+{
1428+ IndicatorDatetimeService * self = INDICATOR_DATETIME_SERVICE (o);
1429+
1430+ switch (property_id)
1431+ {
1432+ case PROP_CLOCK:
1433+ indicator_datetime_service_set_clock (self, g_value_get_object (value));
1434+ break;
1435+
1436+ case PROP_PLANNER:
1437+ indicator_datetime_service_set_planner (self, g_value_get_object (value));
1438+ break;
1439+
1440+ default:
1441+ G_OBJECT_WARN_INVALID_PROPERTY_ID (o, property_id, pspec);
1442+ }
1443+}
1444+
1445+
1446+static void
1447+>>>>>>> MERGE-SOURCE
1448 my_dispose (GObject * o)
1449 {
1450 int i;
1451@@ -1845,6 +2052,7 @@
1452 g_clear_object (&p->cancellable);
1453 }
1454
1455+<<<<<<< TREE
1456 set_detect_location_enabled (self, FALSE);
1457
1458 if (p->planner != NULL)
1459@@ -1854,6 +2062,10 @@
1460 }
1461 g_clear_pointer (&p->upcoming_appointments, indicator_datetime_planner_free_appointments);
1462 g_clear_pointer (&p->calendar_appointments, indicator_datetime_planner_free_appointments);
1463+=======
1464+ indicator_datetime_service_set_clock (self, NULL);
1465+ indicator_datetime_service_set_planner (self, NULL);
1466+>>>>>>> MERGE-SOURCE
1467
1468 if (p->login1_manager != NULL)
1469 {
1470@@ -1877,12 +2089,17 @@
1471 for (i=0; i<N_PROFILES; ++i)
1472 g_clear_object (&p->menus[i].menu);
1473
1474- g_clear_pointer (&p->internal_timezone, g_time_zone_unref);
1475 g_clear_object (&p->calendar_action);
1476 g_clear_object (&p->desktop_header_action);
1477 g_clear_object (&p->phone_header_action);
1478 g_clear_object (&p->conn);
1479
1480+ g_clear_pointer (&p->desktop_title_variant, g_variant_unref);
1481+ g_clear_pointer (&p->phone_title_variant, g_variant_unref);
1482+ g_clear_pointer (&p->visible_true_variant, g_variant_unref);
1483+ g_clear_pointer (&p->visible_false_variant, g_variant_unref);
1484+ g_clear_pointer (&p->alarm_icon_variant, g_variant_unref);
1485+
1486 G_OBJECT_CLASS (indicator_datetime_service_parent_class)->dispose (o);
1487 }
1488
1489@@ -1893,6 +2110,7 @@
1490 priv_t * p = self->priv;
1491
1492 g_free (p->clock_app_icon_filename);
1493+ g_free (p->header_label_format_string);
1494 g_clear_pointer (&p->skew_time, g_date_time_unref);
1495 g_clear_pointer (&p->calendar_date, g_date_time_unref);
1496
1497@@ -1906,9 +2124,45 @@
1498 static void
1499 indicator_datetime_service_init (IndicatorDatetimeService * self)
1500 {
1501+ GIcon * icon;
1502+ priv_t * p;
1503+
1504+ /* init the priv pointer */
1505+
1506+ p = G_TYPE_INSTANCE_GET_PRIVATE (self,
1507+ INDICATOR_TYPE_DATETIME_SERVICE,
1508+ IndicatorDatetimeServicePrivate);
1509+ self->priv = p;
1510+
1511+ p->cancellable = g_cancellable_new ();
1512+
1513+ p->settings = g_settings_new (SETTINGS_INTERFACE);
1514+
1515+ p->desktop_title_variant = g_variant_new ("{sv}", "title", g_variant_new_string (_("Date and Time")));
1516+ g_variant_ref_sink (p->desktop_title_variant);
1517+
1518+ p->phone_title_variant = g_variant_new ("{sv}", "title", g_variant_new_string (_("Upcoming")));
1519+ g_variant_ref_sink (p->phone_title_variant);
1520+
1521+ p->visible_true_variant = g_variant_new ("{sv}", "visible", g_variant_new_boolean (TRUE));
1522+ g_variant_ref_sink (p->visible_true_variant);
1523+
1524+ p->visible_false_variant = g_variant_new ("{sv}", "visible", g_variant_new_boolean (FALSE));
1525+ g_variant_ref_sink (p->visible_false_variant);
1526+
1527+ icon = g_themed_icon_new_with_default_fallbacks (ALARM_CLOCK_ICON_NAME);
1528+ p->alarm_icon_variant = g_variant_new ("{sv}", "icon", g_icon_serialize (icon));
1529+ g_variant_ref_sink (p->alarm_icon_variant);
1530+ g_object_unref (icon);
1531+}
1532+
1533+static void
1534+my_constructed (GObject * gself)
1535+{
1536+ IndicatorDatetimeService * self = INDICATOR_DATETIME_SERVICE (gself);
1537+ priv_t * p = self->priv;
1538+ GString * gstr = g_string_new (NULL);
1539 guint i, n;
1540- priv_t * p;
1541- GString * gstr = g_string_new (NULL);
1542
1543 /* these are the settings that affect the
1544 contents of the respective sections */
1545@@ -1945,16 +2199,8 @@
1546 };
1547
1548
1549- /* init the priv pointer */
1550-
1551- p = G_TYPE_INSTANCE_GET_PRIVATE (self,
1552- INDICATOR_TYPE_DATETIME_SERVICE,
1553- IndicatorDatetimeServicePrivate);
1554- self->priv = p;
1555-
1556- p->cancellable = g_cancellable_new ();
1557-
1558 /***
1559+<<<<<<< TREE
1560 **** Create the planner and listen for changes
1561 ***/
1562
1563@@ -1966,9 +2212,11 @@
1564
1565 /***
1566 **** Create the settings object and listen for changes
1567+=======
1568+ **** Listen for settings changes
1569+>>>>>>> MERGE-SOURCE
1570 ***/
1571
1572- p->settings = g_settings_new (SETTINGS_INTERFACE);
1573 for (i=0, n=G_N_ELEMENTS(header_settings); i<n; i++)
1574 {
1575 g_string_printf (gstr, "changed::%s", header_settings[i]);
1576@@ -2046,6 +2294,12 @@
1577
1578 object_class->dispose = my_dispose;
1579 object_class->finalize = my_finalize;
1580+<<<<<<< TREE
1581+=======
1582+ object_class->constructed = my_constructed;
1583+ object_class->get_property = my_get_property;
1584+ object_class->set_property = my_set_property;
1585+>>>>>>> MERGE-SOURCE
1586
1587 g_type_class_add_private (klass, sizeof (IndicatorDatetimeServicePrivate));
1588
1589@@ -2057,6 +2311,27 @@
1590 NULL, NULL,
1591 g_cclosure_marshal_VOID__VOID,
1592 G_TYPE_NONE, 0);
1593+<<<<<<< TREE
1594+=======
1595+
1596+ /* install properties */
1597+
1598+ properties[PROP_0] = NULL;
1599+
1600+ properties[PROP_CLOCK] = g_param_spec_object ("clock",
1601+ "Clock",
1602+ "The clock",
1603+ INDICATOR_TYPE_DATETIME_CLOCK,
1604+ flags);
1605+
1606+ properties[PROP_PLANNER] = g_param_spec_object ("planner",
1607+ "Planner",
1608+ "The appointment provider",
1609+ INDICATOR_TYPE_DATETIME_PLANNER,
1610+ flags);
1611+
1612+ g_object_class_install_properties (object_class, PROP_LAST, properties);
1613+>>>>>>> MERGE-SOURCE
1614 }
1615
1616 /***
1617@@ -2064,26 +2339,25 @@
1618 ***/
1619
1620 IndicatorDatetimeService *
1621+<<<<<<< TREE
1622 indicator_datetime_service_new (void)
1623+=======
1624+indicator_datetime_service_new (IndicatorDatetimeClock * clock,
1625+ IndicatorDatetimePlanner * planner)
1626+>>>>>>> MERGE-SOURCE
1627 {
1628+<<<<<<< TREE
1629 GObject * o = g_object_new (INDICATOR_TYPE_DATETIME_SERVICE, NULL);
1630+=======
1631+ GObject * o = g_object_new (INDICATOR_TYPE_DATETIME_SERVICE,
1632+ "clock", clock,
1633+ "planner", planner,
1634+ NULL);
1635+>>>>>>> MERGE-SOURCE
1636
1637 return INDICATOR_DATETIME_SERVICE (o);
1638 }
1639
1640-/* This currently just returns the system time,
1641- As we add test coverage, we'll need this to bypass the system time. */
1642-GDateTime *
1643-indicator_datetime_service_get_localtime (IndicatorDatetimeService * self)
1644-{
1645- priv_t * p = self->priv;
1646-
1647- if (G_UNLIKELY (p->internal_timezone == NULL))
1648- update_internal_timezone (self);
1649-
1650- return g_date_time_new_now (p->internal_timezone);
1651-}
1652-
1653 void
1654 indicator_datetime_service_set_calendar_date (IndicatorDatetimeService * self,
1655 GDateTime * date)
1656@@ -2102,3 +2376,78 @@
1657 if (dirty)
1658 update_appointment_lists (self);
1659 }
1660+<<<<<<< TREE
1661+=======
1662+
1663+static void
1664+on_clock_changed (IndicatorDatetimeService * self)
1665+{
1666+ on_local_time_jumped (self);
1667+}
1668+
1669+void
1670+indicator_datetime_service_set_clock (IndicatorDatetimeService * self,
1671+ IndicatorDatetimeClock * clock)
1672+{
1673+ priv_t * p;
1674+
1675+ g_return_if_fail (INDICATOR_IS_DATETIME_SERVICE (self));
1676+ g_return_if_fail ((clock == NULL) || INDICATOR_IS_DATETIME_CLOCK (clock));
1677+
1678+ p = self->priv;
1679+
1680+ /* clear the old clock */
1681+
1682+ if (p->clock != NULL)
1683+ {
1684+ g_signal_handlers_disconnect_by_data (p->clock, self);
1685+ g_clear_object (&p->clock);
1686+ }
1687+
1688+ /* set the new clock */
1689+
1690+ if (clock != NULL)
1691+ {
1692+ p->clock = g_object_ref (clock);
1693+
1694+ g_signal_connect_swapped (p->clock, "changed",
1695+ G_CALLBACK(on_clock_changed), self);
1696+ on_clock_changed (self);
1697+ }
1698+}
1699+
1700+void
1701+indicator_datetime_service_set_planner (IndicatorDatetimeService * self,
1702+ IndicatorDatetimePlanner * planner)
1703+{
1704+ priv_t * p;
1705+
1706+ g_return_if_fail (INDICATOR_IS_DATETIME_SERVICE (self));
1707+ g_return_if_fail ((planner == NULL) || INDICATOR_IS_DATETIME_PLANNER (planner));
1708+
1709+ p = self->priv;
1710+
1711+ /* clear the old planner & appointments */
1712+
1713+ if (p->planner != NULL)
1714+ {
1715+ g_signal_handlers_disconnect_by_data (p->planner, self);
1716+ g_clear_object (&p->planner);
1717+ }
1718+
1719+ g_clear_pointer (&p->upcoming_appointments, indicator_datetime_planner_free_appointments);
1720+ g_clear_pointer (&p->calendar_appointments, indicator_datetime_planner_free_appointments);
1721+
1722+ /* set the new planner & begin fetching appointments from it */
1723+
1724+ if (planner != NULL)
1725+ {
1726+ p->planner = g_object_ref (planner);
1727+
1728+ g_signal_connect_swapped (p->planner, "appointments-changed",
1729+ G_CALLBACK(update_appointment_lists), self);
1730+
1731+ update_appointment_lists (self);
1732+ }
1733+}
1734+>>>>>>> MERGE-SOURCE
1735
1736=== modified file 'src/service.h'
1737--- src/service.h 2013-10-22 22:01:47 +0000
1738+++ src/service.h 2013-10-29 00:19:32 +0000
1739@@ -22,6 +22,12 @@
1740
1741 #include <glib.h>
1742 #include <glib-object.h>
1743+<<<<<<< TREE
1744+=======
1745+
1746+#include "clock.h"
1747+#include "planner.h"
1748+>>>>>>> MERGE-SOURCE
1749
1750 G_BEGIN_DECLS
1751
1752@@ -62,13 +68,28 @@
1753
1754 GType indicator_datetime_service_get_type (void);
1755
1756+<<<<<<< TREE
1757 IndicatorDatetimeService * indicator_datetime_service_new (void);
1758
1759 GDateTime * indicator_datetime_service_get_localtime (IndicatorDatetimeService * service);
1760+=======
1761+IndicatorDatetimeService * indicator_datetime_service_new (IndicatorDatetimeClock * clock,
1762+ IndicatorDatetimePlanner * planner);
1763+>>>>>>> MERGE-SOURCE
1764
1765 void indicator_datetime_service_set_calendar_date (IndicatorDatetimeService * self,
1766 GDateTime * date);
1767
1768+<<<<<<< TREE
1769+=======
1770+void indicator_datetime_service_set_planner (IndicatorDatetimeService * self,
1771+ IndicatorDatetimePlanner * planner);
1772+
1773+
1774+void indicator_datetime_service_set_clock (IndicatorDatetimeService * self,
1775+ IndicatorDatetimeClock * clock);
1776+
1777+>>>>>>> MERGE-SOURCE
1778
1779 G_END_DECLS
1780
1781
1782=== modified file 'src/timezone.h'
1783--- src/timezone.h 2013-09-09 17:43:31 +0000
1784+++ src/timezone.h 2013-10-29 00:19:32 +0000
1785@@ -37,8 +37,6 @@
1786
1787 GType indicator_datetime_timezone_get_type (void);
1788
1789-#define INDICATOR_DATETIME_TIMEZONE_PROPERTY_TIMEZONE "timezone"
1790-
1791 /**
1792 * Abstract Base Class for objects that provide a timezone.
1793 *

Subscribers

People subscribed via source and target branches