From 18a091e005bffe0c32d6e7efdfe368cdfd8aae55 Mon Sep 17 00:00:00 2001 From: Automatic PS uploader Date: Wed, 28 Aug 2013 10:09:19 +0000 Subject: Releasing 13.10.0+13.10.20130828.2-0ubuntu1, based on r245 --- debian/changelog | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index 81abd59..60f8cfe 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,9 +1,13 @@ -indicator-datetime (13.10.0-0ubuntu1) UNRELEASED; urgency=low +indicator-datetime (13.10.0+13.10.20130828.2-0ubuntu1) saucy; urgency=low + [ Ted Gould ] * Updating version to make the Conflicts/Replace nicer * Split out gnome-control-center panel into it's own package - -- Ted Gould Tue, 27 Aug 2013 10:26:47 -0500 + [ Ubuntu daily release ] + * Automatic snapshot from revision 245 + + -- Ubuntu daily release Wed, 28 Aug 2013 10:09:19 +0000 indicator-datetime (12.10.3+13.10.20130822.1-0ubuntu1) saucy; urgency=low -- cgit v1.2.3 From eed6a021223e34437d8df21a7c428a3dd74f5ae5 Mon Sep 17 00:00:00 2001 From: Jeremy Bicha Date: Sun, 1 Sep 2013 15:32:51 -0400 Subject: Really delete *.la file --- debian/rules | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/debian/rules b/debian/rules index a350b13..4762c8f 100755 --- a/debian/rules +++ b/debian/rules @@ -12,8 +12,7 @@ override_dh_auto_configure: dh_auto_configure -- --disable-static --disable-silent-rules override_dh_install: - find debian/indicator-datetime -name \*.la -delete - find debian/indicator-datetime -name \*.a -delete + find $(CURDIR) -name \*.la -delete cd po; intltool-update --pot --verbose dh_install --fail-missing # Language packs -- cgit v1.2.3 From 2f4de37b9cb610931e41980de4acc3c07286918b Mon Sep 17 00:00:00 2001 From: Jeremy Bicha Date: Mon, 2 Sep 2013 10:08:49 -0400 Subject: Don't install *.la files instead of deleting them --- debian/rules | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/debian/rules b/debian/rules index 4762c8f..25854b8 100755 --- a/debian/rules +++ b/debian/rules @@ -12,9 +12,8 @@ override_dh_auto_configure: dh_auto_configure -- --disable-static --disable-silent-rules override_dh_install: - find $(CURDIR) -name \*.la -delete cd po; intltool-update --pot --verbose - dh_install --fail-missing + dh_install -X.la --fail-missing # Language packs for d in $$(find debian/indicator-datetime -type f \( -name "*.desktop" -o -name "*.directory" \) ); do \ sed -ri '/^(Name|GenericName|Comment|X-GNOME-FullName)\[/d' $$d; \ -- cgit v1.2.3 From 3dbb294322444364cd1e5e9caa333c44338ea392 Mon Sep 17 00:00:00 2001 From: Automatic PS uploader Date: Tue, 3 Sep 2013 02:08:17 +0000 Subject: Releasing 13.10.0+13.10.20130903-0ubuntu1, based on r247 --- debian/changelog | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/debian/changelog b/debian/changelog index 60f8cfe..d2bd251 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,13 @@ +indicator-datetime (13.10.0+13.10.20130903-0ubuntu1) saucy; urgency=low + + [ Jeremy Bicha ] + * Really don't install *.la file. + + [ Ubuntu daily release ] + * Automatic snapshot from revision 247 + + -- Ubuntu daily release Tue, 03 Sep 2013 02:08:17 +0000 + indicator-datetime (13.10.0+13.10.20130828.2-0ubuntu1) saucy; urgency=low [ Ted Gould ] -- cgit v1.2.3 From e52036bc485871c70e1f3f651680587bc796809c Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Tue, 3 Sep 2013 17:22:46 -0500 Subject: Add a signal handler for the slightly different prototype. --- src/timezone-geoclue.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/timezone-geoclue.c b/src/timezone-geoclue.c index 239ac50..f7dcf5c 100644 --- a/src/timezone-geoclue.c +++ b/src/timezone-geoclue.c @@ -77,6 +77,18 @@ on_address_changed (GeoclueAddress * address G_GNUC_UNUSED, } } +/* The signal doesn't have the parameter for an error, so it ends up needing + a NULL inserted. */ +static void +on_address_changed_sig (GeoclueAddress * address G_GNUC_UNUSED, + int timestamp G_GNUC_UNUSED, + GHashTable * addy_data, + GeoclueAccuracy * accuracy G_GNUC_UNUSED, + gpointer gself) +{ + return on_address_changed(address, timestamp, addy_data, accuracy, NULL, gself); +} + static void on_address_created (GeoclueMasterClient * master G_GNUC_UNUSED, GeoclueAddress * address, @@ -95,7 +107,7 @@ on_address_created (GeoclueMasterClient * master G_GNUC_UNUSED, p->address = g_object_ref (address); geoclue_address_get_address_async (address, on_address_changed, gself); - g_signal_connect (address, "address-changed", G_CALLBACK(on_address_changed), gself); + g_signal_connect (address, "address-changed", G_CALLBACK(on_address_changed_sig), gself); } } @@ -161,7 +173,7 @@ geo_stop (IndicatorDatetimeTimezoneGeoclue * self) if (p->address != NULL) { - g_signal_handlers_disconnect_by_func (p->address, on_address_changed, self); + g_signal_handlers_disconnect_by_func (p->address, on_address_changed_sig, self); g_clear_object (&p->address); } -- cgit v1.2.3 -- cgit v1.2.3 From 9debe3352135af9f53d1e7a979f5a46b5410dd60 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Tue, 3 Sep 2013 21:47:27 -0500 Subject: Protect against invalid begin or end dates --- src/planner.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/planner.c b/src/planner.c index 1643651..6cbf80c 100644 --- a/src/planner.c +++ b/src/planner.c @@ -184,6 +184,8 @@ indicator_datetime_planner_get_appointments (IndicatorDatetimePlanner * self, GD GSList * appointments; g_return_val_if_fail (INDICATOR_IS_DATETIME_PLANNER (self), NULL); + g_return_val_if_fail (begin != NULL, NULL); + g_return_val_if_fail (end != NULL, NULL); appointments = INDICATOR_DATETIME_PLANNER_GET_CLASS (self)->get_appointments (self, begin, end); return g_slist_sort (appointments, compare_appointments_by_start_time); -- cgit v1.2.3 From 2a97f6029b467702a362d0b1b7108717366d903e Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Tue, 3 Sep 2013 21:55:23 -0500 Subject: Don't unref NULLs --- src/service.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/service.c b/src/service.c index fec2bb1..421e3dd 100644 --- a/src/service.c +++ b/src/service.c @@ -577,9 +577,9 @@ get_all_appointments_this_month (IndicatorDatetimeService * self) if (p->planner != NULL) { - GDateTime * calendar_date; - GDateTime * begin; - GDateTime * end; + GDateTime * calendar_date = NULL; + GDateTime * begin = NULL; + GDateTime * end = NULL; int y, m, d; calendar_date = get_calendar_date (self); @@ -593,9 +593,12 @@ get_all_appointments_this_month (IndicatorDatetimeService * self) begin, end); - g_date_time_unref (end); - g_date_time_unref (begin); - g_date_time_unref (calendar_date); + if (end != NULL) + g_date_time_unref (end); + if (begin != NULL) + g_date_time_unref (begin); + if (calendar_date != NULL) + g_date_time_unref (calendar_date); } return appointments; -- cgit v1.2.3 From 039722a99003890732e6a06de7005fbd1ea2b4d3 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 5 Sep 2013 11:57:05 -0500 Subject: change the Planner API s.t. get_appoinments() is an async function. Breaks everything --- src/planner.c | 31 +++++++++++++++++++++++++++++-- src/planner.h | 38 ++++++++++++++++++++++++++++++++------ 2 files changed, 61 insertions(+), 8 deletions(-) diff --git a/src/planner.c b/src/planner.c index 1643651..124aeae 100644 --- a/src/planner.c +++ b/src/planner.c @@ -178,17 +178,44 @@ compare_appointments_by_start_time (gconstpointer ga, gconstpointer gb) return g_date_time_compare (a->begin, b->begin); } +void +indicator_datetime_planner_get_appointments (IndicatorDatetimePlanner * self, + GDateTime * begin, + GDateTime * end, + GAsyncReadyCallback callback, + gpointer user_data) +{ + IndicatorDatetimePlannerClass * klass; + + g_return_if_fail (INDICATOR_IS_DATETIME_PLANNER (self)); + + klass = INDICATOR_DATETIME_PLANNER_GET_CLASS (self); + g_return_if_fail (klass->get_appointments != NULL); + klass->get_appointments (self, begin, end, callback, user_data); +} + GSList * -indicator_datetime_planner_get_appointments (IndicatorDatetimePlanner * self, GDateTime * begin, GDateTime * end) +indicator_datetime_planner_get_appointments_finish (IndicatorDatetimePlanner * self, + GAsyncResult * res, + GError ** error) { + IndicatorDatetimePlannerClass * klass; GSList * appointments; g_return_val_if_fail (INDICATOR_IS_DATETIME_PLANNER (self), NULL); - appointments = INDICATOR_DATETIME_PLANNER_GET_CLASS (self)->get_appointments (self, begin, end); + klass = INDICATOR_DATETIME_PLANNER_GET_CLASS (self); + g_return_val_if_fail (klass->get_appointments_finish != NULL, NULL); + appointments = klass->get_appointments_finish (self, res, error); return g_slist_sort (appointments, compare_appointments_by_start_time); } +void +indicator_datetime_planner_free_appointments (GSList * l) +{ + g_slist_free_full (l, (GDestroyNotify)indicator_datetime_appt_free); +} + gboolean indicator_datetime_planner_is_configured (IndicatorDatetimePlanner * self) { diff --git a/src/planner.h b/src/planner.h index f6148c6..206bfe5 100644 --- a/src/planner.h +++ b/src/planner.h @@ -22,6 +22,7 @@ #include #include /* parent class */ +#include G_BEGIN_DECLS @@ -70,7 +71,16 @@ struct _IndicatorDatetimePlannerClass /* virtual functions */ - GSList* (*get_appointments) (IndicatorDatetimePlanner * self, GDateTime * begin, GDateTime * end); + void (*get_appointments) (IndicatorDatetimePlanner * self, + GDateTime * begin, + GDateTime * end, + GAsyncReadyCallback callback, + gpointer user_data); + + GSList* (*get_appointments_finish) (IndicatorDatetimePlanner * self, + GAsyncResult * res, + GError ** error); + gboolean (*is_configured) (IndicatorDatetimePlanner * self); void (*activate) (IndicatorDatetimePlanner * self); @@ -85,17 +95,33 @@ void indicator_datetime_appt_free (struct IndicatorDatetimeAppt * appt); /** * Get a list of appointments, sorted by start time. + */ +void indicator_datetime_planner_get_appointments (IndicatorDatetimePlanner * self, + GDateTime * begin, + GDateTime * end, + GAsyncReadyCallback callback, + gpointer user_data); + +/** + * Finishes the async call begun with indicator_datetime_planner_get_appointments() * - * An easy way to free the list properly in one step is as follows: - * - * g_slist_free_full (list, (GDestroyNotify)indicator_datetime_appt_free); - * + * To free the list properly, use indicator_datetime_planner_free_appointments() * * Return value: (element-type IndicatorDatetimeAppt) * (transfer full): * list of appointments */ -GSList * indicator_datetime_planner_get_appointments (IndicatorDatetimePlanner * self, GDateTime * begin, GDateTime * end); +GSList * indicator_datetime_planner_get_appointments_finish (IndicatorDatetimePlanner * self, + GAsyncResult * res, + GError ** error); + +/** + * Convenience function for freeing a GSList of IndicatorDatetimeAppt. + * + * Equivalent to g_slist_free_full (list, (GDestroyNotify)indicator_datetime_appt_free); + */ +void indicator_datetime_planner_free_appointments (GSList *); + /** * Returns false if the planner's backend is not configured. -- cgit v1.2.3 From f3271cfae21dad242b2732f54a58c4b2636d0057 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 5 Sep 2013 12:01:40 -0500 Subject: update the service to use Planner's async API --- src/service.c | 227 ++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 148 insertions(+), 79 deletions(-) diff --git a/src/service.c b/src/service.c index fec2bb1..55344d8 100644 --- a/src/service.c +++ b/src/service.c @@ -118,6 +118,15 @@ struct _IndicatorDatetimeServicePrivate GSimpleAction * calendar_action; GDBusProxy * login1_manager; + + /* all the appointments in the selected calendar_date's month. + Used when populating the 'appointment-days' entry in + create_calendar_state() */ + GSList * calendar_appointments; + + /* appointments over the next few weeks. + Used when building SECTION_APPOINTMENTS */ + GSList * upcoming_appointments; }; typedef IndicatorDatetimeServicePrivate priv_t; @@ -569,38 +578,6 @@ get_calendar_date (IndicatorDatetimeService * self) return date; } -static GSList * -get_all_appointments_this_month (IndicatorDatetimeService * self) -{ - GSList * appointments = NULL; - priv_t * p = self->priv; - - if (p->planner != NULL) - { - GDateTime * calendar_date; - GDateTime * begin; - GDateTime * end; - int y, m, d; - - calendar_date = get_calendar_date (self); - g_date_time_get_ymd (calendar_date, &y, &m, &d); - begin = g_date_time_new_local (y, m, 1, - 0, 0, 0); - end = g_date_time_new_local (y, m, g_date_get_days_in_month(m,y), - 23, 59, 0); - - appointments = indicator_datetime_planner_get_appointments (p->planner, - begin, - end); - - g_date_time_unref (end); - g_date_time_unref (begin); - g_date_time_unref (calendar_date); - } - - return appointments; -} - static GVariant * create_calendar_state (IndicatorDatetimeService * self) { @@ -611,15 +588,13 @@ create_calendar_state (IndicatorDatetimeService * self) GVariantBuilder day_builder; GDateTime * date; GSList * l; - GSList * appts; gboolean b; priv_t * p = self->priv; g_variant_builder_init (&dict_builder, G_VARIANT_TYPE_DICTIONARY); key = "appointment-days"; - appts = get_all_appointments_this_month (self); - for (l=appts; l!=NULL; l=l->next) + for (l=p->calendar_appointments; l!=NULL; l=l->next) { const struct IndicatorDatetimeAppt * appt = l->data; days[g_date_time_get_day_of_month (appt->begin)] = TRUE; @@ -630,7 +605,6 @@ create_calendar_state (IndicatorDatetimeService * self) g_variant_builder_add (&day_builder, "i", i); g_variant_builder_add (&dict_builder, "{sv}", key, g_variant_builder_end (&day_builder)); - g_slist_free_full (appts, (GDestroyNotify)indicator_datetime_appt_free); key = "calendar-day"; date = get_calendar_date (self); @@ -726,38 +700,6 @@ create_phone_calendar_section (IndicatorDatetimeService * self) **** ***/ -/* gets the next MAX_APPTS appointments */ -static GSList * -get_upcoming_appointments (IndicatorDatetimeService * self) -{ - const int MAX_APPTS = 5; - GSList * l; - GSList * appts = NULL; - priv_t * p = self->priv; - - if (p->planner != NULL) - { - GDateTime * begin = get_calendar_date (self); - GDateTime * end = g_date_time_add_months (begin, 1); - - appts = indicator_datetime_planner_get_appointments (p->planner, - begin, - end); - - g_date_time_unref (end); - g_date_time_unref (begin); - } - - /* truncate at MAX_APPTS */ - if ((l = g_slist_nth (appts, MAX_APPTS-1))) - { - g_slist_free_full (l->next, (GDestroyNotify)indicator_datetime_appt_free); - l->next = NULL; - } - - return appts; -} - static gboolean service_has_alarms (IndicatorDatetimeService * self) { @@ -765,7 +707,7 @@ service_has_alarms (IndicatorDatetimeService * self) GSList * appts; GSList * l; - appts = get_upcoming_appointments (self); + appts = self->priv->upcoming_appointments; for (l=appts; l!=NULL; l=l->next) { struct IndicatorDatetimeAppt * appt = l->data; @@ -773,7 +715,6 @@ service_has_alarms (IndicatorDatetimeService * self) break; } - g_slist_free_full (appts, (GDestroyNotify)indicator_datetime_appt_free); return has_alarms; } @@ -809,13 +750,15 @@ get_appointment_time_format (struct IndicatorDatetimeAppt * appt, static void add_appointments (IndicatorDatetimeService * self, GMenu * menu, gboolean terse) { + const int MAX_APPTS = 5; GDateTime * now = indicator_datetime_service_get_localtime (self); GSList * appts; GSList * l; + int i; /* build appointment menuitems */ - appts = get_upcoming_appointments (self); - for (l=appts; l!=NULL; l=l->next) + appts = self->priv->upcoming_appointments; + for (l=appts, i=0; l!=NULL && inext, i++) { struct IndicatorDatetimeAppt * appt = l->data; char * fmt = get_appointment_time_format (appt, now, terse); @@ -824,7 +767,7 @@ add_appointments (IndicatorDatetimeService * self, GMenu * menu, gboolean terse) menu_item = g_menu_item_new (appt->summary, NULL); - if (!appt->has_alarms) + if (appt->color && !appt->has_alarms) g_menu_item_set_attribute (menu_item, "x-canonical-color", "s", appt->color); @@ -845,7 +788,6 @@ add_appointments (IndicatorDatetimeService * self, GMenu * menu, gboolean terse) /* cleanup */ g_date_time_unref (now); - g_slist_free_full (appts, (GDestroyNotify)indicator_datetime_appt_free); } static GMenuModel * @@ -1603,6 +1545,132 @@ on_login1_manager_proxy_ready (GObject * object G_GNUC_UNUSED, } } +/*** +**** Appointments +***/ + +static void +set_calendar_appointments (IndicatorDatetimeService * self, + GSList * appointments) +{ + priv_t * p = self->priv; + + /* repopulate the list */ + indicator_datetime_planner_free_appointments (p->calendar_appointments); + p->calendar_appointments = appointments; + + /* sync the menus/actions */ + update_calendar_action_state (self); + rebuild_calendar_section_soon (self); +} + +static void +on_calendar_appointments_ready (GObject * source, + GAsyncResult * res, + gpointer self) +{ + IndicatorDatetimePlanner * planner; + GError * error; + GSList * appointments; + + planner = INDICATOR_DATETIME_PLANNER (source); + error = NULL; + appointments = indicator_datetime_planner_get_appointments_finish (planner, + res, + &error); + + if (error != NULL) + { + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + g_warning ("can't get this month's appointments: %s", error->message); + + g_error_free (error); + } + else + { + set_calendar_appointments (INDICATOR_DATETIME_SERVICE (self), + appointments); + } +} + +static void +set_upcoming_appointments (IndicatorDatetimeService * self, + GSList * appointments) +{ + priv_t * p = self->priv; + + /* repopulate the list */ + indicator_datetime_planner_free_appointments (p->upcoming_appointments); + p->upcoming_appointments = appointments; + + /* sync the menus/actions */ + rebuild_appointments_section_soon (self); +} + +static void +on_upcoming_appointments_ready (GObject * source, + GAsyncResult * res, + gpointer self) +{ + IndicatorDatetimePlanner * planner; + GError * error; + GSList * appointments; + + planner = INDICATOR_DATETIME_PLANNER (source); + error = NULL; + appointments = indicator_datetime_planner_get_appointments_finish (planner, + res, + &error); + + if (error != NULL) + { + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + g_warning ("can't get upcoming appointments: %s", error->message); + + g_error_free (error); + } + else + { + set_upcoming_appointments (INDICATOR_DATETIME_SERVICE (self), + appointments); + } +} + +static void +on_appointments_changed (IndicatorDatetimeService * self) +{ + IndicatorDatetimePlanner * planner; + GDateTime * calendar_date; + GDateTime * begin; + GDateTime * end; + int y, m, d; + + planner = self->priv->planner; + calendar_date = get_calendar_date (self); + + /* get all the appointments in the calendar month */ + g_date_time_get_ymd (calendar_date, &y, &m, &d); + begin = g_date_time_new_local (y, m, 1, 0, 0, 0); + end = g_date_time_new_local (y, m, g_date_get_days_in_month(m,y), 23, 59, 0); + indicator_datetime_planner_get_appointments (planner, begin, end, + on_calendar_appointments_ready, + self); + g_date_time_unref (begin); + g_date_time_unref (end); + + /* get the upcoming appointments */ + begin = g_date_time_ref (calendar_date); + end = g_date_time_add_months (begin, 1); + indicator_datetime_planner_get_appointments (planner, begin, end, + on_upcoming_appointments_ready, + self); + g_date_time_unref (begin); + g_date_time_unref (end); + + g_date_time_unref (calendar_date); +} + + /*** **** GDBus ***/ @@ -1642,9 +1710,6 @@ on_bus_acquired (GDBusConnection * connection, char * path = g_strdup_printf ("%s/%s", BUS_PATH, menu_names[i]); struct ProfileMenuInfo * menu = &p->menus[i]; - if (menu->menu == NULL) - create_menu (self, i); - if ((id = g_dbus_connection_export_menu_model (connection, path, G_MENU_MODEL (menu->menu), @@ -1735,6 +1800,8 @@ my_dispose (GObject * o) g_signal_handlers_disconnect_by_data (p->planner, self); g_clear_object (&p->planner); } + g_clear_pointer (&p->upcoming_appointments, indicator_datetime_planner_free_appointments); + g_clear_pointer (&p->calendar_appointments, indicator_datetime_planner_free_appointments); if (p->login1_manager != NULL) { @@ -1758,7 +1825,6 @@ my_dispose (GObject * o) for (i=0; imenus[i].menu); - g_clear_object (&p->planner); g_clear_object (&p->calendar_action); g_clear_object (&p->desktop_header_action); g_clear_object (&p->phone_header_action); @@ -1841,7 +1907,7 @@ indicator_datetime_service_init (IndicatorDatetimeService * self) p->planner = indicator_datetime_planner_eds_new (); g_signal_connect_swapped (p->planner, "appointments-changed", - G_CALLBACK(rebuild_calendar_section_soon), self); + G_CALLBACK(on_appointments_changed), self); /*** @@ -1913,6 +1979,9 @@ indicator_datetime_service_init (IndicatorDatetimeService * self) on_local_time_jumped (self); + for (i=0; i Date: Thu, 5 Sep 2013 12:12:54 -0500 Subject: make the EDS planner completely nonblocking. --- src/planner-eds.c | 337 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 259 insertions(+), 78 deletions(-) diff --git a/src/planner-eds.c b/src/planner-eds.c index 276058d..5cf4527 100644 --- a/src/planner-eds.c +++ b/src/planner-eds.c @@ -19,8 +19,6 @@ #include "config.h" -#include /* GFile, GFileMonitor */ - #include #include #include @@ -30,6 +28,8 @@ struct _IndicatorDatetimePlannerEdsPriv { + GSList * sources; + GCancellable * cancellable; ESourceRegistry * source_registry; }; @@ -39,6 +39,8 @@ G_DEFINE_TYPE (IndicatorDatetimePlannerEds, indicator_datetime_planner_eds, INDICATOR_TYPE_DATETIME_PLANNER) +G_DEFINE_QUARK ("source-client", source_client) + /*** **** ***/ @@ -60,23 +62,70 @@ indicator_datetime_appt_free (struct IndicatorDatetimeAppt * appt) **** my_get_appointments() helpers ***/ -struct my_get_appointments_data +struct get_appointments_task_data { - ESource * source; + /* how many subtasks are still running on */ + int subtask_count; + + /* the list of appointments to be returned */ GSList * appointments; /* ensure that recurring events don't get multiple IndicatorDatetimeAppts */ GHashTable * added; }; +static void +get_appointments_task_data_free (gpointer gdata) +{ + struct get_appointments_task_data * data = gdata; + g_hash_table_unref (data->added); + g_slice_free (struct get_appointments_task_data, data); +} + +static void +on_all_subtasks_done (GTask * task) +{ + struct get_appointments_task_data * data = g_task_get_task_data (task); + g_task_return_pointer (task, data->appointments, NULL); + g_object_unref (task); +} + +struct get_appointments_subtask_data +{ + GTask * task; + + gchar * color; +}; + +static void +on_subtask_done (gpointer gsubdata) +{ + struct get_appointments_subtask_data * subdata; + GTask * task; + struct get_appointments_task_data * data; + + subdata = gsubdata; + task = subdata->task; + + /* free the subtask data */ + g_free (subdata->color); + g_slice_free (struct get_appointments_subtask_data, subdata); + + /* poke the task */ + data = g_task_get_task_data (task); + if (--data->subtask_count <= 0) + on_all_subtasks_done (task); +} + static gboolean my_get_appointments_foreach (ECalComponent * component, time_t begin, time_t end, - gpointer gdata) + gpointer gsubdata) { const ECalComponentVType vtype = e_cal_component_get_vtype (component); - struct my_get_appointments_data * data = gdata; + struct get_appointments_subtask_data * subdata = gsubdata; + struct get_appointments_task_data * data = g_task_get_task_data (subdata->task); if ((vtype == E_CAL_COMPONENT_EVENT) || (vtype == E_CAL_COMPONENT_TODO)) { @@ -117,7 +166,7 @@ my_get_appointments_foreach (ECalComponent * component, appt->begin = g_date_time_new_from_unix_local (begin); appt->end = g_date_time_new_from_unix_local (end); - appt->color = e_source_selectable_dup_color (e_source_get_extension (data->source, E_SOURCE_EXTENSION_CALENDAR)); + appt->color = g_strdup (subdata->color); appt->is_event = vtype == E_CAL_COMPONENT_EVENT; appt->summary = g_strdup (text.value); @@ -133,24 +182,26 @@ my_get_appointments_foreach (ECalComponent * component, return G_SOURCE_CONTINUE; } - /*** **** IndicatorDatetimePlanner virtual funcs ***/ -static GSList * +static void my_get_appointments (IndicatorDatetimePlanner * planner, GDateTime * begin_datetime, - GDateTime * end_datetime) + GDateTime * end_datetime, + GAsyncReadyCallback callback, + gpointer user_data) { - GList * l; - GList * sources; + GSList * l; priv_t * p; const char * str; icaltimezone * default_timezone; - struct my_get_appointments_data data; + struct get_appointments_task_data * data; const int64_t begin = g_date_time_to_unix (begin_datetime); const int64_t end = g_date_time_to_unix (end_datetime); + GTask * task; + gboolean subtasks_added; p = INDICATOR_DATETIME_PLANNER_EDS (planner)->priv; @@ -172,60 +223,56 @@ my_get_appointments (IndicatorDatetimePlanner * planner, *** walk through the sources to build the appointment list **/ - data.source = NULL; - data.appointments = NULL; - data.added = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + data = g_slice_new0 (struct get_appointments_task_data); + data->added = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + task = g_task_new (planner, p->cancellable, callback, user_data); + g_task_set_task_data (task, data, get_appointments_task_data_free); - sources = e_source_registry_list_sources (p->source_registry, E_SOURCE_EXTENSION_CALENDAR); - for (l=sources; l!=NULL; l=l->next) + subtasks_added = FALSE; + for (l=p->sources; l!=NULL; l=l->next) { - GError * err; ESource * source; - ECalClient * ecc; - - source = E_SOURCE (l->data); - if (e_source_get_enabled (source)) - { - err = NULL; - ecc = e_cal_client_new (source, E_CAL_CLIENT_SOURCE_TYPE_EVENTS, &err); - if (err != NULL) - { - g_warning ("Can't create ecal client: %s", err->message); - g_error_free (err); - } - else - { - if (!e_client_open_sync (E_CLIENT (ecc), TRUE, NULL, &err)) - { - g_debug ("Failed to open ecal client: %s", err->message); - g_error_free (err); - } - else - { - if (default_timezone != NULL) - e_cal_client_set_default_timezone (ecc, default_timezone); - - data.source = source; - e_cal_client_generate_instances_sync (ecc, begin, end, my_get_appointments_foreach, &data); - } - - g_object_unref (ecc); - } - } + ECalClient * client; + struct get_appointments_subtask_data * subdata; + + source = l->data; + client = g_object_get_qdata (l->data, source_client_quark()); + if (client == NULL) + continue; + + if (default_timezone != NULL) + e_cal_client_set_default_timezone (client, default_timezone); + + subdata = g_slice_new (struct get_appointments_subtask_data); + subdata->task = task; + subdata->color = e_source_selectable_dup_color (e_source_get_extension (source, E_SOURCE_EXTENSION_CALENDAR)); + + data->subtask_count++; + subtasks_added = TRUE; + e_cal_client_generate_instances (client, + begin, + end, + p->cancellable, + my_get_appointments_foreach, + subdata, + on_subtask_done); } - g_list_free_full (sources, g_object_unref); + if (!subtasks_added) + on_all_subtasks_done (task); +} - g_debug ("%s EDS get_appointments returning %d appointments", G_STRLOC, g_slist_length (data.appointments)); - g_hash_table_destroy (data.added); - return data.appointments; +static GSList * +my_get_appointments_finish (IndicatorDatetimePlanner * self G_GNUC_UNUSED, + GAsyncResult * res, + GError ** error) +{ + return g_task_propagate_pointer (G_TASK(res), error); } gboolean my_is_configured (IndicatorDatetimePlanner * planner) { - GList * sources; - gboolean have_sources; IndicatorDatetimePlannerEds * self; /* confirm that it's installed... */ @@ -238,10 +285,7 @@ my_is_configured (IndicatorDatetimePlanner * planner) /* see if there are any calendar sources */ self = INDICATOR_DATETIME_PLANNER_EDS (planner); - sources = e_source_registry_list_sources (self->priv->source_registry, E_SOURCE_EXTENSION_CALENDAR); - have_sources = sources != NULL; - g_list_free_full (sources, g_object_unref); - return have_sources; + return self->priv->sources != NULL; } static void @@ -278,6 +322,148 @@ my_activate_time (IndicatorDatetimePlanner * self G_GNUC_UNUSED, g_free (isodate); } +/*** +**** Source / Client Wrangling +***/ + +static void +on_client_connected (GObject * unused G_GNUC_UNUSED, + GAsyncResult * res, + gpointer gself) +{ + GError * error; + EClient * client; + + error = NULL; + client = e_cal_client_connect_finish (res, &error); + if (error != NULL) + { + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + g_warning ("indicator-datetime cannot connect to EDS source: %s", error->message); + + g_error_free (error); + } + else + { + /* we've got a new connected ECalClient, so store it & notify clients */ + + g_object_set_qdata_full (G_OBJECT(e_client_get_source(client)), + source_client_quark(), + client, + g_object_unref); + + indicator_datetime_planner_emit_appointments_changed (gself); + } +} + +static void +on_source_enabled (ESourceRegistry * registry G_GNUC_UNUSED, + ESource * source, + gpointer gself) +{ + IndicatorDatetimePlannerEds * self = INDICATOR_DATETIME_PLANNER_EDS (gself); + priv_t * p = self->priv; + + e_cal_client_connect (source, + E_CAL_CLIENT_SOURCE_TYPE_EVENTS, + p->cancellable, + on_client_connected, + self); +} + +static void +on_source_added (ESourceRegistry * registry, + ESource * source, + gpointer gself) +{ + IndicatorDatetimePlannerEds * self = INDICATOR_DATETIME_PLANNER_EDS (gself); + priv_t * p = self->priv; + + p->sources = g_slist_prepend (p->sources, g_object_ref(source)); + + if (e_source_get_enabled (source)) + on_source_enabled (registry, source, gself); +} + +static void +on_source_disabled (ESourceRegistry * registry G_GNUC_UNUSED, + ESource * source, + gpointer gself) +{ + ECalClient * client; + + /* If this source has a connected ECalClient, remove it & notify clients */ + if ((client = g_object_steal_qdata (G_OBJECT(source), source_client_quark()))) + { + g_object_unref (client); + indicator_datetime_planner_emit_appointments_changed (gself); + } +} + +static void +on_source_removed (ESourceRegistry * registry, + ESource * source, + gpointer gself) +{ + IndicatorDatetimePlannerEds * self = INDICATOR_DATETIME_PLANNER_EDS (gself); + priv_t * p = self->priv; + + on_source_disabled (registry, source, gself); + + p->sources = g_slist_remove (p->sources, source); + g_object_unref (source); +} + +static void +on_source_changed (ESourceRegistry * registry G_GNUC_UNUSED, + ESource * source G_GNUC_UNUSED, + gpointer gself) +{ + indicator_datetime_planner_emit_appointments_changed (gself); +} + +static void +on_source_registry_ready (GObject * source_object G_GNUC_UNUSED, + GAsyncResult * res, + gpointer gself) +{ + GError * error; + ESourceRegistry * r; + + error = NULL; + r = e_source_registry_new_finish (res, &error); + if (error != NULL) + { + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + g_warning ("indicator-datetime cannot show EDS appointments: %s", error->message); + + g_error_free (error); + } + else + { + IndicatorDatetimePlannerEds * self; + priv_t * p; + GList * l; + GList * sources; + + self = INDICATOR_DATETIME_PLANNER_EDS (gself); + p = self->priv; + + g_signal_connect (r, "source-added", G_CALLBACK(on_source_added), self); + g_signal_connect (r, "source-removed", G_CALLBACK(on_source_removed), self); + g_signal_connect (r, "source-changed", G_CALLBACK(on_source_changed), self); + g_signal_connect (r, "source-disabled", G_CALLBACK(on_source_disabled), self); + g_signal_connect (r, "source-enabled", G_CALLBACK(on_source_enabled), self); + + p->source_registry = r; + + sources = e_source_registry_list_sources (r, E_SOURCE_EXTENSION_CALENDAR); + for (l=sources; l!=NULL; l=l->next) + on_source_added (r, l->data, self); + g_list_free_full (sources, g_object_unref); + } +} + /*** **** GObject virtual funcs ***/ @@ -288,6 +474,12 @@ my_dispose (GObject * o) IndicatorDatetimePlannerEds * self = INDICATOR_DATETIME_PLANNER_EDS (o); priv_t * p = self->priv; + if (p->cancellable != NULL) + { + g_cancellable_cancel (p->cancellable); + g_clear_object (&p->cancellable); + } + if (p->source_registry != NULL) { g_signal_handlers_disconnect_by_func (p->source_registry, @@ -301,7 +493,7 @@ my_dispose (GObject * o) } /*** -**** Insantiation +**** Instantiation ***/ static void @@ -318,6 +510,7 @@ indicator_datetime_planner_eds_class_init (IndicatorDatetimePlannerEdsClass * kl planner_class->activate = my_activate; planner_class->activate_time = my_activate_time; planner_class->get_appointments = my_get_appointments; + planner_class->get_appointments_finish = my_get_appointments_finish; g_type_class_add_private (klass, sizeof (IndicatorDatetimePlannerEdsPriv)); } @@ -326,7 +519,6 @@ static void indicator_datetime_planner_eds_init (IndicatorDatetimePlannerEds * self) { priv_t * p; - GError * err; p = G_TYPE_INSTANCE_GET_PRIVATE (self, INDICATOR_TYPE_DATETIME_PLANNER_EDS, @@ -334,22 +526,11 @@ indicator_datetime_planner_eds_init (IndicatorDatetimePlannerEds * self) self->priv = p; - err = 0; - p->source_registry = e_source_registry_new_sync (NULL, &err); - if (err != NULL) - { - g_warning ("indicator-datetime cannot show EDS appointments: %s", err->message); - g_error_free (err); - } - else - { - gpointer o = p->source_registry; - g_signal_connect_swapped (o, "source-added", G_CALLBACK(indicator_datetime_planner_emit_appointments_changed), self); - g_signal_connect_swapped (o, "source-removed", G_CALLBACK(indicator_datetime_planner_emit_appointments_changed), self); - g_signal_connect_swapped (o, "source-changed", G_CALLBACK(indicator_datetime_planner_emit_appointments_changed), self); - g_signal_connect_swapped (o, "source-disabled", G_CALLBACK(indicator_datetime_planner_emit_appointments_changed), self); - g_signal_connect_swapped (o, "source-enabled", G_CALLBACK(indicator_datetime_planner_emit_appointments_changed), self); - } + p->cancellable = g_cancellable_new (); + + e_source_registry_new (p->cancellable, + on_source_registry_ready, + self); } /*** -- cgit v1.2.3 From 7ecf093c9ae63453babe3fd3fffcc26f6115fb58 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 5 Sep 2013 12:58:03 -0500 Subject: use GSlice for allocating/freeing indicator appt structs --- src/planner-eds.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/planner-eds.c b/src/planner-eds.c index 5cf4527..1c0ffc5 100644 --- a/src/planner-eds.c +++ b/src/planner-eds.c @@ -54,7 +54,7 @@ indicator_datetime_appt_free (struct IndicatorDatetimeAppt * appt) g_date_time_unref (appt->begin); g_free (appt->color); g_free (appt->summary); - g_free (appt); + g_slice_free (struct IndicatorDatetimeAppt, appt); } } @@ -146,7 +146,7 @@ my_get_appointments_foreach (ECalComponent * component, ECalComponentText text; struct IndicatorDatetimeAppt * appt; - appt = g_new0 (struct IndicatorDatetimeAppt, 1); + appt = g_slice_new0 (struct IndicatorDatetimeAppt); /* Determine whether this is a recurring event. NB: icalrecurrencetype supports complex recurrence patterns; -- cgit v1.2.3 From d79408477c6fae230193f11be058c564f230ab8f Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 5 Sep 2013 12:59:48 -0500 Subject: use GSlice for allocating/freeing service's setlocation_data structs --- src/service.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/service.c b/src/service.c index 55344d8..4c51e31 100644 --- a/src/service.c +++ b/src/service.c @@ -1082,7 +1082,7 @@ setlocation_data_free (struct setlocation_data * data) { g_free (data->timezone_id); g_free (data->name); - g_free (data); + g_slice_free (struct setlocation_data, data); } static void @@ -1166,7 +1166,7 @@ indicator_datetime_service_set_location (IndicatorDatetimeService * self, g_return_if_fail (name && *name); g_return_if_fail (timezone_id && *timezone_id); - data = g_new0 (struct setlocation_data, 1); + data = g_slice_new0 (struct setlocation_data); data->timezone_id = g_strdup (timezone_id); data->name = g_strdup (name); data->service = self; -- cgit v1.2.3 From fdd57db6d6a81951da34675ee89e6e0f1b77b59e Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 5 Sep 2013 13:01:07 -0500 Subject: use GSlice for allocating/freeing service's TimeLocation structs --- src/service.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/service.c b/src/service.c index 4c51e31..c36e996 100644 --- a/src/service.c +++ b/src/service.c @@ -908,7 +908,7 @@ time_location_free (struct TimeLocation * loc) g_date_time_unref (loc->local_time); g_free (loc->name); g_free (loc->zone); - g_free (loc); + g_slice_free (struct TimeLocation, loc); } static struct TimeLocation* @@ -916,7 +916,7 @@ time_location_new (const char * zone, const char * name, gboolean visible) { - struct TimeLocation * loc = g_new (struct TimeLocation, 1); + struct TimeLocation * loc = g_slice_new (struct TimeLocation); GTimeZone * tz = g_time_zone_new (zone); loc->zone = g_strdup (zone); loc->name = g_strdup (name); -- cgit v1.2.3 From 86333cb7f91ef594088ded32927454940745d96d Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 5 Sep 2013 13:24:28 -0500 Subject: in our private T_() function, avoid a couple of unnecessary strdup & frees --- src/utils.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/utils.c b/src/utils.c index b99de94..50d896d 100644 --- a/src/utils.c +++ b/src/utils.c @@ -134,9 +134,9 @@ T_(const char *msg) LC_MESSAGES directory, so we won't find any translation there. */ char *message_locale = g_strdup(setlocale(LC_MESSAGES, NULL)); - char *time_locale = g_strdup(setlocale(LC_TIME, NULL)); + const char *time_locale = setlocale (LC_TIME, NULL); char *language = g_strdup(g_getenv("LANGUAGE")); - char *rv; + const char *rv; if (language) g_unsetenv("LANGUAGE"); setlocale(LC_MESSAGES, time_locale); @@ -149,7 +149,6 @@ T_(const char *msg) if (language) g_setenv("LANGUAGE", language, TRUE); g_free(message_locale); - g_free(time_locale); g_free(language); return rv; } -- cgit v1.2.3 From 1272fff388d793a44dc166850e5f1005bb5741b0 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 5 Sep 2013 13:25:05 -0500 Subject: in service.c, use g_variant_new_take_string() instead of g_variant_new_string() where appropriate --- src/service.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/service.c b/src/service.c index c36e996..d7ae22f 100644 --- a/src/service.c +++ b/src/service.c @@ -499,12 +499,11 @@ create_desktop_header_state (IndicatorDatetimeService * self) g_variant_builder_init (&b, G_VARIANT_TYPE("a{sv}")); g_variant_builder_add (&b, "{sv}", "accessible-desc", g_variant_new_string (str)); - g_variant_builder_add (&b, "{sv}", "label", g_variant_new_string (str)); + g_variant_builder_add (&b, "{sv}", "label", g_variant_new_take_string (str)); g_variant_builder_add (&b, "{sv}", "visible", g_variant_new_boolean (visible)); /* cleanup */ g_date_time_unref (now); - g_free (str); g_free (fmt); return g_variant_builder_end (&b); } @@ -528,7 +527,6 @@ create_phone_header_state (IndicatorDatetimeService * self) now = indicator_datetime_service_get_localtime (self); fmt = get_terse_time_format_string (now); label = g_date_time_format (now, fmt); - g_variant_builder_add (&b, "{sv}", "label", g_variant_new_string (label)); /* icon */ if ((has_alarms = service_has_alarms (self))) @@ -545,14 +543,12 @@ create_phone_header_state (IndicatorDatetimeService * self) else a11y = g_strdup (label); g_variant_builder_add (&b, "{sv}", "accessible-desc", - g_variant_new_string (a11y)); + g_variant_new_take_string (a11y)); - /* visible */ g_variant_builder_add (&b, "{sv}", "visible", g_variant_new_boolean (TRUE)); + g_variant_builder_add (&b, "{sv}", "label", g_variant_new_take_string (label)); /* cleanup */ - g_free (a11y); - g_free (label); g_date_time_unref (now); return g_variant_builder_end (&b); } -- cgit v1.2.3 From 7eb56163c3032e4da74255cee732fcaf142cafe1 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 5 Sep 2013 16:27:35 -0500 Subject: in planner-eds, use g_atomic_int for enc/dec of the subtask_count --- src/planner-eds.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/planner-eds.c b/src/planner-eds.c index 1c0ffc5..f121a32 100644 --- a/src/planner-eds.c +++ b/src/planner-eds.c @@ -113,7 +113,7 @@ on_subtask_done (gpointer gsubdata) /* poke the task */ data = g_task_get_task_data (task); - if (--data->subtask_count <= 0) + if (g_atomic_int_dec_and_test (&data->subtask_count)) on_all_subtasks_done (task); } @@ -247,7 +247,7 @@ my_get_appointments (IndicatorDatetimePlanner * planner, subdata->task = task; subdata->color = e_source_selectable_dup_color (e_source_get_extension (source, E_SOURCE_EXTENSION_CALENDAR)); - data->subtask_count++; + g_atomic_int_inc (&data->subtask_count); subtasks_added = TRUE; e_cal_client_generate_instances (client, begin, -- cgit v1.2.3 From a7d1945d1988bc0b85e83f903191c6ee125a97af Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 5 Sep 2013 17:50:38 -0500 Subject: fix 'upcoming appointment' section menuitems issue reported by ted --- src/service.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/service.c b/src/service.c index c36e996..ce99c59 100644 --- a/src/service.c +++ b/src/service.c @@ -1637,7 +1637,7 @@ on_upcoming_appointments_ready (GObject * source, } static void -on_appointments_changed (IndicatorDatetimeService * self) +update_appointment_lists (IndicatorDatetimeService * self) { IndicatorDatetimePlanner * planner; GDateTime * calendar_date; @@ -1907,7 +1907,7 @@ indicator_datetime_service_init (IndicatorDatetimeService * self) p->planner = indicator_datetime_planner_eds_new (); g_signal_connect_swapped (p->planner, "appointments-changed", - G_CALLBACK(on_appointments_changed), self); + G_CALLBACK(update_appointment_lists), self); /*** @@ -2041,8 +2041,5 @@ indicator_datetime_service_set_calendar_date (IndicatorDatetimeService * self, /* sync the menuitems and action states */ if (dirty) - { - update_calendar_action_state (self); - rebuild_appointments_section_soon (self); - } + update_appointment_lists (self); } -- cgit v1.2.3 From f35c8eb35f88ef43e71395445067d30cd3a48c72 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 5 Sep 2013 18:00:34 -0500 Subject: in update_appointment_lists(), safeguard against NULL GDateTimes. --- src/service.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/service.c b/src/service.c index ce99c59..c46beeb 100644 --- a/src/service.c +++ b/src/service.c @@ -1652,22 +1652,23 @@ update_appointment_lists (IndicatorDatetimeService * self) g_date_time_get_ymd (calendar_date, &y, &m, &d); begin = g_date_time_new_local (y, m, 1, 0, 0, 0); end = g_date_time_new_local (y, m, g_date_get_days_in_month(m,y), 23, 59, 0); - indicator_datetime_planner_get_appointments (planner, begin, end, - on_calendar_appointments_ready, - self); - g_date_time_unref (begin); - g_date_time_unref (end); + if (begin && end) + indicator_datetime_planner_get_appointments (planner, begin, end, + on_calendar_appointments_ready, + self); + g_clear_pointer (&begin, g_date_time_unref); + g_clear_pointer (&end, g_date_time_unref); /* get the upcoming appointments */ begin = g_date_time_ref (calendar_date); end = g_date_time_add_months (begin, 1); - indicator_datetime_planner_get_appointments (planner, begin, end, - on_upcoming_appointments_ready, - self); - g_date_time_unref (begin); - g_date_time_unref (end); - - g_date_time_unref (calendar_date); + if (begin && end) + indicator_datetime_planner_get_appointments (planner, begin, end, + on_upcoming_appointments_ready, + self); + g_clear_pointer (&begin, g_date_time_unref); + g_clear_pointer (&end, g_date_time_unref); + g_clear_pointer (&calendar_date, g_date_time_unref); } -- cgit v1.2.3 From f96fb5c43dcfa24f155bda145fe53c1d87669a36 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 6 Sep 2013 12:45:52 -0500 Subject: Removing check for NULL items --- src/service.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/service.c b/src/service.c index 421e3dd..5fba01e 100644 --- a/src/service.c +++ b/src/service.c @@ -593,12 +593,9 @@ get_all_appointments_this_month (IndicatorDatetimeService * self) begin, end); - if (end != NULL) - g_date_time_unref (end); - if (begin != NULL) - g_date_time_unref (begin); - if (calendar_date != NULL) - g_date_time_unref (calendar_date); + g_date_time_unref (end); + g_date_time_unref (begin); + g_date_time_unref (calendar_date); } return appointments; -- cgit v1.2.3 From 55ed2b1b22607f3b9618640294d233eee15db767 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 6 Sep 2013 12:47:27 -0500 Subject: Making sure we have 0.1 between our bounds on the seconds --- src/service.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/service.c b/src/service.c index 5fba01e..c1f8752 100644 --- a/src/service.c +++ b/src/service.c @@ -585,9 +585,9 @@ get_all_appointments_this_month (IndicatorDatetimeService * self) calendar_date = get_calendar_date (self); g_date_time_get_ymd (calendar_date, &y, &m, &d); begin = g_date_time_new_local (y, m, 1, - 0, 0, 0); + 0, 0, 0.1); end = g_date_time_new_local (y, m, g_date_get_days_in_month(m,y), - 23, 59, 0); + 23, 59, 59.9); appointments = indicator_datetime_planner_get_appointments (p->planner, begin, -- cgit v1.2.3 From dfc6f669720cd38250c57bf2efff97caedfaca81 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 6 Sep 2013 12:52:30 -0500 Subject: Make all seconds a tenth of a second in bounds --- src/service.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/service.c b/src/service.c index c46beeb..f6d1d59 100644 --- a/src/service.c +++ b/src/service.c @@ -227,7 +227,7 @@ calculate_seconds_until_next_fifteen_minutes (GDateTime * now) g_date_time_get_day_of_month (next), g_date_time_get_hour (next), g_date_time_get_minute (next), - 1); + 0.1); str = g_date_time_format (start_of_next, "%F %T"); g_debug ("%s %s the next timestamp rebuild will be at %s", G_STRLOC, G_STRFUNC, str); @@ -299,7 +299,7 @@ calculate_milliseconds_until_next_minute (GDateTime * now) g_date_time_get_day_of_month (next), g_date_time_get_hour (next), g_date_time_get_minute (next), - 0); + 0.1); interval_usec = g_date_time_difference (start_of_next, now); interval_msec = (interval_usec + 999) / 1000; @@ -1650,8 +1650,8 @@ update_appointment_lists (IndicatorDatetimeService * self) /* get all the appointments in the calendar month */ g_date_time_get_ymd (calendar_date, &y, &m, &d); - begin = g_date_time_new_local (y, m, 1, 0, 0, 0); - end = g_date_time_new_local (y, m, g_date_get_days_in_month(m,y), 23, 59, 0); + begin = g_date_time_new_local (y, m, 1, 0, 0, 0.1); + end = g_date_time_new_local (y, m, g_date_get_days_in_month(m,y), 23, 59, 59.9); if (begin && end) indicator_datetime_planner_get_appointments (planner, begin, end, on_calendar_appointments_ready, -- cgit v1.2.3 From 188c34d1c975b35f8ec36442ca971520014c419b Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sat, 7 Sep 2013 07:05:02 -0500 Subject: copyediting: use G_VARIANT_TYPE_VARDICT instead of G_VARIANT_TYPE('a{sv}') --- src/service.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/service.c b/src/service.c index c46beeb..364463a 100644 --- a/src/service.c +++ b/src/service.c @@ -497,7 +497,7 @@ create_desktop_header_state (IndicatorDatetimeService * self) g_warning ("%s", str); } - g_variant_builder_init (&b, G_VARIANT_TYPE("a{sv}")); + g_variant_builder_init (&b, G_VARIANT_TYPE_VARDICT); g_variant_builder_add (&b, "{sv}", "accessible-desc", g_variant_new_string (str)); g_variant_builder_add (&b, "{sv}", "label", g_variant_new_string (str)); g_variant_builder_add (&b, "{sv}", "visible", g_variant_new_boolean (visible)); @@ -522,7 +522,7 @@ create_phone_header_state (IndicatorDatetimeService * self) gboolean has_alarms; gchar * a11y; - g_variant_builder_init (&b, G_VARIANT_TYPE("a{sv}")); + g_variant_builder_init (&b, G_VARIANT_TYPE_VARDICT); /* label */ now = indicator_datetime_service_get_localtime (self); -- cgit v1.2.3 From fd1d19cbdc2d29d8ada8a304221cabf6cac95e7a Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sat, 7 Sep 2013 07:06:58 -0500 Subject: in service.c, remove unnecessary function get_time_format_mode() --- src/service.c | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/src/service.c b/src/service.c index 364463a..1aed147 100644 --- a/src/service.c +++ b/src/service.c @@ -433,34 +433,12 @@ typedef enum } TimeFormatMode; -/* gets the user's time-format from GSettings */ -static TimeFormatMode -get_time_format_mode (IndicatorDatetimeService * self) -{ - char * str; - TimeFormatMode mode; - - str = g_settings_get_string (self->priv->settings, SETTINGS_TIME_FORMAT_S); - - if (!g_strcmp0 ("12-hour", str)) - mode = TIME_FORMAT_MODE_12_HOUR; - else if (!g_strcmp0 ("24-hour", str)) - mode = TIME_FORMAT_MODE_24_HOUR; - else if (!g_strcmp0 ("custom", str)) - mode = TIME_FORMAT_MODE_CUSTOM; - else - mode = TIME_FORMAT_MODE_LOCALE_DEFAULT; - - g_free (str); - return mode; -} - static gchar * get_header_label_format_string (IndicatorDatetimeService * self) { char * fmt; - const TimeFormatMode mode = get_time_format_mode (self); GSettings * s = self->priv->settings; + const TimeFormatMode mode = g_settings_get_enum (s, SETTINGS_TIME_FORMAT_S); if (mode == TIME_FORMAT_MODE_CUSTOM) { -- cgit v1.2.3 From c81e028e66f6d574e6657f782d90493857192975 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sat, 7 Sep 2013 07:07:51 -0500 Subject: both service.c and utils.c have an enum for the time format mode, so share it in settings-shared.h --- src/service.c | 9 --------- src/settings-shared.h | 9 +++++++++ src/utils.c | 15 ++++----------- 3 files changed, 13 insertions(+), 20 deletions(-) diff --git a/src/service.c b/src/service.c index 1aed147..0d8192a 100644 --- a/src/service.c +++ b/src/service.c @@ -424,15 +424,6 @@ skew_timer_func (gpointer gself) **** ***/ -typedef enum -{ - TIME_FORMAT_MODE_LOCALE_DEFAULT, - TIME_FORMAT_MODE_12_HOUR, - TIME_FORMAT_MODE_24_HOUR, - TIME_FORMAT_MODE_CUSTOM -} -TimeFormatMode; - static gchar * get_header_label_format_string (IndicatorDatetimeService * self) { diff --git a/src/settings-shared.h b/src/settings-shared.h index 27ce34c..afcccb6 100644 --- a/src/settings-shared.h +++ b/src/settings-shared.h @@ -22,6 +22,15 @@ with this program. If not, see . #ifndef __DATETIME_SETTINGS_SHARED_H__ #define __DATETIME_SETTINGS_SHARED_H__ +typedef enum +{ + TIME_FORMAT_MODE_LOCALE_DEFAULT, + TIME_FORMAT_MODE_12_HOUR, + TIME_FORMAT_MODE_24_HOUR, + TIME_FORMAT_MODE_CUSTOM +} +TimeFormatMode; + #define SETTINGS_INTERFACE "com.canonical.indicator.datetime" #define SETTINGS_SHOW_CLOCK_S "show-clock" #define SETTINGS_TIME_FORMAT_S "time-format" diff --git a/src/utils.c b/src/utils.c index b99de94..5b1f58f 100644 --- a/src/utils.c +++ b/src/utils.c @@ -348,14 +348,6 @@ get_full_date_format_string (gboolean show_day, gboolean show_date) * */ -enum -{ - SETTINGS_TIME_LOCALE = 0, - SETTINGS_TIME_12_HOUR = 1, - SETTINGS_TIME_24_HOUR = 2, - SETTINGS_TIME_CUSTOM = 3 -}; - const gchar * get_full_time_format_string (void) { @@ -370,15 +362,16 @@ get_full_time_format_string (void) switch (g_settings_get_enum (settings, SETTINGS_TIME_FORMAT_S)) { - case SETTINGS_TIME_LOCALE: + case TIME_FORMAT_MODE_LOCALE_DEFAULT: twelvehour = is_locale_12h(); break; - case SETTINGS_TIME_24_HOUR: + case TIME_FORMAT_MODE_24_HOUR: twelvehour = FALSE; break; - default: + case TIME_FORMAT_MODE_12_HOUR: + case TIME_FORMAT_MODE_CUSTOM: twelvehour = TRUE; break; } -- cgit v1.2.3 From e2096aa3f7d1a78ad0a8968a29529a6609a6fd5a Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sat, 7 Sep 2013 07:10:53 -0500 Subject: in the utils functions, add a GSettings argument for the functions that use a GSettings s.t. they don't have to keep reloading settings in a temporary every time they're called. --- src/datetime-prefs-locations.c | 5 ++++- src/datetime-prefs.c | 20 ++++++++++---------- src/service.c | 13 +++++++------ src/utils.c | 29 ++++++++++++++--------------- src/utils.h | 11 +++++++---- 5 files changed, 42 insertions(+), 36 deletions(-) diff --git a/src/datetime-prefs-locations.c b/src/datetime-prefs-locations.c index bc044a2..ca3d9b5 100644 --- a/src/datetime-prefs-locations.c +++ b/src/datetime-prefs-locations.c @@ -417,6 +417,7 @@ update_times (GtkWidget * dlg) g_signal_handlers_block_by_func (store, save_when_idle, dlg); + GSettings * settings = g_settings_new (SETTINGS_INTERFACE); GtkTreeIter iter; if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter)) { GDateTime * now = g_date_time_new_now_local (); @@ -428,7 +429,7 @@ update_times (GtkWidget * dlg) if (strzone && *strzone) { GTimeZone * tz = g_time_zone_new (strzone); GDateTime * now_tz = g_date_time_to_timezone (now, tz); - gchar * format = generate_full_format_string_at_time (now, now_tz); + gchar * format = generate_full_format_string_at_time (now, now_tz, settings); gchar * time_str = g_date_time_format (now_tz, format); gchar * old_time_str; @@ -447,6 +448,8 @@ update_times (GtkWidget * dlg) g_date_time_unref (now); } + g_object_unref (settings); + g_signal_handlers_unblock_by_func (store, save_when_idle, dlg); return TRUE; diff --git a/src/datetime-prefs.c b/src/datetime-prefs.c index 25c9b2a..9b48ca9 100644 --- a/src/datetime-prefs.c +++ b/src/datetime-prefs.c @@ -70,6 +70,7 @@ struct _IndicatorDatetimePanelPrivate gboolean user_edited_time; gboolean changing_time; GtkWidget * loc_dlg; + GSettings * settings; CcTimezoneCompletion * completion; }; @@ -214,7 +215,7 @@ toggle_ntp (GtkWidget * radio, GParamSpec * pspec, IndicatorDatetimePanel * self static void sync_entry (IndicatorDatetimePanel * self, const gchar * location) { - gchar * name = get_current_zone_name (location); + gchar * name = get_current_zone_name (location, self->priv->settings); gtk_entry_set_text (GTK_ENTRY (self->priv->tz_entry), name); g_free (name); @@ -599,11 +600,9 @@ timezone_selected (GtkEntryCompletion * widget, GtkTreeModel * model, zone = cc_timezone_map_get_timezone_at_coords (self->priv->tzmap, lon, lat); } - GSettings * conf = g_settings_new (SETTINGS_INTERFACE); gchar * tz_name = g_strdup_printf ("%s %s", zone, name); - g_settings_set_string (conf, SETTINGS_TIMEZONE_NAME_S, tz_name); + g_settings_set_string (self->priv->settings, SETTINGS_TIMEZONE_NAME_S, tz_name); g_free (tz_name); - g_object_unref (conf); cc_timezone_map_set_timezone (self->priv->tzmap, zone); @@ -623,7 +622,7 @@ entry_focus_out (GtkEntry * entry, GdkEventFocus * event, IndicatorDatetimePanel gchar * zone; g_object_get (location, "zone", &zone, NULL); - gchar * name = get_current_zone_name (zone); + gchar * name = get_current_zone_name (zone, self->priv->settings); gboolean correct = (g_strcmp0 (gtk_entry_get_text (entry), name) == 0); g_free (name); g_free (zone); @@ -639,14 +638,18 @@ entry_focus_out (GtkEntry * entry, GdkEventFocus * event, IndicatorDatetimePanel static void indicator_datetime_panel_init (IndicatorDatetimePanel * self) { + GError * error; + GSettings * conf; + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, INDICATOR_DATETIME_TYPE_PANEL, IndicatorDatetimePanelPrivate); - GError * error = NULL; + self->priv->settings = conf = g_settings_new (SETTINGS_INTERFACE); self->priv->builder = gtk_builder_new (); gtk_builder_set_translation_domain (self->priv->builder, GETTEXT_PACKAGE); + error = NULL; gtk_builder_add_from_file (self->priv->builder, DATETIME_DIALOG_UI_FILE, &error); if (error != NULL) { /* We have to abort, we can't continue without the ui file */ @@ -655,8 +658,6 @@ indicator_datetime_panel_init (IndicatorDatetimePanel * self) return; } - GSettings * conf = g_settings_new (SETTINGS_INTERFACE); - /* Add policykit button */ GtkWidget * polkit_button = gtk_lock_button_new (NULL); @@ -755,8 +756,6 @@ indicator_datetime_panel_init (IndicatorDatetimePanel * self) #undef WIG - g_object_unref (conf); - gtk_widget_show_all (panel); gtk_container_add (GTK_CONTAINER (self), panel); } @@ -769,6 +768,7 @@ indicator_datetime_panel_dispose (GObject * object) g_clear_object (&priv->builder); g_clear_object (&priv->proxy); + g_clear_object (&priv->settings); if (priv->loc_dlg) { gtk_widget_destroy (priv->loc_dlg); diff --git a/src/service.c b/src/service.c index 0d8192a..3340337 100644 --- a/src/service.c +++ b/src/service.c @@ -439,7 +439,7 @@ get_header_label_format_string (IndicatorDatetimeService * self) { gboolean show_day = g_settings_get_boolean (s, SETTINGS_SHOW_DAY_S); gboolean show_date = g_settings_get_boolean (s, SETTINGS_SHOW_DATE_S); - fmt = generate_full_format_string (show_day, show_date); + fmt = generate_full_format_string (show_day, show_date, s); } return fmt; @@ -690,6 +690,7 @@ service_has_alarms (IndicatorDatetimeService * self) static char * get_appointment_time_format (struct IndicatorDatetimeAppt * appt, GDateTime * now, + GSettings * settings, gboolean terse) { char * fmt; @@ -698,7 +699,7 @@ get_appointment_time_format (struct IndicatorDatetimeAppt * appt, if (appt->is_daily) { const char * time_fmt = terse ? get_terse_time_format_string (appt->begin) - : get_full_time_format_string (); + : get_full_time_format_string (settings); fmt = join_date_and_time_format_strings (_("Daily"), time_fmt); } else if (full_day) @@ -710,7 +711,7 @@ get_appointment_time_format (struct IndicatorDatetimeAppt * appt, else { fmt = terse ? generate_terse_format_string_at_time (now, appt->begin) - : generate_full_format_string_at_time (now, appt->begin); + : generate_full_format_string_at_time (now, appt->begin, settings); } return fmt; @@ -730,7 +731,7 @@ add_appointments (IndicatorDatetimeService * self, GMenu * menu, gboolean terse) for (l=appts, i=0; l!=NULL && inext, i++) { struct IndicatorDatetimeAppt * appt = l->data; - char * fmt = get_appointment_time_format (appt, now, terse); + char * fmt = get_appointment_time_format (appt, now, self->priv->settings, terse); const gint64 unix_time = g_date_time_to_unix (appt->begin); GMenuItem * menu_item; @@ -970,7 +971,7 @@ create_locations_section (IndicatorDatetimeService * self) const char * tz = indicator_datetime_timezone_get_timezone (detected_timezones[i]); if (tz && *tz) { - gchar * name = get_current_zone_name (tz); + gchar * name = get_current_zone_name (tz, p->settings); locations = locations_add (locations, tz, name, visible); g_free (name); } @@ -1012,7 +1013,7 @@ create_locations_section (IndicatorDatetimeService * self) detailed_action = g_strdup_printf ("indicator.set-location::%s %s", loc->zone, loc->name); - fmt = generate_full_format_string_at_time (now, loc->local_time); + fmt = generate_full_format_string_at_time (now, loc->local_time, p->settings); menu_item = g_menu_item_new (label, detailed_action); g_menu_item_set_attribute (menu_item, "x-canonical-type", diff --git a/src/utils.c b/src/utils.c index 5b1f58f..f8aa1f8 100644 --- a/src/utils.c +++ b/src/utils.c @@ -82,19 +82,18 @@ split_settings_location (const gchar * location, gchar ** zone, gchar ** name) } gchar * -get_current_zone_name (const gchar * location) +get_current_zone_name (const gchar * location, GSettings * settings) { gchar * new_zone, * new_name; + gchar * tz_name; gchar * old_zone, * old_name; gchar * rv; split_settings_location (location, &new_zone, &new_name); - GSettings * conf = g_settings_new (SETTINGS_INTERFACE); - gchar * tz_name = g_settings_get_string (conf, SETTINGS_TIMEZONE_NAME_S); + tz_name = g_settings_get_string (settings, SETTINGS_TIMEZONE_NAME_S); split_settings_location (tz_name, &old_zone, &old_name); g_free (tz_name); - g_object_unref (conf); // new_name is always just a sanitized version of a timezone. // old_name is potentially a saved "pretty" version of a timezone name from @@ -349,14 +348,13 @@ get_full_date_format_string (gboolean show_day, gboolean show_date) */ const gchar * -get_full_time_format_string (void) +get_full_time_format_string (GSettings * settings) { - GSettings * settings; gboolean twelvehour; gboolean show_seconds; const gchar * fmt; - settings = g_settings_new (SETTINGS_INTERFACE); + g_return_val_if_fail (settings != NULL, NULL); show_seconds = g_settings_get_boolean (settings, SETTINGS_SHOW_SECONDS_S); @@ -370,14 +368,11 @@ get_full_time_format_string (void) twelvehour = FALSE; break; - case TIME_FORMAT_MODE_12_HOUR: - case TIME_FORMAT_MODE_CUSTOM: + default: twelvehour = TRUE; break; } - g_object_unref (settings); - if (twelvehour && show_seconds) /* TRANSLATORS: a strftime(3) format for 12hr time w/seconds */ fmt = T_("%l:%M:%S %p"); @@ -395,19 +390,23 @@ get_full_time_format_string (void) } gchar * -generate_full_format_string (gboolean show_day, gboolean show_date) +generate_full_format_string (gboolean show_day, gboolean show_date, GSettings * settings) { const gchar * date_fmt = get_full_date_format_string (show_day, show_date); - const gchar * time_fmt = get_full_time_format_string (); + const gchar * time_fmt = get_full_time_format_string (settings); return join_date_and_time_format_strings (date_fmt, time_fmt); } gchar * -generate_full_format_string_at_time (GDateTime * now, GDateTime * time) +generate_full_format_string_at_time (GDateTime * now, GDateTime * time, GSettings * settings) { gboolean show_day; gboolean show_date; + g_return_val_if_fail (now != NULL, NULL); + g_return_val_if_fail (time != NULL, NULL); + g_return_val_if_fail (settings != NULL, NULL); + switch (get_date_proximity (now, time)) { case DATE_PROXIMITY_TODAY: @@ -427,6 +426,6 @@ generate_full_format_string_at_time (GDateTime * now, GDateTime * time) break; } - return generate_full_format_string (show_day, show_date); + return generate_full_format_string (show_day, show_date, settings); } diff --git a/src/utils.h b/src/utils.h index 3b0d0a2..fff9194 100644 --- a/src/utils.h +++ b/src/utils.h @@ -33,7 +33,8 @@ void split_settings_location (const char * location, char ** zone, char ** name); -gchar * get_current_zone_name (const char * location); +gchar * get_current_zone_name (const char * location, + GSettings * settings); gchar* join_date_and_time_format_strings (const char * date_fmt, const char * time_fmt); @@ -43,16 +44,18 @@ gchar* join_date_and_time_format_strings (const char * date_fmt, const gchar * get_terse_time_format_string (GDateTime * time); -const gchar * get_full_time_format_string (void); +const gchar * get_full_time_format_string (GSettings * settings); gchar * generate_terse_format_string_at_time (GDateTime * now, GDateTime * time); gchar * generate_full_format_string (gboolean show_day, - gboolean show_date); + gboolean show_date, + GSettings * settings); gchar * generate_full_format_string_at_time (GDateTime * now, - GDateTime * time); + GDateTime * time, + GSettings * settings); G_END_DECLS -- cgit v1.2.3 From 88275c3ae0a002a50a594fb0193805e51f80060d Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sat, 7 Sep 2013 07:45:58 -0500 Subject: remove unnecessary strdup/free of the location menuitems' labels --- src/service.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/service.c b/src/service.c index 2e7b30c..45d152c 100644 --- a/src/service.c +++ b/src/service.c @@ -1030,12 +1030,12 @@ create_locations_section (IndicatorDatetimeService * self) struct TimeLocation * loc = l->data; if (loc->visible) { - char * label; + const char * label; char * detailed_action; char * fmt; GMenuItem * menu_item; - label = g_strdup (loc->name); + label = loc->name; detailed_action = g_strdup_printf ("indicator.set-location::%s %s", loc->zone, loc->name); @@ -1053,7 +1053,6 @@ create_locations_section (IndicatorDatetimeService * self) g_object_unref (menu_item); g_free (fmt); g_free (detailed_action); - g_free (label); } } -- cgit v1.2.3 From f1152966057612e552fb44528bb523e20a61fcac Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sat, 7 Sep 2013 07:46:17 -0500 Subject: remove unnecessary strdup/free of the location menuitems' labels --- src/service.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/service.c b/src/service.c index 45d152c..03a2bb4 100644 --- a/src/service.c +++ b/src/service.c @@ -648,10 +648,8 @@ add_localtime_menuitem (GMenu * menu, static void add_calendar_menuitem (GMenu * menu) { - char * label; GMenuItem * menu_item; - label = g_strdup ("[calendar]"); menu_item = g_menu_item_new ("[calendar]", NULL); g_menu_item_set_action_and_target_value (menu_item, "indicator.calendar", g_variant_new_int64(0)); g_menu_item_set_attribute (menu_item, "x-canonical-type", "s", "com.canonical.indicator.calendar"); @@ -659,7 +657,6 @@ add_calendar_menuitem (GMenu * menu) g_menu_append_item (menu, menu_item); g_object_unref (menu_item); - g_free (label); } static GMenuModel * -- cgit v1.2.3 From 05d0c98b1918fa97369e8b99f6848c19d7b97099 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sat, 7 Sep 2013 09:29:56 -0500 Subject: in service.c's create_locations_section(), remove an unnecessary temporary --- src/service.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/service.c b/src/service.c index 03a2bb4..5d90235 100644 --- a/src/service.c +++ b/src/service.c @@ -1027,18 +1027,16 @@ create_locations_section (IndicatorDatetimeService * self) struct TimeLocation * loc = l->data; if (loc->visible) { - const char * label; char * detailed_action; char * fmt; GMenuItem * menu_item; - label = loc->name; detailed_action = g_strdup_printf ("indicator.set-location::%s %s", loc->zone, loc->name); fmt = generate_full_format_string_at_time (now, loc->local_time); - menu_item = g_menu_item_new (label, detailed_action); + menu_item = g_menu_item_new (loc->name, detailed_action); g_menu_item_set_attribute (menu_item, "x-canonical-type", "s", "com.canonical.indicator.location"); g_menu_item_set_attribute (menu_item, "x-canonical-timezone", -- cgit v1.2.3 From dd147887cb70a52dcba1cd26d9bbf7e29545afc4 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sat, 7 Sep 2013 09:39:38 -0500 Subject: add preliminary unit tests for utils --- src/utils.c | 51 ++++++++++++++---------- tests/Makefile.am | 6 +++ tests/test-utils.cc | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 148 insertions(+), 21 deletions(-) create mode 100644 tests/test-utils.cc diff --git a/src/utils.c b/src/utils.c index b99de94..5dccc52 100644 --- a/src/utils.c +++ b/src/utils.c @@ -53,32 +53,41 @@ is_locale_12h (void) void split_settings_location (const gchar * location, gchar ** zone, gchar ** name) { - gchar * location_dup = g_strdup (location); - gchar * first = strchr (location_dup, ' '); + gchar * location_dup; + gchar * first; - if (first) { - first[0] = 0; - } + location_dup = g_strdup (location); + g_strstrip (location_dup); - if (zone) { - *zone = location_dup; - } + if ((first = strchr (location_dup, ' '))) + *first = '\0'; - if (name) { - gchar * after = first ? g_strstrip (first + 1) : NULL; - if (after == NULL || after[0] == 0) { - /* Make up name from zone */ - gchar * chr = strrchr (location_dup, '/'); - after = g_strdup (chr ? chr + 1 : location_dup); - while ((chr = strchr (after, '_')) != NULL) { /* and turn underscores to spaces */ - *chr = ' '; - } - *name = after; + if (zone != NULL) + { + *zone = location_dup; } - else { - *name = g_strdup (after); + + if (name != NULL) + { + gchar * after = first ? g_strstrip (first + 1) : NULL; + + if (after && *after) + { + *name = g_strdup (after); + } + else /* make the name from zone */ + { + gchar * chr = strrchr (location_dup, '/'); + after = g_strdup (chr ? chr + 1 : location_dup); + + /* replace underscores with spaces */ + for (chr=after; chr && *chr; chr++) + if (*chr == '_') + *chr = ' '; + + *name = after; + } } - } } gchar * diff --git a/tests/Makefile.am b/tests/Makefile.am index dce6076..6435d75 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -50,3 +50,9 @@ test_indicator_CPPFLAGS = $(TEST_CPPFLAGS) -DSCHEMA_DIR="\"$(top_builddir)/tests ### ### ### + +TESTS += test-utils +check_PROGRAMS += test-utils +test_utils_SOURCES = test-utils.cc $(top_srcdir)/src/utils.c +test_utils_LDADD = $(TEST_LIBS) +test_utils_CPPFLAGS = $(TEST_CPPFLAGS) -DSCHEMA_DIR="\"$(top_builddir)/tests/\"" diff --git a/tests/test-utils.cc b/tests/test-utils.cc new file mode 100644 index 0000000..c757a11 --- /dev/null +++ b/tests/test-utils.cc @@ -0,0 +1,112 @@ +/* +Copyright 2012 Canonical Ltd. + +Authors: + Charles Kerr + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License version 3, as published +by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranties of +MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR +PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program. If not, see . +*/ + +#include + +#include + +#include "utils.h" + +/*** +**** +***/ + +TEST (UtilsTest, SplitSettingsLocation) +{ + guint i; + guint n; + + struct { + const char * location; + const char * expected_zone; + const char * expected_name; + } test_cases[] = { + { "America/Chicago Chicago", "America/Chicago", "Chicago" }, + { "America/Chicago Oklahoma City", "America/Chicago", "Oklahoma City" }, + { "America/Los_Angeles", "America/Los_Angeles", "Los Angeles" }, + { "America/Los_Angeles ", "America/Los_Angeles", "Los Angeles" }, + { " America/Los_Angeles", "America/Los_Angeles", "Los Angeles" }, + { " America/Los_Angeles ", "America/Los_Angeles", "Los Angeles" }, + { "UTC UTC", "UTC", "UTC" } + }; + + for (i=0, n=G_N_ELEMENTS(test_cases); i Date: Sat, 7 Sep 2013 09:48:46 -0500 Subject: get coverage reports working. We now have nonzero coverage, whoo --- src/Makefile.am | 83 +++++++++++++++++++++++++++++++++++-------------------- tests/Makefile.am | 4 +-- 2 files changed, 55 insertions(+), 32 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 2f247c1..093a258 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,44 +1,67 @@ -if BUILD_CCPANEL -ccpaneldir = $(libdir)/control-center-1/panels/ -ccpanel_LTLIBRARIES = libindicator-datetime.la -endif +SHARED_CFLAGS = \ + -Wall \ + -Wextra -Wno-missing-field-initializers \ + -Werror \ + $(SERVICE_CFLAGS) \ + $(COVERAGE_CFLAGS) \ + -DTIMEZONE_FILE="\"/etc/timezone\"" \ + -DG_LOG_DOMAIN=\"Indicator-Datetime\" + +### +### +### + +noinst_LIBRARIES = libindicator-datetime-service.a + +libindicator_datetime_service_a_CFLAGS = \ + $(SHARED_CFLAGS) + +libindicator_datetime_service_a_SOURCES = \ + planner.c \ + planner.h \ + planner-eds.c \ + planner-eds.h \ + service.c \ + service.h \ + timezone.c \ + timezone.h \ + timezone-file.c \ + timezone-file.h \ + timezone-geoclue.c \ + timezone-geoclue.h \ + utils.c \ + utils.h \ + dbus-shared.h \ + settings-shared.h + +### +### +### libexec_PROGRAMS = indicator-datetime-service indicator_datetime_service_SOURCES = \ - planner.c \ - planner.h \ - planner-eds.c \ - planner-eds.h \ - service.c \ - service.h \ - main.c \ - timezone.c \ - timezone.h \ - timezone-file.c \ - timezone-file.h \ - timezone-geoclue.c \ - timezone-geoclue.h \ - utils.c \ - utils.h \ - dbus-shared.h \ - settings-shared.h + main.c indicator_datetime_service_CFLAGS = \ - -Wall \ - -Wextra -Wno-missing-field-initializers \ - -Werror \ - $(SERVICE_CFLAGS) \ - $(COVERAGE_CFLAGS) \ - -DTIMEZONE_FILE="\"/etc/timezone\"" \ - -DG_LOG_DOMAIN=\"Indicator-Datetime\" + $(SHARED_CFLAGS) + indicator_datetime_service_LDADD = \ - $(SERVICE_LIBS) + libindicator-datetime-service.a \ + $(SERVICE_LIBS) + indicator_datetime_service_LDFLAGS = \ - $(COVERAGE_LDFLAGS) + $(COVERAGE_LDFLAGS) + +### +### +### if BUILD_CCPANEL +ccpaneldir = $(libdir)/control-center-1/panels/ +ccpanel_LTLIBRARIES = libindicator-datetime.la + libindicator_datetime_la_SOURCES =\ datetime-prefs.c \ datetime-prefs-locations.c \ diff --git a/tests/Makefile.am b/tests/Makefile.am index 6435d75..e204378 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -53,6 +53,6 @@ test_indicator_CPPFLAGS = $(TEST_CPPFLAGS) -DSCHEMA_DIR="\"$(top_builddir)/tests TESTS += test-utils check_PROGRAMS += test-utils -test_utils_SOURCES = test-utils.cc $(top_srcdir)/src/utils.c -test_utils_LDADD = $(TEST_LIBS) +test_utils_SOURCES = test-utils.cc +test_utils_LDADD = $(top_builddir)/src/libindicator-datetime-service.a $(TEST_LIBS) test_utils_CPPFLAGS = $(TEST_CPPFLAGS) -DSCHEMA_DIR="\"$(top_builddir)/tests/\"" -- cgit v1.2.3 From fde292a8ff3c830ea27f3a11f45e959596fede09 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Sun, 8 Sep 2013 13:17:08 -0500 Subject: Bad merge --- src/planner.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/planner.c b/src/planner.c index 17cc55b..e826c2c 100644 --- a/src/planner.c +++ b/src/planner.c @@ -188,6 +188,8 @@ indicator_datetime_planner_get_appointments (IndicatorDatetimePlanner * self, IndicatorDatetimePlannerClass * klass; g_return_if_fail (INDICATOR_IS_DATETIME_PLANNER (self)); + g_return_val_if_fail (begin != NULL, NULL); + g_return_val_if_fail (end != NULL, NULL); klass = INDICATOR_DATETIME_PLANNER_GET_CLASS (self); g_return_if_fail (klass->get_appointments != NULL); @@ -203,8 +205,6 @@ indicator_datetime_planner_get_appointments_finish (IndicatorDatetimePlanner * GSList * appointments; g_return_val_if_fail (INDICATOR_IS_DATETIME_PLANNER (self), NULL); - g_return_val_if_fail (begin != NULL, NULL); - g_return_val_if_fail (end != NULL, NULL); klass = INDICATOR_DATETIME_PLANNER_GET_CLASS (self); g_return_val_if_fail (klass->get_appointments_finish != NULL, NULL); -- cgit v1.2.3 From 2bf6740a420f35942e9f74b7f7ef566de0ba736b Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 9 Sep 2013 11:53:10 -0500 Subject: in utils.h, include gio/gio.h to ensure GSettings struct is declared --- src/utils.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/utils.h b/src/utils.h index fff9194..31a12bc 100644 --- a/src/utils.h +++ b/src/utils.h @@ -24,6 +24,7 @@ with this program. If not, see . #define __DATETIME_UTILS_H__ #include +#include /* GSettings */ G_BEGIN_DECLS -- cgit v1.2.3 From cd6fa3bab97768ef37ac4d6e2499f1a45aae596f Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 9 Sep 2013 12:43:31 -0500 Subject: in the Datetime base class, make a set_timezone() function for subclasses s.t. they don't have to reinvent the wheel. As a result, also remove the 'timezone changed' signale emitter helper --- src/timezone-file.c | 44 +++++++++----------------------------------- src/timezone-geoclue.c | 39 ++------------------------------------- src/timezone.c | 46 ++++++++++++++++++++++++++++++++++++---------- src/timezone.h | 8 ++++---- 4 files changed, 51 insertions(+), 86 deletions(-) diff --git a/src/timezone-file.c b/src/timezone-file.c index 2adf2ca..698ce3e 100644 --- a/src/timezone-file.c +++ b/src/timezone-file.c @@ -35,9 +35,7 @@ static GParamSpec * properties[PROP_LAST] = { 0 }; struct _IndicatorDatetimeTimezoneFilePriv { gchar * filename; - GFile * file; GFileMonitor * monitor; - gchar * timezone; }; typedef IndicatorDatetimeTimezoneFilePriv priv_t; @@ -56,26 +54,18 @@ reload (IndicatorDatetimeTimezoneFile * self) priv_t * p = self->priv; GError * err = NULL; - gchar * new_timezone = NULL; + gchar * timezone = NULL; - if (!g_file_get_contents (p->filename, &new_timezone, NULL, &err)) + if (!g_file_get_contents (p->filename, &timezone, NULL, &err)) { g_warning ("%s Unable to read timezone file '%s': %s", G_STRLOC, p->filename, err->message); g_error_free (err); } else { - g_strstrip (new_timezone); - - if (g_strcmp0 (p->timezone, new_timezone)) - { - g_free (p->timezone); - p->timezone = g_strdup (new_timezone); - g_debug ("%s new timezone set: '%s'", G_STRLOC, p->timezone); - indicator_datetime_timezone_notify_timezone (INDICATOR_DATETIME_TIMEZONE(self)); - } - - g_free (new_timezone); + g_strstrip (timezone); + indicator_datetime_timezone_set_timezone (INDICATOR_DATETIME_TIMEZONE(self), timezone); + g_free (timezone); } } @@ -83,17 +73,17 @@ static void set_filename (IndicatorDatetimeTimezoneFile * self, const char * filename) { GError * err; + GFile * file; priv_t * p = self->priv; g_clear_object (&p->monitor); - g_clear_object (&p->file); g_free (p->filename); p->filename = g_strdup (filename); - p->file = g_file_new_for_path (p->filename); - err = NULL; - p->monitor = g_file_monitor_file (p->file, G_FILE_MONITOR_NONE, NULL, &err); + file = g_file_new_for_path (p->filename); + p->monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, &err); + g_object_unref (file); if (err != NULL) { g_warning ("%s Unable to monitor timezone file '%s': %s", G_STRLOC, TIMEZONE_FILE, err->message); @@ -108,16 +98,6 @@ set_filename (IndicatorDatetimeTimezoneFile * self, const char * filename) reload (self); } -/*** -**** IndicatorDatetimeTimezoneClass funcs -***/ - -static const char * -my_get_timezone (IndicatorDatetimeTimezone * self) -{ - return INDICATOR_DATETIME_TIMEZONE_FILE(self)->priv->timezone; -} - /*** **** GObjectClass funcs ***/ @@ -167,7 +147,6 @@ my_dispose (GObject * o) priv_t * p = self->priv; g_clear_object (&p->monitor); - g_clear_object (&p->file); G_OBJECT_CLASS (indicator_datetime_timezone_file_parent_class)->dispose (o); } @@ -179,7 +158,6 @@ my_finalize (GObject * o) priv_t * p = self->priv; g_free (p->filename); - g_free (p->timezone); G_OBJECT_CLASS (indicator_datetime_timezone_file_parent_class)->finalize (o); } @@ -192,7 +170,6 @@ static void indicator_datetime_timezone_file_class_init (IndicatorDatetimeTimezoneFileClass * klass) { GObjectClass * object_class; - IndicatorDatetimeTimezoneClass * location_class; const GParamFlags flags = G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS; object_class = G_OBJECT_CLASS (klass); @@ -201,9 +178,6 @@ indicator_datetime_timezone_file_class_init (IndicatorDatetimeTimezoneFileClass object_class->set_property = my_set_property; object_class->get_property = my_get_property; - location_class = INDICATOR_DATETIME_TIMEZONE_CLASS (klass); - location_class->get_timezone = my_get_timezone; - g_type_class_add_private (klass, sizeof (IndicatorDatetimeTimezoneFilePriv)); /* install properties */ diff --git a/src/timezone-geoclue.c b/src/timezone-geoclue.c index f7dcf5c..c89558d 100644 --- a/src/timezone-geoclue.c +++ b/src/timezone-geoclue.c @@ -29,7 +29,6 @@ struct _IndicatorDatetimeTimezoneGeocluePriv GeoclueMaster * master; GeoclueMasterClient * client; GeoclueAddress * address; - gchar * timezone; }; typedef IndicatorDatetimeTimezoneGeocluePriv priv_t; @@ -44,19 +43,6 @@ static void geo_restart (IndicatorDatetimeTimezoneGeoclue * self); **** ***/ -static void -set_timezone (IndicatorDatetimeTimezoneGeoclue * self, const gchar * timezone) -{ - priv_t * p = self->priv; - - if (g_strcmp0 (p->timezone, timezone)) - { - g_free (p->timezone); - p->timezone = g_strdup (timezone); - indicator_datetime_timezone_notify_timezone (INDICATOR_DATETIME_TIMEZONE(self)); - } -} - static void on_address_changed (GeoclueAddress * address G_GNUC_UNUSED, int timestamp G_GNUC_UNUSED, @@ -73,7 +59,7 @@ on_address_changed (GeoclueAddress * address G_GNUC_UNUSED, { IndicatorDatetimeTimezoneGeoclue * self = INDICATOR_DATETIME_TIMEZONE_GEOCLUE (gself); const char * timezone = g_hash_table_lookup (addy_data, "timezone"); - set_timezone (self, timezone); + indicator_datetime_timezone_set_timezone (INDICATOR_DATETIME_TIMEZONE(self), timezone); } } @@ -197,12 +183,6 @@ geo_restart (IndicatorDatetimeTimezoneGeoclue * self) **** ***/ -static const char * -my_get_timezone (IndicatorDatetimeTimezone * self) -{ - return INDICATOR_DATETIME_TIMEZONE_GEOCLUE(self)->priv->timezone; -} - static void my_dispose (GObject * o) { @@ -211,29 +191,13 @@ my_dispose (GObject * o) G_OBJECT_CLASS (indicator_datetime_timezone_geoclue_parent_class)->dispose (o); } -static void -my_finalize (GObject * o) -{ - IndicatorDatetimeTimezoneGeoclue * self = INDICATOR_DATETIME_TIMEZONE_GEOCLUE (o); - priv_t * p = self->priv; - - g_free (p->timezone); - - G_OBJECT_CLASS (indicator_datetime_timezone_geoclue_parent_class)->finalize (o); -} - static void indicator_datetime_timezone_geoclue_class_init (IndicatorDatetimeTimezoneGeoclueClass * klass) { GObjectClass * object_class; - IndicatorDatetimeTimezoneClass * location_class; object_class = G_OBJECT_CLASS (klass); object_class->dispose = my_dispose; - object_class->finalize = my_finalize; - - location_class = INDICATOR_DATETIME_TIMEZONE_CLASS (klass); - location_class->get_timezone = my_get_timezone; g_type_class_add_private (klass, sizeof (IndicatorDatetimeTimezoneGeocluePriv)); } @@ -246,6 +210,7 @@ indicator_datetime_timezone_geoclue_init (IndicatorDatetimeTimezoneGeoclue * sel p = G_TYPE_INSTANCE_GET_PRIVATE (self, INDICATOR_TYPE_DATETIME_TIMEZONE_GEOCLUE, IndicatorDatetimeTimezoneGeocluePriv); + self->priv = p; geo_start (self); diff --git a/src/timezone.c b/src/timezone.c index a543155..a21ee8c 100644 --- a/src/timezone.c +++ b/src/timezone.c @@ -32,6 +32,13 @@ enum static GParamSpec * properties[PROP_LAST] = { 0, }; +struct _IndicatorDatetimeTimezonePriv +{ + GString * timezone; +}; + +typedef struct _IndicatorDatetimeTimezonePriv priv_t; + static void my_get_property (GObject * o, guint property_id, @@ -52,9 +59,13 @@ my_get_property (GObject * o, } static void -my_dispose (GObject * object) +my_finalize (GObject * o) { - G_OBJECT_CLASS (indicator_datetime_timezone_parent_class)->dispose (object); + priv_t * p = INDICATOR_DATETIME_TIMEZONE(o)->priv; + + g_string_free (p->timezone, TRUE); + + G_OBJECT_CLASS (indicator_datetime_timezone_parent_class)->dispose (o); } static void @@ -64,11 +75,11 @@ indicator_datetime_timezone_class_init (IndicatorDatetimeTimezoneClass * klass) GObjectClass * object_class; const GParamFlags flags = G_PARAM_READABLE | G_PARAM_STATIC_STRINGS; + g_type_class_add_private (klass, sizeof (IndicatorDatetimeTimezonePriv)); + object_class = G_OBJECT_CLASS (klass); object_class->get_property = my_get_property; - object_class->dispose = my_dispose; - - klass->get_timezone = NULL; + object_class->finalize = my_finalize; properties[PROP_TIMEZONE] = g_param_spec_string ("timezone", "Timezone", @@ -80,8 +91,17 @@ indicator_datetime_timezone_class_init (IndicatorDatetimeTimezoneClass * klass) } static void -indicator_datetime_timezone_init (IndicatorDatetimeTimezone * self G_GNUC_UNUSED) +indicator_datetime_timezone_init (IndicatorDatetimeTimezone * self) { + priv_t * p; + + p = G_TYPE_INSTANCE_GET_PRIVATE (self, + INDICATOR_TYPE_DATETIME_TIMEZONE, + IndicatorDatetimeTimezonePriv); + + p->timezone = g_string_new (NULL); + + self->priv = p; } /*** @@ -93,13 +113,19 @@ indicator_datetime_timezone_get_timezone (IndicatorDatetimeTimezone * self) { g_return_val_if_fail (INDICATOR_IS_DATETIME_TIMEZONE (self), NULL); - return INDICATOR_DATETIME_TIMEZONE_GET_CLASS (self)->get_timezone (self); + return self->priv->timezone->str; } void -indicator_datetime_timezone_notify_timezone (IndicatorDatetimeTimezone * self) +indicator_datetime_timezone_set_timezone (IndicatorDatetimeTimezone * self, + const char * timezone) { - g_return_if_fail (INDICATOR_IS_DATETIME_TIMEZONE (self)); + priv_t * p = self->priv; - g_object_notify_by_pspec (G_OBJECT(self), properties[PROP_TIMEZONE]); + if (g_strcmp0 (p->timezone->str, timezone)) + { + g_string_assign (p->timezone, timezone); + g_debug ("%s new timezone set: '%s'", G_STRLOC, timezone); + g_object_notify_by_pspec (G_OBJECT(self), properties[PROP_TIMEZONE]); + } } diff --git a/src/timezone.h b/src/timezone.h index 076bedc..aaaa296 100644 --- a/src/timezone.h +++ b/src/timezone.h @@ -32,6 +32,7 @@ G_BEGIN_DECLS #define INDICATOR_IS_DATETIME_TIMEZONE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), INDICATOR_TYPE_DATETIME_TIMEZONE)) typedef struct _IndicatorDatetimeTimezone IndicatorDatetimeTimezone; +typedef struct _IndicatorDatetimeTimezonePriv IndicatorDatetimeTimezonePriv; typedef struct _IndicatorDatetimeTimezoneClass IndicatorDatetimeTimezoneClass; GType indicator_datetime_timezone_get_type (void); @@ -51,14 +52,12 @@ struct _IndicatorDatetimeTimezone { /*< private >*/ GObject parent; + IndicatorDatetimeTimezonePriv * priv; }; struct _IndicatorDatetimeTimezoneClass { GObjectClass parent_class; - - /* virtual functions */ - const char * (*get_timezone) (IndicatorDatetimeTimezone * self); }; /*** @@ -67,7 +66,8 @@ struct _IndicatorDatetimeTimezoneClass const char * indicator_datetime_timezone_get_timezone (IndicatorDatetimeTimezone *); -void indicator_datetime_timezone_notify_timezone (IndicatorDatetimeTimezone *); +void indicator_datetime_timezone_set_timezone (IndicatorDatetimeTimezone *, + const char * new_timezone); G_END_DECLS -- cgit v1.2.3 From 0b5af4aca455466f64f855e4328cd29ee15e7548 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 9 Sep 2013 12:56:22 -0500 Subject: fix typo --- src/timezone.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/timezone.c b/src/timezone.c index a21ee8c..ca207f2 100644 --- a/src/timezone.c +++ b/src/timezone.c @@ -65,7 +65,7 @@ my_finalize (GObject * o) g_string_free (p->timezone, TRUE); - G_OBJECT_CLASS (indicator_datetime_timezone_parent_class)->dispose (o); + G_OBJECT_CLASS (indicator_datetime_timezone_parent_class)->finalize (o); } static void -- cgit v1.2.3 From 06d21070a78bdcaac4b1b23384ae5791f8d0f5ff Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 11 Sep 2013 11:34:31 -0500 Subject: add 'title' to the root action's state dict --- src/service.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/service.c b/src/service.c index 0928205..3ba1c24 100644 --- a/src/service.c +++ b/src/service.c @@ -453,6 +453,7 @@ create_desktop_header_state (IndicatorDatetimeService * self) gchar * str; gboolean visible; GDateTime * now; + const gchar * title = _("Date and Time"); visible = g_settings_get_boolean (self->priv->settings, SETTINGS_SHOW_CLOCK_S); @@ -469,6 +470,7 @@ create_desktop_header_state (IndicatorDatetimeService * self) g_variant_builder_init (&b, G_VARIANT_TYPE_VARDICT); g_variant_builder_add (&b, "{sv}", "accessible-desc", g_variant_new_string (str)); g_variant_builder_add (&b, "{sv}", "label", g_variant_new_take_string (str)); + g_variant_builder_add (&b, "{sv}", "title", g_variant_new_string (title)); g_variant_builder_add (&b, "{sv}", "visible", g_variant_new_boolean (visible)); /* cleanup */ @@ -489,6 +491,7 @@ create_phone_header_state (IndicatorDatetimeService * self) gchar * label; gboolean has_alarms; gchar * a11y; + const gchar * title = _("Date and Time"); g_variant_builder_init (&b, G_VARIANT_TYPE_VARDICT); @@ -515,6 +518,7 @@ create_phone_header_state (IndicatorDatetimeService * self) g_variant_new_take_string (a11y)); g_variant_builder_add (&b, "{sv}", "visible", g_variant_new_boolean (TRUE)); + g_variant_builder_add (&b, "{sv}", "title", g_variant_new_string (title)); g_variant_builder_add (&b, "{sv}", "label", g_variant_new_take_string (label)); /* cleanup */ -- cgit v1.2.3 From 9233c969e7fe1de9442b233258a183466b5f068a Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 11 Sep 2013 12:12:10 -0500 Subject: in the phone profile, move the day-of-week entry from the first menuitem to the header action state's title as per the spec --- src/service.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/service.c b/src/service.c index 3ba1c24..ce8139f 100644 --- a/src/service.c +++ b/src/service.c @@ -491,7 +491,7 @@ create_phone_header_state (IndicatorDatetimeService * self) gchar * label; gboolean has_alarms; gchar * a11y; - const gchar * title = _("Date and Time"); + gchar * title; g_variant_builder_init (&b, G_VARIANT_TYPE_VARDICT); @@ -518,9 +518,12 @@ create_phone_header_state (IndicatorDatetimeService * self) g_variant_new_take_string (a11y)); g_variant_builder_add (&b, "{sv}", "visible", g_variant_new_boolean (TRUE)); - g_variant_builder_add (&b, "{sv}", "title", g_variant_new_string (title)); g_variant_builder_add (&b, "{sv}", "label", g_variant_new_take_string (label)); + /* title is day-of-week */ + title = g_date_time_format (now, _("%A")); + g_variant_builder_add (&b, "{sv}", "title", g_variant_new_take_string (title)); + /* cleanup */ g_date_time_unref (now); return g_variant_builder_end (&b); @@ -651,9 +654,6 @@ create_phone_calendar_section (IndicatorDatetimeService * self) { GMenu * menu = g_menu_new (); - /* strftime(3) format string to show day of week */ - add_localtime_menuitem (menu, self, _("%A"), NULL); - /* strftime(3) format string to show date */ add_localtime_menuitem (menu, self, _("%e %B %Y"), "calendar"); -- cgit v1.2.3 From 67f71fb0f277f1a4ad9f7551732cede667c2849c Mon Sep 17 00:00:00 2001 From: Automatic PS uploader Date: Fri, 13 Sep 2013 15:16:38 +0000 Subject: Releasing 13.10.0+13.10.20130913-0ubuntu1, based on r256 --- debian/changelog | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/debian/changelog b/debian/changelog index d2bd251..03a19db 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,27 @@ +indicator-datetime (13.10.0+13.10.20130913-0ubuntu1) saucy; urgency=low + + [ Charles Kerr ] + * Make the EDS planner nonblocking. (LP: #1204532) + * Minor changes that eliminate unnecessary temporary strings. + * This change adds a GSettings* arg to the utils functions so that + they don't have to churn through temporary GSettings objects. These + functions are usually called in a loop, causing a lot of GSettings + temporaries, even though the calling code already has an instance + for that GSettings schema. + * name says it all; this branch is for improving indicator-datetime + test coverage. + * Remove code duplication between timezone-file and timezone-geoclue. + * Adds a title in the header's action state. (LP: #1223635) + + [ Ted Gould ] + * Fix GeoClue signal handler to have proper prototype. (LP: #1195874) + * Protect against invalid begin or end dates. (LP: #1216263) + + [ Ubuntu daily release ] + * Automatic snapshot from revision 256 + + -- Ubuntu daily release Fri, 13 Sep 2013 15:16:38 +0000 + indicator-datetime (13.10.0+13.10.20130903-0ubuntu1) saucy; urgency=low [ Jeremy Bicha ] -- cgit v1.2.3 From e221b04f893a6e8c0e70106fd54342b318f3f26e Mon Sep 17 00:00:00 2001 From: Timo Jyrinki Date: Mon, 23 Sep 2013 07:32:05 +0300 Subject: Add X-Ubuntu-Gettext-Domain in .desktop file to use translations (LP: #1223498) --- data/gnome-indicator-datetime-panel.desktop.in | 1 + 1 file changed, 1 insertion(+) diff --git a/data/gnome-indicator-datetime-panel.desktop.in b/data/gnome-indicator-datetime-panel.desktop.in index 68571db..b7202b4 100644 --- a/data/gnome-indicator-datetime-panel.desktop.in +++ b/data/gnome-indicator-datetime-panel.desktop.in @@ -10,3 +10,4 @@ Type=Application Categories=GNOME;GTK;Utility;DesktopSettings;Settings;X-GNOME-SystemSettings;X-GNOME-Settings-Panel; X-GNOME-Settings-Panel=indicator-datetime OnlyShowIn=Unity; +X-Ubuntu-Gettext-Domain=indicator-datetime -- cgit v1.2.3 From 244b8007da33ee7bbaa66eb4da12f9db0001d51c Mon Sep 17 00:00:00 2001 From: Automatic PS uploader Date: Tue, 24 Sep 2013 08:58:52 +0000 Subject: Releasing 13.10.0+13.10.20130924.2-0ubuntu1, based on r258 --- debian/changelog | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/debian/changelog b/debian/changelog index 03a19db..69b0521 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,14 @@ +indicator-datetime (13.10.0+13.10.20130924.2-0ubuntu1) saucy; urgency=low + + [ Timo Jyrinki ] + * Add X-Ubuntu-Gettext-Domain in .desktop file to use translations + (LP: #1223498). (LP: #1223498) + + [ Ubuntu daily release ] + * Automatic snapshot from revision 258 + + -- Ubuntu daily release Tue, 24 Sep 2013 08:58:52 +0000 + indicator-datetime (13.10.0+13.10.20130913-0ubuntu1) saucy; urgency=low [ Charles Kerr ] -- cgit v1.2.3 From 158a962cee927c7b4cb9a70266681886a8895b48 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 25 Sep 2013 17:16:22 -0500 Subject: Use url-dispatcher instead of invoking system-settings directly. --- configure.ac | 14 ++++++++------ debian/control | 1 + src/service.c | 3 ++- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/configure.ac b/configure.ac index c165a3b..8b95695 100644 --- a/configure.ac +++ b/configure.ac @@ -51,15 +51,17 @@ GEOCLUE_REQUIRED_VERSION=0.12.0 ICAL_REQUIRED_VERSION=0.48 ECAL_REQUIRED_VERSION=3.5 EDS_REQUIRED_VERSION=3.5 +URL_DISPATCHER_1_REQUIRED_VERSION=1 GTK3_REQUIRED_VERSION=3.1.4 -PKG_CHECK_MODULES(SERVICE, glib-2.0 >= $GLIB_REQUIRED_VERSION - gio-2.0 >= $GIO_REQUIRED_VERSION - geoclue >= $GEOCLUE_REQUIRED_VERSION - libical >= $ICAL_REQUIRED_VERSION - libecal-1.2 >= $ECAL_REQUIRED_VERSION - libedataserver-1.2 >= EDS_REQUIRED_VERSION) +PKG_CHECK_MODULES(SERVICE, [glib-2.0 >= $GLIB_REQUIRED_VERSION + gio-2.0 >= $GIO_REQUIRED_VERSION + geoclue >= $GEOCLUE_REQUIRED_VERSION + libical >= $ICAL_REQUIRED_VERSION + libecal-1.2 >= $ECAL_REQUIRED_VERSION + libedataserver-1.2 >= EDS_REQUIRED_VERSION + url-dispatcher-1 >= URL_DISPATCHER_1_REQUIRED_VERSION]) ########################### # Control Center panel diff --git a/debian/control b/debian/control index ae07129..67938bf 100644 --- a/debian/control +++ b/debian/control @@ -22,6 +22,7 @@ Build-Depends: debhelper (>= 9), libgconf2-dev (>= 2.31), libgnome-control-center-dev, libtimezonemap1-dev, + liburl-dispatcher1-dev, Standards-Version: 3.9.3 Homepage: https://launchpad.net/indicator-datetime # If you aren't a member of ~indicator-applet-developers but need to upload diff --git a/src/service.c b/src/service.c index ce8139f..2528f41 100644 --- a/src/service.c +++ b/src/service.c @@ -24,6 +24,7 @@ #include #include +#include #include "dbus-shared.h" #include "planner-eds.h" @@ -1282,7 +1283,7 @@ on_phone_settings_activated (GSimpleAction * a G_GNUC_UNUSED, GVariant * param G_GNUC_UNUSED, gpointer gself G_GNUC_UNUSED) { - execute_command ("system-settings time-date"); + url_dispatch_send ("settings://system/time-date", NULL, NULL); } static void -- cgit v1.2.3 From 0f52c0f5344ccb91157541301f91b4ca9087948f Mon Sep 17 00:00:00 2001 From: Automatic PS uploader Date: Mon, 30 Sep 2013 06:32:59 +0000 Subject: Releasing 13.10.0+13.10.20130930-0ubuntu1, based on r260 --- debian/changelog | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/debian/changelog b/debian/changelog index 69b0521..3ac0eaa 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,14 @@ +indicator-datetime (13.10.0+13.10.20130930-0ubuntu1) saucy; urgency=low + + [ Charles Kerr ] + * Use url-dispatcher instead of invoking system-settings directly. + (LP: #1230819) + + [ Ubuntu daily release ] + * Automatic snapshot from revision 260 + + -- Ubuntu daily release Mon, 30 Sep 2013 06:32:59 +0000 + indicator-datetime (13.10.0+13.10.20130924.2-0ubuntu1) saucy; urgency=low [ Timo Jyrinki ] -- cgit v1.2.3 From 68e0937c7bcee9bc0d6b29e7de136c3b2762d495 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 3 Oct 2013 08:04:46 -0500 Subject: remove the leading zero in the hour component of 'terse' time format. --- src/utils.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils.c b/src/utils.c index 9b0f24f..bbb24ac 100644 --- a/src/utils.c +++ b/src/utils.c @@ -301,8 +301,8 @@ get_terse_time_format_string (GDateTime * time) if (g_date_time_get_minute (time) != 0) { - /* a strftime(3) fmt string for a HH:MM 12 hour time, eg "06:59 PM" */ - fmt = T_("%I:%M %p"); + /* a strftime(3) fmt string for a H:MM 12 hour time, eg "6:59 PM" */ + fmt = T_("%l:%M %p"); } else { -- cgit v1.2.3 From 5b22711fc71e6d0eb5dc8075cb7446b71b7549e1 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 3 Oct 2013 09:36:25 -0500 Subject: sync unit tests to not look for the leading zero --- tests/test-utils.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/test-utils.cc b/tests/test-utils.cc index c757a11..d0f277b 100644 --- a/tests/test-utils.cc +++ b/tests/test-utils.cc @@ -78,12 +78,12 @@ TEST (UtilsTest, GenerateTerseFormatString) GDateTime * time; const char * expected_format_string; } test_cases[] = { - { g_date_time_ref(arbitrary_day), g_date_time_ref(arbitrary_day), "%I:%M %p" }, /* identical time */ - { g_date_time_ref(arbitrary_day), g_date_time_add_hours(arbitrary_day,1), "%I:%M %p" }, /* later today */ - { g_date_time_ref(arbitrary_day), g_date_time_add_days(arbitrary_day,1), "Tomorrow" EM_SPACE "%I:%M %p" }, /* tomorrow */ - { g_date_time_ref(arbitrary_day), g_date_time_add_days(arbitrary_day,2), "%a" EM_SPACE "%I:%M %p" }, - { g_date_time_ref(arbitrary_day), g_date_time_add_days(arbitrary_day,6), "%a" EM_SPACE "%I:%M %p" }, - { g_date_time_ref(arbitrary_day), g_date_time_add_days(arbitrary_day,7), "%d %b" EM_SPACE "%I:%M %p" }, /* over one week away */ + { g_date_time_ref(arbitrary_day), g_date_time_ref(arbitrary_day), "%l:%M %p" }, /* identical time */ + { g_date_time_ref(arbitrary_day), g_date_time_add_hours(arbitrary_day,1), "%l:%M %p" }, /* later today */ + { g_date_time_ref(arbitrary_day), g_date_time_add_days(arbitrary_day,1), "Tomorrow" EM_SPACE "%l:%M %p" }, /* tomorrow */ + { g_date_time_ref(arbitrary_day), g_date_time_add_days(arbitrary_day,2), "%a" EM_SPACE "%l:%M %p" }, + { g_date_time_ref(arbitrary_day), g_date_time_add_days(arbitrary_day,6), "%a" EM_SPACE "%l:%M %p" }, + { g_date_time_ref(arbitrary_day), g_date_time_add_days(arbitrary_day,7), "%d %b" EM_SPACE "%l:%M %p" }, /* over one week away */ { g_date_time_ref(on_the_hour), g_date_time_ref(on_the_hour), "%l %p" }, /* identical time */ { g_date_time_ref(on_the_hour), g_date_time_add_hours(on_the_hour,1), "%l %p" }, /* later today */ -- cgit v1.2.3 From 55108acdde8854c7e6846da9152165dfec3be69d Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 3 Oct 2013 15:53:56 -0500 Subject: Update settings URL to settings:///system --- src/service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/service.c b/src/service.c index 2528f41..f2b2768 100644 --- a/src/service.c +++ b/src/service.c @@ -1283,7 +1283,7 @@ on_phone_settings_activated (GSimpleAction * a G_GNUC_UNUSED, GVariant * param G_GNUC_UNUSED, gpointer gself G_GNUC_UNUSED) { - url_dispatch_send ("settings://system/time-date", NULL, NULL); + url_dispatch_send ("settings:///system/time-date", NULL, NULL); } static void -- cgit v1.2.3 From d9deaaaeb8c09db33539b498effe88b549d15b0f Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 3 Oct 2013 16:16:24 -0500 Subject: phone: show appointments at 1AM as '1 AM', clock times as '1:00 AM' --- src/service.c | 2 +- src/utils.c | 10 ++++++++-- src/utils.h | 2 ++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/service.c b/src/service.c index 2528f41..ee00723 100644 --- a/src/service.c +++ b/src/service.c @@ -498,7 +498,7 @@ create_phone_header_state (IndicatorDatetimeService * self) /* label */ now = indicator_datetime_service_get_localtime (self); - fmt = get_terse_time_format_string (now); + fmt = get_terse_header_time_format_string (); label = g_date_time_format (now, fmt); /* icon */ diff --git a/src/utils.c b/src/utils.c index bbb24ac..60fd393 100644 --- a/src/utils.c +++ b/src/utils.c @@ -294,6 +294,13 @@ get_terse_date_format_string (date_proximity_t proximity) return fmt; } +const gchar* +get_terse_header_time_format_string (void) +{ + /* a strftime(3) fmt string for a H:MM 12 hour time, eg "6:59 PM" */ + return T_("%l:%M %p"); +} + const gchar * get_terse_time_format_string (GDateTime * time) { @@ -301,8 +308,7 @@ get_terse_time_format_string (GDateTime * time) if (g_date_time_get_minute (time) != 0) { - /* a strftime(3) fmt string for a H:MM 12 hour time, eg "6:59 PM" */ - fmt = T_("%l:%M %p"); + fmt = get_terse_header_time_format_string (); } else { diff --git a/src/utils.h b/src/utils.h index 31a12bc..24eddb6 100644 --- a/src/utils.h +++ b/src/utils.h @@ -45,6 +45,8 @@ gchar* join_date_and_time_format_strings (const char * date_fmt, const gchar * get_terse_time_format_string (GDateTime * time); +const gchar * get_terse_header_time_format_string (void); + const gchar * get_full_time_format_string (GSettings * settings); gchar * generate_terse_format_string_at_time (GDateTime * now, -- cgit v1.2.3 From d3ae965a5bdc7d82aeff4ad515bad8c1f74bcaf9 Mon Sep 17 00:00:00 2001 From: Automatic PS uploader Date: Fri, 4 Oct 2013 02:29:27 +0000 Subject: Releasing 13.10.0+13.10.20131004-0ubuntu1, based on r264 --- debian/changelog | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/debian/changelog b/debian/changelog index 3ac0eaa..918b53c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,18 @@ +indicator-datetime (13.10.0+13.10.20131004-0ubuntu1) saucy; urgency=low + + [ Charles Kerr ] + * Change the tablet time format string to remove leading zeroes from + the hour component of the time format (ie, H:MM rather than HH:MM). + (LP: #1234483) + * on the phone, show appointments at 1AM as '1 AM', clock times as + '1:00 AM'. (LP: #1220297) + * Update settings URL to settings:///system. (LP: #1231444) + + [ Ubuntu daily release ] + * Automatic snapshot from revision 264 + + -- Ubuntu daily release Fri, 04 Oct 2013 02:29:26 +0000 + indicator-datetime (13.10.0+13.10.20130930-0ubuntu1) saucy; urgency=low [ Charles Kerr ] -- cgit v1.2.3 From 4a65017c75fdd77cb24ada70a2c817c28c2cfa01 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Fri, 4 Oct 2013 09:29:29 -0500 Subject: start tracking failure-to-connect-to-bus on indicator-datetime --- src/service.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/service.c b/src/service.c index 2528f41..0be73f5 100644 --- a/src/service.c +++ b/src/service.c @@ -1726,6 +1726,9 @@ on_name_lost (GDBusConnection * connection G_GNUC_UNUSED, { IndicatorDatetimeService * self = INDICATOR_DATETIME_SERVICE (gself); + if (connection == NULL) + g_error ("Unable to get bus connection to own name '%s'", name); + g_debug ("%s %s name lost %s", G_STRLOC, G_STRFUNC, name); unexport (self); -- cgit v1.2.3 From c89170a38fb65a47c304c503a9299e79198e999e Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Fri, 4 Oct 2013 11:47:11 -0500 Subject: when an unsupported date format is being used, tell what it is so that we can triage the issue. --- src/service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/service.c b/src/service.c index d50319e..49a1d0c 100644 --- a/src/service.c +++ b/src/service.c @@ -464,7 +464,7 @@ create_desktop_header_state (IndicatorDatetimeService * self) str = g_date_time_format (now, fmt); if (str == NULL) { - str = g_strdup (_("Unsupported date format")); + str = g_strdup_printf (_("Unsupported date format '%s'"), fmt); g_warning ("%s", str); } -- cgit v1.2.3 From 866303a69708759c302311eb21f9c97d648e0607 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Fri, 4 Oct 2013 14:45:28 -0500 Subject: don't use ascii quote marks. --- src/service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/service.c b/src/service.c index 49a1d0c..e8d4764 100644 --- a/src/service.c +++ b/src/service.c @@ -464,7 +464,7 @@ create_desktop_header_state (IndicatorDatetimeService * self) str = g_date_time_format (now, fmt); if (str == NULL) { - str = g_strdup_printf (_("Unsupported date format '%s'"), fmt); + str = g_strdup_printf (_("Unsupported date format “%s”"), fmt); g_warning ("%s", str); } -- cgit v1.2.3 From 5338030ee49808e45013ba99017230a4c9fcf92f Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Fri, 4 Oct 2013 14:46:30 -0500 Subject: fix typo in the potfile unit tests' error messages --- tests/Makefile.am.strings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Makefile.am.strings b/tests/Makefile.am.strings index 26a23a8..4a89e8f 100644 --- a/tests/Makefile.am.strings +++ b/tests/Makefile.am.strings @@ -29,7 +29,7 @@ test-space-ellipsis: $(top_srcdir)/po test-ascii-quotes: $(top_srcdir)/po @echo "#!/bin/bash" > $@ @echo "(cd $(top_srcdir)/po && make $(GETTEXT_PACKAGE).pot)" >> $@ - @echo "grep -c -e \"^msgid \\\".*'.*\\\"\" $(top_srcdir)/po/$(GETTEXT_PACKAGE).pot > /dev/null && echo \"ASCII apostrophy found in user visible strings\" >&2 && exit 1" >> $@ + @echo "grep -c -e \"^msgid \\\".*'.*\\\"\" $(top_srcdir)/po/$(GETTEXT_PACKAGE).pot > /dev/null && echo \"ASCII apostrophe found in user visible strings\" >&2 && exit 1" >> $@ @echo "grep -c -e \"^msgid \\\".*\\\".*\\\"\" $(top_srcdir)/po/$(GETTEXT_PACKAGE).pot > /dev/null && echo \"ASCII quote found in user visible strings\" >&2 && exit 1" >> $@ @echo "grep -c -e \"^msgid \\\".*\\\`.*\\\"\" $(top_srcdir)/po/$(GETTEXT_PACKAGE).pot > /dev/null && echo \"ASCII backtick found in user visible strings\" >&2 && exit 1" >> $@ @echo "exit 0" >> $@ -- cgit v1.2.3 From 5485aef44178391f822edbdee1560bdc36f11501 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 8 Oct 2013 20:42:16 -0500 Subject: add a timer to test periodically to see if we've reached an EDS alarm --- src/planner.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/planner.h b/src/planner.h index 206bfe5..adc820e 100644 --- a/src/planner.h +++ b/src/planner.h @@ -42,6 +42,7 @@ struct IndicatorDatetimeAppt { char * color; char * summary; + char * url; GDateTime * begin; GDateTime * end; gboolean is_event; -- cgit v1.2.3 From 414c9ee4a5d04c7d8b1aa893ba68936c3107430b Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 8 Oct 2013 20:53:10 -0500 Subject: add a timer to periodically check to see if EDS alarms have been reached. --- src/service.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/src/service.c b/src/service.c index e8d4764..1123c51 100644 --- a/src/service.c +++ b/src/service.c @@ -107,6 +107,7 @@ struct _IndicatorDatetimeServicePrivate guint header_timer; guint timezone_timer; + guint alarm_timer; /* Which year/month to show in the calendar, and which day should get the cursor. @@ -376,6 +377,96 @@ start_header_timer (IndicatorDatetimeService * self) g_date_time_unref (now); } +/*** +**** +***/ + +static void start_alarm_timer (IndicatorDatetimeService * self); + +static gboolean +datetimes_have_the_same_minute (GDateTime * a, GDateTime * b) +{ + int ay, am, ad; + int by, bm, bd; + + g_date_time_get_ymd (a, &ay, &am, &ad); + g_date_time_get_ymd (b, &by, &bm, &bd); + + return (ay == by) && + (am == bm) && + (ad == ad) && + (g_date_time_get_hour (a) == g_date_time_get_hour (b)) && + (g_date_time_get_minute (a) == g_date_time_get_minute (b)); +} + +/* This is called on the minute, every minute. + We check for alarms that start at the current time. + If we find any, we dispatch the URL associated with them. */ +static void +dispatch_alarm_urls (IndicatorDatetimeService * self) +{ + GDateTime * now = indicator_datetime_service_get_localtime (self); + GSList * l; + + for (l=self->priv->upcoming_appointments; l!=NULL; l=l->next) + { + const struct IndicatorDatetimeAppt * appt = l->data; + + if ((appt->has_alarms) && + (appt->url != NULL) && + (g_str_has_prefix (appt->url, "alarm:///")) && + (datetimes_have_the_same_minute (now, appt->begin))) + { + gchar * str = g_date_time_format (appt->begin, "%F %H:%M"); + g_debug ("at %s, dispatching url \"%s\" for appointment \"%s\"", str, appt->url, appt->summary); + url_dispatch_send (appt->url, NULL, NULL); + g_free (str); + } + } + + g_date_time_unref (now); +} + +static gboolean +on_alarm_timer (gpointer self) +{ + dispatch_alarm_urls (self); + + /* Restarting the timer to recalculate the interval. This helps us to hit + our marks despite clock skew, suspend+resume, leap seconds, etc */ + start_alarm_timer (self); + return G_SOURCE_REMOVE; +} + +static void +start_alarm_timer (IndicatorDatetimeService * self) +{ + priv_t * p; + GDateTime * now; + guint interval_msec; + + p = self->priv; + + indicator_clear_timer (&p->alarm_timer); + + now = indicator_datetime_service_get_localtime (self); + interval_msec = calculate_milliseconds_until_next_minute (now); + interval_msec += 50; /* add a small margin to ensure the callback + fires /after/ next is reached */ + + p->alarm_timer = g_timeout_add_full (G_PRIORITY_HIGH, + interval_msec, + on_alarm_timer, + self, + NULL); + + g_date_time_unref (now); +} + +/*** +**** +***/ + /** * General purpose handler for rebuilding sections and restarting their timers * when time jumps for whatever reason: @@ -1782,6 +1873,7 @@ my_dispose (GObject * o) indicator_clear_timer (&p->rebuild_id); indicator_clear_timer (&p->timezone_timer); indicator_clear_timer (&p->header_timer); + indicator_clear_timer (&p->alarm_timer); if (p->settings != NULL) { @@ -1948,6 +2040,8 @@ indicator_datetime_service_init (IndicatorDatetimeService * self) on_local_time_jumped (self); + start_alarm_timer (self); + for (i=0; i Date: Tue, 8 Oct 2013 20:53:41 -0500 Subject: add a uri-searching subtask whenever we find an appointment --- src/planner-eds.c | 198 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 165 insertions(+), 33 deletions(-) diff --git a/src/planner-eds.c b/src/planner-eds.c index f121a32..dd41428 100644 --- a/src/planner-eds.c +++ b/src/planner-eds.c @@ -54,16 +54,23 @@ indicator_datetime_appt_free (struct IndicatorDatetimeAppt * appt) g_date_time_unref (appt->begin); g_free (appt->color); g_free (appt->summary); + g_free (appt->url); g_slice_free (struct IndicatorDatetimeAppt, appt); } } /*** -**** my_get_appointments() helpers +**** +**** my_get_appointments() helpers +**** ***/ -struct get_appointments_task_data +/* whole-task data that all the subtasks can see */ +struct appointment_task_data { + /* a ref to the planner's cancellable */ + GCancellable * cancellable; + /* how many subtasks are still running on */ int subtask_count; @@ -74,47 +81,164 @@ struct get_appointments_task_data GHashTable * added; }; +static struct appointment_task_data * +appointment_task_data_new (GCancellable * cancellable) +{ + struct appointment_task_data * data; + + data = g_slice_new0 (struct appointment_task_data); + data->added = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + data->cancellable = g_object_ref (cancellable); + return data; +} + static void -get_appointments_task_data_free (gpointer gdata) +appointment_task_data_free (gpointer gdata) { - struct get_appointments_task_data * data = gdata; + struct appointment_task_data * data = gdata; + + g_object_unref (data->cancellable); g_hash_table_unref (data->added); - g_slice_free (struct get_appointments_task_data, data); + g_slice_free (struct appointment_task_data, data); } static void -on_all_subtasks_done (GTask * task) +appointment_task_done (GTask * task) { - struct get_appointments_task_data * data = g_task_get_task_data (task); + struct appointment_task_data * data = g_task_get_task_data (task); + g_task_return_pointer (task, data->appointments, NULL); g_object_unref (task); } -struct get_appointments_subtask_data +static void +appointment_task_decrement_subtasks (GTask * task) +{ + struct appointment_task_data * data = g_task_get_task_data (task); + + if (g_atomic_int_dec_and_test (&data->subtask_count)) + appointment_task_done (task); +} + +static void +appointment_task_increment_subtasks (GTask * task) { + struct appointment_task_data * data = g_task_get_task_data (task); + + g_atomic_int_inc (&data->subtask_count); +} + +/** +*** get-the-appointment's-uri subtasks +**/ + +struct appointment_uri_subtask_data +{ + /* The parent task */ GTask * task; - gchar * color; + /* The appointment whose uri we're looking for. + This pointer is owned by the Task and isn't reffed/unreffed by the subtask */ + struct IndicatorDatetimeAppt * appt; }; static void -on_subtask_done (gpointer gsubdata) +appointment_uri_subtask_done (struct appointment_uri_subtask_data * subdata) +{ + GTask * task = subdata->task; + + /* free the subtask data */ + g_slice_free (struct appointment_uri_subtask_data, subdata); + + appointment_task_decrement_subtasks (task); +} + +static struct appointment_uri_subtask_data * +appointment_uri_subtask_data_new (GTask * task, struct IndicatorDatetimeAppt * appt) +{ + struct appointment_uri_subtask_data * subdata; + + appointment_task_increment_subtasks (task); + + subdata = g_slice_new0 (struct appointment_uri_subtask_data); + subdata->task = task; + subdata->appt = appt; + return subdata; +} + +static void +on_appointment_uris_ready (GObject * client, + GAsyncResult * res, + gpointer gsubdata) +{ + GSList * uris; + GError * error; + struct appointment_uri_subtask_data * subdata = gsubdata; + + uris = NULL; + error = NULL; + e_cal_client_get_attachment_uris_finish (E_CAL_CLIENT(client), res, &uris, &error); + if (error != NULL) + { + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + g_warning ("Error getting appointment uris: %s", error->message); + + g_error_free (error); + } + else if (uris != NULL) + { + struct IndicatorDatetimeAppt * appt = subdata->appt; + appt->url = g_strdup (uris->data); /* copy the first URL */ + g_debug ("found url '%s' for appointment '%s'", appt->url, appt->summary); + e_client_util_free_string_slist (uris); + } + + appointment_uri_subtask_done (subdata); +} + +/** +*** enumerate-the-components subtasks +**/ + +/* data struct for the enumerate-components subtask */ +struct appointment_component_subtask_data { - struct get_appointments_subtask_data * subdata; + /* The parent task */ GTask * task; - struct get_appointments_task_data * data; - subdata = gsubdata; - task = subdata->task; + /* The client we're walking through. The subtask owns a ref to this */ + ECalClient * client; + + /* The appointment's color coding. The subtask owns this string */ + gchar * color; +}; + +static void +on_appointment_component_subtask_done (gpointer gsubdata) +{ + struct appointment_component_subtask_data * subdata = gsubdata; + GTask * task = subdata->task; /* free the subtask data */ g_free (subdata->color); - g_slice_free (struct get_appointments_subtask_data, subdata); + g_object_unref (subdata->client); + g_slice_free (struct appointment_component_subtask_data, subdata); - /* poke the task */ - data = g_task_get_task_data (task); - if (g_atomic_int_dec_and_test (&data->subtask_count)) - on_all_subtasks_done (task); + appointment_task_decrement_subtasks (task); +} + +static struct appointment_component_subtask_data * +appointment_component_subtask_data_new (GTask * task, ECalClient * client, const gchar * color) +{ + struct appointment_component_subtask_data * subdata; + + appointment_task_increment_subtasks (task); + + subdata = g_slice_new0 (struct appointment_component_subtask_data); + subdata->task = task; + subdata->client = g_object_ref (client); + subdata->color = g_strdup (color); + return subdata; } static gboolean @@ -124,8 +248,8 @@ my_get_appointments_foreach (ECalComponent * component, gpointer gsubdata) { const ECalComponentVType vtype = e_cal_component_get_vtype (component); - struct get_appointments_subtask_data * subdata = gsubdata; - struct get_appointments_task_data * data = g_task_get_task_data (subdata->task); + struct appointment_component_subtask_data * subdata = gsubdata; + struct appointment_task_data * data = g_task_get_task_data (subdata->task); if ((vtype == E_CAL_COMPONENT_EVENT) || (vtype == E_CAL_COMPONENT_TODO)) { @@ -145,6 +269,7 @@ my_get_appointments_foreach (ECalComponent * component, GSList * recur_list; ECalComponentText text; struct IndicatorDatetimeAppt * appt; + struct appointment_uri_subtask_data * uri_subdata; appt = g_slice_new0 (struct IndicatorDatetimeAppt); @@ -176,6 +301,15 @@ my_get_appointments_foreach (ECalComponent * component, data->appointments = g_slist_prepend (data->appointments, appt); g_hash_table_add (data->added, g_strdup(uid)); + + /* start a new subtask to get the associated URIs */ + uri_subdata = appointment_uri_subtask_data_new (subdata->task, appt); + e_cal_client_get_attachment_uris (subdata->client, + uid, + NULL, + data->cancellable, + on_appointment_uris_ready, + uri_subdata); } } @@ -197,7 +331,6 @@ my_get_appointments (IndicatorDatetimePlanner * planner, priv_t * p; const char * str; icaltimezone * default_timezone; - struct get_appointments_task_data * data; const int64_t begin = g_date_time_to_unix (begin_datetime); const int64_t end = g_date_time_to_unix (end_datetime); GTask * task; @@ -223,17 +356,18 @@ my_get_appointments (IndicatorDatetimePlanner * planner, *** walk through the sources to build the appointment list **/ - data = g_slice_new0 (struct get_appointments_task_data); - data->added = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); task = g_task_new (planner, p->cancellable, callback, user_data); - g_task_set_task_data (task, data, get_appointments_task_data_free); + g_task_set_task_data (task, + appointment_task_data_new (p->cancellable), + appointment_task_data_free); subtasks_added = FALSE; for (l=p->sources; l!=NULL; l=l->next) { ESource * source; ECalClient * client; - struct get_appointments_subtask_data * subdata; + const char * color; + struct appointment_component_subtask_data * subdata; source = l->data; client = g_object_get_qdata (l->data, source_client_quark()); @@ -243,11 +377,9 @@ my_get_appointments (IndicatorDatetimePlanner * planner, if (default_timezone != NULL) e_cal_client_set_default_timezone (client, default_timezone); - subdata = g_slice_new (struct get_appointments_subtask_data); - subdata->task = task; - subdata->color = e_source_selectable_dup_color (e_source_get_extension (source, E_SOURCE_EXTENSION_CALENDAR)); - - g_atomic_int_inc (&data->subtask_count); + /* start a new subtask to enumerate all the components in this client. */ + color = e_source_selectable_get_color (e_source_get_extension (source, E_SOURCE_EXTENSION_CALENDAR)); + subdata = appointment_component_subtask_data_new (task, client, color); subtasks_added = TRUE; e_cal_client_generate_instances (client, begin, @@ -255,11 +387,11 @@ my_get_appointments (IndicatorDatetimePlanner * planner, p->cancellable, my_get_appointments_foreach, subdata, - on_subtask_done); + on_appointment_component_subtask_done); } if (!subtasks_added) - on_all_subtasks_done (task); + appointment_task_done (task); } static GSList * -- cgit v1.2.3 From c1a349811e64c1e8597ad4ec391d150eda163512 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 9 Oct 2013 08:21:16 -0500 Subject: in the case of recurring appointments, allow multiple entries with the same uid to be returned by get_appointments(). This is so the client can always find the timestamp of the instance that occurs next. --- src/planner-eds.c | 10 +++------- src/planner.h | 7 ++++--- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/planner-eds.c b/src/planner-eds.c index dd41428..e5f0b43 100644 --- a/src/planner-eds.c +++ b/src/planner-eds.c @@ -55,6 +55,7 @@ indicator_datetime_appt_free (struct IndicatorDatetimeAppt * appt) g_free (appt->color); g_free (appt->summary); g_free (appt->url); + g_free (appt->uid); g_slice_free (struct IndicatorDatetimeAppt, appt); } } @@ -76,9 +77,6 @@ struct appointment_task_data /* the list of appointments to be returned */ GSList * appointments; - - /* ensure that recurring events don't get multiple IndicatorDatetimeAppts */ - GHashTable * added; }; static struct appointment_task_data * @@ -87,7 +85,6 @@ appointment_task_data_new (GCancellable * cancellable) struct appointment_task_data * data; data = g_slice_new0 (struct appointment_task_data); - data->added = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); data->cancellable = g_object_ref (cancellable); return data; } @@ -98,7 +95,7 @@ appointment_task_data_free (gpointer gdata) struct appointment_task_data * data = gdata; g_object_unref (data->cancellable); - g_hash_table_unref (data->added); + g_slice_free (struct appointment_task_data, data); } @@ -260,7 +257,6 @@ my_get_appointments_foreach (ECalComponent * component, e_cal_component_get_status (component, &status); if ((uid != NULL) && - (!g_hash_table_contains (data->added, uid)) && (status != ICAL_STATUS_COMPLETED) && (status != ICAL_STATUS_CANCELLED)) { @@ -294,13 +290,13 @@ my_get_appointments_foreach (ECalComponent * component, appt->color = g_strdup (subdata->color); appt->is_event = vtype == E_CAL_COMPONENT_EVENT; appt->summary = g_strdup (text.value); + appt->uid = g_strdup (uid); alarm_uids = e_cal_component_get_alarm_uids (component); appt->has_alarms = alarm_uids != NULL; cal_obj_uid_list_free (alarm_uids); data->appointments = g_slist_prepend (data->appointments, appt); - g_hash_table_add (data->added, g_strdup(uid)); /* start a new subtask to get the associated URIs */ uri_subdata = appointment_uri_subtask_data_new (subdata->task, appt); diff --git a/src/planner.h b/src/planner.h index adc820e..ffe8937 100644 --- a/src/planner.h +++ b/src/planner.h @@ -40,9 +40,10 @@ GType indicator_datetime_planner_get_type (void); struct IndicatorDatetimeAppt { - char * color; - char * summary; - char * url; + gchar * color; + gchar * summary; + gchar * url; + gchar * uid; GDateTime * begin; GDateTime * end; gboolean is_event; -- cgit v1.2.3 From de4e79a613c01baf566658ffb593c665f15a2e78 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 9 Oct 2013 08:22:09 -0500 Subject: instead of testing for alarms once per minute, set a timer for the next alarm occurence. --- src/service.c | 119 +++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 89 insertions(+), 30 deletions(-) diff --git a/src/service.c b/src/service.c index 1123c51..07f6a51 100644 --- a/src/service.c +++ b/src/service.c @@ -381,7 +381,15 @@ start_header_timer (IndicatorDatetimeService * self) **** ***/ -static void start_alarm_timer (IndicatorDatetimeService * self); +static void set_alarm_timer (IndicatorDatetimeService * self); + +static gboolean +appointment_has_alarm_url (const struct IndicatorDatetimeAppt * appt) +{ + return (appt->has_alarms) && + (appt->url != NULL);// && + //(g_str_has_prefix (appt->url, "alarm:///")); +} static gboolean datetimes_have_the_same_minute (GDateTime * a, GDateTime * b) @@ -394,13 +402,12 @@ datetimes_have_the_same_minute (GDateTime * a, GDateTime * b) return (ay == by) && (am == bm) && - (ad == ad) && + (ad == bd) && (g_date_time_get_hour (a) == g_date_time_get_hour (b)) && (g_date_time_get_minute (a) == g_date_time_get_minute (b)); } -/* This is called on the minute, every minute. - We check for alarms that start at the current time. +/* Check for alarms that start at the current time. If we find any, we dispatch the URL associated with them. */ static void dispatch_alarm_urls (IndicatorDatetimeService * self) @@ -412,13 +419,12 @@ dispatch_alarm_urls (IndicatorDatetimeService * self) { const struct IndicatorDatetimeAppt * appt = l->data; - if ((appt->has_alarms) && - (appt->url != NULL) && - (g_str_has_prefix (appt->url, "alarm:///")) && - (datetimes_have_the_same_minute (now, appt->begin))) + if (appointment_has_alarm_url (appt) && + datetimes_have_the_same_minute (now, appt->begin)) { - gchar * str = g_date_time_format (appt->begin, "%F %H:%M"); - g_debug ("at %s, dispatching url \"%s\" for appointment \"%s\"", str, appt->url, appt->summary); + gchar * str = g_date_time_format (appt->begin, "%F %T"); + g_debug ("at %s, dispatching url \"%s\" for appointment \"%s\"", + str, appt->url, appt->summary); url_dispatch_send (appt->url, NULL, NULL); g_free (str); } @@ -427,38 +433,73 @@ dispatch_alarm_urls (IndicatorDatetimeService * self) g_date_time_unref (now); } +static void update_appointment_lists (IndicatorDatetimeService * self); + static gboolean on_alarm_timer (gpointer self) { dispatch_alarm_urls (self); - - /* Restarting the timer to recalculate the interval. This helps us to hit - our marks despite clock skew, suspend+resume, leap seconds, etc */ - start_alarm_timer (self); + + /* rebuild the alarm list asynchronously. + when it's done, set_upcoming_appointments() will update the alarm timer */ + update_appointment_lists (self); + return G_SOURCE_REMOVE; } +/* if there are upcoming alarms, set the alarm timer to the nearest one. + otherwise, unset the alarm timer. */ static void -start_alarm_timer (IndicatorDatetimeService * self) +set_alarm_timer (IndicatorDatetimeService * self) { priv_t * p; GDateTime * now; - guint interval_msec; - - p = self->priv; + GDateTime * alarm_time; + GSList * l; + p = self->priv; indicator_clear_timer (&p->alarm_timer); now = indicator_datetime_service_get_localtime (self); - interval_msec = calculate_milliseconds_until_next_minute (now); - interval_msec += 50; /* add a small margin to ensure the callback - fires /after/ next is reached */ - p->alarm_timer = g_timeout_add_full (G_PRIORITY_HIGH, - interval_msec, - on_alarm_timer, - self, - NULL); + /* find the time of the next alarm on our calendar */ + alarm_time = NULL; + for (l=p->upcoming_appointments; l!=NULL; l=l->next) + { + const struct IndicatorDatetimeAppt * appt = l->data; + + if (appointment_has_alarm_url (appt)) + if (g_date_time_compare (appt->begin, now) > 0) + if (!alarm_time || g_date_time_compare (alarm_time, appt->begin) > 0) + alarm_time = appt->begin; + } + + /* if there's an upcoming alarm, set a timer to wake up at that time */ + if (alarm_time != NULL) + { + GTimeSpan interval_msec; + gchar * str; + GDateTime * then; + + interval_msec = g_date_time_difference (alarm_time, now); + interval_msec += G_USEC_PER_SEC; /* fire a moment after alarm_time */ + interval_msec /= 1000; /* convert from usec to msec */ + + str = g_date_time_format (alarm_time, "%F %T"); + g_debug ("%s is the next alarm time", str); + g_free (str); + then = g_date_time_add_seconds (now, interval_msec/1000); + str = g_date_time_format (then, "%F %T"); + g_debug ("%s is when we'll wake up for it", str); + g_free (str); + g_date_time_unref (then); + + p->alarm_timer = g_timeout_add_full (G_PRIORITY_HIGH, + (guint) interval_msec, + on_alarm_timer, + self, + NULL); + } g_date_time_unref (now); } @@ -810,20 +851,33 @@ static void add_appointments (IndicatorDatetimeService * self, GMenu * menu, gboolean terse) { const int MAX_APPTS = 5; - GDateTime * now = indicator_datetime_service_get_localtime (self); + GDateTime * now; + GHashTable * added; GSList * appts; GSList * l; int i; + now = indicator_datetime_service_get_localtime (self); + + added = g_hash_table_new (g_str_hash, g_str_equal); + /* build appointment menuitems */ appts = self->priv->upcoming_appointments; for (l=appts, i=0; l!=NULL && inext, i++) { struct IndicatorDatetimeAppt * appt = l->data; - char * fmt = get_appointment_time_format (appt, now, self->priv->settings, terse); - const gint64 unix_time = g_date_time_to_unix (appt->begin); + char * fmt; + gint64 unix_time; GMenuItem * menu_item; + if (g_hash_table_contains (added, appt->uid)) + continue; + + g_hash_table_add (added, appt->uid); + + fmt = get_appointment_time_format (appt, now, self->priv->settings, terse); + unix_time = g_date_time_to_unix (appt->begin); + menu_item = g_menu_item_new (appt->summary, NULL); if (appt->color && !appt->has_alarms) @@ -846,6 +900,7 @@ add_appointments (IndicatorDatetimeService * self, GMenu * menu, gboolean terse) } /* cleanup */ + g_hash_table_unref (added); g_date_time_unref (now); } @@ -1661,6 +1716,10 @@ set_upcoming_appointments (IndicatorDatetimeService * self, /* sync the menus/actions */ rebuild_appointments_section_soon (self); + + /* alarm timer is keyed off of the next alarm time, + so it needs to be rebuilt when tehe appointment list changes */ + set_alarm_timer (self); } static void @@ -2040,7 +2099,7 @@ indicator_datetime_service_init (IndicatorDatetimeService * self) on_local_time_jumped (self); - start_alarm_timer (self); + set_alarm_timer (self); for (i=0; i Date: Wed, 9 Oct 2013 13:28:15 +0000 Subject: remove debugging stubs --- src/service.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/service.c b/src/service.c index 07f6a51..28ef32d 100644 --- a/src/service.c +++ b/src/service.c @@ -387,8 +387,8 @@ static gboolean appointment_has_alarm_url (const struct IndicatorDatetimeAppt * appt) { return (appt->has_alarms) && - (appt->url != NULL);// && - //(g_str_has_prefix (appt->url, "alarm:///")); + (appt->url != NULL) && + (g_str_has_prefix (appt->url, "alarm:///")); } static gboolean -- cgit v1.2.3 From 1282befc5d9629ba0daacc2099811ccf19e4ed1b Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 9 Oct 2013 11:39:36 -0500 Subject: add url activation for appointment menuitems on the phone profile. --- README | 8 ++++++- src/service.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 66 insertions(+), 16 deletions(-) diff --git a/README b/README index 5dc9764..b31db05 100644 --- a/README +++ b/README @@ -7,11 +7,17 @@ ACTIONS Parameter: None * "activate-planner" - Description: opens up a calendar appointment editor. + Description: opens an appointment editor. State: None Parameter: int64, a time_t hinting which day/time to show in the planner, or 0 for the current day + * "activate-appointment" + Description: opens an appointment editor to the specified appointment. + State: None + Parameter: string, an opaque uid to specify which appointment to use. + This uid comes from the menuitems' target values. + * "set-location" Description: Set the current location. This will try to set the current timezone to the new location's timezone. diff --git a/src/service.c b/src/service.c index 28ef32d..1de4617 100644 --- a/src/service.c +++ b/src/service.c @@ -378,7 +378,7 @@ start_header_timer (IndicatorDatetimeService * self) } /*** -**** +**** ALARMS ***/ static void set_alarm_timer (IndicatorDatetimeService * self); @@ -407,6 +407,22 @@ datetimes_have_the_same_minute (GDateTime * a, GDateTime * b) (g_date_time_get_minute (a) == g_date_time_get_minute (b)); } +static void +dispatch_alarm_url (const struct IndicatorDatetimeAppt * appt) +{ + gchar * str; + + g_return_if_fail (appt != NULL); + g_return_if_fail (appointment_has_alarm_url (appt)); + + str = g_date_time_format (appt->begin, "%F %T"); + g_debug ("dispatching url \"%s\" for appointment \"%s\", which begins at %s", + appt->url, appt->summary, str); + g_free (str); + + url_dispatch_send (appt->url, NULL, NULL); +} + /* Check for alarms that start at the current time. If we find any, we dispatch the URL associated with them. */ static void @@ -419,15 +435,8 @@ dispatch_alarm_urls (IndicatorDatetimeService * self) { const struct IndicatorDatetimeAppt * appt = l->data; - if (appointment_has_alarm_url (appt) && - datetimes_have_the_same_minute (now, appt->begin)) - { - gchar * str = g_date_time_format (appt->begin, "%F %T"); - g_debug ("at %s, dispatching url \"%s\" for appointment \"%s\"", - str, appt->url, appt->summary); - url_dispatch_send (appt->url, NULL, NULL); - g_free (str); - } + if (appointment_has_alarm_url (appt) && datetimes_have_the_same_minute (now, appt->begin)) + dispatch_alarm_url (appt); } g_date_time_unref (now); @@ -848,7 +857,7 @@ get_appointment_time_format (struct IndicatorDatetimeAppt * appt, } static void -add_appointments (IndicatorDatetimeService * self, GMenu * menu, gboolean terse) +add_appointments (IndicatorDatetimeService * self, GMenu * menu, gboolean phone) { const int MAX_APPTS = 5; GDateTime * now; @@ -875,7 +884,7 @@ add_appointments (IndicatorDatetimeService * self, GMenu * menu, gboolean terse) g_hash_table_add (added, appt->uid); - fmt = get_appointment_time_format (appt, now, self->priv->settings, terse); + fmt = get_appointment_time_format (appt, now, self->priv->settings, phone); unix_time = g_date_time_to_unix (appt->begin); menu_item = g_menu_item_new (appt->summary, NULL); @@ -891,9 +900,15 @@ add_appointments (IndicatorDatetimeService * self, GMenu * menu, gboolean terse) g_menu_item_set_attribute (menu_item, "x-canonical-type", "s", appt->has_alarms ? "com.canonical.indicator.alarm" : "com.canonical.indicator.appointment"); - g_menu_item_set_action_and_target_value (menu_item, - "indicator.activate-planner", - g_variant_new_int64 (unix_time)); + + if (phone) + g_menu_item_set_action_and_target_value (menu_item, + "indicator.activate-appointment", + g_variant_new_string (appt->uid)); + else + g_menu_item_set_action_and_target_value (menu_item, + "indicator.activate-planner", + g_variant_new_int64 (unix_time)); g_menu_append_item (menu, menu_item); g_object_unref (menu_item); g_free (fmt); @@ -1432,6 +1447,34 @@ on_phone_settings_activated (GSimpleAction * a G_GNUC_UNUSED, url_dispatch_send ("settings:///system/time-date", NULL, NULL); } +static void +on_activate_appointment (GSimpleAction * a G_GNUC_UNUSED, + GVariant * param, + gpointer gself) +{ + priv_t * p = INDICATOR_DATETIME_SERVICE(gself)->priv; + const gchar * uid = g_variant_get_string (param, NULL); + + if (uid != NULL) + { + const struct IndicatorDatetimeAppt * appt; + GSList * l; + + /* find the appointment that matches that uid */ + for (l=p->upcoming_appointments, appt=NULL; l && !appt; l=l->next) + { + const struct IndicatorDatetimeAppt * tmp = l->data; + if (!g_strcmp0 (uid, tmp->uid)) + appt = tmp; + } + + /* if that appointment's an alarm, dispatch its url */ + g_debug ("%s: uri '%s'; matching appt is %p", G_STRFUNC, uid, appt); + if (appt && appointment_has_alarm_url (appt)) + dispatch_alarm_url (appt); + } +} + static void on_activate_planner (GSimpleAction * a G_GNUC_UNUSED, GVariant * param, @@ -1486,6 +1529,7 @@ init_gactions (IndicatorDatetimeService * self) { "activate-desktop-settings", on_desktop_settings_activated }, { "activate-phone-settings", on_phone_settings_activated }, { "activate-planner", on_activate_planner, "x", NULL }, + { "activate-appointment", on_activate_appointment, "s", NULL }, { "set-location", on_set_location, "s" } }; -- cgit v1.2.3 From 70487ccce4dbcf04f9dfb02ba50f7e88e428f14a Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 9 Oct 2013 21:02:17 -0500 Subject: move planner instantiation to main.c so that we can prepare to pass in a mock planner for testing --- src/main.c | 12 ++++-- src/service.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++---------- src/service.h | 7 +++- 3 files changed, 118 insertions(+), 24 deletions(-) diff --git a/src/main.c b/src/main.c index c75b2d7..710db66 100644 --- a/src/main.c +++ b/src/main.c @@ -25,6 +25,7 @@ #include #include +#include "planner-eds.h" #include "service.h" /*** @@ -41,23 +42,28 @@ on_name_lost (gpointer instance G_GNUC_UNUSED, gpointer loop) int main (int argc G_GNUC_UNUSED, char ** argv G_GNUC_UNUSED) { - GMainLoop * loop; + IndicatorDatetimePlanner * planner; IndicatorDatetimeService * service; + GMainLoop * loop; /* boilerplate i18n */ setlocale (LC_ALL, ""); bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); textdomain (GETTEXT_PACKAGE); + /* get the planner */ + planner = indicator_datetime_planner_eds_new (); + /* run */ - service = indicator_datetime_service_new (); + service = indicator_datetime_service_new (planner); loop = g_main_loop_new (NULL, FALSE); g_signal_connect (service, INDICATOR_DATETIME_SERVICE_SIGNAL_NAME_LOST, G_CALLBACK(on_name_lost), loop); g_main_loop_run (loop); /* cleanup */ - g_clear_object (&service); g_main_loop_unref (loop); + g_object_unref (service); + g_object_unref (planner); return 0; } diff --git a/src/service.c b/src/service.c index 1de4617..57d0a7e 100644 --- a/src/service.c +++ b/src/service.c @@ -27,7 +27,6 @@ #include #include "dbus-shared.h" -#include "planner-eds.h" #include "timezone-file.h" #include "timezone-geoclue.h" #include "service.h" @@ -49,6 +48,15 @@ enum static guint signals[LAST_SIGNAL] = { 0 }; +enum +{ + PROP_0, + PROP_PLANNER, + PROP_LAST +}; + +static GParamSpec * properties[PROP_LAST] = { 0 }; + enum { SECTION_HEADER = (1<<0), @@ -1935,6 +1943,45 @@ on_name_lost (GDBusConnection * connection G_GNUC_UNUSED, **** GObject virtual functions ***/ +static void +my_get_property (GObject * o, + guint property_id, + GValue * value, + GParamSpec * pspec) +{ + IndicatorDatetimeService * self = INDICATOR_DATETIME_SERVICE (o); + + switch (property_id) + { + case PROP_PLANNER: + g_value_set_object (value, self->priv->planner); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (o, property_id, pspec); + } +} + +static void +my_set_property (GObject * o, + guint property_id, + const GValue * value, + GParamSpec * pspec) +{ + IndicatorDatetimeService * self = INDICATOR_DATETIME_SERVICE (o); + + switch (property_id) + { + case PROP_PLANNER: + indicator_datetime_service_set_planner (self, g_value_get_object (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (o, property_id, pspec); + } +} + + static void my_dispose (GObject * o) { @@ -1958,13 +2005,7 @@ my_dispose (GObject * o) set_detect_location_enabled (self, FALSE); - if (p->planner != NULL) - { - g_signal_handlers_disconnect_by_data (p->planner, self); - g_clear_object (&p->planner); - } - g_clear_pointer (&p->upcoming_appointments, indicator_datetime_planner_free_appointments); - g_clear_pointer (&p->calendar_appointments, indicator_datetime_planner_free_appointments); + indicator_datetime_service_set_planner (self, NULL); if (p->login1_manager != NULL) { @@ -2064,16 +2105,6 @@ indicator_datetime_service_init (IndicatorDatetimeService * self) p->cancellable = g_cancellable_new (); - /*** - **** Create the planner and listen for changes - ***/ - - p->planner = indicator_datetime_planner_eds_new (); - - g_signal_connect_swapped (p->planner, "appointments-changed", - G_CALLBACK(update_appointment_lists), self); - - /*** **** Create the settings object and listen for changes ***/ @@ -2155,9 +2186,12 @@ static void indicator_datetime_service_class_init (IndicatorDatetimeServiceClass * klass) { GObjectClass * object_class = G_OBJECT_CLASS (klass); + const GParamFlags flags = G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS; object_class->dispose = my_dispose; object_class->finalize = my_finalize; + object_class->get_property = my_get_property; + object_class->set_property = my_set_property; g_type_class_add_private (klass, sizeof (IndicatorDatetimeServicePrivate)); @@ -2169,6 +2203,18 @@ indicator_datetime_service_class_init (IndicatorDatetimeServiceClass * klass) NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + /* install properties */ + + properties[PROP_0] = NULL; + + properties[PROP_PLANNER] = g_param_spec_object ("planner", + "Planner", + "The appointment provider", + INDICATOR_TYPE_DATETIME_PLANNER, + flags); + + g_object_class_install_properties (object_class, PROP_LAST, properties); } /*** @@ -2176,9 +2222,11 @@ indicator_datetime_service_class_init (IndicatorDatetimeServiceClass * klass) ***/ IndicatorDatetimeService * -indicator_datetime_service_new (void) +indicator_datetime_service_new (IndicatorDatetimePlanner * planner) { - GObject * o = g_object_new (INDICATOR_TYPE_DATETIME_SERVICE, NULL); + GObject * o = g_object_new (INDICATOR_TYPE_DATETIME_SERVICE, + "planner", planner, + NULL); return INDICATOR_DATETIME_SERVICE (o); } @@ -2209,3 +2257,38 @@ indicator_datetime_service_set_calendar_date (IndicatorDatetimeService * self, if (dirty) update_appointment_lists (self); } + +void +indicator_datetime_service_set_planner (IndicatorDatetimeService * self, + IndicatorDatetimePlanner * planner) +{ + priv_t * p; + + g_return_if_fail (INDICATOR_IS_DATETIME_SERVICE (self)); + g_return_if_fail (INDICATOR_IS_DATETIME_PLANNER (planner)); + + p = self->priv; + + /* clear the old planner & appointments */ + + if (p->planner != NULL) + { + g_signal_handlers_disconnect_by_data (p->planner, self); + g_clear_object (&p->planner); + } + + g_clear_pointer (&p->upcoming_appointments, indicator_datetime_planner_free_appointments); + g_clear_pointer (&p->calendar_appointments, indicator_datetime_planner_free_appointments); + + /* set the new planner & begin fetching appointments from it */ + + if (planner != NULL) + { + p->planner = g_object_ref (planner); + + g_signal_connect_swapped (p->planner, "appointments-changed", + G_CALLBACK(update_appointment_lists), self); + + update_appointment_lists (self); + } +} diff --git a/src/service.h b/src/service.h index b142882..25bb59a 100644 --- a/src/service.h +++ b/src/service.h @@ -22,6 +22,7 @@ #include #include +#include "planner.h" G_BEGIN_DECLS @@ -62,13 +63,17 @@ struct _IndicatorDatetimeServiceClass GType indicator_datetime_service_get_type (void); -IndicatorDatetimeService * indicator_datetime_service_new (void); +IndicatorDatetimeService * indicator_datetime_service_new (IndicatorDatetimePlanner * planner); GDateTime * indicator_datetime_service_get_localtime (IndicatorDatetimeService * service); void indicator_datetime_service_set_calendar_date (IndicatorDatetimeService * self, GDateTime * date); +void indicator_datetime_service_set_planner (IndicatorDatetimeService * self, + IndicatorDatetimePlanner * planner); + + G_END_DECLS -- cgit v1.2.3 From ba639a9fb011ad337eef8d2bd5e4bcbdca3b136a Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 9 Oct 2013 21:04:31 -0500 Subject: remove vestigal function declaration from planner-eds.h --- src/planner-eds.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/planner-eds.h b/src/planner-eds.h index a2c803a..dea9371 100644 --- a/src/planner-eds.h +++ b/src/planner-eds.h @@ -51,8 +51,6 @@ struct _IndicatorDatetimePlannerEdsClass IndicatorDatetimePlannerClass parent_class; }; -gboolean indicator_datetime_planner_eds_is_usable (void); - IndicatorDatetimePlanner * indicator_datetime_planner_eds_new (void); G_END_DECLS -- cgit v1.2.3 From bc40e6a71d5eccf0fce96807d71d2f220207259b Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 9 Oct 2013 21:06:35 -0500 Subject: move the implementation of indicator_datetime_appt_free() from planner-eds.c to planner.c --- src/planner-eds.c | 19 ------------------- src/planner.c | 20 ++++++++++++++++++++ 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/planner-eds.c b/src/planner-eds.c index e5f0b43..b188392 100644 --- a/src/planner-eds.c +++ b/src/planner-eds.c @@ -41,25 +41,6 @@ G_DEFINE_TYPE (IndicatorDatetimePlannerEds, G_DEFINE_QUARK ("source-client", source_client) -/*** -**** -***/ - -void -indicator_datetime_appt_free (struct IndicatorDatetimeAppt * appt) -{ - if (appt != NULL) - { - g_date_time_unref (appt->end); - g_date_time_unref (appt->begin); - g_free (appt->color); - g_free (appt->summary); - g_free (appt->url); - g_free (appt->uid); - g_slice_free (struct IndicatorDatetimeAppt, appt); - } -} - /*** **** **** my_get_appointments() helpers diff --git a/src/planner.c b/src/planner.c index e826c2c..9b9a77f 100644 --- a/src/planner.c +++ b/src/planner.c @@ -259,3 +259,23 @@ indicator_datetime_planner_get_timezone (IndicatorDatetimePlanner * self) return self->priv->timezone; } + +/*** +**** +***/ + +void +indicator_datetime_appt_free (struct IndicatorDatetimeAppt * appt) +{ + if (appt != NULL) + { + g_date_time_unref (appt->end); + g_date_time_unref (appt->begin); + g_free (appt->color); + g_free (appt->summary); + g_free (appt->url); + g_free (appt->uid); + g_slice_free (struct IndicatorDatetimeAppt, appt); + } +} + -- cgit v1.2.3 From c8a8c56f668f50e5cdeff5255ec74e82e3af7e32 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 9 Oct 2013 21:24:43 -0500 Subject: planner-eds's is_configured() function should be private --- src/planner-eds.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/planner-eds.c b/src/planner-eds.c index b188392..876fdfc 100644 --- a/src/planner-eds.c +++ b/src/planner-eds.c @@ -379,7 +379,7 @@ my_get_appointments_finish (IndicatorDatetimePlanner * self G_GNUC_UNUSED, return g_task_propagate_pointer (G_TASK(res), error); } -gboolean +static gboolean my_is_configured (IndicatorDatetimePlanner * planner) { IndicatorDatetimePlannerEds * self; -- cgit v1.2.3 From b6b0c140f922385d947fa12dfff179a5491a1722 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 9 Oct 2013 21:31:13 -0500 Subject: add a preliminary mock planner for testing alarms/appointments isolated apart from the EDS backend --- src/Makefile.am | 2 + src/main.c | 11 +++- src/planner-mock.c | 178 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/planner-mock.h | 58 +++++++++++++++++ 4 files changed, 248 insertions(+), 1 deletion(-) create mode 100644 src/planner-mock.c create mode 100644 src/planner-mock.h diff --git a/src/Makefile.am b/src/Makefile.am index 093a258..640650a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -20,6 +20,8 @@ libindicator_datetime_service_a_CFLAGS = \ libindicator_datetime_service_a_SOURCES = \ planner.c \ planner.h \ + planner-mock.c \ + planner-mock.h \ planner-eds.c \ planner-eds.h \ service.c \ diff --git a/src/main.c b/src/main.c index 710db66..073c876 100644 --- a/src/main.c +++ b/src/main.c @@ -26,6 +26,7 @@ #include #include "planner-eds.h" +#include "planner-mock.h" #include "service.h" /*** @@ -52,7 +53,15 @@ main (int argc G_GNUC_UNUSED, char ** argv G_GNUC_UNUSED) textdomain (GETTEXT_PACKAGE); /* get the planner */ - planner = indicator_datetime_planner_eds_new (); + if (g_getenv ("INDICATOR_DATETIME_USE_FAKE_PLANNER") != NULL) + { + g_message ("Using fake appointment book for testing"); + planner = indicator_datetime_planner_mock_new (); + } + else + { + planner = indicator_datetime_planner_eds_new (); + } /* run */ service = indicator_datetime_service_new (planner); diff --git a/src/planner-mock.c b/src/planner-mock.c new file mode 100644 index 0000000..e67ad7e --- /dev/null +++ b/src/planner-mock.c @@ -0,0 +1,178 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include "config.h" + +#include "planner-mock.h" + +struct _IndicatorDatetimePlannerMockPriv +{ + gboolean is_configured; +}; + +typedef IndicatorDatetimePlannerMockPriv priv_t; + +G_DEFINE_TYPE (IndicatorDatetimePlannerMock, + indicator_datetime_planner_mock, + INDICATOR_TYPE_DATETIME_PLANNER) + +/*** +**** IndicatorDatetimePlanner virtual funcs +***/ + +static void +my_get_appointments (IndicatorDatetimePlanner * planner, + GDateTime * begin_datetime, + GDateTime * end_datetime G_GNUC_UNUSED, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask * task; + GSList * appointments; + struct IndicatorDatetimeAppt * appt; + struct IndicatorDatetimeAppt * prev; + + task = g_task_new (planner, NULL, callback, user_data); + + /** + *** Build the appointments list + **/ + + appointments = NULL; + + /* add a daily appointment that occurs at the beginning of the next minute */ + appt = g_slice_new0 (struct IndicatorDatetimeAppt); + appt->is_daily = TRUE; + appt->begin = g_date_time_add_seconds (begin_datetime, 60-g_date_time_get_seconds(begin_datetime)); + appt->end = g_date_time_add_minutes (appt->begin, 1); + appt->color = g_strdup ("#00FF00"); + appt->is_event = TRUE; + appt->summary = g_strdup ("Daily alarm"); + appt->uid = g_strdup ("this uid isn't very random."); + appt->has_alarms = TRUE; + appt->url = g_strdup ("alarm:///some-alarm-info-goes-here"); + appointments = g_slist_prepend (appointments, appt); + prev = appt; + + /* and add one for a minute later that has an alarm uri */ + appt = g_slice_new0 (struct IndicatorDatetimeAppt); + appt->is_daily = TRUE; + appt->begin = g_date_time_add_minutes (prev->end, 1); + appt->end = g_date_time_add_minutes (appt->begin, 1); + appt->color = g_strdup ("#0000FF"); + appt->is_event = TRUE; + appt->summary = g_strdup ("Second Daily alarm"); + appt->uid = g_strdup ("this uid isn't very random either."); + appt->has_alarms = FALSE; + appointments = g_slist_prepend (appointments, appt); + + /* done */ + g_task_return_pointer (task, appointments, NULL); + g_object_unref (task); +} + +static GSList * +my_get_appointments_finish (IndicatorDatetimePlanner * self G_GNUC_UNUSED, + GAsyncResult * res, + GError ** error) +{ + return g_task_propagate_pointer (G_TASK(res), error); +} + +static gboolean +my_is_configured (IndicatorDatetimePlanner * planner) +{ + IndicatorDatetimePlannerMock * self; + self = INDICATOR_DATETIME_PLANNER_MOCK (planner); + return self->priv->is_configured; +} + +static void +my_activate (IndicatorDatetimePlanner * self G_GNUC_UNUSED) +{ + g_message ("%s %s", G_STRLOC, G_STRFUNC); +} + +static void +my_activate_time (IndicatorDatetimePlanner * self G_GNUC_UNUSED, + GDateTime * activate_time) +{ + gchar * str = g_date_time_format (activate_time, "%F %T"); + g_message ("%s %s: %s", G_STRLOC, G_STRFUNC, str); + g_free (str); +} + +/*** +**** GObject virtual funcs +***/ + +static void +my_dispose (GObject * o) +{ + G_OBJECT_CLASS (indicator_datetime_planner_mock_parent_class)->dispose (o); +} + +/*** +**** Instantiation +***/ + +static void +indicator_datetime_planner_mock_class_init (IndicatorDatetimePlannerMockClass * klass) +{ + GObjectClass * object_class; + IndicatorDatetimePlannerClass * planner_class; + + object_class = G_OBJECT_CLASS (klass); + object_class->dispose = my_dispose; + + planner_class = INDICATOR_DATETIME_PLANNER_CLASS (klass); + planner_class->is_configured = my_is_configured; + planner_class->activate = my_activate; + planner_class->activate_time = my_activate_time; + planner_class->get_appointments = my_get_appointments; + planner_class->get_appointments_finish = my_get_appointments_finish; + + g_type_class_add_private (klass, sizeof (IndicatorDatetimePlannerMockPriv)); +} + +static void +indicator_datetime_planner_mock_init (IndicatorDatetimePlannerMock * self) +{ + priv_t * p; + + p = G_TYPE_INSTANCE_GET_PRIVATE (self, + INDICATOR_TYPE_DATETIME_PLANNER_MOCK, + IndicatorDatetimePlannerMockPriv); + + p->is_configured = TRUE; + + self->priv = p; +} + +/*** +**** Public +***/ + +IndicatorDatetimePlanner * +indicator_datetime_planner_mock_new (void) +{ + gpointer o = g_object_new (INDICATOR_TYPE_DATETIME_PLANNER_MOCK, NULL); + + return INDICATOR_DATETIME_PLANNER (o); +} diff --git a/src/planner-mock.h b/src/planner-mock.h new file mode 100644 index 0000000..8d7d7c2 --- /dev/null +++ b/src/planner-mock.h @@ -0,0 +1,58 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#ifndef __INDICATOR_DATETIME_PLANNER_MOCK__H__ +#define __INDICATOR_DATETIME_PLANNER_MOCK__H__ + +#include "planner.h" /* parent class */ + +G_BEGIN_DECLS + +#define INDICATOR_TYPE_DATETIME_PLANNER_MOCK (indicator_datetime_planner_mock_get_type()) +#define INDICATOR_DATETIME_PLANNER_MOCK(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), INDICATOR_TYPE_DATETIME_PLANNER_MOCK, IndicatorDatetimePlannerMock)) +#define INDICATOR_DATETIME_PLANNER_MOCK_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), INDICATOR_TYPE_DATETIME_PLANNER_MOCK, IndicatorDatetimePlannerMockClass)) +#define INDICATOR_IS_DATETIME_PLANNER_MOCK(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), INDICATOR_TYPE_DATETIME_PLANNER_MOCK)) + +typedef struct _IndicatorDatetimePlannerMock IndicatorDatetimePlannerMock; +typedef struct _IndicatorDatetimePlannerMockPriv IndicatorDatetimePlannerMockPriv; +typedef struct _IndicatorDatetimePlannerMockClass IndicatorDatetimePlannerMockClass; + +GType indicator_datetime_planner_mock_get_type (void); + +/** + * An IndicatorDatetimePlanner which uses Evolution Data Server + * to get its list of appointments. + */ +struct _IndicatorDatetimePlannerMock +{ + /*< private >*/ + IndicatorDatetimePlanner parent; + IndicatorDatetimePlannerMockPriv * priv; +}; + +struct _IndicatorDatetimePlannerMockClass +{ + IndicatorDatetimePlannerClass parent_class; +}; + +IndicatorDatetimePlanner * indicator_datetime_planner_mock_new (void); + +G_END_DECLS + +#endif /* __INDICATOR_DATETIME_PLANNER_MOCK__H__ */ -- cgit v1.2.3 From a52e3b86ee0dbce56221d1327c6c62a6d8e163e3 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 9 Oct 2013 21:33:15 -0500 Subject: preliminary implementation of snap decision --- configure.ac | 2 ++ debian/control | 1 + src/main.c | 6 +++++ src/service.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++----------- 4 files changed, 73 insertions(+), 14 deletions(-) diff --git a/configure.ac b/configure.ac index 8b95695..5b9dda6 100644 --- a/configure.ac +++ b/configure.ac @@ -51,6 +51,7 @@ GEOCLUE_REQUIRED_VERSION=0.12.0 ICAL_REQUIRED_VERSION=0.48 ECAL_REQUIRED_VERSION=3.5 EDS_REQUIRED_VERSION=3.5 +LIBNOTIFY_REQUIRED_VERSION=0.7.6 URL_DISPATCHER_1_REQUIRED_VERSION=1 GTK3_REQUIRED_VERSION=3.1.4 @@ -61,6 +62,7 @@ PKG_CHECK_MODULES(SERVICE, [glib-2.0 >= $GLIB_REQUIRED_VERSION libical >= $ICAL_REQUIRED_VERSION libecal-1.2 >= $ECAL_REQUIRED_VERSION libedataserver-1.2 >= EDS_REQUIRED_VERSION + libnotify >= $LIBNOTIFY_REQUIRED_VERSION url-dispatcher-1 >= URL_DISPATCHER_1_REQUIRED_VERSION]) ########################### diff --git a/debian/control b/debian/control index 67938bf..0815e1b 100644 --- a/debian/control +++ b/debian/control @@ -10,6 +10,7 @@ Build-Depends: debhelper (>= 9), libxorg-gtest-dev, libgtest-dev, libglib2.0-dev (>= 2.35.4), + libnotify-dev (>= 0.7.6), libido3-0.1-dev (>= 0.2.90), libgeoclue-dev (>= 0.12.0), libecal1.2-dev (>= 3.5), diff --git a/src/main.c b/src/main.c index 073c876..34e9b98 100644 --- a/src/main.c +++ b/src/main.c @@ -24,6 +24,7 @@ #include #include +#include #include "planner-eds.h" #include "planner-mock.h" @@ -52,6 +53,11 @@ main (int argc G_GNUC_UNUSED, char ** argv G_GNUC_UNUSED) bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); textdomain (GETTEXT_PACKAGE); + /* init libnotify */ + if (!notify_init ("indicator-datetime-service")) + g_critical ("libnotify initialization failed"); + + /* get the planner */ if (g_getenv ("INDICATOR_DATETIME_USE_FAKE_PLANNER") != NULL) { diff --git a/src/service.c b/src/service.c index 57d0a7e..c76b07e 100644 --- a/src/service.c +++ b/src/service.c @@ -24,6 +24,7 @@ #include #include +#include #include #include "dbus-shared.h" @@ -431,31 +432,80 @@ dispatch_alarm_url (const struct IndicatorDatetimeAppt * appt) url_dispatch_send (appt->url, NULL, NULL); } -/* Check for alarms that start at the current time. - If we find any, we dispatch the URL associated with them. */ +#if 0 static void -dispatch_alarm_urls (IndicatorDatetimeService * self) +on_notification_closed (NotifyNotification * nn, gpointer gself) { - GDateTime * now = indicator_datetime_service_get_localtime (self); - GSList * l; + //IndicatorDatetimeService * self = INDICATOR_DATETIME_SERVICE (gself); - for (l=self->priv->upcoming_appointments; l!=NULL; l=l->next) - { - const struct IndicatorDatetimeAppt * appt = l->data; + g_message ("hello world"); - if (appointment_has_alarm_url (appt) && datetimes_have_the_same_minute (now, appt->begin)) - dispatch_alarm_url (appt); - } + /* cleanup */ + g_signal_handlers_disconnect_by_data (nn, gself); + g_object_unref (nn); +} +#endif - g_date_time_unref (now); +static void +on_alarm_popup_ok_clicked (NotifyNotification * nn G_GNUC_UNUSED, char * action G_GNUC_UNUSED, gpointer gurl) +{ + const char * url = gurl; + url_dispatch_send (url, NULL, NULL); } +#define ALARM_ICON_NAME "alarm-symbolic" + static void update_appointment_lists (IndicatorDatetimeService * self); static gboolean -on_alarm_timer (gpointer self) +on_alarm_timer (gpointer gself) { - dispatch_alarm_urls (self); + GDateTime * now; + GSList * l; + IndicatorDatetimeService * self = INDICATOR_DATETIME_SERVICE (gself); + + /* Check for alarms that start at the current time. + * If we find one, trigger a snap decision displaying + * the appointment text and a single button to dismiss */ + now = indicator_datetime_service_get_localtime (self); + for (l=self->priv->upcoming_appointments; l!=NULL; l=l->next) + { + gchar * title; + const gchar * body; + const struct IndicatorDatetimeAppt * appt = l->data; + NotifyNotification * nn; + GError * error; + + if (!appointment_has_alarm_url (appt)) + continue; + + if (!datetimes_have_the_same_minute (now, appt->begin)) + continue; + + title = g_date_time_format (now, get_terse_time_format_string (now)); + body = appt->summary; + nn = notify_notification_new (title, body, ALARM_ICON_NAME); + + notify_notification_set_hint (nn, "x-canonical-snap-decisions", + g_variant_new_boolean(TRUE)); + notify_notification_set_hint (nn, "x-canonical-private-button-tint", + g_variant_new_boolean(TRUE)); + notify_notification_add_action (nn, "ok", _("OK"), + on_alarm_popup_ok_clicked, + g_strdup (appt->url), g_free); + //g_signal_connect (nn, "closed", G_CALLBACK(on_notification_closed), self); + + error = NULL; + notify_notification_show (nn, &error); + if (error != NULL) + { + g_warning ("Unable to show alarm '%s' popup: %s", body, error->message); + g_error_free (error); + dispatch_alarm_url (appt); + } + g_free (title); + } + g_date_time_unref (now); /* rebuild the alarm list asynchronously. when it's done, set_upcoming_appointments() will update the alarm timer */ -- cgit v1.2.3 From dae4fdd39e5381083345e87759dbaffddabe14e4 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 9 Oct 2013 22:55:26 -0500 Subject: more wiring in of mock objects --- src/main.c | 38 +++++++++++++++++++++++++++----------- src/service.c | 7 +++++-- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/src/main.c b/src/main.c index 34e9b98..45ee180 100644 --- a/src/main.c +++ b/src/main.c @@ -21,6 +21,7 @@ #include #include /* exit() */ +#include #include #include @@ -30,6 +31,8 @@ #include "planner-mock.h" #include "service.h" +#define TEST_MODE + /*** **** ***/ @@ -41,6 +44,18 @@ on_name_lost (gpointer instance G_GNUC_UNUSED, gpointer loop) g_main_loop_quit ((GMainLoop*)loop); } +#ifdef TEST_MODE +static void +log_handler (const gchar * log_domain, + GLogLevelFlags log_level, + const gchar * message, + gpointer fp) +{ + fprintf (fp, "%s %d %s\n", log_domain, (int)log_level, message); + fflush (fp); +} +#endif + int main (int argc G_GNUC_UNUSED, char ** argv G_GNUC_UNUSED) { @@ -57,17 +72,15 @@ main (int argc G_GNUC_UNUSED, char ** argv G_GNUC_UNUSED) if (!notify_init ("indicator-datetime-service")) g_critical ("libnotify initialization failed"); - - /* get the planner */ - if (g_getenv ("INDICATOR_DATETIME_USE_FAKE_PLANNER") != NULL) - { - g_message ("Using fake appointment book for testing"); - planner = indicator_datetime_planner_mock_new (); - } - else - { - planner = indicator_datetime_planner_eds_new (); - } + /* set up the planner */ +#ifdef TEST_MODE + g_warning ("Using fake appointment book for testing! Probably shouldn't merge this to trunk."); + FILE * fp = fopen ("/tmp/indicator-datetime-log.txt", "w+"); + g_log_set_handler ("Indicator-Datetime", G_LOG_LEVEL_MASK, log_handler, fp); + planner = indicator_datetime_planner_mock_new (); +#else + planner = indicator_datetime_planner_eds_new (); +#endif /* run */ service = indicator_datetime_service_new (planner); @@ -80,5 +93,8 @@ main (int argc G_GNUC_UNUSED, char ** argv G_GNUC_UNUSED) g_main_loop_unref (loop); g_object_unref (service); g_object_unref (planner); +#ifdef TEST_MODE + fclose (fp); +#endif return 0; } diff --git a/src/service.c b/src/service.c index c76b07e..61d50aa 100644 --- a/src/service.c +++ b/src/service.c @@ -472,6 +472,7 @@ on_alarm_timer (gpointer gself) { gchar * title; const gchar * body; + const gchar * icon_name; const struct IndicatorDatetimeAppt * appt = l->data; NotifyNotification * nn; GError * error; @@ -484,8 +485,10 @@ on_alarm_timer (gpointer gself) title = g_date_time_format (now, get_terse_time_format_string (now)); body = appt->summary; - nn = notify_notification_new (title, body, ALARM_ICON_NAME); - + icon_name = ALARM_ICON_NAME; + g_debug ("creating a snap decision with title '%s', body '%s', icon '%s'", + title, body, icon_name); + nn = notify_notification_new (title, body, icon_name); notify_notification_set_hint (nn, "x-canonical-snap-decisions", g_variant_new_boolean(TRUE)); notify_notification_set_hint (nn, "x-canonical-private-button-tint", -- cgit v1.2.3 From da87e44c2fedfea688a77137b7e10e227538e63a Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 9 Oct 2013 23:26:26 -0500 Subject: extract-method: show_snap_decision_for_alarm --- src/service.c | 73 ++++++++++++++++++++++++++++++----------------------------- 1 file changed, 37 insertions(+), 36 deletions(-) diff --git a/src/service.c b/src/service.c index 61d50aa..37f5756 100644 --- a/src/service.c +++ b/src/service.c @@ -453,7 +453,40 @@ on_alarm_popup_ok_clicked (NotifyNotification * nn G_GNUC_UNUSED, char * action url_dispatch_send (url, NULL, NULL); } -#define ALARM_ICON_NAME "alarm-symbolic" +static void +show_snap_decision_for_alarm (const struct IndicatorDatetimeAppt * appt) +{ + gchar * title; + const gchar * body; + const gchar * icon_name; + NotifyNotification * nn; + GError * error; + + title = g_date_time_format (appt->begin, + get_terse_time_format_string (appt->begin)); + body = appt->summary; + icon_name = "alarm-symbolic"; + g_debug ("creating a snap decision with title '%s', body '%s', icon '%s'", + title, body, icon_name); + nn = notify_notification_new (title, body, icon_name); + notify_notification_set_hint (nn, "x-canonical-snap-decisions", + g_variant_new_boolean(TRUE)); + notify_notification_set_hint (nn, "x-canonical-private-button-tint", + g_variant_new_boolean(TRUE)); + notify_notification_add_action (nn, "ok", _("OK"), + on_alarm_popup_ok_clicked, + g_strdup (appt->url), g_free); + error = NULL; + notify_notification_show (nn, &error); + if (error != NULL) + { + g_warning ("Unable to show alarm '%s' popup: %s", body, error->message); + g_error_free (error); + dispatch_alarm_url (appt); + } + + g_free (title); +} static void update_appointment_lists (IndicatorDatetimeService * self); @@ -470,43 +503,11 @@ on_alarm_timer (gpointer gself) now = indicator_datetime_service_get_localtime (self); for (l=self->priv->upcoming_appointments; l!=NULL; l=l->next) { - gchar * title; - const gchar * body; - const gchar * icon_name; const struct IndicatorDatetimeAppt * appt = l->data; - NotifyNotification * nn; - GError * error; - if (!appointment_has_alarm_url (appt)) - continue; - - if (!datetimes_have_the_same_minute (now, appt->begin)) - continue; - - title = g_date_time_format (now, get_terse_time_format_string (now)); - body = appt->summary; - icon_name = ALARM_ICON_NAME; - g_debug ("creating a snap decision with title '%s', body '%s', icon '%s'", - title, body, icon_name); - nn = notify_notification_new (title, body, icon_name); - notify_notification_set_hint (nn, "x-canonical-snap-decisions", - g_variant_new_boolean(TRUE)); - notify_notification_set_hint (nn, "x-canonical-private-button-tint", - g_variant_new_boolean(TRUE)); - notify_notification_add_action (nn, "ok", _("OK"), - on_alarm_popup_ok_clicked, - g_strdup (appt->url), g_free); - //g_signal_connect (nn, "closed", G_CALLBACK(on_notification_closed), self); - - error = NULL; - notify_notification_show (nn, &error); - if (error != NULL) - { - g_warning ("Unable to show alarm '%s' popup: %s", body, error->message); - g_error_free (error); - dispatch_alarm_url (appt); - } - g_free (title); + if (appointment_has_alarm_url (appt)) + if (datetimes_have_the_same_minute (now, appt->begin)) + show_snap_decision_for_alarm (appt); } g_date_time_unref (now); -- cgit v1.2.3 From b23d4229f6ba49d0171034582dd700c6c2328795 Mon Sep 17 00:00:00 2001 From: Automatic PS uploader Date: Fri, 11 Oct 2013 04:27:42 +0000 Subject: Releasing 13.10.0+13.10.20131011-0ubuntu1, based on r267 --- debian/changelog | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/debian/changelog b/debian/changelog index 918b53c..dddf7a5 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,17 @@ +indicator-datetime (13.10.0+13.10.20131011-0ubuntu1) saucy; urgency=low + + [ Charles Kerr ] + * start tracking failure-to-connect-to-bus errors on indicator- + datetime. (LP: #1227519) + * When an unsupported date format is being used, improve the error + message to also include the unsupported date format so that users + can include it in their bug reports. (LP: #1196059) + + [ Ubuntu daily release ] + * Automatic snapshot from revision 267 + + -- Ubuntu daily release Fri, 11 Oct 2013 04:27:40 +0000 + indicator-datetime (13.10.0+13.10.20131004-0ubuntu1) saucy; urgency=low [ Charles Kerr ] -- cgit v1.2.3 From 1293e7fe8e13a6cae1798038e2511b0bc652be41 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 14 Oct 2013 20:04:38 -0500 Subject: use ubuntu mobile's icon name for the alarm clock icon --- src/service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/service.c b/src/service.c index e8d4764..480b4ce 100644 --- a/src/service.c +++ b/src/service.c @@ -505,7 +505,7 @@ create_phone_header_state (IndicatorDatetimeService * self) if ((has_alarms = service_has_alarms (self))) { GIcon * icon; - icon = g_themed_icon_new_with_default_fallbacks ("alarm-symbolic"); + icon = g_themed_icon_new_with_default_fallbacks ("alarm-clock"); g_variant_builder_add (&b, "{sv}", "icon", g_icon_serialize (icon)); g_object_unref (icon); } -- cgit v1.2.3 From b702e8346b7337859f700a935b89046392be4ba9 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 14 Oct 2013 20:49:53 -0500 Subject: add an icon for alarm appointment menuitems --- src/service.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/service.c b/src/service.c index 480b4ce..6601914 100644 --- a/src/service.c +++ b/src/service.c @@ -36,6 +36,7 @@ #define SKEW_CHECK_INTERVAL_SEC 10 #define SKEW_DIFF_THRESHOLD_USEC ((SKEW_CHECK_INTERVAL_SEC+5) * G_USEC_PER_SEC) +#define ALARM_CLOCK_ICON_NAME "alarm-clock" G_DEFINE_TYPE (IndicatorDatetimeService, indicator_datetime_service, @@ -505,7 +506,7 @@ create_phone_header_state (IndicatorDatetimeService * self) if ((has_alarms = service_has_alarms (self))) { GIcon * icon; - icon = g_themed_icon_new_with_default_fallbacks ("alarm-clock"); + icon = g_themed_icon_new_with_default_fallbacks (ALARM_CLOCK_ICON_NAME); g_variant_builder_add (&b, "{sv}", "icon", g_icon_serialize (icon)); g_object_unref (icon); } @@ -735,7 +736,10 @@ add_appointments (IndicatorDatetimeService * self, GMenu * menu, gboolean terse) menu_item = g_menu_item_new (appt->summary, NULL); - if (appt->color && !appt->has_alarms) + if (appt->has_alarms) + g_menu_item_set_attribute (menu_item, G_MENU_ATTRIBUTE_ICON, + "s", ALARM_CLOCK_ICON_NAME); + else if (appt->color != NULL) g_menu_item_set_attribute (menu_item, "x-canonical-color", "s", appt->color); -- cgit v1.2.3 From 7095c0ea670693393cafd8a4d3c295a32855d54e Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 14 Oct 2013 23:20:49 -0500 Subject: ccache our internal GTimeZone instead of constantly re-creating it. --- src/service.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/service.c b/src/service.c index e8d4764..34b7408 100644 --- a/src/service.c +++ b/src/service.c @@ -94,6 +94,9 @@ struct _IndicatorDatetimeServicePrivate IndicatorDatetimeTimezone * tz_geoclue; IndicatorDatetimePlanner * planner; + /* cached GTimeZone for use by indicator_datetime_service_get_localtime() */ + GTimeZone * internal_timezone; + guint own_id; guint actions_export_id; GDBusConnection * conn; @@ -376,6 +379,23 @@ start_header_timer (IndicatorDatetimeService * self) g_date_time_unref (now); } +static void +update_internal_timezone (IndicatorDatetimeService * self) +{ + priv_t * p = self->priv; + const char * id; + + /* find the id from tz_file or tz_geoclue if possible; NULL otherwise */ + id = NULL; + if (!id && p->tz_file) + id = indicator_datetime_timezone_get_timezone (p->tz_file); + if (!id && p->tz_geoclue) + id = indicator_datetime_timezone_get_timezone (p->tz_geoclue); + + g_clear_pointer (&p->internal_timezone, g_time_zone_unref); + p->internal_timezone = g_time_zone_new (id); +} + /** * General purpose handler for rebuilding sections and restarting their timers * when time jumps for whatever reason: @@ -394,6 +414,7 @@ on_local_time_jumped (IndicatorDatetimeService * self) 1. rebuild the necessary states / menuitems when time jumps 2. restart the timers so their new wait interval is correct */ + update_internal_timezone (self); on_header_timer (self); on_timezone_timer (self); } @@ -1794,6 +1815,7 @@ my_dispose (GObject * o) for (i=0; imenus[i].menu); + g_clear_pointer (&p->internal_timezone, g_time_zone_unref); g_clear_object (&p->calendar_action); g_clear_object (&p->desktop_header_action); g_clear_object (&p->phone_header_action); @@ -1989,9 +2011,14 @@ indicator_datetime_service_new (void) /* This currently just returns the system time, As we add test coverage, we'll need this to bypass the system time. */ GDateTime * -indicator_datetime_service_get_localtime (IndicatorDatetimeService * self G_GNUC_UNUSED) +indicator_datetime_service_get_localtime (IndicatorDatetimeService * self) { - return g_date_time_new_now_local (); + priv_t * p = self->priv; + + if (p->internal_timezone == NULL) + update_internal_timezone (self); + + return g_date_time_new_now (p->internal_timezone); } void -- cgit v1.2.3 From 8441fc4f840d668e2b7fe1582f90eef66e272652 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 14 Oct 2013 23:54:40 -0500 Subject: tweak snap decision comments --- src/service.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/service.c b/src/service.c index 37f5756..270f214 100644 --- a/src/service.c +++ b/src/service.c @@ -493,13 +493,11 @@ static void update_appointment_lists (IndicatorDatetimeService * self); static gboolean on_alarm_timer (gpointer gself) { + IndicatorDatetimeService * self = INDICATOR_DATETIME_SERVICE (gself); GDateTime * now; GSList * l; - IndicatorDatetimeService * self = INDICATOR_DATETIME_SERVICE (gself); - /* Check for alarms that start at the current time. - * If we find one, trigger a snap decision displaying - * the appointment text and a single button to dismiss */ + /* If there are any alarms at the current time, show a snap decision */ now = indicator_datetime_service_get_localtime (self); for (l=self->priv->upcoming_appointments; l!=NULL; l=l->next) { @@ -512,7 +510,8 @@ on_alarm_timer (gpointer gself) g_date_time_unref (now); /* rebuild the alarm list asynchronously. - when it's done, set_upcoming_appointments() will update the alarm timer */ + set_upcoming_appointments() will update the alarm timer when this + async call is done, so no need to restart the timer here... */ update_appointment_lists (self); return G_SOURCE_REMOVE; -- cgit v1.2.3 From 3097e2675ece317bc06ae12439e821be774a4ead Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 15 Oct 2013 09:29:49 -0500 Subject: random fiddling: add G_UNLIKELY to the internal_timezone test --- src/service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/service.c b/src/service.c index 34b7408..7bd4f6a 100644 --- a/src/service.c +++ b/src/service.c @@ -2015,7 +2015,7 @@ indicator_datetime_service_get_localtime (IndicatorDatetimeService * self) { priv_t * p = self->priv; - if (p->internal_timezone == NULL) + if (G_UNLIKELY (p->internal_timezone == NULL)) update_internal_timezone (self); return g_date_time_new_now (p->internal_timezone); -- cgit v1.2.3 From 50dbb636dc2078b21a7d981b1d4d3c3a25384648 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 15 Oct 2013 14:14:41 -0500 Subject: use the clock app's icon for the 'Clock' menuitem, and launch the clock app when it's clicked. --- configure.ac | 6 ++++-- debian/control | 1 + src/service.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 61 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 8b95695..c41dc38 100644 --- a/configure.ac +++ b/configure.ac @@ -52,6 +52,7 @@ ICAL_REQUIRED_VERSION=0.48 ECAL_REQUIRED_VERSION=3.5 EDS_REQUIRED_VERSION=3.5 URL_DISPATCHER_1_REQUIRED_VERSION=1 +JSON_GLIB_REQUIRED_VERSION=0.16.2 GTK3_REQUIRED_VERSION=3.1.4 @@ -60,8 +61,9 @@ PKG_CHECK_MODULES(SERVICE, [glib-2.0 >= $GLIB_REQUIRED_VERSION geoclue >= $GEOCLUE_REQUIRED_VERSION libical >= $ICAL_REQUIRED_VERSION libecal-1.2 >= $ECAL_REQUIRED_VERSION - libedataserver-1.2 >= EDS_REQUIRED_VERSION - url-dispatcher-1 >= URL_DISPATCHER_1_REQUIRED_VERSION]) + libedataserver-1.2 >= $EDS_REQUIRED_VERSION + url-dispatcher-1 >= $URL_DISPATCHER_1_REQUIRED_VERSION + json-glib-1.0 >= $JSON_GLIB_REQUIRED_VERSION]) ########################### # Control Center panel diff --git a/debian/control b/debian/control index 67938bf..993d41a 100644 --- a/debian/control +++ b/debian/control @@ -40,6 +40,7 @@ Depends: ${shlibs:Depends}, systemd-shim, Recommends: indicator-applet | indicator-renderer, evolution-data-server, + click, gnome-control-center-datetime | ubuntu-system-settings, Conflicts: indicator-datetime (<< 13.10.0) Replaces: indicator-datetime (<< 13.10.0) diff --git a/src/service.c b/src/service.c index 12857bb..2516b2d 100644 --- a/src/service.c +++ b/src/service.c @@ -24,6 +24,7 @@ #include #include +#include #include #include "dbus-shared.h" @@ -783,14 +784,57 @@ add_appointments (IndicatorDatetimeService * self, GMenu * menu, gboolean terse) g_date_time_unref (now); } +static const gchar * +get_clock_app_icon_filename (void) +{ + static gboolean initialized = FALSE; + static gchar * icon_filename = NULL; + + /* try to extract the clock app's filename from click. (/$pkgdir/$icon) */ + if (!initialized) + { + gchar * pkgdir = NULL; + g_spawn_command_line_sync ("click pkgdir com.ubuntu.clock", &pkgdir, NULL, NULL, NULL); + if (pkgdir != NULL) + { + gchar * manifest = NULL; + g_strstrip (pkgdir); + g_spawn_command_line_sync ("click info com.ubuntu.clock", &manifest, NULL, NULL, NULL); + if (manifest != NULL) + { + JsonParser * parser = json_parser_new (); + if (json_parser_load_from_data (parser, manifest, -1, NULL)) + { + JsonNode * root = json_parser_get_root (parser); /* transfer-none */ + if ((root != NULL) && (JSON_NODE_TYPE(root) == JSON_NODE_OBJECT)) + { + JsonObject * o = json_node_get_object (root); /* transfer-none */ + const gchar * icon_name = json_object_get_string_member (o, "icon"); + icon_filename = g_build_filename (pkgdir, icon_name, NULL); + } + } + g_object_unref (parser); + g_free (manifest); + } + g_free (pkgdir); + } + + initialized = TRUE; + } + + return icon_filename; +} + static GMenuModel * create_phone_appointments_section (IndicatorDatetimeService * self) { GMenu * menu = g_menu_new (); GMenuItem * menu_item; + const gchar * icon_filename; - menu_item = g_menu_item_new (_("Clock"), NULL); - g_menu_item_set_attribute (menu_item, G_MENU_ATTRIBUTE_ICON, "s", "clock"); + menu_item = g_menu_item_new (_("Clock"), "indicator.activate-phone-clock-app"); + if ((icon_filename = get_clock_app_icon_filename ())) + g_menu_item_set_attribute (menu_item, G_MENU_ATTRIBUTE_ICON, "s", icon_filename); g_menu_append_item (menu, menu_item); g_object_unref (menu_item); @@ -1311,6 +1355,15 @@ on_phone_settings_activated (GSimpleAction * a G_GNUC_UNUSED, url_dispatch_send ("settings:///system/time-date", NULL, NULL); } +static void +on_phone_clock_activated (GSimpleAction * a G_GNUC_UNUSED, + GVariant * param G_GNUC_UNUSED, + gpointer gself G_GNUC_UNUSED) +{ + const char * url = "appid://com.ubuntu.clock/clock/current-user-version"; + url_dispatch_send (url, NULL, NULL); +} + static void on_activate_planner (GSimpleAction * a G_GNUC_UNUSED, GVariant * param, @@ -1364,6 +1417,7 @@ init_gactions (IndicatorDatetimeService * self) GActionEntry entries[] = { { "activate-desktop-settings", on_desktop_settings_activated }, { "activate-phone-settings", on_phone_settings_activated }, + { "activate-phone-clock-app", on_phone_clock_activated }, { "activate-planner", on_activate_planner, "x", NULL }, { "set-location", on_set_location, "s" } }; -- cgit v1.2.3 From 6eb9b44c0596ee601cd631278aee6562f93e0007 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 15 Oct 2013 14:44:23 -0500 Subject: make clock_app_icon_filename a field of IndicatorDatetimeServicePriv --- src/service.c | 69 ++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/src/service.c b/src/service.c index 2516b2d..a82e310 100644 --- a/src/service.c +++ b/src/service.c @@ -99,6 +99,13 @@ struct _IndicatorDatetimeServicePrivate /* cached GTimeZone for use by indicator_datetime_service_get_localtime() */ GTimeZone * internal_timezone; + /* the clock app's icon filename */ + gchar * clock_app_icon_filename; + + /* Whether or not we've tried to load the clock app's icon. + This way we don't keep trying to reload it on the desktop */ + gboolean clock_app_icon_initialized; + guint own_id; guint actions_export_id; GDBusConnection * conn; @@ -784,42 +791,39 @@ add_appointments (IndicatorDatetimeService * self, GMenu * menu, gboolean terse) g_date_time_unref (now); } -static const gchar * + +/* try to extract the clock app's filename from click. (/$pkgdir/$icon) */ +static gchar * get_clock_app_icon_filename (void) { - static gboolean initialized = FALSE; - static gchar * icon_filename = NULL; + gchar * icon_filename = NULL; + gchar * pkgdir; - /* try to extract the clock app's filename from click. (/$pkgdir/$icon) */ - if (!initialized) + pkgdir = NULL; + g_spawn_command_line_sync ("click pkgdir com.ubuntu.clock", &pkgdir, NULL, NULL, NULL); + if (pkgdir != NULL) { - gchar * pkgdir = NULL; - g_spawn_command_line_sync ("click pkgdir com.ubuntu.clock", &pkgdir, NULL, NULL, NULL); - if (pkgdir != NULL) + gchar * manifest = NULL; + g_strstrip (pkgdir); + g_spawn_command_line_sync ("click info com.ubuntu.clock", &manifest, NULL, NULL, NULL); + if (manifest != NULL) { - gchar * manifest = NULL; - g_strstrip (pkgdir); - g_spawn_command_line_sync ("click info com.ubuntu.clock", &manifest, NULL, NULL, NULL); - if (manifest != NULL) + JsonParser * parser = json_parser_new (); + if (json_parser_load_from_data (parser, manifest, -1, NULL)) { - JsonParser * parser = json_parser_new (); - if (json_parser_load_from_data (parser, manifest, -1, NULL)) + JsonNode * root = json_parser_get_root (parser); /* transfer-none */ + if ((root != NULL) && (JSON_NODE_TYPE(root) == JSON_NODE_OBJECT)) { - JsonNode * root = json_parser_get_root (parser); /* transfer-none */ - if ((root != NULL) && (JSON_NODE_TYPE(root) == JSON_NODE_OBJECT)) - { - JsonObject * o = json_node_get_object (root); /* transfer-none */ - const gchar * icon_name = json_object_get_string_member (o, "icon"); - icon_filename = g_build_filename (pkgdir, icon_name, NULL); - } + JsonObject * o = json_node_get_object (root); /* transfer-none */ + const gchar * icon_name = json_object_get_string_member (o, "icon"); + if (icon_name != NULL) + icon_filename = g_build_filename (pkgdir, icon_name, NULL); } - g_object_unref (parser); - g_free (manifest); } - g_free (pkgdir); + g_object_unref (parser); + g_free (manifest); } - - initialized = TRUE; + g_free (pkgdir); } return icon_filename; @@ -828,13 +832,19 @@ get_clock_app_icon_filename (void) static GMenuModel * create_phone_appointments_section (IndicatorDatetimeService * self) { + priv_t * p = self->priv; GMenu * menu = g_menu_new (); GMenuItem * menu_item; - const gchar * icon_filename; + + if (G_UNLIKELY (!p->clock_app_icon_initialized)) + { + p->clock_app_icon_initialized = TRUE; + p->clock_app_icon_filename = get_clock_app_icon_filename (); + } menu_item = g_menu_item_new (_("Clock"), "indicator.activate-phone-clock-app"); - if ((icon_filename = get_clock_app_icon_filename ())) - g_menu_item_set_attribute (menu_item, G_MENU_ATTRIBUTE_ICON, "s", icon_filename); + if (p->clock_app_icon_filename != NULL) + g_menu_item_set_attribute (menu_item, G_MENU_ATTRIBUTE_ICON, "s", p->clock_app_icon_filename); g_menu_append_item (menu, menu_item); g_object_unref (menu_item); @@ -1888,6 +1898,7 @@ my_finalize (GObject * o) IndicatorDatetimeService * self = INDICATOR_DATETIME_SERVICE(o); priv_t * p = self->priv; + g_free (p->clock_app_icon_filename); g_clear_pointer (&p->skew_time, g_date_time_unref); g_clear_pointer (&p->calendar_date, g_date_time_unref); -- cgit v1.2.3 From bd3296deab1f75d92733620c607ea3b2cc6c6d05 Mon Sep 17 00:00:00 2001 From: Automatic PS uploader Date: Wed, 16 Oct 2013 02:35:10 +0000 Subject: Releasing 13.10.0+13.10.20131016-0ubuntu1, based on r271 --- debian/changelog | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/debian/changelog b/debian/changelog index dddf7a5..a9ae881 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,18 @@ +indicator-datetime (13.10.0+13.10.20131016-0ubuntu1) saucy; urgency=low + + [ Charles Kerr ] + * Use the Unity Mobile icon name for the alarm clock icon. + * cache our internal GTimeZone instead of constantly re-creating it. + (LP: #1238043) + * Changes the phone profile's "Clock" menuitem in two ways: 1. instead + of using a stock icon, try to use the clock app's icon. 2. when + clicked, launch the clock app. (LP: #1227106) + + [ Ubuntu daily release ] + * Automatic snapshot from revision 271 + + -- Ubuntu daily release Wed, 16 Oct 2013 02:35:10 +0000 + indicator-datetime (13.10.0+13.10.20131011-0ubuntu1) saucy; urgency=low [ Charles Kerr ] -- cgit v1.2.3 From ba2b68b8f38555986c10eb57e9425ccca19199de Mon Sep 17 00:00:00 2001 From: Marcus Tomlinson Date: Wed, 16 Oct 2013 15:45:25 +0200 Subject: Fixed datetime title text to read "Date and Time" rather than the day of the week (as per spec). --- src/service.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/service.c b/src/service.c index a82e310..0b6a138 100644 --- a/src/service.c +++ b/src/service.c @@ -522,7 +522,7 @@ create_phone_header_state (IndicatorDatetimeService * self) gchar * label; gboolean has_alarms; gchar * a11y; - gchar * title; + const gchar * title = _("Date and Time"); g_variant_builder_init (&b, G_VARIANT_TYPE_VARDICT); @@ -550,10 +550,7 @@ create_phone_header_state (IndicatorDatetimeService * self) g_variant_builder_add (&b, "{sv}", "visible", g_variant_new_boolean (TRUE)); g_variant_builder_add (&b, "{sv}", "label", g_variant_new_take_string (label)); - - /* title is day-of-week */ - title = g_date_time_format (now, _("%A")); - g_variant_builder_add (&b, "{sv}", "title", g_variant_new_take_string (title)); + g_variant_builder_add (&b, "{sv}", "title", g_variant_new_string (title)); /* cleanup */ g_date_time_unref (now); -- cgit v1.2.3 From 7034036ebfc0c4a9f2e9e47bced53ae61c3719b8 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 16 Oct 2013 09:50:25 -0500 Subject: don't crash with a g_error() in on_bus_lost(). There's a valid case for this happening when the greeter's bus is force-shutdown --- src/service.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/service.c b/src/service.c index a82e310..c283cf6 100644 --- a/src/service.c +++ b/src/service.c @@ -1815,9 +1815,6 @@ on_name_lost (GDBusConnection * connection G_GNUC_UNUSED, { IndicatorDatetimeService * self = INDICATOR_DATETIME_SERVICE (gself); - if (connection == NULL) - g_error ("Unable to get bus connection to own name '%s'", name); - g_debug ("%s %s name lost %s", G_STRLOC, G_STRFUNC, name); unexport (self); -- cgit v1.2.3 From a5eff35aea5fcbdd97b6d9459e5b05fcb4279676 Mon Sep 17 00:00:00 2001 From: Didier Roche Date: Wed, 16 Oct 2013 17:01:11 +0200 Subject: remove invalid click recommends and downgrade to Suggests --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index 993d41a..22828b5 100644 --- a/debian/control +++ b/debian/control @@ -40,8 +40,8 @@ Depends: ${shlibs:Depends}, systemd-shim, Recommends: indicator-applet | indicator-renderer, evolution-data-server, - click, gnome-control-center-datetime | ubuntu-system-settings, +Suggests: click, Conflicts: indicator-datetime (<< 13.10.0) Replaces: indicator-datetime (<< 13.10.0) Description: Simple clock -- cgit v1.2.3 From a590af19ae6364df31d20a60b0e5050610521d9b Mon Sep 17 00:00:00 2001 From: Marcus Tomlinson Date: Wed, 16 Oct 2013 17:16:02 +0200 Subject: Updated date formatted string in create_phone_calendar_section() from "%e %B %Y" to "%a, %e %B %Y". --- src/service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/service.c b/src/service.c index 0b6a138..17a3cb5 100644 --- a/src/service.c +++ b/src/service.c @@ -683,7 +683,7 @@ create_phone_calendar_section (IndicatorDatetimeService * self) GMenu * menu = g_menu_new (); /* strftime(3) format string to show date */ - add_localtime_menuitem (menu, self, _("%e %B %Y"), "calendar"); + add_localtime_menuitem (menu, self, _("%a, %e %B %Y"), "calendar"); return G_MENU_MODEL (menu); } -- cgit v1.2.3 From fc8dba4e15736ab90da77fe162573f33cd0ba792 Mon Sep 17 00:00:00 2001 From: Automatic PS uploader Date: Wed, 16 Oct 2013 15:30:11 +0000 Subject: Releasing 13.10.0+13.10.20131016.2-0ubuntu1, based on r274 --- debian/changelog | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/debian/changelog b/debian/changelog index a9ae881..fc74793 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,17 @@ +indicator-datetime (13.10.0+13.10.20131016.2-0ubuntu1) saucy; urgency=low + + [ Charles Kerr ] + * Remove the g_error() call that caused an abort() in the call to + on_name_lost() in our bus handler. (LP: #1238737) + + [ Didier Roche ] + * remove invalid click recommends and downgrade to Suggests + + [ Ubuntu daily release ] + * Automatic snapshot from revision 274 + + -- Ubuntu daily release Wed, 16 Oct 2013 15:30:10 +0000 + indicator-datetime (13.10.0+13.10.20131016-0ubuntu1) saucy; urgency=low [ Charles Kerr ] -- cgit v1.2.3 From 32c75bdf48fd0cf14ef76ca338f30edcb6e9b0ac Mon Sep 17 00:00:00 2001 From: Marcus Tomlinson Date: Wed, 16 Oct 2013 17:34:53 +0200 Subject: Fixed date formatted string menu item to display the full name of current day rather than the shortend version. --- src/service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/service.c b/src/service.c index 17a3cb5..4536aa7 100644 --- a/src/service.c +++ b/src/service.c @@ -683,7 +683,7 @@ create_phone_calendar_section (IndicatorDatetimeService * self) GMenu * menu = g_menu_new (); /* strftime(3) format string to show date */ - add_localtime_menuitem (menu, self, _("%a, %e %B %Y"), "calendar"); + add_localtime_menuitem (menu, self, _("%A, %e %B %Y"), "calendar"); return G_MENU_MODEL (menu); } -- cgit v1.2.3 From b2bdf943be53745107a7618e6b11c440fcf71387 Mon Sep 17 00:00:00 2001 From: Marcus Tomlinson Date: Wed, 16 Oct 2013 18:34:39 +0200 Subject: Replace "Date and Time" menu title on phone with "Upcoming" according to updated spec. --- src/service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/service.c b/src/service.c index 4536aa7..b24049c 100644 --- a/src/service.c +++ b/src/service.c @@ -522,7 +522,7 @@ create_phone_header_state (IndicatorDatetimeService * self) gchar * label; gboolean has_alarms; gchar * a11y; - const gchar * title = _("Date and Time"); + const gchar * title = _("Upcoming"); g_variant_builder_init (&b, G_VARIANT_TYPE_VARDICT); -- cgit v1.2.3 From 8dadf00b78312867f33a2f6dcd39118a1beb150c Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 16 Oct 2013 14:52:54 -0500 Subject: for testing purposes, fire off a snap decision as soon as the datetime indicator is started. this way one can test on phablet by running as user phablet --- src/main.c | 57 ++++++++++++++++++++++++++++++++++++++++----------------- src/service.c | 33 ++++++++++----------------------- 2 files changed, 50 insertions(+), 40 deletions(-) diff --git a/src/main.c b/src/main.c index 45ee180..c7ad34a 100644 --- a/src/main.c +++ b/src/main.c @@ -31,30 +31,55 @@ #include "planner-mock.h" #include "service.h" -#define TEST_MODE - /*** **** ***/ static void -on_name_lost (gpointer instance G_GNUC_UNUSED, gpointer loop) +on_name_lost (gpointer instance G_GNUC_UNUSED, gpointer loop G_GNUC_UNUSED) { g_message ("exiting: service couldn't acquire or lost ownership of busname"); g_main_loop_quit ((GMainLoop*)loop); } -#ifdef TEST_MODE static void -log_handler (const gchar * log_domain, - GLogLevelFlags log_level, - const gchar * message, - gpointer fp) +action_ok (NotifyNotification *notification G_GNUC_UNUSED, + char *action, + gpointer gurl) { - fprintf (fp, "%s %d %s\n", log_domain, (int)log_level, message); - fflush (fp); + const char * url = gurl; + g_message ("'%s' clicked for snap decision; url is '%s'", action, url); +} + +static void +show_snap_decision (void) +{ + const gchar * title = "Title"; + const gchar * body = "Body"; + const gchar * icon_name = "alarm-clock"; + NotifyNotification * nn; + GError * error; + + g_debug ("creating a snap decision with title '%s', body '%s', icon '%s'", + title, body, icon_name); + + nn = notify_notification_new (title, body, icon_name); + notify_notification_set_hint (nn, "x-canonical-snap-decisions", + g_variant_new_boolean(TRUE)); + notify_notification_set_hint (nn, "x-canonical-private-button-tint", + g_variant_new_boolean(TRUE)); + notify_notification_add_action (nn, "action_accept", _("OK"), + action_ok, g_strdup("hello world"), g_free); + + g_message ("showing notification %p", nn); + error = NULL; + notify_notification_show (nn, &error); + if (error != NULL) + { + g_warning ("Unable to show alarm '%s' popup: %s", body, error->message); + g_error_free (error); + } } -#endif int main (int argc G_GNUC_UNUSED, char ** argv G_GNUC_UNUSED) @@ -74,14 +99,15 @@ main (int argc G_GNUC_UNUSED, char ** argv G_GNUC_UNUSED) /* set up the planner */ #ifdef TEST_MODE - g_warning ("Using fake appointment book for testing! Probably shouldn't merge this to trunk."); - FILE * fp = fopen ("/tmp/indicator-datetime-log.txt", "w+"); - g_log_set_handler ("Indicator-Datetime", G_LOG_LEVEL_MASK, log_handler, fp); + g_warning ("Using fake appointment book for testing! " + "Probably shouldn't merge this to trunk."); planner = indicator_datetime_planner_mock_new (); #else planner = indicator_datetime_planner_eds_new (); #endif + show_snap_decision (); + /* run */ service = indicator_datetime_service_new (planner); loop = g_main_loop_new (NULL, FALSE); @@ -93,8 +119,5 @@ main (int argc G_GNUC_UNUSED, char ** argv G_GNUC_UNUSED) g_main_loop_unref (loop); g_object_unref (service); g_object_unref (planner); -#ifdef TEST_MODE - fclose (fp); -#endif return 0; } diff --git a/src/service.c b/src/service.c index 270f214..fd3d937 100644 --- a/src/service.c +++ b/src/service.c @@ -432,24 +432,13 @@ dispatch_alarm_url (const struct IndicatorDatetimeAppt * appt) url_dispatch_send (appt->url, NULL, NULL); } -#if 0 static void -on_notification_closed (NotifyNotification * nn, gpointer gself) -{ - //IndicatorDatetimeService * self = INDICATOR_DATETIME_SERVICE (gself); - - g_message ("hello world"); - - /* cleanup */ - g_signal_handlers_disconnect_by_data (nn, gself); - g_object_unref (nn); -} -#endif - -static void -on_alarm_popup_ok_clicked (NotifyNotification * nn G_GNUC_UNUSED, char * action G_GNUC_UNUSED, gpointer gurl) +action_ok (NotifyNotification *notification G_GNUC_UNUSED, + char *action, + gpointer gurl) { const char * url = gurl; + g_debug ("'%s' clicked for snap decision %s", action, url); url_dispatch_send (url, NULL, NULL); } @@ -465,17 +454,18 @@ show_snap_decision_for_alarm (const struct IndicatorDatetimeAppt * appt) title = g_date_time_format (appt->begin, get_terse_time_format_string (appt->begin)); body = appt->summary; - icon_name = "alarm-symbolic"; + icon_name = "alarm-clock"; g_debug ("creating a snap decision with title '%s', body '%s', icon '%s'", title, body, icon_name); + nn = notify_notification_new (title, body, icon_name); notify_notification_set_hint (nn, "x-canonical-snap-decisions", g_variant_new_boolean(TRUE)); notify_notification_set_hint (nn, "x-canonical-private-button-tint", g_variant_new_boolean(TRUE)); - notify_notification_add_action (nn, "ok", _("OK"), - on_alarm_popup_ok_clicked, - g_strdup (appt->url), g_free); + notify_notification_add_action (nn, "action_accept", _("OK"), + action_ok, g_strdup(appt->url), g_free); + error = NULL; notify_notification_show (nn, &error); if (error != NULL) @@ -1981,14 +1971,11 @@ on_name_lost (GDBusConnection * connection G_GNUC_UNUSED, { IndicatorDatetimeService * self = INDICATOR_DATETIME_SERVICE (gself); - if (connection == NULL) - g_error ("Unable to get bus connection to own name '%s'", name); - g_debug ("%s %s name lost %s", G_STRLOC, G_STRFUNC, name); unexport (self); - g_signal_emit (self, signals[SIGNAL_NAME_LOST], 0, NULL); + //g_signal_emit (self, signals[SIGNAL_NAME_LOST], 0, NULL); } -- cgit v1.2.3 From a96e714329ea80e676af5dc5db69ba5b62a25b6e Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 16 Oct 2013 16:48:01 -0500 Subject: add a test mode for alarms. --- src/main.c | 78 ++++++++++++++++++++++++-------------------------------------- 1 file changed, 30 insertions(+), 48 deletions(-) diff --git a/src/main.c b/src/main.c index c7ad34a..3be51eb 100644 --- a/src/main.c +++ b/src/main.c @@ -35,55 +35,28 @@ **** ***/ +/* When enabled, new alarms will show up every minute to test snap decisions */ +static gboolean test_alarms = FALSE; + +static GOptionEntry entries[] = { + { "test-alarms", '\0', 0, G_OPTION_ARG_NONE, &test_alarms, "Test Alarms", NULL }, + { NULL } +}; + static void on_name_lost (gpointer instance G_GNUC_UNUSED, gpointer loop G_GNUC_UNUSED) { g_message ("exiting: service couldn't acquire or lost ownership of busname"); - g_main_loop_quit ((GMainLoop*)loop); -} -static void -action_ok (NotifyNotification *notification G_GNUC_UNUSED, - char *action, - gpointer gurl) -{ - const char * url = gurl; - g_message ("'%s' clicked for snap decision; url is '%s'", action, url); -} - -static void -show_snap_decision (void) -{ - const gchar * title = "Title"; - const gchar * body = "Body"; - const gchar * icon_name = "alarm-clock"; - NotifyNotification * nn; - GError * error; - - g_debug ("creating a snap decision with title '%s', body '%s', icon '%s'", - title, body, icon_name); - - nn = notify_notification_new (title, body, icon_name); - notify_notification_set_hint (nn, "x-canonical-snap-decisions", - g_variant_new_boolean(TRUE)); - notify_notification_set_hint (nn, "x-canonical-private-button-tint", - g_variant_new_boolean(TRUE)); - notify_notification_add_action (nn, "action_accept", _("OK"), - action_ok, g_strdup("hello world"), g_free); - - g_message ("showing notification %p", nn); - error = NULL; - notify_notification_show (nn, &error); - if (error != NULL) - { - g_warning ("Unable to show alarm '%s' popup: %s", body, error->message); - g_error_free (error); - } + if (!test_alarms) + g_main_loop_quit ((GMainLoop*)loop); } int main (int argc G_GNUC_UNUSED, char ** argv G_GNUC_UNUSED) { + GOptionContext * context; + GError * error; IndicatorDatetimePlanner * planner; IndicatorDatetimeService * service; GMainLoop * loop; @@ -97,16 +70,25 @@ main (int argc G_GNUC_UNUSED, char ** argv G_GNUC_UNUSED) if (!notify_init ("indicator-datetime-service")) g_critical ("libnotify initialization failed"); + /* parse command-line options */ + context = g_option_context_new (NULL); + g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE); + if (!g_option_context_parse (context, &argc, &argv, &error)) + { + g_print("option parsing failed: %s\n", error->message); + return EXIT_FAILURE; + } + /* set up the planner */ -#ifdef TEST_MODE - g_warning ("Using fake appointment book for testing! " - "Probably shouldn't merge this to trunk."); - planner = indicator_datetime_planner_mock_new (); -#else - planner = indicator_datetime_planner_eds_new (); -#endif - - show_snap_decision (); + if (test_alarms) + { + g_message ("Using fake appointment book for testing alarms."); + planner = indicator_datetime_planner_mock_new (); + } + else + { + planner = indicator_datetime_planner_eds_new (); + } /* run */ service = indicator_datetime_service_new (planner); -- cgit v1.2.3 From 42b338cdced3f34d719ffda6108818df2e85a84b Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 16 Oct 2013 16:48:28 -0500 Subject: use a two-button snap decision because one-button snap decisions don't show up. --- src/service.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/service.c b/src/service.c index fd3d937..09ee4d4 100644 --- a/src/service.c +++ b/src/service.c @@ -401,8 +401,10 @@ appointment_has_alarm_url (const struct IndicatorDatetimeAppt * appt) } static gboolean -datetimes_have_the_same_minute (GDateTime * a, GDateTime * b) +datetimes_have_the_same_minute (GDateTime * a G_GNUC_UNUSED, GDateTime * b G_GNUC_UNUSED) { +return TRUE; +#if 0 int ay, am, ad; int by, bm, bd; @@ -414,6 +416,7 @@ datetimes_have_the_same_minute (GDateTime * a, GDateTime * b) (ad == bd) && (g_date_time_get_hour (a) == g_date_time_get_hour (b)) && (g_date_time_get_minute (a) == g_date_time_get_minute (b)); +#endif } static void @@ -433,13 +436,18 @@ dispatch_alarm_url (const struct IndicatorDatetimeAppt * appt) } static void -action_ok (NotifyNotification *notification G_GNUC_UNUSED, - char *action, - gpointer gurl) +on_snap_decided (NotifyNotification * notification G_GNUC_UNUSED, + char * action, + gpointer gurl) { - const char * url = gurl; - g_debug ("'%s' clicked for snap decision %s", action, url); - url_dispatch_send (url, NULL, NULL); + g_debug ("%s: %s", G_STRFUNC, action); + + if (!g_strcmp0 (action, "ok")) + { + const gchar * url = gurl; + g_debug ("dispatching url '%s'", url); + url_dispatch_send (url, NULL, NULL); + } } static void @@ -461,10 +469,10 @@ show_snap_decision_for_alarm (const struct IndicatorDatetimeAppt * appt) nn = notify_notification_new (title, body, icon_name); notify_notification_set_hint (nn, "x-canonical-snap-decisions", g_variant_new_boolean(TRUE)); - notify_notification_set_hint (nn, "x-canonical-private-button-tint", - g_variant_new_boolean(TRUE)); - notify_notification_add_action (nn, "action_accept", _("OK"), - action_ok, g_strdup(appt->url), g_free); + notify_notification_add_action (nn, "ok", _("OK"), + on_snap_decided, g_strdup(appt->url), g_free); + notify_notification_add_action (nn, "cancel", _("Cancel"), + on_snap_decided, NULL, NULL); error = NULL; notify_notification_show (nn, &error); @@ -493,6 +501,8 @@ on_alarm_timer (gpointer gself) { const struct IndicatorDatetimeAppt * appt = l->data; +g_message ("[%s][%s]", g_date_time_format (appt->begin, "%F %T"), appt->url); + if (appointment_has_alarm_url (appt)) if (datetimes_have_the_same_minute (now, appt->begin)) show_snap_decision_for_alarm (appt); @@ -1975,7 +1985,7 @@ on_name_lost (GDBusConnection * connection G_GNUC_UNUSED, unexport (self); - //g_signal_emit (self, signals[SIGNAL_NAME_LOST], 0, NULL); + g_signal_emit (self, signals[SIGNAL_NAME_LOST], 0, NULL); } -- cgit v1.2.3 From 831b21bca8afb458cc33e878d8246a00f68e6dbd Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 16 Oct 2013 21:40:13 -0500 Subject: change ok/cancel buttons to the slightly-more-informative show/dismiss --- src/service.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/service.c b/src/service.c index e83410e..9c30310 100644 --- a/src/service.c +++ b/src/service.c @@ -451,7 +451,7 @@ on_snap_decided (NotifyNotification * notification G_GNUC_UNUSED, { g_debug ("%s: %s", G_STRFUNC, action); - if (!g_strcmp0 (action, "ok")) + if (!g_strcmp0 (action, "show")) { const gchar * url = gurl; g_debug ("dispatching url '%s'", url); @@ -478,9 +478,9 @@ show_snap_decision_for_alarm (const struct IndicatorDatetimeAppt * appt) nn = notify_notification_new (title, body, icon_name); notify_notification_set_hint (nn, "x-canonical-snap-decisions", g_variant_new_boolean(TRUE)); - notify_notification_add_action (nn, "ok", _("OK"), + notify_notification_add_action (nn, "show", _("Show"), on_snap_decided, g_strdup(appt->url), g_free); - notify_notification_add_action (nn, "cancel", _("Cancel"), + notify_notification_add_action (nn, "dismiss", _("Dismiss"), on_snap_decided, NULL, NULL); error = NULL; -- cgit v1.2.3 From 05c1039f4b9f0014371bb767089755317ea2d322 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 16 Oct 2013 21:41:28 -0500 Subject: in the alarm snap decision, add x-canonical-private-button-tint hint to highlight the 'Show' button --- src/service.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/service.c b/src/service.c index 9c30310..e42b689 100644 --- a/src/service.c +++ b/src/service.c @@ -476,8 +476,12 @@ show_snap_decision_for_alarm (const struct IndicatorDatetimeAppt * appt) title, body, icon_name); nn = notify_notification_new (title, body, icon_name); - notify_notification_set_hint (nn, "x-canonical-snap-decisions", - g_variant_new_boolean(TRUE)); + notify_notification_set_hint_string (nn, + "x-canonical-snap-decisions", + "true"); + notify_notification_set_hint_string (nn, + "x-canonical-private-button-tint", + "true"); notify_notification_add_action (nn, "show", _("Show"), on_snap_decided, g_strdup(appt->url), g_free); notify_notification_add_action (nn, "dismiss", _("Dismiss"), -- cgit v1.2.3 From f1fe817863e7f167fdb4f98ebd9e5fed33d659b3 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Thu, 17 Oct 2013 08:23:13 -0400 Subject: Work around glib's type initialization deadlock --- src/main.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main.c b/src/main.c index f791683..cd7a6a5 100644 --- a/src/main.c +++ b/src/main.c @@ -60,6 +60,12 @@ main (int argc G_GNUC_UNUSED, char ** argv G_GNUC_UNUSED) IndicatorDatetimeService * service; GMainLoop * loop; + /* Work around a deadlock in glib's type initialization. It can be + * removed when https://bugzilla.gnome.org/show_bug.cgi?id=674885 is + * fixed. + */ + g_type_ensure (G_TYPE_DBUS_CONNECTION); + /* boilerplate i18n */ setlocale (LC_ALL, ""); bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); -- cgit v1.2.3 From bcc04892148c7396e638f45e96fcba42d0034ec7 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 17 Oct 2013 16:32:44 -0500 Subject: refactor the timezone and current time provider into a gobject Interface 'IndicatorDatetimeClock' --- src/Makefile.am | 6 +- src/clock-live.c | 306 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/clock-live.h | 73 ++++++++++++ src/clock.c | 110 ++++++++++++++++++ src/clock.h | 76 +++++++++++++ src/main.c | 41 ++----- src/planner-mock.c | 178 ------------------------------ src/planner-mock.h | 58 ---------- src/service.c | 230 ++++++++++++++++---------------------- src/service.h | 10 +- tests/planner-mock.c | 178 ++++++++++++++++++++++++++++++ tests/planner-mock.h | 58 ++++++++++ 12 files changed, 916 insertions(+), 408 deletions(-) create mode 100644 src/clock-live.c create mode 100644 src/clock-live.h create mode 100644 src/clock.c create mode 100644 src/clock.h delete mode 100644 src/planner-mock.c delete mode 100644 src/planner-mock.h create mode 100644 tests/planner-mock.c create mode 100644 tests/planner-mock.h diff --git a/src/Makefile.am b/src/Makefile.am index 640650a..be7eb4d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -18,10 +18,12 @@ libindicator_datetime_service_a_CFLAGS = \ $(SHARED_CFLAGS) libindicator_datetime_service_a_SOURCES = \ + clock.c \ + clock.h \ + clock-live.c \ + clock-live.h \ planner.c \ planner.h \ - planner-mock.c \ - planner-mock.h \ planner-eds.c \ planner-eds.h \ service.c \ diff --git a/src/clock-live.c b/src/clock-live.c new file mode 100644 index 0000000..6e694ed --- /dev/null +++ b/src/clock-live.c @@ -0,0 +1,306 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include +#include + +#include "config.h" + +#include "clock-live.h" +#include "settings-shared.h" +#include "timezone-file.h" +#include "timezone-geoclue.h" + +/*** +**** private struct +***/ + +struct _IndicatorDatetimeClockLivePriv +{ + GSettings * settings; + + /* cached GTimeZone for use by indicator_datetime_service_get_localtime() */ + GTimeZone * internal_timezone; + + IndicatorDatetimeTimezone * tz_file; + IndicatorDatetimeTimezone * tz_geoclue; +}; + +typedef IndicatorDatetimeClockLivePriv priv_t; + +/*** +**** GObject boilerplate +***/ + +static void indicator_datetime_clock_interface_init ( + IndicatorDatetimeClockInterface * iface); + +G_DEFINE_TYPE_WITH_CODE ( + IndicatorDatetimeClockLive, + indicator_datetime_clock_live, + G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (INDICATOR_TYPE_DATETIME_CLOCK, + indicator_datetime_clock_interface_init)); + +/*** +**** Convenience func +***/ + +#if 0 +static void +emit_changed (IndicatorDatetimeClockLive * self) +{ + indicator_datetime_clock_emit_changed (INDICATOR_DATETIME_CLOCK (self)); +} +#endif + +/*** +**** Timezones +***/ + +static void +update_internal_timezone (IndicatorDatetimeClockLive * self) +{ + priv_t * p = self->priv; + const char * id; + + /* find the id from tz_file or tz_geoclue if possible; NULL otherwise */ + id = NULL; + if (p->tz_file != NULL ) + id = indicator_datetime_timezone_get_timezone (p->tz_file); + if (!id && p->tz_geoclue) + id = indicator_datetime_timezone_get_timezone (p->tz_geoclue); + + g_clear_pointer (&p->internal_timezone, g_time_zone_unref); + p->internal_timezone = g_time_zone_new (id); +} + +static void +on_current_timezone_changed (IndicatorDatetimeClockLive * self) +{ + indicator_datetime_clock_emit_changed (INDICATOR_DATETIME_CLOCK (self)); +} + +static void +set_detect_location_enabled (IndicatorDatetimeClockLive * self, gboolean enabled) +{ + priv_t * p = self->priv; + gboolean changed = FALSE; + + /* geoclue */ + + if (!p->tz_geoclue && enabled) + { + p->tz_geoclue = indicator_datetime_timezone_geoclue_new (); + g_signal_connect_swapped (p->tz_geoclue, "notify::timezone", + G_CALLBACK(on_current_timezone_changed), + self); + changed = TRUE; + } + else if (p->tz_geoclue && !enabled) + { + g_signal_handlers_disconnect_by_func (p->tz_geoclue, + on_current_timezone_changed, + self); + g_clear_object (&p->tz_geoclue); + changed = TRUE; + } + + /* timezone file */ + + if (!p->tz_file && enabled) + { + p->tz_file = indicator_datetime_timezone_file_new (TIMEZONE_FILE); + g_signal_connect_swapped (p->tz_file, "notify::timezone", + G_CALLBACK(on_current_timezone_changed), + self); + changed = TRUE; + } + else if (p->tz_file && !enabled) + { + g_signal_handlers_disconnect_by_func (p->tz_file, + on_current_timezone_changed, + self); + g_clear_object (&p->tz_file); + changed = TRUE; + } + + if (changed) + on_current_timezone_changed (self); +} + +/* When the 'auto-detect timezone' boolean setting changes, + start or stop watching geoclue and /etc/timezone */ +static void +on_detect_location_changed (IndicatorDatetimeClockLive * self) +{ + const gboolean enabled = g_settings_get_boolean (self->priv->settings, SETTINGS_SHOW_DETECTED_S); + set_detect_location_enabled (self, enabled); +} + +/*** +**** IndicatorDatetimeClock virtual functions +***/ + +static gchar ** +my_get_timezones (IndicatorDatetimeClock * clock G_GNUC_UNUSED) +{ + IndicatorDatetimeClockLive * self; + priv_t * p; + GHashTable * hash; + gchar ** timezones; + int i; + GHashTableIter iter; + gpointer key; + + self = INDICATOR_DATETIME_CLOCK_LIVE (clock); + p = self->priv; + + hash = g_hash_table_new (g_str_hash, g_str_equal); + + if (p->tz_file != NULL) + { + const gchar * tz = indicator_datetime_timezone_get_timezone (p->tz_file); + if (tz && *tz) + g_hash_table_add (hash, (gpointer) tz); + } + + if (p->tz_geoclue != NULL) + { + const gchar * tz = indicator_datetime_timezone_get_timezone (p->tz_geoclue); + if (tz && *tz) + g_hash_table_add (hash, (gpointer) tz); + } + + timezones = g_new0 (gchar*, g_hash_table_size(hash) + 1); + i = 0; + g_hash_table_iter_init (&iter, hash); + while (g_hash_table_iter_next (&iter, &key, NULL)) + timezones[i++] = g_strdup (key); + g_hash_table_unref (hash); + return timezones; +} + +static GDateTime * +my_get_current_time (IndicatorDatetimeClock * clock) +{ + IndicatorDatetimeClockLive * self; + priv_t * p; + + self = INDICATOR_DATETIME_CLOCK_LIVE (clock); + p = self->priv; + + if (G_UNLIKELY (p->internal_timezone == NULL)) + update_internal_timezone (self); + + return g_date_time_new_now (p->internal_timezone); +} + +/*** +**** GObject virtual functions +***/ + +static void +my_dispose (GObject * o) +{ + IndicatorDatetimeClockLive * self; + priv_t * p; + + self = INDICATOR_DATETIME_CLOCK_LIVE(o); + p = self->priv; + + g_clear_pointer (&p->internal_timezone, g_time_zone_unref); + + if (p->settings != NULL) + { + g_signal_handlers_disconnect_by_data (p->settings, self); + g_clear_object (&p->settings); + } + + set_detect_location_enabled (self, FALSE); + + G_OBJECT_CLASS (indicator_datetime_clock_live_parent_class)->dispose (o); +} + +static void +my_finalize (GObject * o) +{ +#if 0 + IndicatorDatetimeClockLive * self; + priv_t * p; + + self = INDICATOR_DATETIME_CLOCK_LIVE(o); + p = self->priv; +#endif + + G_OBJECT_CLASS (indicator_datetime_clock_live_parent_class)->dispose (o); +} + +/*** +**** Instantiation +***/ + +static void +indicator_datetime_clock_live_class_init (IndicatorDatetimeClockLiveClass * klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = my_dispose; + object_class->finalize = my_finalize; + + g_type_class_add_private (klass, + sizeof (IndicatorDatetimeClockLivePriv)); +} + +static void +indicator_datetime_clock_interface_init (IndicatorDatetimeClockInterface * iface) +{ + iface->get_timezones = my_get_timezones; + iface->get_current_time = my_get_current_time; +} + +static void +indicator_datetime_clock_live_init (IndicatorDatetimeClockLive * self) +{ + IndicatorDatetimeClockLivePriv * p; + + p = G_TYPE_INSTANCE_GET_PRIVATE (self, + INDICATOR_TYPE_DATETIME_CLOCK_LIVE, + IndicatorDatetimeClockLivePriv); + self->priv = p; + + p->settings = g_settings_new (SETTINGS_INTERFACE); + g_signal_connect (p->settings, "changed::" SETTINGS_SHOW_DETECTED_S, + G_CALLBACK(on_detect_location_changed), self); + + + on_detect_location_changed (self); +} + +/*** +**** Public API +***/ + +IndicatorDatetimeClock * +indicator_datetime_clock_live_new (void) +{ + gpointer o = g_object_new (INDICATOR_TYPE_DATETIME_CLOCK_LIVE, NULL); + + return INDICATOR_DATETIME_CLOCK (o); +} diff --git a/src/clock-live.h b/src/clock-live.h new file mode 100644 index 0000000..4425f5b --- /dev/null +++ b/src/clock-live.h @@ -0,0 +1,73 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#ifndef __INDICATOR_DATETIME_CLOCK_LIVE__H__ +#define __INDICATOR_DATETIME_CLOCK_LIVE__H__ + +#include /* parent class */ + +#include "clock.h" + +G_BEGIN_DECLS + +#define INDICATOR_TYPE_DATETIME_CLOCK_LIVE \ + (indicator_datetime_clock_live_get_type()) + +#define INDICATOR_DATETIME_CLOCK_LIVE(o) \ + (G_TYPE_CHECK_INSTANCE_CAST ((o), \ + INDICATOR_TYPE_DATETIME_CLOCK_LIVE, \ + IndicatorDatetimeClockLive)) + +#define INDICATOR_DATETIME_CLOCK_LIVE_GET_CLASS(o) \ + (G_TYPE_INSTANCE_GET_CLASS ((o), \ + INDICATOR_TYPE_DATETIME_CLOCK_LIVE, \ + IndicatorDatetimeClockLiveClass)) + +#define INDICATOR_IS_DATETIME_CLOCK_LIVE(o) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((o), \ + INDICATOR_TYPE_DATETIME_CLOCK_LIVE)) + +typedef struct _IndicatorDatetimeClockLive + IndicatorDatetimeClockLive; +typedef struct _IndicatorDatetimeClockLivePriv + IndicatorDatetimeClockLivePriv; +typedef struct _IndicatorDatetimeClockLiveClass + IndicatorDatetimeClockLiveClass; + +/** + * An IndicatorDatetimeClock which gives live clock times + * from timezones determined by geoclue and /etc/timezone + */ +struct _IndicatorDatetimeClockLive +{ + GObject parent_instance; + + IndicatorDatetimeClockLivePriv * priv; +}; + +struct _IndicatorDatetimeClockLiveClass +{ + GObjectClass parent_class; +}; + +IndicatorDatetimeClock * indicator_datetime_clock_live_new (void); + +G_END_DECLS + +#endif /* __INDICATOR_DATETIME_CLOCK_LIVE__H__ */ diff --git a/src/clock.c b/src/clock.c new file mode 100644 index 0000000..1abdd21 --- /dev/null +++ b/src/clock.c @@ -0,0 +1,110 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include "clock.h" + +enum +{ + SIGNAL_CHANGED, + SIGNAL_LAST +}; + +static guint signals[SIGNAL_LAST] = { 0 }; + +G_DEFINE_INTERFACE (IndicatorDatetimeClock, + indicator_datetime_clock, + 0); + +static void +indicator_datetime_clock_default_init (IndicatorDatetimeClockInterface * klass) +{ + signals[SIGNAL_CHANGED] = g_signal_new ( + "changed", + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IndicatorDatetimeClockInterface, changed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +/*** +**** PUBLIC API +***/ + +/** + * Get a strv of timezones. + * + * Return value: (element-type char*) + * (transfer full): + * array of timezone strings + */ +gchar ** +indicator_datetime_clock_get_timezones (IndicatorDatetimeClock * self) +{ + gchar ** timezones; + IndicatorDatetimeClockInterface * iface; + + g_return_val_if_fail (INDICATOR_IS_DATETIME_CLOCK(self), NULL); + iface = INDICATOR_DATETIME_CLOCK_GET_INTERFACE(self); + + if (iface->get_timezones != NULL) + timezones = iface->get_timezones (self); + else + timezones = NULL; + + return timezones; +} + +/** + * Get the current time. + * + * Return value: (element-type GDateTime*) + * (transfer full): + * the current time. + */ +GDateTime * +indicator_datetime_clock_get_current_time (IndicatorDatetimeClock * self) +{ + GDateTime * now; + IndicatorDatetimeClockInterface * iface; + + g_return_val_if_fail (INDICATOR_IS_DATETIME_CLOCK(self), NULL); + iface = INDICATOR_DATETIME_CLOCK_GET_INTERFACE(self); + + if (iface->get_current_time != NULL) + now = iface->get_current_time (self); + else + now = NULL; + + return now; +} + +/** + * Emits the "changed" signal. + * + * This should only be called by subclasses. + */ +void +indicator_datetime_clock_emit_changed (IndicatorDatetimeClock * self) +{ + g_return_if_fail (INDICATOR_IS_DATETIME_CLOCK (self)); + + g_signal_emit (self, signals[SIGNAL_CHANGED], 0, NULL); +} diff --git a/src/clock.h b/src/clock.h new file mode 100644 index 0000000..8932895 --- /dev/null +++ b/src/clock.h @@ -0,0 +1,76 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#ifndef __INDICATOR_DATETIME_CLOCK__H__ +#define __INDICATOR_DATETIME_CLOCK__H__ + +#include + +G_BEGIN_DECLS + +#define INDICATOR_TYPE_DATETIME_CLOCK \ + (indicator_datetime_clock_get_type ()) + +#define INDICATOR_DATETIME_CLOCK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + INDICATOR_TYPE_DATETIME_CLOCK, \ + IndicatorDatetimeClock)) + +#define INDICATOR_IS_DATETIME_CLOCK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INDICATOR_TYPE_DATETIME_CLOCK)) + +#define INDICATOR_DATETIME_CLOCK_GET_INTERFACE(inst) \ + (G_TYPE_INSTANCE_GET_INTERFACE ((inst), \ + INDICATOR_TYPE_DATETIME_CLOCK, \ + IndicatorDatetimeClockInterface)) + +typedef struct _IndicatorDatetimeClock + IndicatorDatetimeClock; + +typedef struct _IndicatorDatetimeClockInterface + IndicatorDatetimeClockInterface; + +struct _IndicatorDatetimeClockInterface +{ + GTypeInterface parent_iface; + + /* signals */ + void (*changed) (IndicatorDatetimeClock * self); + + /* virtual functions */ + gchar** (*get_timezones) (IndicatorDatetimeClock * self); + GDateTime* (*get_current_time) (IndicatorDatetimeClock * self); +}; + +GType indicator_datetime_clock_get_type (void); + +/*** +**** +***/ + +gchar ** indicator_datetime_clock_get_timezones (IndicatorDatetimeClock * clock); + +GDateTime * indicator_datetime_clock_get_current_time (IndicatorDatetimeClock * clock); + +void indicator_datetime_clock_emit_changed (IndicatorDatetimeClock * clock); + + +G_END_DECLS + +#endif /* __INDICATOR_DATETIME_CLOCK__H__ */ diff --git a/src/main.c b/src/main.c index f791683..9305794 100644 --- a/src/main.c +++ b/src/main.c @@ -26,36 +26,26 @@ #include #include +#include "clock-live.h" #include "planner-eds.h" -#include "planner-mock.h" #include "service.h" /*** **** ***/ -/* When enabled, new alarms will show up every minute to test snap decisions */ -static gboolean test_alarms = FALSE; - -static GOptionEntry entries[] = { - { "test-alarms", '\0', 0, G_OPTION_ARG_NONE, &test_alarms, "Test Alarms", NULL }, - { NULL } -}; - static void on_name_lost (gpointer instance G_GNUC_UNUSED, gpointer loop) { g_message ("exiting: service couldn't acquire or lost ownership of busname"); - if (!test_alarms) - g_main_loop_quit ((GMainLoop*)loop); + g_main_loop_quit ((GMainLoop*)loop); } int main (int argc G_GNUC_UNUSED, char ** argv G_GNUC_UNUSED) { - GOptionContext * context; - GError * error; + IndicatorDatetimeClock * clock; IndicatorDatetimePlanner * planner; IndicatorDatetimeService * service; GMainLoop * loop; @@ -69,28 +59,10 @@ main (int argc G_GNUC_UNUSED, char ** argv G_GNUC_UNUSED) if (!notify_init ("indicator-datetime-service")) g_critical ("libnotify initialization failed"); - /* parse command-line options */ - context = g_option_context_new (NULL); - g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE); - if (!g_option_context_parse (context, &argc, &argv, &error)) - { - g_print("option parsing failed: %s\n", error->message); - return EXIT_FAILURE; - } - - /* set up the planner */ - if (test_alarms) - { - g_message ("Using fake appointment book for testing alarms."); - planner = indicator_datetime_planner_mock_new (); - } - else - { - planner = indicator_datetime_planner_eds_new (); - } - /* run */ - service = indicator_datetime_service_new (planner); + clock = indicator_datetime_clock_live_new (); + planner = indicator_datetime_planner_eds_new (); + service = indicator_datetime_service_new (clock, planner); loop = g_main_loop_new (NULL, FALSE); g_signal_connect (service, INDICATOR_DATETIME_SERVICE_SIGNAL_NAME_LOST, G_CALLBACK(on_name_lost), loop); @@ -100,5 +72,6 @@ main (int argc G_GNUC_UNUSED, char ** argv G_GNUC_UNUSED) g_main_loop_unref (loop); g_object_unref (service); g_object_unref (planner); + g_object_unref (clock); return 0; } diff --git a/src/planner-mock.c b/src/planner-mock.c deleted file mode 100644 index e67ad7e..0000000 --- a/src/planner-mock.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright 2013 Canonical Ltd. - * - * Authors: - * Charles Kerr - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 3, as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranties of - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - */ - -#include "config.h" - -#include "planner-mock.h" - -struct _IndicatorDatetimePlannerMockPriv -{ - gboolean is_configured; -}; - -typedef IndicatorDatetimePlannerMockPriv priv_t; - -G_DEFINE_TYPE (IndicatorDatetimePlannerMock, - indicator_datetime_planner_mock, - INDICATOR_TYPE_DATETIME_PLANNER) - -/*** -**** IndicatorDatetimePlanner virtual funcs -***/ - -static void -my_get_appointments (IndicatorDatetimePlanner * planner, - GDateTime * begin_datetime, - GDateTime * end_datetime G_GNUC_UNUSED, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask * task; - GSList * appointments; - struct IndicatorDatetimeAppt * appt; - struct IndicatorDatetimeAppt * prev; - - task = g_task_new (planner, NULL, callback, user_data); - - /** - *** Build the appointments list - **/ - - appointments = NULL; - - /* add a daily appointment that occurs at the beginning of the next minute */ - appt = g_slice_new0 (struct IndicatorDatetimeAppt); - appt->is_daily = TRUE; - appt->begin = g_date_time_add_seconds (begin_datetime, 60-g_date_time_get_seconds(begin_datetime)); - appt->end = g_date_time_add_minutes (appt->begin, 1); - appt->color = g_strdup ("#00FF00"); - appt->is_event = TRUE; - appt->summary = g_strdup ("Daily alarm"); - appt->uid = g_strdup ("this uid isn't very random."); - appt->has_alarms = TRUE; - appt->url = g_strdup ("alarm:///some-alarm-info-goes-here"); - appointments = g_slist_prepend (appointments, appt); - prev = appt; - - /* and add one for a minute later that has an alarm uri */ - appt = g_slice_new0 (struct IndicatorDatetimeAppt); - appt->is_daily = TRUE; - appt->begin = g_date_time_add_minutes (prev->end, 1); - appt->end = g_date_time_add_minutes (appt->begin, 1); - appt->color = g_strdup ("#0000FF"); - appt->is_event = TRUE; - appt->summary = g_strdup ("Second Daily alarm"); - appt->uid = g_strdup ("this uid isn't very random either."); - appt->has_alarms = FALSE; - appointments = g_slist_prepend (appointments, appt); - - /* done */ - g_task_return_pointer (task, appointments, NULL); - g_object_unref (task); -} - -static GSList * -my_get_appointments_finish (IndicatorDatetimePlanner * self G_GNUC_UNUSED, - GAsyncResult * res, - GError ** error) -{ - return g_task_propagate_pointer (G_TASK(res), error); -} - -static gboolean -my_is_configured (IndicatorDatetimePlanner * planner) -{ - IndicatorDatetimePlannerMock * self; - self = INDICATOR_DATETIME_PLANNER_MOCK (planner); - return self->priv->is_configured; -} - -static void -my_activate (IndicatorDatetimePlanner * self G_GNUC_UNUSED) -{ - g_message ("%s %s", G_STRLOC, G_STRFUNC); -} - -static void -my_activate_time (IndicatorDatetimePlanner * self G_GNUC_UNUSED, - GDateTime * activate_time) -{ - gchar * str = g_date_time_format (activate_time, "%F %T"); - g_message ("%s %s: %s", G_STRLOC, G_STRFUNC, str); - g_free (str); -} - -/*** -**** GObject virtual funcs -***/ - -static void -my_dispose (GObject * o) -{ - G_OBJECT_CLASS (indicator_datetime_planner_mock_parent_class)->dispose (o); -} - -/*** -**** Instantiation -***/ - -static void -indicator_datetime_planner_mock_class_init (IndicatorDatetimePlannerMockClass * klass) -{ - GObjectClass * object_class; - IndicatorDatetimePlannerClass * planner_class; - - object_class = G_OBJECT_CLASS (klass); - object_class->dispose = my_dispose; - - planner_class = INDICATOR_DATETIME_PLANNER_CLASS (klass); - planner_class->is_configured = my_is_configured; - planner_class->activate = my_activate; - planner_class->activate_time = my_activate_time; - planner_class->get_appointments = my_get_appointments; - planner_class->get_appointments_finish = my_get_appointments_finish; - - g_type_class_add_private (klass, sizeof (IndicatorDatetimePlannerMockPriv)); -} - -static void -indicator_datetime_planner_mock_init (IndicatorDatetimePlannerMock * self) -{ - priv_t * p; - - p = G_TYPE_INSTANCE_GET_PRIVATE (self, - INDICATOR_TYPE_DATETIME_PLANNER_MOCK, - IndicatorDatetimePlannerMockPriv); - - p->is_configured = TRUE; - - self->priv = p; -} - -/*** -**** Public -***/ - -IndicatorDatetimePlanner * -indicator_datetime_planner_mock_new (void) -{ - gpointer o = g_object_new (INDICATOR_TYPE_DATETIME_PLANNER_MOCK, NULL); - - return INDICATOR_DATETIME_PLANNER (o); -} diff --git a/src/planner-mock.h b/src/planner-mock.h deleted file mode 100644 index 8d7d7c2..0000000 --- a/src/planner-mock.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2013 Canonical Ltd. - * - * Authors: - * Charles Kerr - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 3, as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranties of - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - */ - -#ifndef __INDICATOR_DATETIME_PLANNER_MOCK__H__ -#define __INDICATOR_DATETIME_PLANNER_MOCK__H__ - -#include "planner.h" /* parent class */ - -G_BEGIN_DECLS - -#define INDICATOR_TYPE_DATETIME_PLANNER_MOCK (indicator_datetime_planner_mock_get_type()) -#define INDICATOR_DATETIME_PLANNER_MOCK(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), INDICATOR_TYPE_DATETIME_PLANNER_MOCK, IndicatorDatetimePlannerMock)) -#define INDICATOR_DATETIME_PLANNER_MOCK_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), INDICATOR_TYPE_DATETIME_PLANNER_MOCK, IndicatorDatetimePlannerMockClass)) -#define INDICATOR_IS_DATETIME_PLANNER_MOCK(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), INDICATOR_TYPE_DATETIME_PLANNER_MOCK)) - -typedef struct _IndicatorDatetimePlannerMock IndicatorDatetimePlannerMock; -typedef struct _IndicatorDatetimePlannerMockPriv IndicatorDatetimePlannerMockPriv; -typedef struct _IndicatorDatetimePlannerMockClass IndicatorDatetimePlannerMockClass; - -GType indicator_datetime_planner_mock_get_type (void); - -/** - * An IndicatorDatetimePlanner which uses Evolution Data Server - * to get its list of appointments. - */ -struct _IndicatorDatetimePlannerMock -{ - /*< private >*/ - IndicatorDatetimePlanner parent; - IndicatorDatetimePlannerMockPriv * priv; -}; - -struct _IndicatorDatetimePlannerMockClass -{ - IndicatorDatetimePlannerClass parent_class; -}; - -IndicatorDatetimePlanner * indicator_datetime_planner_mock_new (void); - -G_END_DECLS - -#endif /* __INDICATOR_DATETIME_PLANNER_MOCK__H__ */ diff --git a/src/service.c b/src/service.c index 08945bc..b777b8c 100644 --- a/src/service.c +++ b/src/service.c @@ -29,8 +29,6 @@ #include #include "dbus-shared.h" -#include "timezone-file.h" -#include "timezone-geoclue.h" #include "service.h" #include "settings-shared.h" #include "utils.h" @@ -54,6 +52,7 @@ static guint signals[LAST_SIGNAL] = { 0 }; enum { PROP_0, + PROP_CLOCK, PROP_PLANNER, PROP_LAST }; @@ -101,13 +100,9 @@ struct _IndicatorDatetimeServicePrivate GSettings * settings; - IndicatorDatetimeTimezone * tz_file; - IndicatorDatetimeTimezone * tz_geoclue; + IndicatorDatetimeClock * clock; IndicatorDatetimePlanner * planner; - /* cached GTimeZone for use by indicator_datetime_service_get_localtime() */ - GTimeZone * internal_timezone; - /* the clock app's icon filename */ gchar * clock_app_icon_filename; @@ -168,6 +163,12 @@ indicator_clear_timer (guint * tag) } } +static inline GDateTime * +indicator_datetime_service_get_localtime (IndicatorDatetimeService * self) +{ + return indicator_datetime_clock_get_current_time (self->priv->clock); +} + /*** **** ***/ @@ -589,23 +590,6 @@ set_alarm_timer (IndicatorDatetimeService * self) **** ***/ -static void -update_internal_timezone (IndicatorDatetimeService * self) -{ - priv_t * p = self->priv; - const char * id; - - /* find the id from tz_file or tz_geoclue if possible; NULL otherwise */ - id = NULL; - if (!id && p->tz_file) - id = indicator_datetime_timezone_get_timezone (p->tz_file); - if (!id && p->tz_geoclue) - id = indicator_datetime_timezone_get_timezone (p->tz_geoclue); - - g_clear_pointer (&p->internal_timezone, g_time_zone_unref); - p->internal_timezone = g_time_zone_new (id); -} - /** * General purpose handler for rebuilding sections and restarting their timers * when time jumps for whatever reason: @@ -624,7 +608,6 @@ on_local_time_jumped (IndicatorDatetimeService * self) 1. rebuild the necessary states / menuitems when time jumps 2. restart the timers so their new wait interval is correct */ - update_internal_timezone (self); on_header_timer (self); on_timezone_timer (self); } @@ -1100,61 +1083,6 @@ create_desktop_appointments_section (IndicatorDatetimeService * self) **** ***/ -static void -on_current_timezone_changed (IndicatorDatetimeService * self) -{ - on_local_time_jumped (self); -} - -/* When the 'auto-detect timezone' boolean setting changes, - start or stop watching geoclue and /etc/timezone */ -static void -set_detect_location_enabled (IndicatorDatetimeService * self, gboolean enabled) -{ - gboolean changed = FALSE; - priv_t * p = self->priv; - - /* geoclue */ - - if (!p->tz_geoclue && enabled) - { - p->tz_geoclue = indicator_datetime_timezone_geoclue_new (); - g_signal_connect_swapped (p->tz_geoclue, "notify::timezone", - G_CALLBACK(on_current_timezone_changed), - self); - changed = TRUE; - } - else if (p->tz_geoclue && !enabled) - { - g_signal_handlers_disconnect_by_func (p->tz_geoclue, - on_current_timezone_changed, - self); - g_clear_object (&p->tz_geoclue); - changed = TRUE; - } - - /* timezone file */ - - if (!p->tz_file && enabled) - { - p->tz_file = indicator_datetime_timezone_file_new (TIMEZONE_FILE); - g_signal_connect_swapped (p->tz_file, "notify::timezone", - G_CALLBACK(on_current_timezone_changed), - self); - changed = TRUE; - } - else if (p->tz_file && !enabled) - { - g_signal_handlers_disconnect_by_func (p->tz_file, - on_current_timezone_changed, - self); - g_clear_object (&p->tz_file); - changed = TRUE; - } - - if (changed) - on_current_timezone_changed (self); -} /* A temp struct used by create_locations_section() for pruning duplicates and sorting. */ @@ -1240,44 +1168,30 @@ create_locations_section (IndicatorDatetimeService * self) GSList * l; GSList * locations = NULL; gchar ** user_locations; - gboolean visible; - IndicatorDatetimeTimezone * detected_timezones[2]; + gchar ** detected_timezones; priv_t * p = self->priv; GDateTime * now = indicator_datetime_service_get_localtime (self); - set_detect_location_enabled (self, - g_settings_get_boolean (p->settings, SETTINGS_SHOW_DETECTED_S)); - menu = g_menu_new (); /*** - **** Build a list of locations to add: use geo_timezone, - **** current_timezone, and SETTINGS_LOCATIONS_S, but omit duplicates. + **** Build a list of locations to add, omitting duplicates ***/ - /* maybe add the auto-detected timezones */ - detected_timezones[0] = p->tz_geoclue; - detected_timezones[1] = p->tz_file; - visible = g_settings_get_boolean (p->settings, SETTINGS_SHOW_DETECTED_S); - for (i=0; iclock); + for (i=0; detected_timezones && detected_timezones[i]; i++) { - if (detected_timezones[i] != NULL) - { - const char * tz = indicator_datetime_timezone_get_timezone (detected_timezones[i]); - if (tz && *tz) - { - gchar * name = get_current_zone_name (tz, p->settings); - locations = locations_add (locations, tz, name, visible); - g_free (name); - } - } + const char * tz = detected_timezones[i]; + gchar * name = get_current_zone_name (tz, p->settings); + locations = locations_add (locations, tz, name, TRUE); } + g_strfreev (detected_timezones); /* maybe add the user-specified locations */ user_locations = g_settings_get_strv (p->settings, SETTINGS_LOCATIONS_S); if (user_locations != NULL) { - visible = g_settings_get_boolean (p->settings, SETTINGS_SHOW_LOCATIONS_S); + const gboolean visible = g_settings_get_boolean (p->settings, SETTINGS_SHOW_LOCATIONS_S); for (i=0; user_locations[i] != NULL; i++) { @@ -1735,6 +1649,9 @@ rebuild_now (IndicatorDatetimeService * self, int sections) struct ProfileMenuInfo * desktop = &p->menus[PROFILE_DESKTOP]; struct ProfileMenuInfo * greeter = &p->menus[PROFILE_GREETER]; + if (p->actions == NULL) + return; + if (sections & SECTION_HEADER) { g_simple_action_set_state (p->desktop_header_action, @@ -2088,6 +2005,10 @@ my_get_property (GObject * o, switch (property_id) { + case PROP_CLOCK: + g_value_set_object (value, self->priv->clock); + break; + case PROP_PLANNER: g_value_set_object (value, self->priv->planner); break; @@ -2107,6 +2028,10 @@ my_set_property (GObject * o, switch (property_id) { + case PROP_CLOCK: + indicator_datetime_service_set_clock (self, g_value_get_object (value)); + break; + case PROP_PLANNER: indicator_datetime_service_set_planner (self, g_value_get_object (value)); break; @@ -2138,8 +2063,7 @@ my_dispose (GObject * o) g_clear_object (&p->cancellable); } - set_detect_location_enabled (self, FALSE); - + indicator_datetime_service_set_clock (self, NULL); indicator_datetime_service_set_planner (self, NULL); if (p->login1_manager != NULL) @@ -2165,7 +2089,6 @@ my_dispose (GObject * o) for (i=0; imenus[i].menu); - g_clear_pointer (&p->internal_timezone, g_time_zone_unref); g_clear_object (&p->calendar_action); g_clear_object (&p->desktop_header_action); g_clear_object (&p->phone_header_action); @@ -2194,9 +2117,27 @@ my_finalize (GObject * o) static void indicator_datetime_service_init (IndicatorDatetimeService * self) { - guint i, n; priv_t * p; + + /* init the priv pointer */ + + p = G_TYPE_INSTANCE_GET_PRIVATE (self, + INDICATOR_TYPE_DATETIME_SERVICE, + IndicatorDatetimeServicePrivate); + self->priv = p; + + p->cancellable = g_cancellable_new (); + + p->settings = g_settings_new (SETTINGS_INTERFACE); +} + +static void +my_constructed (GObject * gself) +{ + IndicatorDatetimeService * self = INDICATOR_DATETIME_SERVICE (gself); + priv_t * p = self->priv; GString * gstr = g_string_new (NULL); + guint i, n; /* these are the settings that affect the contents of the respective sections */ @@ -2233,20 +2174,10 @@ indicator_datetime_service_init (IndicatorDatetimeService * self) }; - /* init the priv pointer */ - - p = G_TYPE_INSTANCE_GET_PRIVATE (self, - INDICATOR_TYPE_DATETIME_SERVICE, - IndicatorDatetimeServicePrivate); - self->priv = p; - - p->cancellable = g_cancellable_new (); - /*** - **** Create the settings object and listen for changes + **** Listen for settings changes ***/ - p->settings = g_settings_new (SETTINGS_INTERFACE); for (i=0, n=G_N_ELEMENTS(header_settings); idispose = my_dispose; object_class->finalize = my_finalize; + object_class->constructed = my_constructed; object_class->get_property = my_get_property; object_class->set_property = my_set_property; @@ -2345,6 +2277,12 @@ indicator_datetime_service_class_init (IndicatorDatetimeServiceClass * klass) properties[PROP_0] = NULL; + properties[PROP_CLOCK] = g_param_spec_object ("clock", + "Clock", + "The clock", + G_TYPE_OBJECT, + flags); + properties[PROP_PLANNER] = g_param_spec_object ("planner", "Planner", "The appointment provider", @@ -2359,28 +2297,17 @@ indicator_datetime_service_class_init (IndicatorDatetimeServiceClass * klass) ***/ IndicatorDatetimeService * -indicator_datetime_service_new (IndicatorDatetimePlanner * planner) +indicator_datetime_service_new (IndicatorDatetimeClock * clock, + IndicatorDatetimePlanner * planner) { GObject * o = g_object_new (INDICATOR_TYPE_DATETIME_SERVICE, + "clock", clock, "planner", planner, NULL); return INDICATOR_DATETIME_SERVICE (o); } -/* This currently just returns the system time, - As we add test coverage, we'll need this to bypass the system time. */ -GDateTime * -indicator_datetime_service_get_localtime (IndicatorDatetimeService * self) -{ - priv_t * p = self->priv; - - if (G_UNLIKELY (p->internal_timezone == NULL)) - update_internal_timezone (self); - - return g_date_time_new_now (p->internal_timezone); -} - void indicator_datetime_service_set_calendar_date (IndicatorDatetimeService * self, GDateTime * date) @@ -2400,6 +2327,43 @@ indicator_datetime_service_set_calendar_date (IndicatorDatetimeService * self, update_appointment_lists (self); } +static void +on_clock_changed (IndicatorDatetimeService * self) +{ + on_local_time_jumped (self); +} + +void +indicator_datetime_service_set_clock (IndicatorDatetimeService * self, + IndicatorDatetimeClock * clock) +{ + priv_t * p; + + g_return_if_fail (INDICATOR_IS_DATETIME_SERVICE (self)); + g_return_if_fail ((clock == NULL) || INDICATOR_IS_DATETIME_CLOCK (clock)); + + p = self->priv; + + /* clear the old clock */ + + if (p->clock != NULL) + { + g_signal_handlers_disconnect_by_data (p->clock, self); + g_clear_object (&p->clock); + } + + /* set the new clock */ + + if (clock != NULL) + { + p->clock = g_object_ref (clock); + + g_signal_connect_swapped (p->clock, "changed", + G_CALLBACK(on_clock_changed), self); + on_clock_changed (self); + } +} + void indicator_datetime_service_set_planner (IndicatorDatetimeService * self, IndicatorDatetimePlanner * planner) @@ -2407,7 +2371,7 @@ indicator_datetime_service_set_planner (IndicatorDatetimeService * self, priv_t * p; g_return_if_fail (INDICATOR_IS_DATETIME_SERVICE (self)); - g_return_if_fail (INDICATOR_IS_DATETIME_PLANNER (planner)); + g_return_if_fail ((planner == NULL) || INDICATOR_IS_DATETIME_PLANNER (planner)); p = self->priv; diff --git a/src/service.h b/src/service.h index 25bb59a..d38db72 100644 --- a/src/service.h +++ b/src/service.h @@ -22,6 +22,8 @@ #include #include + +#include "clock.h" #include "planner.h" G_BEGIN_DECLS @@ -63,9 +65,8 @@ struct _IndicatorDatetimeServiceClass GType indicator_datetime_service_get_type (void); -IndicatorDatetimeService * indicator_datetime_service_new (IndicatorDatetimePlanner * planner); - -GDateTime * indicator_datetime_service_get_localtime (IndicatorDatetimeService * service); +IndicatorDatetimeService * indicator_datetime_service_new (IndicatorDatetimeClock * clock, + IndicatorDatetimePlanner * planner); void indicator_datetime_service_set_calendar_date (IndicatorDatetimeService * self, GDateTime * date); @@ -74,6 +75,9 @@ void indicator_datetime_service_set_planner (IndicatorDatetimeService * self, IndicatorDatetimePlanner * planner); +void indicator_datetime_service_set_clock (IndicatorDatetimeService * self, + IndicatorDatetimeClock * clock); + G_END_DECLS diff --git a/tests/planner-mock.c b/tests/planner-mock.c new file mode 100644 index 0000000..e67ad7e --- /dev/null +++ b/tests/planner-mock.c @@ -0,0 +1,178 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include "config.h" + +#include "planner-mock.h" + +struct _IndicatorDatetimePlannerMockPriv +{ + gboolean is_configured; +}; + +typedef IndicatorDatetimePlannerMockPriv priv_t; + +G_DEFINE_TYPE (IndicatorDatetimePlannerMock, + indicator_datetime_planner_mock, + INDICATOR_TYPE_DATETIME_PLANNER) + +/*** +**** IndicatorDatetimePlanner virtual funcs +***/ + +static void +my_get_appointments (IndicatorDatetimePlanner * planner, + GDateTime * begin_datetime, + GDateTime * end_datetime G_GNUC_UNUSED, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask * task; + GSList * appointments; + struct IndicatorDatetimeAppt * appt; + struct IndicatorDatetimeAppt * prev; + + task = g_task_new (planner, NULL, callback, user_data); + + /** + *** Build the appointments list + **/ + + appointments = NULL; + + /* add a daily appointment that occurs at the beginning of the next minute */ + appt = g_slice_new0 (struct IndicatorDatetimeAppt); + appt->is_daily = TRUE; + appt->begin = g_date_time_add_seconds (begin_datetime, 60-g_date_time_get_seconds(begin_datetime)); + appt->end = g_date_time_add_minutes (appt->begin, 1); + appt->color = g_strdup ("#00FF00"); + appt->is_event = TRUE; + appt->summary = g_strdup ("Daily alarm"); + appt->uid = g_strdup ("this uid isn't very random."); + appt->has_alarms = TRUE; + appt->url = g_strdup ("alarm:///some-alarm-info-goes-here"); + appointments = g_slist_prepend (appointments, appt); + prev = appt; + + /* and add one for a minute later that has an alarm uri */ + appt = g_slice_new0 (struct IndicatorDatetimeAppt); + appt->is_daily = TRUE; + appt->begin = g_date_time_add_minutes (prev->end, 1); + appt->end = g_date_time_add_minutes (appt->begin, 1); + appt->color = g_strdup ("#0000FF"); + appt->is_event = TRUE; + appt->summary = g_strdup ("Second Daily alarm"); + appt->uid = g_strdup ("this uid isn't very random either."); + appt->has_alarms = FALSE; + appointments = g_slist_prepend (appointments, appt); + + /* done */ + g_task_return_pointer (task, appointments, NULL); + g_object_unref (task); +} + +static GSList * +my_get_appointments_finish (IndicatorDatetimePlanner * self G_GNUC_UNUSED, + GAsyncResult * res, + GError ** error) +{ + return g_task_propagate_pointer (G_TASK(res), error); +} + +static gboolean +my_is_configured (IndicatorDatetimePlanner * planner) +{ + IndicatorDatetimePlannerMock * self; + self = INDICATOR_DATETIME_PLANNER_MOCK (planner); + return self->priv->is_configured; +} + +static void +my_activate (IndicatorDatetimePlanner * self G_GNUC_UNUSED) +{ + g_message ("%s %s", G_STRLOC, G_STRFUNC); +} + +static void +my_activate_time (IndicatorDatetimePlanner * self G_GNUC_UNUSED, + GDateTime * activate_time) +{ + gchar * str = g_date_time_format (activate_time, "%F %T"); + g_message ("%s %s: %s", G_STRLOC, G_STRFUNC, str); + g_free (str); +} + +/*** +**** GObject virtual funcs +***/ + +static void +my_dispose (GObject * o) +{ + G_OBJECT_CLASS (indicator_datetime_planner_mock_parent_class)->dispose (o); +} + +/*** +**** Instantiation +***/ + +static void +indicator_datetime_planner_mock_class_init (IndicatorDatetimePlannerMockClass * klass) +{ + GObjectClass * object_class; + IndicatorDatetimePlannerClass * planner_class; + + object_class = G_OBJECT_CLASS (klass); + object_class->dispose = my_dispose; + + planner_class = INDICATOR_DATETIME_PLANNER_CLASS (klass); + planner_class->is_configured = my_is_configured; + planner_class->activate = my_activate; + planner_class->activate_time = my_activate_time; + planner_class->get_appointments = my_get_appointments; + planner_class->get_appointments_finish = my_get_appointments_finish; + + g_type_class_add_private (klass, sizeof (IndicatorDatetimePlannerMockPriv)); +} + +static void +indicator_datetime_planner_mock_init (IndicatorDatetimePlannerMock * self) +{ + priv_t * p; + + p = G_TYPE_INSTANCE_GET_PRIVATE (self, + INDICATOR_TYPE_DATETIME_PLANNER_MOCK, + IndicatorDatetimePlannerMockPriv); + + p->is_configured = TRUE; + + self->priv = p; +} + +/*** +**** Public +***/ + +IndicatorDatetimePlanner * +indicator_datetime_planner_mock_new (void) +{ + gpointer o = g_object_new (INDICATOR_TYPE_DATETIME_PLANNER_MOCK, NULL); + + return INDICATOR_DATETIME_PLANNER (o); +} diff --git a/tests/planner-mock.h b/tests/planner-mock.h new file mode 100644 index 0000000..8d7d7c2 --- /dev/null +++ b/tests/planner-mock.h @@ -0,0 +1,58 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#ifndef __INDICATOR_DATETIME_PLANNER_MOCK__H__ +#define __INDICATOR_DATETIME_PLANNER_MOCK__H__ + +#include "planner.h" /* parent class */ + +G_BEGIN_DECLS + +#define INDICATOR_TYPE_DATETIME_PLANNER_MOCK (indicator_datetime_planner_mock_get_type()) +#define INDICATOR_DATETIME_PLANNER_MOCK(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), INDICATOR_TYPE_DATETIME_PLANNER_MOCK, IndicatorDatetimePlannerMock)) +#define INDICATOR_DATETIME_PLANNER_MOCK_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), INDICATOR_TYPE_DATETIME_PLANNER_MOCK, IndicatorDatetimePlannerMockClass)) +#define INDICATOR_IS_DATETIME_PLANNER_MOCK(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), INDICATOR_TYPE_DATETIME_PLANNER_MOCK)) + +typedef struct _IndicatorDatetimePlannerMock IndicatorDatetimePlannerMock; +typedef struct _IndicatorDatetimePlannerMockPriv IndicatorDatetimePlannerMockPriv; +typedef struct _IndicatorDatetimePlannerMockClass IndicatorDatetimePlannerMockClass; + +GType indicator_datetime_planner_mock_get_type (void); + +/** + * An IndicatorDatetimePlanner which uses Evolution Data Server + * to get its list of appointments. + */ +struct _IndicatorDatetimePlannerMock +{ + /*< private >*/ + IndicatorDatetimePlanner parent; + IndicatorDatetimePlannerMockPriv * priv; +}; + +struct _IndicatorDatetimePlannerMockClass +{ + IndicatorDatetimePlannerClass parent_class; +}; + +IndicatorDatetimePlanner * indicator_datetime_planner_mock_new (void); + +G_END_DECLS + +#endif /* __INDICATOR_DATETIME_PLANNER_MOCK__H__ */ -- cgit v1.2.3 From 758a4880f645242f1c7753990dc46f880a7e9de8 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 17 Oct 2013 17:48:06 -0500 Subject: cleanup: dead code removal, fix comments, smaller implementation of update_internal_localtime() --- src/clock-live.c | 47 ++++++++++++++--------------------------------- src/clock.c | 6 +++--- src/clock.h | 4 ++-- src/main.c | 6 ++++-- src/service.c | 2 +- 5 files changed, 24 insertions(+), 41 deletions(-) diff --git a/src/clock-live.c b/src/clock-live.c index 6e694ed..564d990 100644 --- a/src/clock-live.c +++ b/src/clock-live.c @@ -35,7 +35,7 @@ struct _IndicatorDatetimeClockLivePriv { GSettings * settings; - /* cached GTimeZone for use by indicator_datetime_service_get_localtime() */ + /* cached GTimeZone for use by get_localtime() */ GTimeZone * internal_timezone; IndicatorDatetimeTimezone * tz_file; @@ -58,39 +58,10 @@ G_DEFINE_TYPE_WITH_CODE ( G_IMPLEMENT_INTERFACE (INDICATOR_TYPE_DATETIME_CLOCK, indicator_datetime_clock_interface_init)); -/*** -**** Convenience func -***/ - -#if 0 -static void -emit_changed (IndicatorDatetimeClockLive * self) -{ - indicator_datetime_clock_emit_changed (INDICATOR_DATETIME_CLOCK (self)); -} -#endif - /*** **** Timezones ***/ -static void -update_internal_timezone (IndicatorDatetimeClockLive * self) -{ - priv_t * p = self->priv; - const char * id; - - /* find the id from tz_file or tz_geoclue if possible; NULL otherwise */ - id = NULL; - if (p->tz_file != NULL ) - id = indicator_datetime_timezone_get_timezone (p->tz_file); - if (!id && p->tz_geoclue) - id = indicator_datetime_timezone_get_timezone (p->tz_geoclue); - - g_clear_pointer (&p->internal_timezone, g_time_zone_unref); - p->internal_timezone = g_time_zone_new (id); -} - static void on_current_timezone_changed (IndicatorDatetimeClockLive * self) { @@ -159,7 +130,7 @@ on_detect_location_changed (IndicatorDatetimeClockLive * self) ***/ static gchar ** -my_get_timezones (IndicatorDatetimeClock * clock G_GNUC_UNUSED) +my_get_timezones (IndicatorDatetimeClock * clock) { IndicatorDatetimeClockLive * self; priv_t * p; @@ -197,8 +168,18 @@ my_get_timezones (IndicatorDatetimeClock * clock G_GNUC_UNUSED) return timezones; } +static void +update_internal_timezone (IndicatorDatetimeClockLive * self) +{ + priv_t * p = self->priv; + gchar ** timezones = my_get_timezones (INDICATOR_DATETIME_CLOCK (self)); + g_clear_pointer (&p->internal_timezone, g_time_zone_unref); + p->internal_timezone = g_time_zone_new (timezones ? timezones[0] : NULL); + g_strfreev (timezones); +} + static GDateTime * -my_get_current_time (IndicatorDatetimeClock * clock) +my_get_localtime (IndicatorDatetimeClock * clock) { IndicatorDatetimeClockLive * self; priv_t * p; @@ -271,8 +252,8 @@ indicator_datetime_clock_live_class_init (IndicatorDatetimeClockLiveClass * klas static void indicator_datetime_clock_interface_init (IndicatorDatetimeClockInterface * iface) { + iface->get_localtime = my_get_localtime; iface->get_timezones = my_get_timezones; - iface->get_current_time = my_get_current_time; } static void diff --git a/src/clock.c b/src/clock.c index 1abdd21..a5cefee 100644 --- a/src/clock.c +++ b/src/clock.c @@ -80,7 +80,7 @@ indicator_datetime_clock_get_timezones (IndicatorDatetimeClock * self) * the current time. */ GDateTime * -indicator_datetime_clock_get_current_time (IndicatorDatetimeClock * self) +indicator_datetime_clock_get_localtime (IndicatorDatetimeClock * self) { GDateTime * now; IndicatorDatetimeClockInterface * iface; @@ -88,8 +88,8 @@ indicator_datetime_clock_get_current_time (IndicatorDatetimeClock * self) g_return_val_if_fail (INDICATOR_IS_DATETIME_CLOCK(self), NULL); iface = INDICATOR_DATETIME_CLOCK_GET_INTERFACE(self); - if (iface->get_current_time != NULL) - now = iface->get_current_time (self); + if (iface->get_localtime != NULL) + now = iface->get_localtime (self); else now = NULL; diff --git a/src/clock.h b/src/clock.h index 8932895..0c10dab 100644 --- a/src/clock.h +++ b/src/clock.h @@ -55,7 +55,7 @@ struct _IndicatorDatetimeClockInterface /* virtual functions */ gchar** (*get_timezones) (IndicatorDatetimeClock * self); - GDateTime* (*get_current_time) (IndicatorDatetimeClock * self); + GDateTime* (*get_localtime) (IndicatorDatetimeClock * self); }; GType indicator_datetime_clock_get_type (void); @@ -66,7 +66,7 @@ GType indicator_datetime_clock_get_type (void); gchar ** indicator_datetime_clock_get_timezones (IndicatorDatetimeClock * clock); -GDateTime * indicator_datetime_clock_get_current_time (IndicatorDatetimeClock * clock); +GDateTime * indicator_datetime_clock_get_localtime (IndicatorDatetimeClock * clock); void indicator_datetime_clock_emit_changed (IndicatorDatetimeClock * clock); diff --git a/src/main.c b/src/main.c index 9305794..dc08419 100644 --- a/src/main.c +++ b/src/main.c @@ -59,17 +59,19 @@ main (int argc G_GNUC_UNUSED, char ** argv G_GNUC_UNUSED) if (!notify_init ("indicator-datetime-service")) g_critical ("libnotify initialization failed"); - /* run */ + /* create the service */ clock = indicator_datetime_clock_live_new (); planner = indicator_datetime_planner_eds_new (); service = indicator_datetime_service_new (clock, planner); + + /* run */ loop = g_main_loop_new (NULL, FALSE); g_signal_connect (service, INDICATOR_DATETIME_SERVICE_SIGNAL_NAME_LOST, G_CALLBACK(on_name_lost), loop); g_main_loop_run (loop); + g_main_loop_unref (loop); /* cleanup */ - g_main_loop_unref (loop); g_object_unref (service); g_object_unref (planner); g_object_unref (clock); diff --git a/src/service.c b/src/service.c index b777b8c..f2b0b34 100644 --- a/src/service.c +++ b/src/service.c @@ -166,7 +166,7 @@ indicator_clear_timer (guint * tag) static inline GDateTime * indicator_datetime_service_get_localtime (IndicatorDatetimeService * self) { - return indicator_datetime_clock_get_current_time (self->priv->clock); + return indicator_datetime_clock_get_localtime (self->priv->clock); } /*** -- cgit v1.2.3 From 1a898e4eada6f50bd6f3e3b227d1ab0e143ec06d Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 17 Oct 2013 18:15:33 -0500 Subject: cache the timezone strv; lazy-rebuilding it when needed --- src/clock-live.c | 54 +++++++++++++++++++++++------------------------------- src/clock.c | 4 ++-- src/clock.h | 8 ++++---- src/service.c | 3 +-- 4 files changed, 30 insertions(+), 39 deletions(-) diff --git a/src/clock-live.c b/src/clock-live.c index 564d990..a5e42ec 100644 --- a/src/clock-live.c +++ b/src/clock-live.c @@ -35,11 +35,9 @@ struct _IndicatorDatetimeClockLivePriv { GSettings * settings; - /* cached GTimeZone for use by get_localtime() */ - GTimeZone * internal_timezone; - IndicatorDatetimeTimezone * tz_file; IndicatorDatetimeTimezone * tz_geoclue; + gchar ** timezones; }; typedef IndicatorDatetimeClockLivePriv priv_t; @@ -65,6 +63,8 @@ G_DEFINE_TYPE_WITH_CODE ( static void on_current_timezone_changed (IndicatorDatetimeClockLive * self) { + g_clear_pointer (&self->priv->timezones, g_strfreev); + indicator_datetime_clock_emit_changed (INDICATOR_DATETIME_CLOCK (self)); } @@ -129,18 +129,15 @@ on_detect_location_changed (IndicatorDatetimeClockLive * self) **** IndicatorDatetimeClock virtual functions ***/ -static gchar ** -my_get_timezones (IndicatorDatetimeClock * clock) +static void +rebuild_timezone_strv (IndicatorDatetimeClockLive * self) { - IndicatorDatetimeClockLive * self; priv_t * p; GHashTable * hash; - gchar ** timezones; int i; GHashTableIter iter; gpointer key; - self = INDICATOR_DATETIME_CLOCK_LIVE (clock); p = self->priv; hash = g_hash_table_new (g_str_hash, g_str_equal); @@ -159,38 +156,35 @@ my_get_timezones (IndicatorDatetimeClock * clock) g_hash_table_add (hash, (gpointer) tz); } - timezones = g_new0 (gchar*, g_hash_table_size(hash) + 1); + g_strfreev (p->timezones); + p->timezones = g_new0 (gchar*, g_hash_table_size(hash) + 1); i = 0; g_hash_table_iter_init (&iter, hash); while (g_hash_table_iter_next (&iter, &key, NULL)) - timezones[i++] = g_strdup (key); + p->timezones[i++] = g_strdup (key); g_hash_table_unref (hash); - return timezones; } -static void -update_internal_timezone (IndicatorDatetimeClockLive * self) +static const gchar ** +my_get_timezones (IndicatorDatetimeClock * clock) { + IndicatorDatetimeClockLive * self = INDICATOR_DATETIME_CLOCK_LIVE (clock); priv_t * p = self->priv; - gchar ** timezones = my_get_timezones (INDICATOR_DATETIME_CLOCK (self)); - g_clear_pointer (&p->internal_timezone, g_time_zone_unref); - p->internal_timezone = g_time_zone_new (timezones ? timezones[0] : NULL); - g_strfreev (timezones); + + if (p->timezones == NULL) + rebuild_timezone_strv (self); + + return (const gchar **) p->timezones; } static GDateTime * my_get_localtime (IndicatorDatetimeClock * clock) { - IndicatorDatetimeClockLive * self; - priv_t * p; - - self = INDICATOR_DATETIME_CLOCK_LIVE (clock); - p = self->priv; - - if (G_UNLIKELY (p->internal_timezone == NULL)) - update_internal_timezone (self); - - return g_date_time_new_now (p->internal_timezone); + const gchar ** zones = my_get_timezones (clock); + GTimeZone * zone = g_time_zone_new (zones ? zones[0] : NULL); + GDateTime * time = g_date_time_new_now (zone); + g_time_zone_unref (zone); + return time; } /*** @@ -206,8 +200,6 @@ my_dispose (GObject * o) self = INDICATOR_DATETIME_CLOCK_LIVE(o); p = self->priv; - g_clear_pointer (&p->internal_timezone, g_time_zone_unref); - if (p->settings != NULL) { g_signal_handlers_disconnect_by_data (p->settings, self); @@ -222,13 +214,13 @@ my_dispose (GObject * o) static void my_finalize (GObject * o) { -#if 0 IndicatorDatetimeClockLive * self; priv_t * p; self = INDICATOR_DATETIME_CLOCK_LIVE(o); p = self->priv; -#endif + + g_strfreev (p->timezones); G_OBJECT_CLASS (indicator_datetime_clock_live_parent_class)->dispose (o); } diff --git a/src/clock.c b/src/clock.c index a5cefee..adfb0eb 100644 --- a/src/clock.c +++ b/src/clock.c @@ -55,10 +55,10 @@ indicator_datetime_clock_default_init (IndicatorDatetimeClockInterface * klass) * (transfer full): * array of timezone strings */ -gchar ** +const gchar ** indicator_datetime_clock_get_timezones (IndicatorDatetimeClock * self) { - gchar ** timezones; + const gchar ** timezones; IndicatorDatetimeClockInterface * iface; g_return_val_if_fail (INDICATOR_IS_DATETIME_CLOCK(self), NULL); diff --git a/src/clock.h b/src/clock.h index 0c10dab..40cdf1c 100644 --- a/src/clock.h +++ b/src/clock.h @@ -54,7 +54,7 @@ struct _IndicatorDatetimeClockInterface void (*changed) (IndicatorDatetimeClock * self); /* virtual functions */ - gchar** (*get_timezones) (IndicatorDatetimeClock * self); + const gchar** (*get_timezones) (IndicatorDatetimeClock * self); GDateTime* (*get_localtime) (IndicatorDatetimeClock * self); }; @@ -64,11 +64,11 @@ GType indicator_datetime_clock_get_type (void); **** ***/ -gchar ** indicator_datetime_clock_get_timezones (IndicatorDatetimeClock * clock); +const gchar ** indicator_datetime_clock_get_timezones (IndicatorDatetimeClock * clock); -GDateTime * indicator_datetime_clock_get_localtime (IndicatorDatetimeClock * clock); +GDateTime * indicator_datetime_clock_get_localtime (IndicatorDatetimeClock * clock); -void indicator_datetime_clock_emit_changed (IndicatorDatetimeClock * clock); +void indicator_datetime_clock_emit_changed (IndicatorDatetimeClock * clock); G_END_DECLS diff --git a/src/service.c b/src/service.c index f2b0b34..079456c 100644 --- a/src/service.c +++ b/src/service.c @@ -1168,7 +1168,7 @@ create_locations_section (IndicatorDatetimeService * self) GSList * l; GSList * locations = NULL; gchar ** user_locations; - gchar ** detected_timezones; + const gchar ** detected_timezones; priv_t * p = self->priv; GDateTime * now = indicator_datetime_service_get_localtime (self); @@ -1185,7 +1185,6 @@ create_locations_section (IndicatorDatetimeService * self) gchar * name = get_current_zone_name (tz, p->settings); locations = locations_add (locations, tz, name, TRUE); } - g_strfreev (detected_timezones); /* maybe add the user-specified locations */ user_locations = g_settings_get_strv (p->settings, SETTINGS_LOCATIONS_S); -- cgit v1.2.3 From 2c63a8cda5afbbf0747ec535b73bcc3280d6161b Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 17 Oct 2013 22:12:33 -0500 Subject: because it rarely changes, cache the header_label_format_string. --- src/service.c | 46 ++++++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/src/service.c b/src/service.c index 079456c..b6e9fe8 100644 --- a/src/service.c +++ b/src/service.c @@ -106,6 +106,8 @@ struct _IndicatorDatetimeServicePrivate /* the clock app's icon filename */ gchar * clock_app_icon_filename; + gchar * header_label_format_string; + /* Whether or not we've tried to load the clock app's icon. This way we don't keep trying to reload it on the desktop */ gboolean clock_app_icon_initialized; @@ -179,6 +181,8 @@ static void rebuild_soon (IndicatorDatetimeService * self, int section); static inline void rebuild_header_soon (IndicatorDatetimeService * self) { + g_clear_pointer (&self->priv->header_label_format_string, g_free); + rebuild_soon (self, SECTION_HEADER); } @@ -361,7 +365,7 @@ on_header_timer (gpointer gself) return G_SOURCE_REMOVE; } -static char * get_header_label_format_string (IndicatorDatetimeService *); +static const char * get_header_label_format_string (IndicatorDatetimeService *); static void start_header_timer (IndicatorDatetimeService * self) @@ -375,11 +379,10 @@ start_header_timer (IndicatorDatetimeService * self) if (g_settings_get_boolean (self->priv->settings, SETTINGS_SHOW_CLOCK_S)) { - char * fmt = get_header_label_format_string (self); + const char * fmt = get_header_label_format_string (self); header_shows_seconds = fmt && (strstr(fmt,"%s") || strstr(fmt,"%S") || strstr(fmt,"%T") || strstr(fmt,"%X") || strstr(fmt,"%c")); - g_free (fmt); } if (header_shows_seconds) @@ -639,32 +642,39 @@ skew_timer_func (gpointer gself) **** ***/ -static gchar * +static const gchar * get_header_label_format_string (IndicatorDatetimeService * self) { - char * fmt; - GSettings * s = self->priv->settings; - const TimeFormatMode mode = g_settings_get_enum (s, SETTINGS_TIME_FORMAT_S); + priv_t * p = self->priv; - if (mode == TIME_FORMAT_MODE_CUSTOM) + if (p->header_label_format_string == NULL) { - fmt = g_settings_get_string (s, SETTINGS_CUSTOM_TIME_FORMAT_S); - } - else - { - gboolean show_day = g_settings_get_boolean (s, SETTINGS_SHOW_DAY_S); - gboolean show_date = g_settings_get_boolean (s, SETTINGS_SHOW_DATE_S); - fmt = generate_full_format_string (show_day, show_date, s); + char * fmt; + GSettings * s = p->settings; + const TimeFormatMode mode = g_settings_get_enum (s, SETTINGS_TIME_FORMAT_S); + + if (mode == TIME_FORMAT_MODE_CUSTOM) + { + fmt = g_settings_get_string (s, SETTINGS_CUSTOM_TIME_FORMAT_S); + } + else + { + gboolean show_day = g_settings_get_boolean (s, SETTINGS_SHOW_DAY_S); + gboolean show_date = g_settings_get_boolean (s, SETTINGS_SHOW_DATE_S); + fmt = generate_full_format_string (show_day, show_date, s); + } + + p->header_label_format_string = fmt; } - return fmt; + return p->header_label_format_string; } static GVariant * create_desktop_header_state (IndicatorDatetimeService * self) { GVariantBuilder b; - gchar * fmt; + const gchar * fmt; gchar * str; gboolean visible; GDateTime * now; @@ -690,7 +700,6 @@ create_desktop_header_state (IndicatorDatetimeService * self) /* cleanup */ g_date_time_unref (now); - g_free (fmt); return g_variant_builder_end (&b); } @@ -2103,6 +2112,7 @@ my_finalize (GObject * o) priv_t * p = self->priv; g_free (p->clock_app_icon_filename); + g_free (p->header_label_format_string); g_clear_pointer (&p->skew_time, g_date_time_unref); g_clear_pointer (&p->calendar_date, g_date_time_unref); -- cgit v1.2.3 From 0df37b0d0a4ae9ae14d896965fa37a9e61d0f7ab Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 17 Oct 2013 22:14:37 -0500 Subject: because is rarely changes, cache the GTimeZone used by indicator_datetime_clock_get_localtime() --- src/clock-live.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/clock-live.c b/src/clock-live.c index a5e42ec..de5ce19 100644 --- a/src/clock-live.c +++ b/src/clock-live.c @@ -38,6 +38,7 @@ struct _IndicatorDatetimeClockLivePriv IndicatorDatetimeTimezone * tz_file; IndicatorDatetimeTimezone * tz_geoclue; gchar ** timezones; + GTimeZone * localtime_zone; }; typedef IndicatorDatetimeClockLivePriv priv_t; @@ -63,7 +64,10 @@ G_DEFINE_TYPE_WITH_CODE ( static void on_current_timezone_changed (IndicatorDatetimeClockLive * self) { - g_clear_pointer (&self->priv->timezones, g_strfreev); + priv_t * p = self->priv; + + g_clear_pointer (&p->timezones, g_strfreev); + g_clear_pointer (&p->localtime_zone, g_time_zone_unref); indicator_datetime_clock_emit_changed (INDICATOR_DATETIME_CLOCK (self)); } @@ -130,7 +134,7 @@ on_detect_location_changed (IndicatorDatetimeClockLive * self) ***/ static void -rebuild_timezone_strv (IndicatorDatetimeClockLive * self) +rebuild_timezones (IndicatorDatetimeClockLive * self) { priv_t * p; GHashTable * hash; @@ -163,6 +167,9 @@ rebuild_timezone_strv (IndicatorDatetimeClockLive * self) while (g_hash_table_iter_next (&iter, &key, NULL)) p->timezones[i++] = g_strdup (key); g_hash_table_unref (hash); + + g_clear_pointer (&p->localtime_zone, g_time_zone_unref); + p->localtime_zone = g_time_zone_new (p->timezones ? p->timezones[0] : NULL); } static const gchar ** @@ -171,8 +178,8 @@ my_get_timezones (IndicatorDatetimeClock * clock) IndicatorDatetimeClockLive * self = INDICATOR_DATETIME_CLOCK_LIVE (clock); priv_t * p = self->priv; - if (p->timezones == NULL) - rebuild_timezone_strv (self); + if (G_UNLIKELY (p->timezones == NULL)) + rebuild_timezones (self); return (const gchar **) p->timezones; } @@ -180,11 +187,13 @@ my_get_timezones (IndicatorDatetimeClock * clock) static GDateTime * my_get_localtime (IndicatorDatetimeClock * clock) { - const gchar ** zones = my_get_timezones (clock); - GTimeZone * zone = g_time_zone_new (zones ? zones[0] : NULL); - GDateTime * time = g_date_time_new_now (zone); - g_time_zone_unref (zone); - return time; + IndicatorDatetimeClockLive * self = INDICATOR_DATETIME_CLOCK_LIVE (clock); + priv_t * p = self->priv; + + if (G_UNLIKELY (p->localtime_zone == NULL)) + rebuild_timezones (self); + + return g_date_time_new_now (p->localtime_zone); } /*** @@ -220,6 +229,7 @@ my_finalize (GObject * o) self = INDICATOR_DATETIME_CLOCK_LIVE(o); p = self->priv; + g_clear_pointer (&p->localtime_zone, g_time_zone_unref); g_strfreev (p->timezones); G_OBJECT_CLASS (indicator_datetime_clock_live_parent_class)->dispose (o); -- cgit v1.2.3 From 7fe0540b750cf88062427e8a1536f67bd2c5d8d3 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 17 Oct 2013 23:08:48 -0500 Subject: when building the desktop header state, reuse the label variant --- src/service.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/service.c b/src/service.c index b6e9fe8..4eb1542 100644 --- a/src/service.c +++ b/src/service.c @@ -679,6 +679,7 @@ create_desktop_header_state (IndicatorDatetimeService * self) gboolean visible; GDateTime * now; const gchar * title = _("Date and Time"); + GVariant * label_variant; visible = g_settings_get_boolean (self->priv->settings, SETTINGS_SHOW_CLOCK_S); @@ -692,9 +693,10 @@ create_desktop_header_state (IndicatorDatetimeService * self) g_warning ("%s", str); } + label_variant = g_variant_new_take_string (str); g_variant_builder_init (&b, G_VARIANT_TYPE_VARDICT); - g_variant_builder_add (&b, "{sv}", "accessible-desc", g_variant_new_string (str)); - g_variant_builder_add (&b, "{sv}", "label", g_variant_new_take_string (str)); + g_variant_builder_add (&b, "{sv}", "accessible-desc", label_variant); + g_variant_builder_add (&b, "{sv}", "label", label_variant); g_variant_builder_add (&b, "{sv}", "title", g_variant_new_string (title)); g_variant_builder_add (&b, "{sv}", "visible", g_variant_new_boolean (visible)); @@ -1193,6 +1195,7 @@ create_locations_section (IndicatorDatetimeService * self) const char * tz = detected_timezones[i]; gchar * name = get_current_zone_name (tz, p->settings); locations = locations_add (locations, tz, name, TRUE); + g_free (name); } /* maybe add the user-specified locations */ -- cgit v1.2.3 From be37c5fe747ed79a35d3903c9f549fc9c92fef93 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Fri, 18 Oct 2013 09:03:25 -0500 Subject: since we keep reusing the same GVariants again and again forever, cache them. --- src/service.c | 83 ++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 54 insertions(+), 29 deletions(-) diff --git a/src/service.c b/src/service.c index 4eb1542..cb2ab4f 100644 --- a/src/service.c +++ b/src/service.c @@ -147,6 +147,13 @@ struct _IndicatorDatetimeServicePrivate /* appointments over the next few weeks. Used when building SECTION_APPOINTMENTS */ GSList * upcoming_appointments; + + /* variant cache */ + GVariant * desktop_title_variant; + GVariant * phone_title_variant; + GVariant * visible_true_variant; + GVariant * visible_false_variant; + GVariant * alarm_icon_variant; }; typedef IndicatorDatetimeServicePrivate priv_t; @@ -673,15 +680,15 @@ get_header_label_format_string (IndicatorDatetimeService * self) static GVariant * create_desktop_header_state (IndicatorDatetimeService * self) { + priv_t * p = self->priv; GVariantBuilder b; const gchar * fmt; gchar * str; gboolean visible; GDateTime * now; - const gchar * title = _("Date and Time"); GVariant * label_variant; - visible = g_settings_get_boolean (self->priv->settings, SETTINGS_SHOW_CLOCK_S); + visible = g_settings_get_boolean (p->settings, SETTINGS_SHOW_CLOCK_S); /* build the time string for the label & a11y */ fmt = get_header_label_format_string (self); @@ -697,8 +704,8 @@ create_desktop_header_state (IndicatorDatetimeService * self) g_variant_builder_init (&b, G_VARIANT_TYPE_VARDICT); g_variant_builder_add (&b, "{sv}", "accessible-desc", label_variant); g_variant_builder_add (&b, "{sv}", "label", label_variant); - g_variant_builder_add (&b, "{sv}", "title", g_variant_new_string (title)); - g_variant_builder_add (&b, "{sv}", "visible", g_variant_new_boolean (visible)); + g_variant_builder_add_value (&b, p->desktop_title_variant); + g_variant_builder_add_value (&b, visible ? p->visible_true_variant : p->visible_false_variant); /* cleanup */ g_date_time_unref (now); @@ -711,43 +718,37 @@ service_has_alarms (IndicatorDatetimeService * self); static GVariant * create_phone_header_state (IndicatorDatetimeService * self) { + priv_t * p = self->priv; + const gboolean has_alarms = service_has_alarms (self); GVariantBuilder b; GDateTime * now; const gchar * fmt; - gchar * label; - gboolean has_alarms; - gchar * a11y; - const gchar * title = _("Upcoming"); g_variant_builder_init (&b, G_VARIANT_TYPE_VARDICT); + g_variant_builder_add_value (&b, p->phone_title_variant); + g_variant_builder_add_value (&b, p->visible_true_variant); + + /* icon */ + if (has_alarms) + g_variant_builder_add_value (&b, p->alarm_icon_variant); - /* label */ + /* label, a11y */ now = indicator_datetime_service_get_localtime (self); fmt = get_terse_header_time_format_string (); - label = g_date_time_format (now, fmt); - - /* icon */ - if ((has_alarms = service_has_alarms (self))) + if (has_alarms) { - GIcon * icon; - icon = g_themed_icon_new_with_default_fallbacks (ALARM_CLOCK_ICON_NAME); - g_variant_builder_add (&b, "{sv}", "icon", g_icon_serialize (icon)); - g_object_unref (icon); + gchar * label = g_date_time_format (now, fmt); + gchar * a11y = g_strdup_printf (_("%s (has alarms)"), label); + g_variant_builder_add (&b, "{sv}", "label", g_variant_new_take_string (label)); + g_variant_builder_add (&b, "{sv}", "accessible-desc", g_variant_new_take_string (a11y)); } - - /* a11y */ - if (has_alarms) - a11y = g_strdup_printf (_("%s (has alarms)"), label); else - a11y = g_strdup (label); - g_variant_builder_add (&b, "{sv}", "accessible-desc", - g_variant_new_take_string (a11y)); - - g_variant_builder_add (&b, "{sv}", "visible", g_variant_new_boolean (TRUE)); - g_variant_builder_add (&b, "{sv}", "label", g_variant_new_take_string (label)); - g_variant_builder_add (&b, "{sv}", "title", g_variant_new_string (title)); + { + GVariant * v = g_variant_new_take_string (g_date_time_format (now, fmt)); + g_variant_builder_add (&b, "{sv}", "label", v); + g_variant_builder_add (&b, "{sv}", "accessible-desc", v); + } - /* cleanup */ g_date_time_unref (now); return g_variant_builder_end (&b); } @@ -2105,6 +2106,12 @@ my_dispose (GObject * o) g_clear_object (&p->phone_header_action); g_clear_object (&p->conn); + g_clear_pointer (&p->desktop_title_variant, g_variant_unref); + g_clear_pointer (&p->phone_title_variant, g_variant_unref); + g_clear_pointer (&p->visible_true_variant, g_variant_unref); + g_clear_pointer (&p->visible_false_variant, g_variant_unref); + g_clear_pointer (&p->alarm_icon_variant, g_variant_unref); + G_OBJECT_CLASS (indicator_datetime_service_parent_class)->dispose (o); } @@ -2129,6 +2136,7 @@ my_finalize (GObject * o) static void indicator_datetime_service_init (IndicatorDatetimeService * self) { + GIcon * icon; priv_t * p; /* init the priv pointer */ @@ -2141,6 +2149,23 @@ indicator_datetime_service_init (IndicatorDatetimeService * self) p->cancellable = g_cancellable_new (); p->settings = g_settings_new (SETTINGS_INTERFACE); + + p->desktop_title_variant = g_variant_new ("{sv}", "title", g_variant_new_string (_("Date and Time"))); + g_variant_ref_sink (p->desktop_title_variant); + + p->phone_title_variant = g_variant_new ("{sv}", "title", g_variant_new_string (_("Upcoming"))); + g_variant_ref_sink (p->phone_title_variant); + + p->visible_true_variant = g_variant_new ("{sv}", "visible", g_variant_new_boolean (TRUE)); + g_variant_ref_sink (p->visible_true_variant); + + p->visible_false_variant = g_variant_new ("{sv}", "visible", g_variant_new_boolean (FALSE)); + g_variant_ref_sink (p->visible_false_variant); + + icon = g_themed_icon_new_with_default_fallbacks (ALARM_CLOCK_ICON_NAME); + p->alarm_icon_variant = g_variant_new ("{sv}", "icon", g_icon_serialize (icon)); + g_variant_ref_sink (p->alarm_icon_variant); + g_object_unref (icon); } static void -- cgit v1.2.3 From 99f3bc0685f85744081eefa0c22d9f7c5b13f327 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Fri, 18 Oct 2013 09:32:53 -0500 Subject: copyediting: nobody uses this #define, so remove it --- src/timezone.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/timezone.h b/src/timezone.h index aaaa296..fa6593d 100644 --- a/src/timezone.h +++ b/src/timezone.h @@ -37,8 +37,6 @@ typedef struct _IndicatorDatetimeTimezoneClass IndicatorDatetimeTimezoneClass; GType indicator_datetime_timezone_get_type (void); -#define INDICATOR_DATETIME_TIMEZONE_PROPERTY_TIMEZONE "timezone" - /** * Abstract Base Class for objects that provide a timezone. * -- cgit v1.2.3 From a2f21a1da1b1f467751020b56b04808f5dd00695 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 23 Oct 2013 09:42:49 -0500 Subject: make GObject a prerequisite of the IndicatorDatetimeClock interface. --- src/clock.c | 2 +- src/service.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/clock.c b/src/clock.c index adfb0eb..2c2fec2 100644 --- a/src/clock.c +++ b/src/clock.c @@ -29,7 +29,7 @@ static guint signals[SIGNAL_LAST] = { 0 }; G_DEFINE_INTERFACE (IndicatorDatetimeClock, indicator_datetime_clock, - 0); + G_TYPE_OBJECT); static void indicator_datetime_clock_default_init (IndicatorDatetimeClockInterface * klass) diff --git a/src/service.c b/src/service.c index cb2ab4f..5fffc11 100644 --- a/src/service.c +++ b/src/service.c @@ -2317,7 +2317,7 @@ indicator_datetime_service_class_init (IndicatorDatetimeServiceClass * klass) properties[PROP_CLOCK] = g_param_spec_object ("clock", "Clock", "The clock", - G_TYPE_OBJECT, + INDICATOR_TYPE_DATETIME_CLOCK, flags); properties[PROP_PLANNER] = g_param_spec_object ("planner", -- cgit v1.2.3 From 6da162acd4a293a1cfe1933c54f6b06935deebbf Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 23 Oct 2013 13:14:25 -0500 Subject: instead of keeping IndicatorDatetimeTimezone objects in separate fields, keep them in a list so they can be handled in a loop. --- src/clock-live.c | 94 ++++++++++++++++++++++++++------------------------------ 1 file changed, 43 insertions(+), 51 deletions(-) diff --git a/src/clock-live.c b/src/clock-live.c index de5ce19..4153747 100644 --- a/src/clock-live.c +++ b/src/clock-live.c @@ -35,9 +35,8 @@ struct _IndicatorDatetimeClockLivePriv { GSettings * settings; - IndicatorDatetimeTimezone * tz_file; - IndicatorDatetimeTimezone * tz_geoclue; - gchar ** timezones; + GSList * timezones; /* IndicatorDatetimeTimezone */ + gchar ** timezones_strv; GTimeZone * localtime_zone; }; @@ -66,7 +65,9 @@ on_current_timezone_changed (IndicatorDatetimeClockLive * self) { priv_t * p = self->priv; - g_clear_pointer (&p->timezones, g_strfreev); + /* Invalidate the timezone information. + These fields will be lazily regenerated by rebuild_timezones() */ + g_clear_pointer (&p->timezones_strv, g_strfreev); g_clear_pointer (&p->localtime_zone, g_time_zone_unref); indicator_datetime_clock_emit_changed (INDICATOR_DATETIME_CLOCK (self)); @@ -75,44 +76,36 @@ on_current_timezone_changed (IndicatorDatetimeClockLive * self) static void set_detect_location_enabled (IndicatorDatetimeClockLive * self, gboolean enabled) { + GSList * l; priv_t * p = self->priv; gboolean changed = FALSE; - /* geoclue */ - - if (!p->tz_geoclue && enabled) + /* clear out the old timezone objects */ + if (p->timezones != NULL) { - p->tz_geoclue = indicator_datetime_timezone_geoclue_new (); - g_signal_connect_swapped (p->tz_geoclue, "notify::timezone", - G_CALLBACK(on_current_timezone_changed), - self); + for (l=p->timezones; l!=NULL; l=l->next) + { + g_signal_handlers_disconnect_by_func (l->data, on_current_timezone_changed, self); + g_object_unref (l->data); + } + + g_slist_free (p->timezones); + p->timezones = NULL; changed = TRUE; } - else if (p->tz_geoclue && !enabled) + + /* maybe add new timezone objects */ + if (enabled) { - g_signal_handlers_disconnect_by_func (p->tz_geoclue, - on_current_timezone_changed, - self); - g_clear_object (&p->tz_geoclue); - changed = TRUE; - } + p->timezones = g_slist_append (p->timezones, indicator_datetime_timezone_geoclue_new ()); + p->timezones = g_slist_append (p->timezones, indicator_datetime_timezone_file_new (TIMEZONE_FILE)); - /* timezone file */ + for (l=p->timezones; l!=NULL; l=l->next) + { + g_signal_connect_swapped (l->data, "notify::timezone", + G_CALLBACK(on_current_timezone_changed), self); + } - if (!p->tz_file && enabled) - { - p->tz_file = indicator_datetime_timezone_file_new (TIMEZONE_FILE); - g_signal_connect_swapped (p->tz_file, "notify::timezone", - G_CALLBACK(on_current_timezone_changed), - self); - changed = TRUE; - } - else if (p->tz_file && !enabled) - { - g_signal_handlers_disconnect_by_func (p->tz_file, - on_current_timezone_changed, - self); - g_clear_object (&p->tz_file); changed = TRUE; } @@ -138,38 +131,37 @@ rebuild_timezones (IndicatorDatetimeClockLive * self) { priv_t * p; GHashTable * hash; + GSList * l; int i; GHashTableIter iter; gpointer key; p = self->priv; + /* Build a hashtable of timezone strings. + This will weed out duplicates. */ hash = g_hash_table_new (g_str_hash, g_str_equal); - - if (p->tz_file != NULL) + for (l=p->timezones; l!=NULL; l=l->next) { - const gchar * tz = indicator_datetime_timezone_get_timezone (p->tz_file); + const gchar * tz = indicator_datetime_timezone_get_timezone (l->data); if (tz && *tz) g_hash_table_add (hash, (gpointer) tz); } - if (p->tz_geoclue != NULL) - { - const gchar * tz = indicator_datetime_timezone_get_timezone (p->tz_geoclue); - if (tz && *tz) - g_hash_table_add (hash, (gpointer) tz); - } - - g_strfreev (p->timezones); - p->timezones = g_new0 (gchar*, g_hash_table_size(hash) + 1); + /* rebuild p->timezone_strv */ + g_strfreev (p->timezones_strv); + p->timezones_strv = g_new0 (gchar*, g_hash_table_size(hash) + 1); i = 0; g_hash_table_iter_init (&iter, hash); while (g_hash_table_iter_next (&iter, &key, NULL)) - p->timezones[i++] = g_strdup (key); - g_hash_table_unref (hash); + p->timezones_strv[i++] = g_strdup (key); + /* rebuild localtime_zone */ g_clear_pointer (&p->localtime_zone, g_time_zone_unref); - p->localtime_zone = g_time_zone_new (p->timezones ? p->timezones[0] : NULL); + p->localtime_zone = g_time_zone_new (p->timezones_strv ? p->timezones_strv[0] : NULL); + + /* cleanup */ + g_hash_table_unref (hash); } static const gchar ** @@ -178,10 +170,10 @@ my_get_timezones (IndicatorDatetimeClock * clock) IndicatorDatetimeClockLive * self = INDICATOR_DATETIME_CLOCK_LIVE (clock); priv_t * p = self->priv; - if (G_UNLIKELY (p->timezones == NULL)) + if (G_UNLIKELY (p->timezones_strv == NULL)) rebuild_timezones (self); - return (const gchar **) p->timezones; + return (const gchar **) p->timezones_strv; } static GDateTime * @@ -230,7 +222,7 @@ my_finalize (GObject * o) p = self->priv; g_clear_pointer (&p->localtime_zone, g_time_zone_unref); - g_strfreev (p->timezones); + g_strfreev (p->timezones_strv); G_OBJECT_CLASS (indicator_datetime_clock_live_parent_class)->dispose (o); } -- cgit v1.2.3 From 378c70c707550cb66f5c6b138fb5f3b7ff737bc2 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Sat, 26 Oct 2013 16:37:14 -0400 Subject: datetime panel: don't try to add empty location names Otherwise NULL is passed into g_utf8_collate_key(). --- src/datetime-prefs-locations.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/datetime-prefs-locations.c b/src/datetime-prefs-locations.c index ca3d9b5..f953ec7 100644 --- a/src/datetime-prefs-locations.c +++ b/src/datetime-prefs-locations.c @@ -96,7 +96,9 @@ time_location_array_new_from_model (GtkTreeModel * model) COL_ZONE, &zone, COL_VISIBLE_NAME, &name, -1); - list = g_slist_prepend (list, time_location_new (zone, name, pos++, now)); + + if (zone && name) + list = g_slist_prepend (list, time_location_new (zone, name, pos++, now)); g_free (name); g_free (zone); -- cgit v1.2.3 From f53915312d1ba02bd200cdbe18d194d803941366 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Mon, 28 Oct 2013 10:12:41 -0700 Subject: Adding a phone_greeter profile --- data/com.canonical.indicator.datetime | 3 +++ 1 file changed, 3 insertions(+) diff --git a/data/com.canonical.indicator.datetime b/data/com.canonical.indicator.datetime index b26b5ec..7fa1e34 100644 --- a/data/com.canonical.indicator.datetime +++ b/data/com.canonical.indicator.datetime @@ -12,3 +12,6 @@ ObjectPath=/com/canonical/indicator/datetime/desktop_greeter [phone] ObjectPath=/com/canonical/indicator/datetime/phone +[phone_greeter] +ObjectPath=/com/canonical/indicator/datetime/desktop_greeter + -- cgit v1.2.3