[gnome-shell] search: Add RemoteSearchProvider



commit f6749fb2045efd6c94719cbf62353225a3b26216
Author: Florian MÃllner <fmuellner gnome org>
Date:   Thu Nov 17 00:11:05 2011 +0100

    search: Add RemoteSearchProvider
    
    Add an asynchronous search provider for results from a DBus service
    implementing the org.gnome.Shell.SearchProvider interface; this
    will allow applications to hook into the Shell's search without
    implementing it in Shell itself or requiring an extension.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=663125

 data/Makefile.am                       |    4 +
 data/org.gnome.ShellSearchProvider.xml |  147 ++++++++++++++++++++++++++++++++
 js/Makefile.am                         |    1 +
 js/ui/remoteSearch.js                  |  131 ++++++++++++++++++++++++++++
 4 files changed, 283 insertions(+), 0 deletions(-)
---
diff --git a/data/Makefile.am b/data/Makefile.am
index cbc7b79..4803081 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -17,6 +17,9 @@ dist_searchproviders_DATA =				\
 	open-search-providers/google.xml		\
 	open-search-providers/wikipedia.xml
 
+introspectiondir = $(datadir)/dbus-1/interfaces
+introspection_DATA = org.gnome.ShellSearchProvider.xml
+
 themedir = $(pkgdatadir)/theme
 dist_theme_DATA =				\
 	theme/calendar-arrow-left.svg		\
@@ -73,6 +76,7 @@ shaders_DATA = \
 EXTRA_DIST =						\
 	gnome-shell.desktop.in.in			\
 	gnome-shell-extension-prefs.desktop.in.in	\
+	$(introspection_DATA)				\
 	$(menu_DATA)					\
 	$(shaders_DATA)					\
 	$(convert_DATA)					\
diff --git a/data/org.gnome.ShellSearchProvider.xml b/data/org.gnome.ShellSearchProvider.xml
new file mode 100644
index 0000000..16fa9ad
--- /dev/null
+++ b/data/org.gnome.ShellSearchProvider.xml
@@ -0,0 +1,147 @@
+<!DOCTYPE node PUBLIC
+'-//freedesktop//DTD D-BUS Object Introspection 1.0//EN'
+'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>
+<node>
+  <interface name="org.gnome.Shell.SearchProvider">
+    <doc:doc>
+      <doc:description>
+        <doc:para>
+          The interface used for integrating into GNOME Shell's search
+          interface.
+        </doc:para>
+      </doc:description>
+    </doc:doc>
+
+    <method name="GetInitialResultSet">
+      <doc:doc>
+        <doc:description>
+          <doc:para>
+            Called when the user first begins a search.
+          </doc:para>
+        </doc:description>
+      </doc:doc>
+      <arg type="as" direction="in">
+        <doc:doc>
+          <doc:summary>
+            <doc:para>
+              Array of search terms, which the provider should treat as
+              logical AND.
+            </doc:para>
+          </doc:summary>
+        </doc:doc>
+      </arg>
+      <arg type="as" direction="out">
+        <doc:doc>
+          <doc:summary>
+            <doc:para>
+              An array of result identifier strings representing items which
+              match the given search terms. Identifiers must be unique within
+              the provider's domain, but other than that may be chosen freely
+              by the provider.
+            </doc:para>
+          </doc:summary>
+        </doc:doc>
+      </arg>
+    </method>
+
+    <method name="GetSubsearchResultSet">
+      <doc:doc>
+        <doc:description>
+          <doc:para>
+            Called when a search is performed which is a "subsearch" of
+            the previous search, e.g. the method may return less results, but
+            not more or different results.
+
+            This allows search providers to only search through the previous
+            result set, rather than possibly performing a full re-query.
+          </doc:para>
+        </doc:description>
+      </doc:doc>
+      <arg type="as" direction="in">
+        <doc:doc>
+          <doc:summary>
+            <doc:para>
+              Array of item identifiers
+            </doc:para>
+          </doc:summary>
+        </doc:doc>
+      </arg>
+      <arg type="as" direction="in">
+        <doc:doc>
+          <doc:summary>
+            <doc:para>
+              Array of updated search terms, which the provider should treat as
+              logical AND.
+            </doc:para>
+          </doc:summary>
+        </doc:doc>
+      </arg>
+      <arg type="as" direction="out">
+        <doc:doc>
+          <doc:summary>
+            <doc:para>
+              An array of result identifier strings representing items which
+              match the given search terms. Identifiers must be unique within
+              the provider's domain, but other than that may be chosen freely
+              by the provider.
+            </doc:para>
+          </doc:summary>
+        </doc:doc>
+      </arg>
+    </method>
+
+    <method name="GetResultMetas">
+      <doc:doc>
+        <doc:description>
+          <doc:para>
+            Return an array of meta data used to display each given result
+          </doc:para>
+        </doc:description>
+      </doc:doc>
+      <arg type="as" direction="in">
+        <doc:doc>
+          <doc:summary>
+            <doc:para>
+              An array of result identifiers as returned by
+              GetInitialResultSet() or GetSubsearchResultSet()
+            </doc:para>
+          </doc:summary>
+        </doc:doc>
+      </arg>
+      <arg type="a{sv}" direction="out">
+        <doc:doc>
+          <doc:summary>
+            <doc:para>
+              A dictionary describing the given search result, containing
+              'id', 'name' (both strings) and either 'icon' (a serialized
+              GIcon) or 'icon-data' (raw image data as (iiibiiay) - width,
+              height, rowstride, has-alpha, bits per sample, channels, data)
+            </doc:para>
+          </doc:summary>
+        </doc:doc>
+      </arg>
+    </method>
+
+    <method name="ActivateResult">
+      <doc:doc>
+        <doc:description>
+          <doc:para>
+            Called when the users chooses a given result. The result should
+            be displayed in the application associated with the corresponding
+            provider.
+          </doc:para>
+        </doc:description>
+      </doc:doc>
+      <arg type="s" direction="in">
+        <doc:doc>
+          <doc:summary>
+            <doc:para>
+              A result identifier as returned by GetInitialResultSet() or
+              GetSubsearchResultSet()
+            </doc:para>
+          </doc:summary>
+        </doc:doc>
+      </arg>
+    </method>
+  </interface>
+</node>
diff --git a/js/Makefile.am b/js/Makefile.am
index 98f7a48..6780617 100644
--- a/js/Makefile.am
+++ b/js/Makefile.am
@@ -75,6 +75,7 @@ nobase_dist_js_DATA = 	\
 	ui/placeDisplay.js	\
 	ui/polkitAuthenticationAgent.js \
 	ui/popupMenu.js		\
+	ui/remoteSearch.js	\
 	ui/runDialog.js		\
 	ui/scripting.js		\
 	ui/search.js		\
diff --git a/js/ui/remoteSearch.js b/js/ui/remoteSearch.js
new file mode 100644
index 0000000..18e5749
--- /dev/null
+++ b/js/ui/remoteSearch.js
@@ -0,0 +1,131 @@
+// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
+
+const Gio = imports.gi.Gio;
+const Lang = imports.lang;
+const St = imports.gi.St;
+
+const Search = imports.ui.search;
+
+const SearchProviderIface = <interface name="org.gnome.Shell.SearchProvider">
+<method name="GetInitialResultSet">
+    <arg type="as" direction="in" />
+    <arg type="as" direction="out" />
+</method>
+<method name="GetSubsearchResultSet">
+    <arg type="as" direction="in" />
+    <arg type="as" direction="in" />
+    <arg type="as" direction="out" />
+</method>
+<method name="GetResultMetas">
+    <arg type="as" direction="in" />
+    <arg type="aa{sv}" direction="out" />
+</method>
+<method name="ActivateResult">
+    <arg type="s" direction="in" />
+</method>
+</interface>;
+
+var SearchProviderProxy = Gio.DBusProxy.makeProxyWrapper(SearchProviderIface);
+
+
+const RemoteSearchProvider = new Lang.Class({
+    Name: 'RemoteSearchProvider',
+    Extends: Search.SearchProvider,
+
+    _init: function(title, icon, dbusName, dbusPath) {
+        this._proxy = new SearchProviderProxy(Gio.DBus.session,
+                                              dbusName, dbusPath);
+
+        this.parent(title.toUpperCase());
+        this.async = true;
+        this._cancellable = new Gio.Cancellable();
+    },
+
+    createIcon: function(size, meta) {
+        if (meta['gicon']) {
+            return new St.Icon({ gicon: Gio.icon_new_for_string(meta['gicon']),
+                                 icon_size: size,
+                                 icon_type: St.IconType.FULLCOLOR });
+        } else if (meta['icon-data']) {
+            let [width, height, rowStride, hasAlpha,
+                 bitsPerSample, nChannels, data] = meta['icon-data'];
+            let textureCache = St.TextureCache.get_default();
+            return textureCache.load_from_raw(data, hasAlpha,
+                                              width, height, rowStride, size);
+        }
+
+        // Ugh, but we want to fall back to something ...
+        return new St.Icon({ icon_name: 'text-x-generic',
+                             icon_size: size,
+                             icon_type: St.IconType.FULLCOLOR });
+    },
+
+    _getResultsFinished: function(results, error) {
+        if (error)
+            return;
+        this.searchSystem.pushResults(this, results[0]);
+    },
+
+    getInitialResultSetAsync: function(terms) {
+        this._cancellable.cancel();
+        this._cancellable.reset();
+        try {
+            this._proxy.GetInitialResultSetRemote(terms,
+                                                  Lang.bind(this, this._getResultsFinished),
+                                                  this._cancellable);
+        } catch(e) {
+            log('Error calling GetInitialResultSet for provider %s: %s'.format( this.title, e.toString()));
+            this.searchSystem.pushResults(this, []);
+        }
+    },
+
+    getSubsearchResultSetAsync: function(previousResults, newTerms) {
+        this._cancellable.cancel();
+        this._cancellable.reset();
+        try {
+            this._proxy.GetSubsearchResultSetRemote(previousResults, newTerms,
+                                                    Lang.bind(this, this._getResultsFinished),
+                                                    this._cancellable);
+        } catch(e) {
+            log('Error calling GetSubsearchResultSet for provider %s: %s'.format(this.title, e.toString()));
+            this.searchSystem.pushResults(this, []);
+        }
+    },
+
+    _getResultMetasFinished: function(results, error, callback) {
+        if (error) {
+            callback([]);
+            return;
+        }
+        let metas = results[0];
+        let resultMetas = [];
+        for (let i = 0; i < metas.length; i++) {
+            for (let prop in metas[i])
+                metas[i][prop] = metas[i][prop].deep_unpack();
+            resultMetas.push({ id: metas[i]['id'],
+                               name: metas[i]['name'],
+                               createIcon: Lang.bind(this,
+                                                     this.createIcon, metas[i]) });
+        }
+        callback(resultMetas);
+    },
+
+    getResultMetasAsync: function(ids, callback) {
+        this._cancellable.cancel();
+        this._cancellable.reset();
+        try {
+            this._proxy.GetResultMetasRemote(ids,
+                                             Lang.bind(this, this._getResultMetasFinished, callback),
+                                             this._cancellable);
+        } catch(e) {
+            log('Error calling GetResultMetas for provider %s: %s'.format(this.title, e.toString()));
+            callback([]);
+        }
+    },
+
+    activateResult: function(id) {
+        this._proxy.ActivateResultRemote(id);
+    }
+});
+
+



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]