From 5882af6e786766022e6f927052820b22db0451af Mon Sep 17 00:00:00 2001 From: Charles Kerr 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(-) (limited to 'src/planner-eds.c') 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(-) (limited to 'src/planner-eds.c') 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 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(-) (limited to 'src/planner-eds.c') 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 daccfe0b40f0da7e8de96a350e99fe8c31bfd867 Mon Sep 17 00:00:00 2001 From: Charles Kerr 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(-) (limited to 'src/planner-eds.c') 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(-) (limited to 'src/planner-eds.c') 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 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(-) (limited to 'src/planner-eds.c') 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(-) (limited to 'src/planner-eds.c') 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