search: Introduce a search engine

This is architectured in such a way that it will
allow us to introduce other searcheable terms in
the future.

All the functionality that in the past was in
GcalManager is now spread across GcalSearchModel,
GcalSearchHitEvent and GcalSearchEngine.
This commit is contained in:
Georges Basile Stavracas Neto
2019-04-29 17:08:53 -03:00
parent 6ecb7465eb
commit 6994723d79
14 changed files with 1140 additions and 62 deletions
+240
View File
@@ -0,0 +1,240 @@
/* gcal-search-model.c
*
* Copyright 2019 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY 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 <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#define G_LOG_DOMAIN "GcalSearchModel"
#include "e-cal-data-model.h"
#include "gcal-debug.h"
#include "gcal-search-hit.h"
#include "gcal-search-hit-event.h"
#include "gcal-search-model.h"
#include "gcal-utils.h"
#include <dazzle.h>
struct _GcalSearchModel
{
GObject parent;
GCancellable *cancellable;
gint max_results;
GListModel *model;
};
static void e_cal_data_model_subscriber_interface_init (ECalDataModelSubscriberInterface *iface);
static void g_list_model_interface_init (GListModelInterface *iface);
G_DEFINE_TYPE_WITH_CODE (GcalSearchModel, gcal_search_model, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (E_TYPE_CAL_DATA_MODEL_SUBSCRIBER,
e_cal_data_model_subscriber_interface_init)
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL,
g_list_model_interface_init))
/*
* Callbacks
*/
static void
on_model_items_changed_cb (GListModel *model,
guint position,
guint removed,
guint added,
GcalSearchModel *self)
{
g_list_model_items_changed (G_LIST_MODEL (self), position, removed, added);
}
/*
* ECalDataModelSubscriber interface
*/
static gint
compare_search_hits_cb (gconstpointer a,
gconstpointer b,
gpointer user_data)
{
GcalSearchHit *hit_a, *hit_b;
gint result;
hit_a = (GcalSearchHit *) a;
hit_b = (GcalSearchHit *) b;
/* Priority */
result = gcal_search_hit_get_priority (hit_a) - gcal_search_hit_get_priority (hit_b);
if (result != 0)
return result;
/* Compare func */
return gcal_search_hit_compare (hit_a, hit_b);
}
static void
gcal_search_model_component_added (ECalDataModelSubscriber *subscriber,
ECalClient *client,
ECalComponent *component)
{
g_autoptr (GcalSearchHitEvent) search_hit = NULL;
g_autoptr (GcalEvent) event = NULL;
g_autoptr (GError) error = NULL;
GcalSearchModel *self;
ESource *source;
self = GCAL_SEARCH_MODEL (subscriber);
if (g_list_model_get_n_items (self->model) > self->max_results)
return;
source = e_client_get_source (E_CLIENT (client));
event = gcal_event_new (source, component, &error);
if (error)
{
g_warning ("Error adding event to search results: %s", error->message);
return;
}
GCAL_TRACE_MSG ("Adding search hit '%s'", gcal_event_get_summary (event));
search_hit = gcal_search_hit_event_new (event);
g_list_store_insert_sorted (G_LIST_STORE (self->model),
search_hit,
compare_search_hits_cb,
self);
}
static void
gcal_search_model_component_modified (ECalDataModelSubscriber *subscriber,
ECalClient *client,
ECalComponent *comp)
{
}
static void
gcal_search_model_component_removed (ECalDataModelSubscriber *subscriber,
ECalClient *client,
const gchar *uid,
const gchar *rid)
{
}
static void
gcal_search_model_freeze (ECalDataModelSubscriber *subscriber)
{
}
static void
gcal_search_model_thaw (ECalDataModelSubscriber *subscriber)
{
}
static void
e_cal_data_model_subscriber_interface_init (ECalDataModelSubscriberInterface *iface)
{
iface->component_added = gcal_search_model_component_added;
iface->component_modified = gcal_search_model_component_modified;
iface->component_removed = gcal_search_model_component_removed;
iface->freeze = gcal_search_model_freeze;
iface->thaw = gcal_search_model_thaw;
}
/*
* GListModel interface
*/
static GType
gcal_search_model_get_item_type (GListModel *model)
{
return DZL_TYPE_SUGGESTION;
}
static guint
gcal_search_model_get_n_items (GListModel *model)
{
GcalSearchModel *self = (GcalSearchModel *)model;
return g_list_model_get_n_items (self->model);
}
static gpointer
gcal_search_model_get_item (GListModel *model,
guint position)
{
GcalSearchModel *self = (GcalSearchModel *)model;
return g_list_model_get_item (self->model, position);
}
static void
g_list_model_interface_init (GListModelInterface *iface)
{
iface->get_item_type = gcal_search_model_get_item_type;
iface->get_n_items = gcal_search_model_get_n_items;
iface->get_item = gcal_search_model_get_item;
}
/*
* GObject overrides
*/
static void
gcal_search_model_finalize (GObject *object)
{
GcalSearchModel *self = (GcalSearchModel *)object;
g_cancellable_cancel (self->cancellable);
g_clear_object (&self->cancellable);
g_clear_object (&self->model);
G_OBJECT_CLASS (gcal_search_model_parent_class)->finalize (object);
}
static void
gcal_search_model_class_init (GcalSearchModelClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = gcal_search_model_finalize;
}
static void
gcal_search_model_init (GcalSearchModel *self)
{
self->model = (GListModel*) g_list_store_new (DZL_TYPE_SUGGESTION);
g_signal_connect_object (self->model, "items-changed", G_CALLBACK (on_model_items_changed_cb), self, 0);
}
GcalSearchModel *
gcal_search_model_new (GCancellable *cancellable,
gint max_results)
{
GcalSearchModel *model;
model = g_object_new (GCAL_TYPE_SEARCH_MODEL, NULL);
model->max_results = max_results;
model->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
return model;
}