aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTed Gould <ted@gould.cx>2013-09-06 12:51:45 -0500
committerTed Gould <ted@gould.cx>2013-09-06 12:51:45 -0500
commitf5746cfe118abf74fd2ef75ed4fb03d9a92cfa14 (patch)
treedc406c0e6d7cf106288c1048beedea1ae1fe69b0 /src
parent55ed2b1b22607f3b9618640294d233eee15db767 (diff)
parentddebe3c47040869cb8fe94729c43f10f2b763550 (diff)
downloadayatana-indicator-datetime-f5746cfe118abf74fd2ef75ed4fb03d9a92cfa14.tar.gz
ayatana-indicator-datetime-f5746cfe118abf74fd2ef75ed4fb03d9a92cfa14.tar.bz2
ayatana-indicator-datetime-f5746cfe118abf74fd2ef75ed4fb03d9a92cfa14.zip
Merge trunk
Diffstat (limited to 'src')
-rw-r--r--src/planner-eds.c341
-rw-r--r--src/planner.c31
-rw-r--r--src/planner.h38
-rw-r--r--src/service.c241
-rw-r--r--src/timezone-geoclue.c16
5 files changed, 490 insertions, 177 deletions
diff --git a/src/planner-eds.c b/src/planner-eds.c
index 276058d..f121a32 100644
--- a/src/planner-eds.c
+++ b/src/planner-eds.c
@@ -19,8 +19,6 @@
#include "config.h"
-#include <gio/gio.h> /* GFile, GFileMonitor */
-
#include <libical/ical.h>
#include <libical/icaltime.h>
#include <libecal/libecal.h>
@@ -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)
+
/***
****
***/
@@ -52,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);
}
}
@@ -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 (g_atomic_int_dec_and_test (&data->subtask_count))
+ 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))
{
@@ -97,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;
@@ -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));
+
+ g_atomic_int_inc (&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
@@ -279,6 +323,148 @@ my_activate_time (IndicatorDatetimePlanner * self G_GNUC_UNUSED,
}
/***
+**** 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);
}
/***
diff --git a/src/planner.c b/src/planner.c
index 6cbf80c..17cc55b 100644
--- a/src/planner.c
+++ b/src/planner.c
@@ -178,19 +178,46 @@ 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);
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);
+ 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 <glib.h>
#include <glib-object.h> /* parent class */
+#include <gio/gio.h>
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.
diff --git a/src/service.c b/src/service.c
index c1f8752..c46beeb 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 = NULL;
- GDateTime * begin = NULL;
- GDateTime * end = NULL;
- 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.1);
- end = g_date_time_new_local (y, m, g_date_get_days_in_month(m,y),
- 23, 59, 59.9);
-
- 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 && i<MAX_APPTS; l=l->next, 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 *
@@ -966,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*
@@ -974,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);
@@ -1140,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
@@ -1224,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;
@@ -1604,6 +1546,133 @@ 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
+update_appointment_lists (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);
+ 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);
+ 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);
+}
+
+
+/***
**** GDBus
***/
@@ -1642,9 +1711,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 +1801,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 +1826,6 @@ my_dispose (GObject * o)
for (i=0; i<N_PROFILES; ++i)
g_clear_object (&p->menus[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 +1908,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(update_appointment_lists), self);
/***
@@ -1913,6 +1980,9 @@ indicator_datetime_service_init (IndicatorDatetimeService * self)
on_local_time_jumped (self);
+ for (i=0; i<N_PROFILES; ++i)
+ create_menu (self, i);
+
g_string_free (gstr, TRUE);
}
@@ -1972,8 +2042,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);
}
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);
}