summaryrefslogtreecommitdiff
path: root/src/contacts-shell-search-provider.vala
diff options
context:
space:
mode:
Diffstat (limited to 'src/contacts-shell-search-provider.vala')
-rw-r--r--src/contacts-shell-search-provider.vala192
1 files changed, 93 insertions, 99 deletions
diff --git a/src/contacts-shell-search-provider.vala b/src/contacts-shell-search-provider.vala
index c47318a..1b895a9 100644
--- a/src/contacts-shell-search-provider.vala
+++ b/src/contacts-shell-search-provider.vala
@@ -1,153 +1,147 @@
-/* -*- Mode: vala; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 8 -*- */
+/*
+ * Copyright (C) 2011 Alexander Larsson <alexl@redhat.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 2 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/>.
+ */
+
using Gee;
+using Folks;
[DBus (name = "org.gnome.Shell.SearchProvider2")]
public class Contacts.SearchProvider : Object {
- SearchProviderApp app;
- Store store;
- Gee.HashMap<string, Contact> contacts_map;
- private uint next_id;
+ private SearchProviderApp app;
+ private IndividualAggregator aggregator;
+ private SimpleQuery query;
+ private Variant serialized_fallback_icon;
public SearchProvider (SearchProviderApp app) {
- this.app = app;
- if (!ensure_eds_accounts (false))
- app.quit ();
- store = new Store ();
- contacts_map = new Gee.HashMap<string, Contact> ();
- next_id = 0;
-
- store.changed.connect ( (c) => {
- contacts_map.set(c.get_data<string> ("search-id"), c);
- });
- store.added.connect ( (c) => {
- var id = next_id++.to_string ();
- c.set_data ("search-id", id);
- contacts_map.set(id, c);
- });
- store.removed.connect ( (c) => {
- contacts_map.unset(c.get_data<string> ("search-id"));
- });
- }
+ // Do this first, since this will be the slowest (and is async anyway)
+ this.aggregator = IndividualAggregator.dup ();
+ this.aggregator.prepare.begin ();
- private static int compare_contacts (Contact a, Contact b) {
- int a_prio = a.is_main ? 0 : -1;
- int b_prio = b.is_main ? 0 : -1;
+ this.app = app;
+ this.serialized_fallback_icon = new ThemedIcon.from_names ({"avatar-default-symbolic"}).serialize ();;
- if (a_prio > b_prio)
- return -1;
- if (a_prio < b_prio)
- return 1;
+ var matched_fields = Query.MATCH_FIELDS_NAMES;
+ foreach (var field in Query.MATCH_FIELDS_ADDRESSES)
+ matched_fields += field;
+ this.query = new SimpleQuery ("", matched_fields);
- if (is_set (a.display_name) && is_set (b.display_name))
- return a.display_name.collate (b.display_name);
+ if (!ensure_eds_accounts (false))
+ this.app.quit ();
+ }
- // Sort empty names last
- if (is_set (a.display_name))
- return -1;
- if (is_set (b.display_name))
- return 1;
+ public async string[] GetInitialResultSet (string[] terms) {
+ return yield do_search (terms);
+ }
- return 0;
+ public async string[] GetSubsearchResultSet (string[] previous_results, string[] new_terms) {
+ return yield do_search (new_terms);
}
private async string[] do_search (string[] terms) {
- app.hold ();
- string[] normalized_terms =
- Utils.canonicalize_for_search (string.joinv(" ", terms)).split(" ");
-
- var matches = new ArrayList<Contact> ();
- foreach (var c in store.get_contacts ()) {
- if (c.is_hidden)
- continue;
+ this.app.hold ();
- if (c.contains_strings (normalized_terms))
- matches.add (c);
+ // Make the query and search view
+ query.query_string = string.joinv(" ", terms);
+ var search_view = new SearchView (aggregator, query);
+ try {
+ yield search_view.prepare ();
+ } catch (Error e) {
+ error ("Couldn't load SearchView: %s", e.message);
+ }
+ var results = new string[search_view.individuals.size];
+ var i = 0;
+ foreach (var individual in search_view.individuals) {
+ results[i] = individual.id;
+ i++;
}
- matches.sort((CompareDataFunc<Contact>) compare_contacts);
-
- var results = new string[matches.size];
- for (int i = 0; i < matches.size; i++)
- results[i] = matches[i].get_data ("search-id");
- app.release ();
+ this.app.release ();
return results;
}
- public async string[] GetInitialResultSet (string[] terms) {
- return yield do_search (terms);
- }
-
- public async string[] GetSubsearchResultSet (string[] previous_results,
- string[] new_terms) {
- return yield do_search (new_terms);
+ public async HashTable<string, Variant>[] GetResultMetas (string[] ids) {
+ return yield get_metas (ids);
}
private async HashTable<string, Variant>[] get_metas (owned string[] ids) {
- app.hold ();
+ this.app.hold ();
+
var results = new ArrayList<HashTable> ();
foreach (var id in ids) {
- var contact = contacts_map.get (id);
-
- if (contact == null)
+ Individual indiv = null;
+ try {
+ indiv = yield aggregator.look_up_individual (id);
+ } catch (Error e) {
+ continue;
+ }
+ if (indiv == null)
continue;
var meta = new HashTable<string, Variant> (str_hash, str_equal);
- meta.insert ("id", new Variant.string (id));
+ meta["id"] = new Variant.string (id);
+ meta["name"] = new Variant.string (indiv.display_name);
+ meta["icon"] = (indiv.avatar != null)? indiv.avatar.serialize () : serialized_fallback_icon;
+
+ // Make a description based the first email address/phone nr/... we can find
+ var description = new StringBuilder ();
+
+ var email = Utils.get_first<EmailFieldDetails> (indiv.email_addresses);
+ if (email != null && email.value != null && email.value != "")
+ description.append (email.value);
- meta.insert ("name", new Variant.string (contact.display_name));
+ var phone = Utils.get_first<PhoneFieldDetails> (indiv.phone_numbers);
+ if (phone != null && phone.value != null && phone.value != "") {
+ if (description.len > 0)
+ description.append (" / ");
+ description.append (phone.value);
+ }
+
+ meta["description"] = description.str;
- if (contact.avatar_icon_data != null)
- meta.insert ("icon", contact.avatar_icon_data);
- else
- meta.insert ("icon", new ThemedIcon ("avatar-default").serialize ());
results.add (meta);
}
- app.release ();
+ this.app.release ();
return results.to_array ();
}
- public async HashTable<string, Variant>[] GetResultMetas (string[] ids) {
- return yield get_metas (ids);
- }
-
- public void ActivateResult (string search_id, string[] terms, uint32 timestamp) {
- app.hold ();
+ public void ActivateResult (string id, string[] terms, uint32 timestamp) {
+ this.app.hold ();
- var contact = contacts_map.get (search_id);
-
- if (contact == null) {
- app.release ();
- return;
- }
-
- string id = contact.individual.id;
try {
- if (!Process.spawn_command_line_async ("gnome-contacts -i " + id))
- stderr.printf ("Failed to launch contact with id '%s'\n", id);
+ Process.spawn_command_line_async ("gnome-contacts -i " + id);
} catch (SpawnError e) {
- stderr.printf ("Failed to launch contact with id '%s'\n", id);
+ stderr.printf ("Failed to launch contact with id '%s': %s\n.", id, e.message);
}
-
- app.release ();
+ this.app.release ();
}
public void LaunchSearch (string[] terms, uint32 timestamp) {
- app.hold ();
+ this.app.hold ();
debug ("LaunchSearch (%s)", string.joinv (", ", terms));
try {
- string[] args = {};
- args += "gnome-contacts";
- args += "--search";
+ string[] args = { "gnome-contacts", "--search" };
args += string.joinv (" ", terms);
- if (!Process.spawn_async (null, args, null, SpawnFlags.SEARCH_PATH, null, null))
- stderr.printf ("Failed to launch Contacts for search\n");
+ Process.spawn_async (null, args, null, SpawnFlags.SEARCH_PATH, null, null);
} catch (SpawnError error) {
stderr.printf ("Failed to launch Contacts for search\n");
}
- app.release ();
+ this.app.release ();
}
}