summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorentin Noël <corentin.noel@collabora.com>2023-03-21 09:09:00 +0100
committerCorentin Noël <tintou@noel.tf>2023-03-25 23:33:53 +0100
commit427b2311b790af4d5467684552082f6a55f7c197 (patch)
treec9c4ec0f5e19fdd0b27979e44088b49c64ef2578
parenta1954fcab6f86754ba355af6bff74c568a246245 (diff)
downloadfolks-tintou/tracker.tar.gz
backends: Add initial tracker backendtintou/tracker
-rw-r--r--.gitlab-ci.yml2
-rw-r--r--backends/meson.build4
-rw-r--r--backends/tracker/meson.build42
-rw-r--r--backends/tracker/tracker-backend-factory.vala41
-rw-r--r--backends/tracker/tracker-backend.vala207
-rw-r--r--backends/tracker/tracker-persona-store.vala271
-rw-r--r--backends/tracker/tracker-persona.vala234
-rw-r--r--meson.build7
-rw-r--r--meson_options.txt1
-rw-r--r--vapi/tracker-sparql-3.0.vapi344
10 files changed, 1152 insertions, 1 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index e4f56b1e..94474d04 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -28,7 +28,7 @@ build-folks:
dbus-glib-devel evolution-data-server-devel glib2-devel
gobject-introspection-devel libgee-devel libxml2-devel meson ninja-build
python3-dbusmock readline-devel redhat-rpm-config telepathy-glib-devel
- telepathy-glib-vala vala valadoc gtk-doc
+ telepathy-glib-vala tracker-devel vala valadoc gtk-doc
dbus-daemon # FIXME: dbus-broker breaks the CI, see https://github.com/bus1/dbus-broker/issues/145
script:
- meson _build -Ddocs=true
diff --git a/backends/meson.build b/backends/meson.build
index f3557257..621390f8 100644
--- a/backends/meson.build
+++ b/backends/meson.build
@@ -38,3 +38,7 @@ endif
if bluez_backend_enabled
subdir('bluez')
endif
+
+if tracker_backend_enabled
+ subdir('tracker')
+endif
diff --git a/backends/tracker/meson.build b/backends/tracker/meson.build
new file mode 100644
index 00000000..a271fa55
--- /dev/null
+++ b/backends/tracker/meson.build
@@ -0,0 +1,42 @@
+tracker_backend_name = 'tracker'
+
+# NOTE: we don't export a backend library here.
+
+tracker_backend_sources = [
+ 'tracker-backend-factory.vala',
+ 'tracker-backend.vala',
+ 'tracker-persona-store.vala',
+ 'tracker-persona.vala',
+]
+
+tracker_backend_deps = [
+ backend_deps,
+ tracker_dep,
+ libm_dep,
+]
+
+tracker_backend_vala_flags = [
+]
+
+tracker_backend_c_flags = [
+ '-include', 'config.h',
+ '-DBACKEND_NAME="@0@"'.format(tracker_backend_name),
+ '-DG_LOG_DOMAIN="@0@"'.format(tracker_backend_name),
+]
+
+tracker_backend = shared_library(tracker_backend_name,
+ tracker_backend_sources,
+ dependencies: tracker_backend_deps,
+ vala_args: tracker_backend_vala_flags,
+ c_args: tracker_backend_c_flags,
+ name_prefix: '',
+ install_dir: folks_backend_dir / tracker_backend_name,
+ install: true,
+)
+
+tracker_backend_dep = declare_dependency(
+ link_with: tracker_backend,
+ include_directories: include_directories('.'),
+)
+
+folks_backends += tracker_backend
diff --git a/backends/tracker/tracker-backend-factory.vala b/backends/tracker/tracker-backend-factory.vala
new file mode 100644
index 00000000..fd30995f
--- /dev/null
+++ b/backends/tracker/tracker-backend-factory.vala
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2023 Collabora Ltd.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Corentin Noël <corentin.noel@collabora.com>
+ */
+
+using Folks;
+
+/**
+ * The backend module entry point.
+ *
+ * @backend_store a store to add the Tracker backends to
+ */
+public void module_init (BackendStore backend_store)
+{
+ backend_store.add_backend (new Folks.Backends.TrackerBackend ());
+}
+
+/**
+ * The backend module exit point.
+ *
+ * @param backend_store the store to remove the backends from
+ */
+public void module_finalize (BackendStore backend_store)
+{
+ /* FIXME: No way to remove backends from the store. */
+}
diff --git a/backends/tracker/tracker-backend.vala b/backends/tracker/tracker-backend.vala
new file mode 100644
index 00000000..ced51ccb
--- /dev/null
+++ b/backends/tracker/tracker-backend.vala
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2023 Collabora Ltd.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Corentin Noël <corentin.noel@collabora.com>
+ */
+
+using GLib;
+using Gee;
+using Folks;
+
+extern const string BACKEND_NAME;
+
+/**
+ * A backend which loads {@link Persona}s from paired Bluetooth
+ * devices using the Phonebook Access Protocol (PBAP) and presents them
+ * using one {@link PersonaStore} per device.
+ */
+public class Folks.Backends.TrackerBackend : Folks.Backend
+{
+ private bool _is_prepared = false;
+ private bool _prepare_pending = false; /* used for unprepare() too */
+ private bool _is_quiescent = false;
+ /* Map from PersonaStore.id to PersonaStore. */
+ private HashMap<string, PersonaStore> _persona_stores;
+ private Map<string, PersonaStore> _persona_stores_ro;
+ private Tracker.Sparql.Connection sparql_connection;
+
+ /**
+ * Whether this Backend has been prepared.
+ *
+ * See {@link Folks.Backend.is_prepared}.
+ *
+ * @since 0.9.6
+ */
+ public override bool is_prepared
+ {
+ get { return this._is_prepared; }
+ }
+
+ /**
+ * Whether this Backend has reached a quiescent state.
+ *
+ * See {@link Folks.Backend.is_quiescent}.
+ *
+ * @since 0.9.6
+ */
+ public override bool is_quiescent
+ {
+ get { return this._is_quiescent; }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 0.9.6
+ */
+ public override string name { get { return BACKEND_NAME; } }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 0.9.6
+ */
+ public override Map<string, Folks.PersonaStore> persona_stores
+ {
+ get { return this._persona_stores_ro; }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 0.9.6
+ */
+ public override void disable_persona_store (Folks.PersonaStore store)
+ {
+ //TODO
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 0.9.6
+ */
+ public override void enable_persona_store (Folks.PersonaStore store)
+ {
+ // TODO
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 0.9.6
+ */
+ public override void set_persona_stores (Set<string>? storeids)
+ {
+ //TODO
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 0.9.6
+ */
+ public TrackerBackend ()
+ {
+ Object ();
+ }
+
+ construct
+ {
+ this._persona_stores = new HashMap<string, PersonaStore> ();
+ this._persona_stores_ro = this._persona_stores.read_only_view;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 0.9.6
+ */
+ public override async void prepare () throws DBusError
+ {
+ var profiling = Internal.profiling_start ("preparing Tracker.Backend");
+
+ if (this._is_prepared || this._prepare_pending)
+ {
+ return;
+ }
+
+ _prepare_pending = true;
+ this.freeze_notify ();
+
+ Cancellable? cancellable = null;
+ try {
+ sparql_connection = yield Tracker.Sparql.Connection.bus_new_async ("org.freedesktop.Tracker3.Miner.EDS", null, null, cancellable);
+ var cursor = yield sparql_connection.query_async (
+ """SELECT ?addressbook ?addressbookName WHERE { ?addressbook a nco:ContactList .
+ OPTIONAL {
+ ?addressbook nie:title ?addressbookName .
+ } }""", cancellable);
+ while (yield cursor.next_async (cancellable)) {
+ long length;
+ unowned var addressbook_urn = cursor.get_string (0, out length);
+ unowned var title = cursor.get_string (1, out length);
+ var store = new TrackerPersonaStore (sparql_connection, addressbook_urn, title);
+ _persona_stores.set (store.id, store);
+ }
+ } catch (Error e) {
+ critical (e.message);
+ }
+
+ this._is_prepared = true;
+ this.notify_property ("is-prepared");
+
+ this._is_quiescent = true;
+ this.notify_property ("is-quiescent");
+
+ this.thaw_notify ();
+ this._prepare_pending = false;
+
+ Internal.profiling_end ((owned) profiling);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 0.9.6
+ */
+ public override async void unprepare () throws GLib.Error
+ {
+ if (!this._is_prepared || this._prepare_pending == true)
+ {
+ return;
+ }
+
+ this._prepare_pending = true;
+
+ this.freeze_notify ();
+
+ //TODO
+
+ this.notify_property ("persona-stores");
+
+ this._is_quiescent = false;
+ this.notify_property ("is-quiescent");
+
+ this._is_prepared = false;
+ this.notify_property ("is-prepared");
+
+ this.thaw_notify ();
+ this._prepare_pending = false;
+ }
+}
+
diff --git a/backends/tracker/tracker-persona-store.vala b/backends/tracker/tracker-persona-store.vala
new file mode 100644
index 00000000..c42e8e8a
--- /dev/null
+++ b/backends/tracker/tracker-persona-store.vala
@@ -0,0 +1,271 @@
+/*
+ * Copyright 2023 Collabora Ltd.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Corentin Noël <corentin.noel@collabora.com>
+ */
+
+using GLib;
+using Gee;
+using Folks;
+
+/**
+ * A persona store which is associated with a single BlueZ PBAP server (i.e.
+ * one {@link PersonaStore} per device). It will create a {@link Persona} for
+ * each contact on the device.
+ *
+ * Since large contact lists can take a long time to download in full (on the
+ * order of 1s per 10 contacts), contacts are downloaded in two phases:
+ * # Phase 1 downloads all non-PHOTO data. This is very fast (on the order of
+ * 1s per 400 contacts)
+ * # Phase 2 downloads all PHOTO data for those contacts. This is slow, but
+ * happens later, in the background.
+ *
+ * Subsequent download attempts happen on an exponentially increasing interval,
+ * up to a limit (once this limit is reached, updates occur on a regular
+ * interval; the linear region). Download attempts repeat indefinitely unless a
+ * certain number of consecutive attempts end in failure. See the documentation
+ * for {@link _schedule_update_contacts} for details.
+ *
+ * @since 0.9.6
+ */
+public class Folks.Backends.TrackerPersonaStore : Folks.PersonaStore
+{
+ private HashMap<string, TrackerPersona> _personas;
+ private Map<string, TrackerPersona> _personas_ro;
+ private bool _is_prepared = false;
+ private bool _prepare_pending = false;
+ private bool _is_quiescent = false;
+ private Tracker.Sparql.Connection sparql_connection;
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 0.9.6
+ */
+ public override string type_id { get { return BACKEND_NAME; } }
+
+ /**
+ * Whether this PersonaStore can add {@link Folks.Persona}s.
+ *
+ * See {@link Folks.PersonaStore.can_add_personas}.
+ *
+ * @since 0.9.6
+ */
+ public override MaybeBool can_add_personas
+ {
+ get { return MaybeBool.FALSE; }
+ }
+
+ /**
+ * Whether this PersonaStore can set the alias of {@link Folks.Persona}s.
+ *
+ * See {@link Folks.PersonaStore.can_alias_personas}.
+ *
+ * @since 0.9.6
+ */
+ public override MaybeBool can_alias_personas
+ {
+ get { return MaybeBool.FALSE; }
+ }
+
+ /**
+ * Whether this PersonaStore can set the groups of {@link Folks.Persona}s.
+ *
+ * See {@link Folks.PersonaStore.can_group_personas}.
+ *
+ * @since 0.9.6
+ */
+ public override MaybeBool can_group_personas
+ {
+ get { return MaybeBool.FALSE; }
+ }
+
+ /**
+ * Whether this PersonaStore can remove {@link Folks.Persona}s.
+ *
+ * See {@link Folks.PersonaStore.can_remove_personas}.
+ *
+ * @since 0.9.6
+ */
+ public override MaybeBool can_remove_personas
+ {
+ get { return MaybeBool.FALSE; }
+ }
+
+ /**
+ * Whether this PersonaStore has been prepared.
+ *
+ * See {@link Folks.PersonaStore.is_prepared}.
+ *
+ * @since 0.9.6
+ */
+ public override bool is_prepared
+ {
+ get { return this._is_prepared; }
+ }
+
+ /**
+ * Whether this PersonaStore has reached a quiescent state.
+ *
+ * See {@link Folks.PersonaStore.is_quiescent}.
+ *
+ * @since 0.9.6
+ */
+ public override bool is_quiescent
+ {
+ get { return this._is_quiescent; }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 0.9.6
+ */
+ private class string[] _always_writeable_properties = {};
+ public override string[] always_writeable_properties
+ {
+ get { return this._always_writeable_properties; }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 0.9.6
+ */
+ public override Map<string, Folks.Persona> personas
+ {
+ get { return this._personas_ro; }
+ }
+
+ /**
+ * Create a new PersonaStore.
+ *
+ * Create a new persona store to expose the {@link Persona}s provided by the
+ * addressbook with the given urn.
+ *
+ * @param sparql_connection the Sparql connection
+ * @param addressbook_urn the URN of the addressbook
+ *
+ * @since 0.9.6
+ */
+ public TrackerPersonaStore (Tracker.Sparql.Connection sparql_connection, string addressbook_urn, string? title)
+ {
+ Object (id: addressbook_urn, display_name: title);
+ this.sparql_connection = sparql_connection;
+ }
+
+ construct
+ {
+ this._personas = new HashMap<string, TrackerPersona> ();
+ this._personas_ro = this._personas.read_only_view;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 0.9.6
+ */
+ public override async void prepare () throws PersonaStoreError
+ {
+ var profiling = Internal.profiling_start ("preparing Tracker.PersonaStore (ID: %s)",
+ this.id);
+
+ if (this._is_prepared || this._prepare_pending)
+ {
+ return;
+ }
+
+ try
+ {
+ this._prepare_pending = true;
+
+ var added_personas = new HashSet<Persona> ();
+ var cursor = yield sparql_connection.query_async (
+ """SELECT ?contact ?contactUID ?contactFullname {
+ <%s> nco:containsContact ?contact .
+ ?contact nco:contactUID ?contactUID .
+ ?contact nco:fullname ?contactFullname
+ }""".printf (id), null);
+ while (yield cursor.next_async (null)) {
+ long length;
+ unowned var contact_urn = cursor.get_string (0, out length);
+ unowned var contact_uid = cursor.get_string (1, out length);
+ unowned var contact_fullname = cursor.get_string (2, out length);
+ var persona = new TrackerPersona (sparql_connection, this, contact_urn, contact_uid, contact_fullname);
+ _personas.set (persona.iid, persona);
+ added_personas.add (persona);
+ }
+
+ if (added_personas.is_empty == false)
+ {
+ this._emit_personas_changed (added_personas, null);
+ }
+
+ this._is_prepared = true;
+ this.notify_property ("is-prepared");
+
+ this._is_quiescent = true;
+ this.notify_property ("is-quiescent");
+ }
+ catch (Error e)
+ {
+ critical (e.message);
+ }
+ finally
+ {
+ this._prepare_pending = false;
+ }
+
+ Internal.profiling_end ((owned) profiling);
+ }
+
+ /**
+ * Remove a {@link Persona} from the PersonaStore.
+ *
+ * See {@link Folks.PersonaStore.remove_persona}.
+ *
+ * @param persona the {@link Persona} to remove
+ * @throws Folks.PersonaStoreError.READ_ONLY every time since the
+ * Tracker backend is read-only.
+ *
+ * @since 0.9.6
+ */
+ public override async void remove_persona (Folks.Persona persona)
+ throws Folks.PersonaStoreError
+ {
+ throw new PersonaStoreError.READ_ONLY (
+ "Personas cannot be removed from this store.");
+ }
+
+ /**
+ * Add a new {@link Persona} to the PersonaStore.
+ *
+ * See {@link Folks.PersonaStore.add_persona_from_details}.
+ *
+ * @param details a map of keys to values giving the persona’s initial details
+ * @throws Folks.PersonaStoreError.READ_ONLY every time since the
+ * Tracker backend is read-only.
+ *
+ * @since 0.9.6
+ */
+ public override async Folks.Persona? add_persona_from_details (
+ HashTable<string, Value?> details) throws Folks.PersonaStoreError
+ {
+ throw new PersonaStoreError.READ_ONLY (
+ "Personas cannot be added to this store.");
+ }
+}
diff --git a/backends/tracker/tracker-persona.vala b/backends/tracker/tracker-persona.vala
new file mode 100644
index 00000000..90039c24
--- /dev/null
+++ b/backends/tracker/tracker-persona.vala
@@ -0,0 +1,234 @@
+/*
+ * Copyright 2023 Collabora Ltd.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Corentin Noël <corentin.noel@collabora.com>
+ */
+
+using GLib;
+using Gee;
+using Folks;
+
+/**
+ * A persona subclass which represents a single persona from a simple key file.
+ *
+ * @since 0.9.6
+ */
+public class Folks.Backends.TrackerPersona : Folks.Persona,
+ AvatarDetails,
+ EmailDetails,
+ NameDetails,
+ PhoneDetails,
+ UrlDetails
+{
+ private const string[] _linkable_properties =
+ {
+ "phone-numbers",
+ "email-addresses"
+ };
+ private static string[] _writeable_properties = { };
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 0.9.6
+ */
+ public override string[] linkable_properties
+ {
+ get { return TrackerPersona._linkable_properties; }
+ }
+
+ private SmallSet<UrlFieldDetails>? _urls = null;
+ private Set<UrlFieldDetails> _urls_ro;
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 0.9.6
+ */
+ [CCode (notify = false)]
+ public Set<UrlFieldDetails> urls
+ {
+ get { return this._urls_ro; }
+ set { this.change_urls.begin (value); } /* not writeable */
+ }
+
+ private LoadableIcon? _avatar = null;
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 0.9.6
+ */
+ [CCode (notify = false)]
+ public LoadableIcon? avatar
+ {
+ get { return this._avatar; }
+ set { this.change_avatar.begin (value); }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 0.9.6
+ */
+ public override string[] writeable_properties
+ {
+ get { return TrackerPersona._writeable_properties; }
+ }
+
+ private SmallSet<PhoneFieldDetails>? _phone_numbers = null;
+ private Set<PhoneFieldDetails> _phone_numbers_ro;
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 0.9.6
+ */
+ [CCode (notify = false)]
+ public Set<PhoneFieldDetails> phone_numbers
+ {
+ get { return this._phone_numbers_ro; }
+ set { this.change_phone_numbers.begin (value); } /* not writeable */
+ }
+
+ private StructuredName? _structured_name = null;
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 0.9.6
+ */
+ [CCode (notify = false)]
+ public StructuredName? structured_name
+ {
+ get { return this._structured_name; }
+ set { this.change_structured_name.begin (value); } /* not writeable */
+ }
+
+ private string _full_name = "";
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 0.9.6
+ */
+ [CCode (notify = false)]
+ public string full_name
+ {
+ get { return this._full_name; }
+ set { this.change_full_name.begin (value); } /* not writeable */
+ }
+
+ private string _nickname = "";
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 0.9.6
+ */
+ [CCode (notify = false)]
+ public string nickname
+ {
+ get { return this._nickname; }
+ set { this.change_nickname.begin (value); } /* not writeable */
+ }
+
+ private SmallSet<EmailFieldDetails>? _email_addresses = null;
+ private Set<EmailFieldDetails> _email_addresses_ro;
+ private Tracker.Sparql.Connection sparql_connection;
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 0.9.6
+ */
+ [CCode (notify = false)]
+ public Set<EmailFieldDetails> email_addresses
+ {
+ get { return this._email_addresses_ro; }
+ set { this.change_email_addresses.begin (value); } /* not writeable */
+ }
+
+ /**
+ * Create a new persona.
+ *
+ * Create a new persona for the {@link PersonaStore} ``store``, representing
+ * the Persona in the given ``vcard``.
+ *
+ * @param vcard the vCard stored as a string
+ * @param card a parsed version of the vCard
+ * @param store the store to which the Persona belongs.
+ * @param is_user whether the Persona is the user itself or not.
+ * @param iid pre-calculated IID for the persona
+ *
+ * @since 0.9.6
+ */
+ public TrackerPersona (Tracker.Sparql.Connection sparql_connection, Folks.PersonaStore store, string urn, string uid, string fullname)
+ {
+ Object(iid: urn, uid: uid, full_name: fullname, store: store);
+ this.sparql_connection = sparql_connection;
+ }
+
+ construct
+ {
+ debug ("Adding Tracker Persona '%s' (IID '%s')", this.uid, this.iid);
+
+ this._phone_numbers = new SmallSet<PhoneFieldDetails> (
+ AbstractFieldDetails<string>.hash_static,
+ AbstractFieldDetails<string>.equal_static);
+ this._phone_numbers_ro = this._phone_numbers.read_only_view;
+ this._email_addresses = new SmallSet<EmailFieldDetails> (
+ AbstractFieldDetails<string>.hash_static,
+ AbstractFieldDetails<string>.equal_static);
+ this._email_addresses_ro = this._email_addresses.read_only_view;
+ this._urls = new SmallSet<UrlFieldDetails> (
+ AbstractFieldDetails<string>.hash_static,
+ AbstractFieldDetails<string>.equal_static);
+ this._urls_ro = this._urls.read_only_view;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 0.9.6
+ */
+ public override void linkable_property_to_links (string prop_name,
+ Folks.Persona.LinkablePropertyCallback callback)
+ {
+ if (prop_name == "phone-numbers")
+ {
+ foreach (var phone_number in this._phone_numbers)
+ {
+ if (phone_number.value != null)
+ callback (phone_number.value);
+ }
+ }
+ else if (prop_name == "email-addresses")
+ {
+ foreach (var email_address in this._email_addresses)
+ {
+ if (email_address.value != null)
+ callback (email_address.value);
+ }
+ }
+ else
+ {
+ /* Chain up */
+ base.linkable_property_to_links (prop_name, callback);
+ }
+ }
+}
diff --git a/meson.build b/meson.build
index 6bdaae27..d2d9bd7e 100644
--- a/meson.build
+++ b/meson.build
@@ -57,6 +57,7 @@ tests_enabled = get_option('tests')
installed_tests_enabled = get_option('installed_tests')
ofono_backend_enabled = get_option('ofono_backend')
telepathy_backend_enabled = get_option('telepathy_backend')
+tracker_backend_enabled = get_option('tracker_backend')
zeitgeist_enabled = get_option('zeitgeist')
import_tool_enabled = get_option('import_tool')
inspect_tool_enabled = get_option('inspect_tool')
@@ -122,6 +123,12 @@ if bluez_backend_enabled
endif
endif
+if tracker_backend_enabled
+ vapi_dir = meson.current_source_dir() / 'vapi'
+ add_project_arguments(['--vapidir', vapi_dir], language: 'vala')
+ tracker_dep = dependency('tracker-sparql-3.0')
+endif
+
if import_tool_enabled
libxml_dep = dependency('libxml-2.0')
endif
diff --git a/meson_options.txt b/meson_options.txt
index 361f30cf..7aadf08d 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -3,6 +3,7 @@ option('bluez_backend', type: 'boolean', value: true, description: 'build the Bl
option('eds_backend', type: 'boolean', value: true, description: 'build the E-D-S backend')
option('ofono_backend', type: 'boolean', value: true, description: 'build the oFono backend')
option('telepathy_backend', type: 'boolean', value: true, description: 'build the Telepathy backend')
+option('tracker_backend', type: 'boolean', value: true, description: 'build the Tracker backend')
option('zeitgeist', type: 'boolean', value: false, description: 'build Zeitgeist support in the Telepathy backend')
# Tools
option('import_tool', type: 'boolean', value: true, description: 'Enable building the meta-contact import tool')
diff --git a/vapi/tracker-sparql-3.0.vapi b/vapi/tracker-sparql-3.0.vapi
new file mode 100644
index 00000000..ae0c2c11
--- /dev/null
+++ b/vapi/tracker-sparql-3.0.vapi
@@ -0,0 +1,344 @@
+/* tracker-sparql-3.0.vapi generated by vapigen, do not modify. */
+
+[CCode (cprefix = "Tracker", gir_namespace = "Tracker", gir_version = "3.0", lower_case_cprefix = "tracker_")]
+namespace Tracker {
+ namespace Prefix {
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h", cname = "TRACKER_PREFIX_DC")]
+ public const string DC;
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h", cname = "TRACKER_PREFIX_MFO")]
+ public const string MFO;
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h", cname = "TRACKER_PREFIX_NAO")]
+ public const string NAO;
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h", cname = "TRACKER_PREFIX_NCO")]
+ public const string NCO;
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h", cname = "TRACKER_PREFIX_NFO")]
+ public const string NFO;
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h", cname = "TRACKER_PREFIX_NIE")]
+ public const string NIE;
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h", cname = "TRACKER_PREFIX_NMM")]
+ public const string NMM;
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h", cname = "TRACKER_PREFIX_NRL")]
+ public const string NRL;
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h", cname = "TRACKER_PREFIX_OSINFO")]
+ public const string OSINFO;
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h", cname = "TRACKER_PREFIX_RDF")]
+ public const string RDF;
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h", cname = "TRACKER_PREFIX_RDFS")]
+ public const string RDFS;
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h", cname = "TRACKER_PREFIX_SLO")]
+ public const string SLO;
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h", cname = "TRACKER_PREFIX_TRACKER")]
+ public const string TRACKER;
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h", cname = "TRACKER_PREFIX_XSD")]
+ public const string XSD;
+ }
+ namespace Sparql {
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h", type_id = "tracker_sparql_connection_get_type ()")]
+ [GIR (name = "SparqlConnection")]
+ public abstract class Connection : GLib.Object {
+ [CCode (has_construct_function = false)]
+ protected Connection ();
+ [Version (since = "3.0")]
+ public static Tracker.Sparql.Connection bus_new (string service_name, string? object_path, GLib.DBusConnection? dbus_connection) throws GLib.Error;
+ [Version (since = "3.1")]
+ public static async Tracker.Sparql.Connection bus_new_async (string service_name, string? object_path, GLib.DBusConnection? dbus_connection, GLib.Cancellable? cancellable = null) throws GLib.Error;
+ [Version (since = "3.0")]
+ public void close ();
+ [Version (since = "3.0")]
+ public async bool close_async (GLib.Cancellable? cancellable = null) throws GLib.Error;
+ public Tracker.Batch create_batch ();
+ public Tracker.Notifier create_notifier ();
+ [Version (since = "3.4")]
+ public async bool deserialize_async (Tracker.DeserializeFlags flags, Tracker.RdfFormat format, string default_graph, GLib.InputStream stream, GLib.Cancellable? cancellable = null) throws GLib.Error;
+ public unowned Tracker.NamespaceManager get_namespace_manager ();
+ [Version (since = "3.3")]
+ public Tracker.Sparql.Statement? load_statement_from_gresource (string resource_path, GLib.Cancellable? cancellable = null) throws GLib.Error;
+ [Version (since = "3.3")]
+ public void map_connection (string handle_name, Tracker.Sparql.Connection service_connection);
+ [Version (since = "3.0")]
+ public static Tracker.Sparql.Connection @new (Tracker.Sparql.ConnectionFlags flags, GLib.File? store, GLib.File? ontology, GLib.Cancellable? cancellable = null) throws GLib.Error;
+ [Version (since = "3.0")]
+ public static async Tracker.Sparql.Connection new_async (Tracker.Sparql.ConnectionFlags flags, GLib.File? store, GLib.File? ontology, GLib.Cancellable? cancellable = null) throws GLib.Error;
+ public Tracker.Sparql.Cursor query (string sparql, GLib.Cancellable? cancellable = null) throws GLib.Error;
+ public async Tracker.Sparql.Cursor query_async (string sparql, GLib.Cancellable? cancellable = null) throws GLib.Error;
+ public Tracker.Sparql.Statement? query_statement (string sparql, GLib.Cancellable? cancellable = null) throws GLib.Error;
+ public static Tracker.Sparql.Connection remote_new (string uri_base);
+ [Version (since = "3.3")]
+ public async GLib.InputStream serialize_async (Tracker.SerializeFlags flags, Tracker.RdfFormat format, string query, GLib.Cancellable? cancellable = null) throws GLib.Error;
+ public void update (string sparql, GLib.Cancellable? cancellable = null) throws GLib.Error;
+ public async bool update_array_async (string sparql, int sparql_length, GLib.Cancellable? cancellable = null) throws GLib.Error;
+ public async void update_async (string sparql, GLib.Cancellable? cancellable = null) throws GLib.Error;
+ [Version (deprecated = true, deprecated_since = "3.5")]
+ public GLib.Variant update_blank (string sparql, GLib.Cancellable? cancellable = null) throws GLib.Error;
+ [Version (deprecated = true, deprecated_since = "3.5")]
+ public async GLib.Variant update_blank_async (string sparql, GLib.Cancellable? cancellable = null) throws GLib.Error;
+ [Version (since = "3.1")]
+ public bool update_resource (string? graph, Tracker.Resource resource, GLib.Cancellable? cancellable = null) throws GLib.Error;
+ [Version (since = "3.1")]
+ public async bool update_resource_async (string? graph, Tracker.Resource resource, GLib.Cancellable? cancellable = null) throws GLib.Error;
+ [Version (since = "3.5")]
+ public Tracker.Sparql.Statement? update_statement (string sparql, GLib.Cancellable? cancellable = null) throws GLib.Error;
+ }
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h", type_id = "tracker_sparql_cursor_get_type ()")]
+ [GIR (name = "SparqlCursor")]
+ public abstract class Cursor : GLib.Object {
+ [CCode (has_construct_function = false)]
+ protected Cursor ();
+ public void close ();
+ public bool get_boolean (int column);
+ public unowned Tracker.Sparql.Connection get_connection ();
+ [Version (since = "3.2")]
+ public GLib.DateTime? get_datetime (int column);
+ public double get_double (int column);
+ public int64 get_integer (int column);
+ public int get_n_columns ();
+ public unowned string? get_string (int column, out long length);
+ public Tracker.Sparql.ValueType get_value_type (int column);
+ public unowned string get_variable_name (int column);
+ public bool is_bound (int column);
+ public bool next (GLib.Cancellable? cancellable = null) throws GLib.Error;
+ public async bool next_async (GLib.Cancellable? cancellable = null) throws GLib.Error;
+ [Version (deprecated = true, deprecated_since = "3.5")]
+ public void rewind ();
+ public Tracker.Sparql.Connection connection { get; construct; }
+ public int n_columns { get; }
+ }
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h", type_id = "tracker_sparql_statement_get_type ()")]
+ [GIR (name = "SparqlStatement")]
+ public abstract class Statement : GLib.Object {
+ [CCode (has_construct_function = false)]
+ protected Statement ();
+ public void bind_boolean (string name, bool value);
+ [Version (since = "3.2")]
+ public void bind_datetime (string name, GLib.DateTime value);
+ public void bind_double (string name, double value);
+ public void bind_int (string name, int64 value);
+ public void bind_string (string name, string value);
+ [Version (since = "3.0")]
+ public void clear_bindings ();
+ public Tracker.Sparql.Cursor execute (GLib.Cancellable? cancellable = null) throws GLib.Error;
+ public async Tracker.Sparql.Cursor execute_async (GLib.Cancellable? cancellable = null) throws GLib.Error;
+ public unowned Tracker.Sparql.Connection get_connection ();
+ public unowned string get_sparql ();
+ [Version (since = "3.3")]
+ public async GLib.InputStream serialize_async (Tracker.SerializeFlags flags, Tracker.RdfFormat format, GLib.Cancellable? cancellable = null) throws GLib.Error;
+ [Version (since = "3.5")]
+ public bool update (GLib.Cancellable? cancellable = null) throws GLib.Error;
+ [Version (since = "3.5")]
+ public async bool update_async (GLib.Cancellable? cancellable = null) throws GLib.Error;
+ public Tracker.Sparql.Connection connection { get; construct; }
+ public string sparql { get; construct; }
+ }
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h", cprefix = "TRACKER_SPARQL_CONNECTION_FLAGS_", has_type_id = false)]
+ [Flags]
+ [GIR (name = "SparqlConnectionFlags")]
+ public enum ConnectionFlags {
+ NONE,
+ READONLY,
+ FTS_ENABLE_STEMMER,
+ FTS_ENABLE_UNACCENT,
+ FTS_ENABLE_STOP_WORDS,
+ FTS_IGNORE_NUMBERS,
+ ANONYMOUS_BNODES
+ }
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h", cprefix = "TRACKER_SPARQL_VALUE_TYPE_", has_type_id = false)]
+ [GIR (name = "SparqlValueType")]
+ public enum ValueType {
+ UNBOUND,
+ URI,
+ STRING,
+ INTEGER,
+ DOUBLE,
+ DATETIME,
+ BLANK_NODE,
+ BOOLEAN
+ }
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h", cprefix = "TRACKER_SPARQL_ERROR_", has_type_id = false)]
+ [GIR (name = "SparqlError")]
+ public errordomain Error {
+ CONSTRAINT,
+ INTERNAL,
+ NO_SPACE,
+ ONTOLOGY_NOT_FOUND,
+ OPEN_ERROR,
+ PARSE,
+ QUERY_FAILED,
+ TYPE,
+ UNKNOWN_CLASS,
+ UNKNOWN_GRAPH,
+ UNKNOWN_PROPERTY,
+ UNSUPPORTED,
+ MISSING_LAST_MODIFIED_HEADER,
+ INCOMPLETE_PROPERTY_DEFINITION,
+ LAST;
+ public static GLib.Quark quark ();
+ }
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h")]
+ public static string escape_string (string literal);
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h")]
+ public static string escape_uri (string uri);
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h")]
+ public static string escape_uri_printf (string format, ...);
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h")]
+ public static string escape_uri_vprintf (string format, va_list args);
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h")]
+ public static GLib.File get_ontology_nepomuk ();
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h")]
+ public static string get_uuid_urn ();
+ }
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h", type_id = "tracker_batch_get_type ()")]
+ public abstract class Batch : GLib.Object {
+ [CCode (has_construct_function = false)]
+ protected Batch ();
+ [Version (since = "3.1")]
+ public void add_resource (string? graph, Tracker.Resource resource);
+ [Version (since = "3.1")]
+ public void add_sparql (string sparql);
+ [Version (since = "3.5")]
+ public void add_statementv (Tracker.Sparql.Statement stmt, [CCode (array_length_cname = "n_values", array_length_pos = 1.5, array_length_type = "guint")] string[] variable_names, [CCode (array_length_cname = "n_values", array_length_pos = 1.5, array_length_type = "guint")] GLib.Value[] values);
+ [Version (since = "3.1")]
+ public bool execute (GLib.Cancellable? cancellable = null) throws GLib.Error;
+ [Version (since = "3.1")]
+ public async bool execute_async (GLib.Cancellable? cancellable = null) throws GLib.Error;
+ public unowned Tracker.Sparql.Connection get_connection ();
+ public Tracker.Sparql.Connection connection { get; construct; }
+ }
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h", type_id = "tracker_endpoint_get_type ()")]
+ public abstract class Endpoint : GLib.Object {
+ [CCode (has_construct_function = false)]
+ protected Endpoint ();
+ public unowned Tracker.Sparql.Connection get_sparql_connection ();
+ public Tracker.Sparql.Connection sparql_connection { get; construct; }
+ }
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h", type_id = "tracker_endpoint_dbus_get_type ()")]
+ public class EndpointDBus : Tracker.Endpoint, GLib.Initable {
+ [CCode (has_construct_function = false)]
+ public EndpointDBus (Tracker.Sparql.Connection sparql_connection, GLib.DBusConnection dbus_connection, string? object_path, GLib.Cancellable? cancellable = null) throws GLib.Error;
+ [NoAccessorMethod]
+ public GLib.DBusConnection dbus_connection { owned get; construct; }
+ [NoAccessorMethod]
+ public string object_path { owned get; construct; }
+ }
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h", type_id = "tracker_endpoint_http_get_type ()")]
+ public class EndpointHttp : Tracker.Endpoint, GLib.Initable {
+ [CCode (has_construct_function = false)]
+ [Version (since = "3.1")]
+ public EndpointHttp (Tracker.Sparql.Connection sparql_connection, uint port, GLib.TlsCertificate? certificate, GLib.Cancellable? cancellable = null) throws GLib.Error;
+ [NoAccessorMethod]
+ public GLib.TlsCertificate http_certificate { owned get; construct; }
+ [NoAccessorMethod]
+ public uint http_port { get; construct; }
+ public signal bool block_remote_address (GLib.SocketAddress address);
+ }
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h", type_id = "tracker_namespace_manager_get_type ()")]
+ public class NamespaceManager : GLib.Object {
+ [CCode (has_construct_function = false)]
+ public NamespaceManager ();
+ public void add_prefix (string prefix, string ns);
+ [Version (since = "3.3")]
+ public string compress_uri (string uri);
+ public string expand_uri (string compact_uri);
+ public void @foreach (GLib.HFunc func);
+ [Version (deprecated = true, deprecated_since = "3.3")]
+ public static unowned Tracker.NamespaceManager get_default ();
+ public bool has_prefix (string prefix);
+ public unowned string? lookup_prefix (string prefix);
+ public string print_turtle ();
+ }
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h", type_id = "tracker_notifier_get_type ()")]
+ public class Notifier : GLib.Object {
+ [CCode (has_construct_function = false)]
+ protected Notifier ();
+ [Version (since = "3.0")]
+ public uint signal_subscribe (GLib.DBusConnection connection, string service, string? object_path, string? graph);
+ [Version (since = "3.0")]
+ public void signal_unsubscribe (uint handler_id);
+ [NoAccessorMethod]
+ public Tracker.Sparql.Connection connection { owned get; construct; }
+ public signal void events (string service, string graph, GLib.GenericArray<Tracker.NotifierEvent> events);
+ }
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h", copy_function = "g_boxed_copy", free_function = "g_boxed_free", type_id = "tracker_notifier_event_get_type ()")]
+ [Compact]
+ public class NotifierEvent {
+ public Tracker.NotifierEventType get_event_type ();
+ public int64 get_id ();
+ public unowned string get_urn ();
+ }
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h", type_id = "tracker_resource_get_type ()")]
+ public class Resource : GLib.Object {
+ [CCode (has_construct_function = false)]
+ public Resource (string? identifier);
+ public void add_boolean (string property_uri, bool value);
+ [Version (since = "3.2")]
+ public void add_datetime (string property_uri, GLib.DateTime value);
+ public void add_double (string property_uri, double value);
+ public void add_gvalue (string property_uri, GLib.Value value);
+ public void add_int (string property_uri, int value);
+ public void add_int64 (string property_uri, int64 value);
+ public void add_relation (string property_uri, Tracker.Resource resource);
+ public void add_string (string property_uri, string value);
+ public void add_take_relation (string property_uri, owned Tracker.Resource resource);
+ public void add_uri (string property_uri, string value);
+ public static Tracker.Resource? deserialize (GLib.Variant variant);
+ public bool get_first_boolean (string property_uri);
+ [Version (since = "3.2")]
+ public unowned GLib.DateTime? get_first_datetime (string property_uri);
+ public double get_first_double (string property_uri);
+ public int get_first_int (string property_uri);
+ public int64 get_first_int64 (string property_uri);
+ public unowned Tracker.Resource? get_first_relation (string property_uri);
+ public unowned string? get_first_string (string property_uri);
+ public unowned string? get_first_uri (string property_uri);
+ public unowned string? get_identifier ();
+ [Version (since = "3.0")]
+ public GLib.List<weak string> get_properties ();
+ [Version (since = "3.1")]
+ public bool get_property_overwrite (string property_uri);
+ public GLib.List<weak GLib.Value?>? get_values (string property_uri);
+ public int identifier_compare_func (string identifier);
+ [Version (deprecated = true, deprecated_since = "3.5")]
+ public string print_jsonld (Tracker.NamespaceManager? namespaces);
+ [Version (since = "3.4")]
+ public string print_rdf (Tracker.NamespaceManager namespaces, Tracker.RdfFormat format, string? graph);
+ public string print_sparql_update (Tracker.NamespaceManager? namespaces, string? graph_id);
+ [Version (deprecated = true, deprecated_since = "3.4")]
+ public string print_turtle (Tracker.NamespaceManager? namespaces);
+ public unowned GLib.Variant? serialize ();
+ public void set_boolean (string property_uri, bool value);
+ [Version (since = "3.2")]
+ public void set_datetime (string property_uri, GLib.DateTime value);
+ public void set_double (string property_uri, double value);
+ public void set_gvalue (string property_uri, GLib.Value value);
+ public void set_identifier (string? identifier);
+ public void set_int (string property_uri, int value);
+ public void set_int64 (string property_uri, int64 value);
+ public void set_relation (string property_uri, Tracker.Resource resource);
+ public void set_string (string property_uri, string value);
+ public void set_take_relation (string property_uri, owned Tracker.Resource resource);
+ public void set_uri (string property_uri, string value);
+ public string identifier { get; set; }
+ }
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h", cprefix = "TRACKER_DESERIALIZE_FLAGS_", has_type_id = false)]
+ public enum DeserializeFlags {
+ NONE
+ }
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h", cprefix = "TRACKER_NOTIFIER_EVENT_", has_type_id = false)]
+ public enum NotifierEventType {
+ CREATE,
+ DELETE,
+ UPDATE
+ }
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h", cprefix = "TRACKER_RDF_FORMAT_", has_type_id = false)]
+ public enum RdfFormat {
+ TURTLE,
+ TRIG,
+ JSON_LD,
+ LAST
+ }
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h", cprefix = "TRACKER_SERIALIZE_FLAGS_", has_type_id = false)]
+ public enum SerializeFlags {
+ NONE
+ }
+ [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h")]
+ public static unowned string check_version (uint required_major, uint required_minor, uint required_micro);
+}