[gnome-contacts] Add search provider for GNOME Shell
- From: Alexander Larsson <alexl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-contacts] Add search provider for GNOME Shell
- Date: Fri, 29 Jun 2012 13:43:16 +0000 (UTC)
commit 19751af1b8d810d0d1ca1772dff113a6766bcbeb
Author: Florian MÃllner <fmuellner gnome org>
Date: Tue Jun 19 23:39:06 2012 +0200
Add search provider for GNOME Shell
GNOME Shell provides a DBus interface for external search provider
implementations; add a small auto-activated service which implements
that interface, to replace the Shell's built-in contact search with
results provided directly by GNOME Contacts.
https://bugzilla.gnome.org/show_bug.cgi?id=679002
configure.ac | 4 +-
data/Makefile.am | 20 +++
data/gnome-contacts-search-provider.ini.in | 6 +
data/org.gnome.Contacts.SearchProvider.service.in | 3 +
po/POTFILES.in | 1 +
src/Makefile.am | 13 ++
src/contacts-contact.vala | 44 ++++++-
src/contacts-shell-search-provider.vala | 155 +++++++++++++++++++++
8 files changed, 243 insertions(+), 3 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index a9fc0b3..e88a8db 100644
--- a/configure.ac
+++ b/configure.ac
@@ -17,7 +17,7 @@ AC_CONFIG_FILES([Makefile
LT_INIT
AC_PROG_CC
-AM_PROG_VALAC([0.14.0])
+AM_PROG_VALAC([0.17.2])
AC_PROG_INSTALL
GLIB_GSETTINGS
@@ -48,7 +48,7 @@ pkg_modules="gtk+-3.0 >= 3.4.0
"
PKG_CHECK_MODULES(CONTACTS, [$pkg_modules])
-CONTACTS_PACKAGES="--pkg gtk+-3.0 --pkg gio-2.0 --pkg folks --pkg folks-telepathy --pkg folks-eds --pkg libnotify"
+CONTACTS_PACKAGES="--pkg gtk+-3.0 --pkg gio-2.0 --pkg gio-unix-2.0 --pkg folks --pkg folks-telepathy --pkg folks-eds --pkg libnotify"
AC_SUBST(CONTACTS_PACKAGES)
gstreamers_modules="gdk-x11-3.0
diff --git a/data/Makefile.am b/data/Makefile.am
index 287c1b1..2576caf 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -3,12 +3,32 @@ NULL=
desktopdir = $(datadir)/applications
desktop_in_files = gnome-contacts.desktop.in
desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
+
+searchproviderdir = $(datadir)/gnome-shell/search-providers
+searchprovider_DATA = gnome-contacts-search-provider.ini
+searchprovider_in_files = gnome-contacts-search-provider.ini.in
+
+%.ini: %.ini.in
+ LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+
@INTLTOOL_DESKTOP_RULE@
+service_in_files = org.gnome.Contacts.SearchProvider.service.in
+
+servicedir = $(datadir)/dbus-1/services
+service_DATA = $(service_in_files:.service.in=.service)
+
+%.service: %.service.in Makefile
+ $(AM_V_GEN) [ -d $(@D) ] || $(mkdir_p) $(@D) ; \
+ sed -e "s|\ libexecdir\@|$(libexecdir)|" $< > $ tmp && mv $ tmp $@
+
EXTRA_DIST = \
gnome-contacts.desktop.in.in \
+ $(searchprovider_DATA) \
+ $(service_in_files) \
$(NULL)
+CLEANFILES = $(service_DATA)
DISTCLEANFILES = \
gnome-contacts.desktop \
gnome-contacts.desktop.in
diff --git a/data/gnome-contacts-search-provider.ini.in b/data/gnome-contacts-search-provider.ini.in
new file mode 100644
index 0000000..9e8da46
--- /dev/null
+++ b/data/gnome-contacts-search-provider.ini.in
@@ -0,0 +1,6 @@
+[Shell Search Provider]
+_Title=Gnome Contacts
+Icon=x-office-address-book
+DesktopId=gnome-contacts.desktop
+BusName=org.gnome.Contacts.SearchProvider
+ObjectPath=/org/gnome/Contacts/SearchProvider
diff --git a/data/org.gnome.Contacts.SearchProvider.service.in b/data/org.gnome.Contacts.SearchProvider.service.in
new file mode 100644
index 0000000..6f45237
--- /dev/null
+++ b/data/org.gnome.Contacts.SearchProvider.service.in
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.gnome.Contacts.SearchProvider
+Exec= libexecdir@/gnome-contacts-search-provider
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 2ab8b5f..38f0a64 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1,3 +1,4 @@
+data/gnome-contacts-search-provider.ini.in
data/gnome-contacts.desktop.in.in
[type: gettext/glade]src/app-menu.ui
src/contacts-app.vala
diff --git a/src/Makefile.am b/src/Makefile.am
index 66c6e68..6ece706 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -75,6 +75,19 @@ gnome_contacts_SOURCES += \
$(NULL)
endif
+libexec_PROGRAMS = gnome-contacts-search-provider
+
+gnome_contacts_search_provider_SOURCES = \
+ contacts-contact.vala \
+ contacts-esd-setup.c \
+ contacts-shell-search-provider.vala \
+ contacts-store.vala \
+ contacts-types.vala \
+ contacts-utils.vala \
+ $(NULL)
+
+gnome_contacts_search_provider_LDADD = $(CONTACTS_LIBS)
+
CLEANFILES = \
$(vala_sources:.vala=.c) \
$(gsettings_SCHEMAS) \
diff --git a/src/contacts-contact.vala b/src/contacts-contact.vala
index 0bcfbae..9520f5d 100644
--- a/src/contacts-contact.vala
+++ b/src/contacts-contact.vala
@@ -142,6 +142,45 @@ public class Contacts.Contact : GLib.Object {
}
}
+ public Icon? serializable_avatar_icon {
+ get {
+ if (individual.avatar != null && individual.avatar.to_string () != null)
+ return individual.avatar;
+
+ return null;
+ }
+ }
+
+ private Variant? _avatar_icon_data;
+ public Variant? avatar_icon_data {
+ get {
+ if (individual.avatar == null)
+ return null;
+
+ if (individual.avatar.to_string () != null)
+ return null;
+
+ if (_avatar_icon_data == null) {
+
+ if (small_avatar == null)
+ return null;
+
+ var pixel_data = Variant.new_from_data (VariantType.BYTESTRING,
+ small_avatar.get_pixels_with_length (),
+ true, small_avatar);
+ _avatar_icon_data = new Variant ("(iiibii ay)",
+ small_avatar.get_width (),
+ small_avatar.get_height (),
+ small_avatar.get_rowstride (),
+ small_avatar.get_has_alpha (),
+ small_avatar.get_bits_per_sample (),
+ small_avatar.get_n_channels (),
+ pixel_data);
+ }
+ return _avatar_icon_data;
+ }
+ }
+
public string display_name {
get {
unowned string? name = individual.full_name;
@@ -436,6 +475,7 @@ public class Contacts.Contact : GLib.Object {
connect_persona (p);
}
_small_avatar = null;
+ _avatar_icon_data = null;
individual.notify.connect(notify_cb);
queue_changed (true);
}
@@ -820,8 +860,10 @@ public class Contacts.Contact : GLib.Object {
}
private void notify_cb (ParamSpec pspec) {
- if (pspec.get_name () == "avatar")
+ if (pspec.get_name () == "avatar") {
_small_avatar = null;
+ _avatar_icon_data = null;
+ }
queue_changed (false);
}
diff --git a/src/contacts-shell-search-provider.vala b/src/contacts-shell-search-provider.vala
new file mode 100644
index 0000000..0f829fc
--- /dev/null
+++ b/src/contacts-shell-search-provider.vala
@@ -0,0 +1,155 @@
+using Gee;
+
+[DBus (name = "org.gnome.Shell.SearchProvider")]
+public class Contacts.SearchProvider : Object {
+ SearchProviderApp app;
+ Store store;
+ Gee.HashMap<string, Contact> contacts_map;
+ private uint next_id;
+
+ public SearchProvider (SearchProviderApp app) {
+ this.app = app;
+ ensure_eds_accounts ();
+ 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"));
+ });
+ }
+
+ 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;
+
+ if (a_prio > b_prio)
+ return -1;
+ if (a_prio < b_prio)
+ return 1;
+
+ if (is_set (a.display_name) && is_set (b.display_name))
+ return a.display_name.collate (b.display_name);
+
+ // Sort empty names last
+ if (is_set (a.display_name))
+ return -1;
+ if (is_set (b.display_name))
+ return 1;
+
+ return 0;
+ }
+
+ private 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;
+
+ if (c.contains_strings (normalized_terms))
+ matches.add (c);
+ }
+
+ matches.sort((CompareFunc<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 ();
+ return results;
+ }
+
+ public string[] GetInitialResultSet (string[] terms) {
+ return do_search (terms);
+ }
+
+ public string[] GetSubsearchResultSet (string[] previous_results,
+ string[] new_terms) {
+ return do_search (new_terms);
+ }
+
+ public HashTable<string, Variant>[] GetResultMetas (string[] ids) {
+ app.hold ();
+ var results = new ArrayList<HashTable> ();
+ foreach (var id in ids) {
+ var contact = contacts_map.get (id);
+
+ if (contact == null)
+ continue;
+
+ var meta = new HashTable<string, Variant> (str_hash, str_equal);
+ meta.insert ("id", new Variant.string (id));
+
+ meta.insert ("name", new Variant.string (contact.display_name));
+
+ if (contact.serializable_avatar_icon != null)
+ meta.insert ("gicon", new Variant.string (contact.serializable_avatar_icon.to_string ()));
+ else if (contact.avatar_icon_data != null)
+ meta.insert ("icon-data", contact.avatar_icon_data);
+ else
+ meta.insert ("gicon", new Variant.string (new ThemedIcon ("avatar-default").to_string ()));
+ results.add (meta);
+ }
+ app.release ();
+ return results.to_array ();
+ }
+
+ public void ActivateResult (string search_id) {
+ app.hold ();
+
+ var contact = contacts_map.get (search_id);
+
+ if (contact == null)
+ 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);
+ } catch (SpawnError e) {
+ stderr.printf ("Failed to launch contact with id '%s'\n", id);
+ }
+
+ app.release ();
+ }
+}
+
+public class Contacts.SearchProviderApp : GLib.Application {
+ public SearchProviderApp () {
+ Object (application_id: "org.gnome.Contacts.SearchProvider",
+ flags: ApplicationFlags.IS_SERVICE,
+ inactivity_timeout: 10000);
+ }
+
+ public override bool dbus_register (GLib.DBusConnection connection, string object_path) {
+ try {
+ connection.register_object (object_path, new SearchProvider (this));
+ } catch (IOError error) {
+ stderr.printf ("Could not register service: %s", error.message);
+ quit ();
+ }
+ return true;
+ }
+
+ public override void startup () {
+ if (Environment.get_variable ("CONTACTS_SEARCH_PROVIDER_PERSIST") != null)
+ hold ();
+ base.startup ();
+ }
+}
+
+int main () {
+ return new Contacts.SearchProviderApp ().run ();
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]