diff options
-rw-r--r-- | src/search/gcal-search-engine.c | 102 | ||||
-rw-r--r-- | src/search/gcal-search-model.c | 74 | ||||
-rw-r--r-- | src/search/gcal-search-model.h | 8 |
3 files changed, 100 insertions, 84 deletions
diff --git a/src/search/gcal-search-engine.c b/src/search/gcal-search-engine.c index 253daff8..47179ae6 100644 --- a/src/search/gcal-search-engine.c +++ b/src/search/gcal-search-engine.c @@ -22,20 +22,12 @@ #include "gcal-context.h" #include "gcal-date-time-utils.h" +#include "gcal-debug.h" #include "gcal-search-engine.h" #include "gcal-search-model.h" #include "gcal-timeline.h" #include "gcal-timeline-subscriber.h" -typedef struct -{ - GcalSearchEngine *engine; - gchar *query; - gint max_results; - GDateTime *range_start; - GDateTime *range_end; -} SearchData; - struct _GcalSearchEngine { GObject parent; @@ -58,59 +50,10 @@ static GParamSpec *properties [N_PROPS]; /* - * Auxiliary methods - */ - -static void -search_data_free (gpointer data) -{ - SearchData *search_data = data; - - if (!data) - return; - - gcal_clear_date_time (&search_data->range_start); - gcal_clear_date_time (&search_data->range_end); - g_clear_pointer (&search_data->query, g_free); - g_clear_object (&search_data->engine); - g_slice_free (SearchData, data); -} - - -/* * Callbacks */ static void -search_func (GTask *task, - gpointer source_object, - gpointer task_data, - GCancellable *cancellable) -{ - g_autoptr (GcalSearchModel) model = NULL; - GcalSearchEngine *self; - SearchData *data; - - self = GCAL_SEARCH_ENGINE (source_object); - data = (SearchData*) task_data; - - model = gcal_search_model_new (cancellable, - data->max_results, - data->range_start, - data->range_end); - - gcal_timeline_set_filter (self->timeline, data->query); - gcal_timeline_add_subscriber (self->timeline, GCAL_TIMELINE_SUBSCRIBER (model)); - - gcal_search_model_wait_for_hits (model, cancellable); - - if (g_cancellable_is_cancelled (cancellable)) - g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_CANCELLED, "Cancelled"); - else - g_task_return_pointer (task, g_steal_pointer (&model), g_object_unref); -} - -static void on_manager_calendar_added_cb (GcalManager *manager, GcalCalendar *calendar, GcalSearchEngine *self) @@ -130,6 +73,31 @@ on_manager_calendar_removed_cb (GcalManager *manager, gcal_timeline_remove_calendar (self->timeline, calendar); } +static void +search_model_hits_cb (GObject *source, + GAsyncResult *result, + gpointer data) +{ + g_autoptr (GError) error = NULL; + g_autoptr (GTask) task = data; + GcalSearchModel *search_model; + + GCAL_ENTRY; + + search_model = GCAL_SEARCH_MODEL (source); + gcal_search_model_wait_for_hits_finish (search_model, result, &error); + + if (error) + { + g_task_return_error (task, g_steal_pointer (&error)); + GCAL_RETURN (); + } + + g_task_return_pointer (task, g_object_ref (search_model), NULL); + + GCAL_EXIT; +} + /* * GObject overrides @@ -246,9 +214,11 @@ gcal_search_engine_search (GcalSearchEngine *self, GAsyncReadyCallback callback, gpointer user_data) { + g_autoptr (GcalSearchModel) model = NULL; + g_autoptr (GDateTime) range_start = NULL; + g_autoptr (GDateTime) range_end = NULL; g_autoptr (GDateTime) now = NULL; g_autoptr (GTask) task = NULL; - SearchData *data = NULL; GTimeZone *timezone; g_return_if_fail (GCAL_IS_SEARCH_ENGINE (self)); @@ -256,20 +226,18 @@ gcal_search_engine_search (GcalSearchEngine *self, timezone = gcal_context_get_timezone (self->context); now = g_date_time_new_now (timezone); + range_start = g_date_time_add_weeks (now, -1); + range_end = g_date_time_add_weeks (now, 3); + model = gcal_search_model_new (cancellable, max_results, range_start, range_end); - data = g_slice_new0 (SearchData); - data->engine = g_object_ref (self); - data->query = g_strdup (search_query); - data->max_results = max_results; - data->range_start = g_date_time_add_weeks (now, -1); - data->range_end = g_date_time_add_weeks (now, 3); + gcal_timeline_set_filter (self->timeline, search_query); + gcal_timeline_add_subscriber (self->timeline, GCAL_TIMELINE_SUBSCRIBER (model)); task = g_task_new (self, cancellable, callback, user_data); g_task_set_source_tag (task, gcal_search_engine_search); g_task_set_priority (task, G_PRIORITY_LOW); - g_task_set_task_data (task, data, (GDestroyNotify) search_data_free); - g_task_run_in_thread (task, search_func); + gcal_search_model_wait_for_hits (model, cancellable, search_model_hits_cb, g_object_ref (task)); } GListModel* diff --git a/src/search/gcal-search-model.c b/src/search/gcal-search-model.c index 892878b3..08cc0370 100644 --- a/src/search/gcal-search-model.c +++ b/src/search/gcal-search-model.c @@ -42,6 +42,9 @@ struct _GcalSearchModel GDateTime *range_end; GListModel *model; + + GTimer *timer; + guint idle_id; }; static void gcal_timeline_subscriber_interface_init (GcalTimelineSubscriberInterface *iface); @@ -58,6 +61,33 @@ G_DEFINE_TYPE_WITH_CODE (GcalSearchModel, gcal_search_model, G_TYPE_OBJECT, * Callbacks */ +static gboolean +check_for_search_hits_cb (gpointer user_data) +{ + GcalSearchModel *self; + GTask *task; + + task = G_TASK (user_data); + self = GCAL_SEARCH_MODEL (g_task_get_source_object (task)); + + if (g_task_return_error_if_cancelled (task)) + goto stop_idle; + + if (g_timer_elapsed (self->timer, NULL) >= WAIT_FOR_RESULTS_MS || + g_list_model_get_n_items (self->model) >= MIN_RESULTS) + { + g_task_return_boolean (task, TRUE); + goto stop_idle; + } + + return G_SOURCE_CONTINUE; + +stop_idle: + g_clear_pointer (&self->timer, g_timer_destroy); + self->idle_id = 0; + return G_SOURCE_REMOVE; +} + static void on_model_items_changed_cb (GListModel *model, guint position, @@ -208,6 +238,9 @@ gcal_search_model_finalize (GObject *object) { GcalSearchModel *self = (GcalSearchModel *)object; + g_assert (self->timer == NULL); + g_assert (self->idle_id == 0); + g_cancellable_cancel (self->cancellable); gcal_clear_date_time (&self->range_start); @@ -251,29 +284,38 @@ gcal_search_model_new (GCancellable *cancellable, } void -gcal_search_model_wait_for_hits (GcalSearchModel *self, - GCancellable *cancellable) +gcal_search_model_wait_for_hits (GcalSearchModel *self, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) { - g_autoptr (GMainContext) thread_context = NULL; - g_autoptr (GTimer) timer = NULL; + g_autoptr (GTask) task = NULL; GCAL_ENTRY; - g_return_if_fail (GCAL_IS_SEARCH_MODEL (self)); + g_assert (self->timer == NULL); + g_assert (self->idle_id == 0); - thread_context = g_main_context_ref_thread_default (); - timer = g_timer_new (); + task = g_task_new (self, cancellable, callback, user_data); + g_task_set_source_tag (task, gcal_search_model_wait_for_hits); + g_task_set_priority (task, G_PRIORITY_LOW); - g_timer_start (timer); + self->timer = g_timer_new (); + self->idle_id = g_idle_add_full (G_PRIORITY_LOW, + check_for_search_hits_cb, + g_object_ref (task), + g_object_unref); - while (g_list_model_get_n_items (self->model) < MIN_RESULTS && - g_timer_elapsed (timer, NULL) < WAIT_FOR_RESULTS_MS) - { - if (g_cancellable_is_cancelled (cancellable)) - break; + GCAL_EXIT; +} - g_main_context_iteration (thread_context, FALSE); - } +gboolean +gcal_search_model_wait_for_hits_finish (GcalSearchModel *self, + GAsyncResult *result, + GError **error) +{ + g_return_val_if_fail (GCAL_IS_SEARCH_MODEL (self), FALSE); + g_return_val_if_fail (g_task_is_valid (result, self), FALSE); - GCAL_EXIT; + return g_task_propagate_boolean (G_TASK (result), error); } diff --git a/src/search/gcal-search-model.h b/src/search/gcal-search-model.h index 97775834..8f040a00 100644 --- a/src/search/gcal-search-model.h +++ b/src/search/gcal-search-model.h @@ -33,6 +33,12 @@ GcalSearchModel* gcal_search_model_new (GCancellable GDateTime *range_end); void gcal_search_model_wait_for_hits (GcalSearchModel *self, - GCancellable *cancellable); + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean gcal_search_model_wait_for_hits_finish (GcalSearchModel *self, + GAsyncResult *result, + GError **error); G_END_DECLS |