[gnome-shell/zeitgeist: 20/22] Add support for Zeitgeist search providers
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell/zeitgeist: 20/22] Add support for Zeitgeist search providers
- Date: Fri, 4 Mar 2011 02:57:56 +0000 (UTC)
commit 8e579024b19c591fa5e315872d49bd8cf0d0e510
Author: Siegfried-Angel Gevatter Pujals <rainct ubuntu com>
Date: Sat Jan 29 00:11:58 2011 +0100
Add support for Zeitgeist search providers
https://bugzilla.gnome.org/show_bug.cgi?id=640659
Co-authored-by: Seif Lotfy <seif lotfy com>
Co-authored-by: Federico Mena Quintero <federico gnome org>
js/Makefile.am | 4 +-
js/misc/docInfo.js | 124 ++++-------------------------
js/ui/docDisplay.js | 51 ------------
js/ui/overview.js | 8 ++-
js/ui/zeitgeistSearch.js | 199 ++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 223 insertions(+), 163 deletions(-)
---
diff --git a/js/Makefile.am b/js/Makefile.am
index 2c1bfb6..2cb6be0 100644
--- a/js/Makefile.am
+++ b/js/Makefile.am
@@ -23,7 +23,6 @@ nobase_dist_js_DATA = \
ui/dash.js \
ui/dateMenu.js \
ui/dnd.js \
- ui/docDisplay.js \
ui/endSessionDialog.js \
ui/environment.js \
ui/extensionSystem.js \
@@ -64,4 +63,5 @@ nobase_dist_js_DATA = \
ui/workspaceThumbnail.js \
ui/workspacesView.js \
ui/workspaceSwitcherPopup.js \
- ui/xdndHandler.js
+ ui/xdndHandler.js \
+ ui/zeitgeistSearch.js
diff --git a/js/misc/docInfo.js b/js/misc/docInfo.js
index 8ec375a..0b4bc36 100644
--- a/js/misc/docInfo.js
+++ b/js/misc/docInfo.js
@@ -1,36 +1,32 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const St = imports.gi.St;
-const Shell = imports.gi.Shell;
-const Lang = imports.lang;
-const Signals = imports.signals;
const Search = imports.ui.search;
-const THUMBNAIL_ICON_MARGIN = 2;
-
-function DocInfo(recentInfo) {
- this._init(recentInfo);
+function ZeitgeistItemInfo(event) {
+ this._init(event);
}
-DocInfo.prototype = {
- _init : function(recentInfo) {
- this.recentInfo = recentInfo;
- // We actually used get_modified() instead of get_visited()
- // here, as GtkRecentInfo doesn't updated get_visited()
- // correctly. See http://bugzilla.gnome.org/show_bug.cgi?id=567094
- this.timestamp = recentInfo.get_modified();
- this.name = recentInfo.get_display_name();
+ZeitgeistItemInfo.prototype = {
+ _init : function(event) {
+ this.event = event;
+ this.subject = event.subjects[0];
+ this.timestamp = event.timestamp;
+ this.name = this.subject.text;
this._lowerName = this.name.toLowerCase();
- this.uri = recentInfo.get_uri();
- this.mimeType = recentInfo.get_mime_type();
+ this.uri = this.subject.uri;
+ this.mimeType = this.subject.mimetype;
+ this.interpretation = this.subject.interpretation;
},
createIcon : function(size) {
- return St.TextureCache.get_default().load_recent_thumbnail(size, this.recentInfo);
+ return St.TextureCache.get_default().load_thumbnail(size, this.uri, this.subject.mimetype);
+ // FIXME: We should consider caching icons
},
- launch : function(workspaceIndex) {
- Shell.DocSystem.get_default().open(this.recentInfo, workspaceIndex);
+ launch : function() {
+ Gio.app_info_launch_default_for_uri(this.uri,
+ global.create_app_launch_context());
},
matchTerms: function(terms) {
@@ -48,93 +44,5 @@ DocInfo.prototype = {
}
}
return mtype;
- }
-};
-
-var docManagerInstance = null;
-
-function getDocManager() {
- if (docManagerInstance == null)
- docManagerInstance = new DocManager();
- return docManagerInstance;
-}
-
-/**
- * DocManager wraps the DocSystem, primarily to expose DocInfo objects.
- */
-function DocManager() {
- this._init();
-}
-
-DocManager.prototype = {
- _init: function() {
- this._docSystem = Shell.DocSystem.get_default();
- this._infosByTimestamp = [];
- this._infosByUri = {};
- this._docSystem.connect('changed', Lang.bind(this, this._reload));
- this._reload();
- },
-
- _reload: function() {
- let docs = this._docSystem.get_all();
- this._infosByTimestamp = [];
- this._infosByUri = {};
- for (let i = 0; i < docs.length; i++) {
- let recentInfo = docs[i];
-
- let docInfo = new DocInfo(recentInfo);
- this._infosByTimestamp.push(docInfo);
- this._infosByUri[docInfo.uri] = docInfo;
- }
- this.emit('changed');
- },
-
- getTimestampOrderedInfos: function() {
- return this._infosByTimestamp;
- },
-
- getInfosByUri: function() {
- return this._infosByUri;
- },
-
- lookupByUri: function(uri) {
- return this._infosByUri[uri];
- },
-
- queueExistenceCheck: function(count) {
- return this._docSystem.queue_existence_check(count);
},
-
- _searchDocs: function(items, terms) {
- let multiplePrefixMatches = [];
- let prefixMatches = [];
- let multipleSubtringMatches = [];
- let substringMatches = [];
- for (let i = 0; i < items.length; i++) {
- let item = items[i];
- let mtype = item.matchTerms(terms);
- if (mtype == Search.MatchType.MULTIPLE_PREFIX)
- multiplePrefixMatches.push(item.uri);
- else if (mtype == Search.MatchType.PREFIX)
- prefixMatches.push(item.uri);
- else if (mtype == Search.MatchType.MULTIPLE_SUBSTRING)
- multipleSubtringMatches.push(item.uri);
- else if (mtype == Search.MatchType.SUBSTRING)
- substringMatches.push(item.uri);
- }
- return multiplePrefixMatches.concat(prefixMatches.concat(multipleSubtringMatches.concat(substringMatches)));
- },
-
- initialSearch: function(terms) {
- return this._searchDocs(this._infosByTimestamp, terms);
- },
-
- subsearch: function(previousResults, terms) {
- return this._searchDocs(previousResults.map(Lang.bind(this,
- function(url) {
- return this._infosByUri[url];
- })), terms);
- }
};
-
-Signals.addSignalMethods(DocManager.prototype);
diff --git a/js/ui/overview.js b/js/ui/overview.js
index 1aeb83b..3c5e6e6 100644
--- a/js/ui/overview.js
+++ b/js/ui/overview.js
@@ -15,7 +15,6 @@ const Gdk = imports.gi.Gdk;
const AppDisplay = imports.ui.appDisplay;
const Dash = imports.ui.dash;
const DND = imports.ui.dnd;
-const DocDisplay = imports.ui.docDisplay;
const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray;
@@ -24,6 +23,7 @@ const PlaceDisplay = imports.ui.placeDisplay;
const Tweener = imports.ui.tweener;
const ViewSelector = imports.ui.viewSelector;
const WorkspacesView = imports.ui.workspacesView;
+const ZeitgeistSearch = imports.ui.zeitgeistSearch;
// Time for initial animation going into Overview mode
const ANIMATION_TIME = 0.25;
@@ -189,7 +189,11 @@ Overview.prototype = {
this.viewSelector.addSearchProvider(new AppDisplay.AppSearchProvider());
this.viewSelector.addSearchProvider(new AppDisplay.PrefsSearchProvider());
this.viewSelector.addSearchProvider(new PlaceDisplay.PlaceSearchProvider());
- this.viewSelector.addSearchProvider(new DocDisplay.DocSearchProvider());
+ this.viewSelector.addSearchProvider(new ZeitgeistSearch.DocumentsAsyncSearchProvider());
+ this.viewSelector.addSearchProvider(new ZeitgeistSearch.VideosAsyncSearchProvider());
+ this.viewSelector.addSearchProvider(new ZeitgeistSearch.MusicAsyncSearchProvider());
+ this.viewSelector.addSearchProvider(new ZeitgeistSearch.PicturesAsyncSearchProvider());
+ this.viewSelector.addSearchProvider(new ZeitgeistSearch.OtherAsyncSearchProvider());
// TODO - recalculate everything when desktop size changes
this.dash = new Dash.Dash();
diff --git a/js/ui/zeitgeistSearch.js b/js/ui/zeitgeistSearch.js
new file mode 100644
index 0000000..efca78b
--- /dev/null
+++ b/js/ui/zeitgeistSearch.js
@@ -0,0 +1,199 @@
+/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*-
+ *
+ * Copyright (C) 2010 Seif Lotfy <seif lotfy com>
+ * Copyright (C) 2011 Siegfried-Angel Gevatter Pujals <siegfried gevatter com>
+ * Copyright (C) 2010-2011 Collabora Ltd.
+ * Authored by: Seif Lotfy <seif lotfy 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, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+const Lang = imports.lang;
+const GLib = imports.gi.GLib;
+const Gio = imports.gi.Gio
+const Semantic = imports.misc.semantic;
+const Zeitgeist = imports.misc.zeitgeist;
+
+const Gettext = imports.gettext.domain('gnome-shell');
+const _ = Gettext.gettext;
+
+const DocInfo = imports.misc.docInfo;
+const Search = imports.ui.search;
+
+// FIXME: The subject cache is never being emptied.
+let ZeitgeistSubjectCache = {};
+
+function ZeitgeistAsyncSearchProvider(title, interpretations) {
+ this._init(title, interpretations);
+}
+
+ZeitgeistAsyncSearchProvider.prototype = {
+ __proto__: Search.SearchProvider.prototype,
+
+ _init: function(title, interpretations) {
+ Search.SearchProvider.prototype._init.call(this, title);
+ this._buildTemplates(interpretations);
+ },
+
+ _buildTemplates: function(interpretations) {
+ this.templates = [];
+ for (let i = 0; i < interpretations.length; i++) {
+ let subject = new Zeitgeist.Subject('', interpretations[i], '', '', '', '', '');
+ let event = new Zeitgeist.Event('', '', '', [subject], []);
+ this.templates.push(event);
+ }
+ },
+
+ _search: function(terms) {
+ this._search_terms = terms;
+ Zeitgeist.fullTextSearch(terms[0]+'*',
+ this.templates,
+ Lang.bind(this, function(events) {
+ if (terms == this._search_terms)
+ this._asyncCallback(events);
+ }));
+ },
+
+ _asyncCancelled: function() {
+ this._search_terms = null;
+ },
+
+ getInitialResultSet: function(terms) {
+ this._search(terms);
+ return [];
+ },
+
+ getSubsearchResultSet: function(previousResults, terms) {
+ this.tryCancelAsync();
+ return this.getInitialResultSet(terms);
+ },
+
+ getResultMeta: function(resultId) {
+ return { 'id': ZeitgeistSubjectCache[resultId].uri,
+ 'name': ZeitgeistSubjectCache[resultId].name,
+ 'icon': ZeitgeistSubjectCache[resultId].createIcon(48) };
+ },
+
+ activateResult: function(resultId) {
+ Gio.app_info_launch_default_for_uri(resultId,
+ global.create_app_launch_context());
+ },
+
+ _asyncCallback: function(events) {
+ let items = [];
+ for (let i = 0; i < events.length; i++) {
+ let event = events[i];
+ let subject = event.subjects[0];
+ let uri = subject.uri.replace('file://', '');
+ uri = GLib.uri_unescape_string(uri, '');
+ if (GLib.file_test(uri, GLib.FileTest.EXISTS)) {
+ if (!ZeitgeistSubjectCache.hasOwnProperty(subject.uri)) {
+ let info = new DocInfo.ZeitgeistItemInfo(event);
+ ZeitgeistSubjectCache[info.uri] = info;
+ }
+ items.push(subject.uri);
+ }
+ }
+ this.addItems(items);
+ }
+};
+
+function DocumentsAsyncSearchProvider() {
+ this._init();
+}
+
+DocumentsAsyncSearchProvider.prototype = {
+ __proto__: ZeitgeistAsyncSearchProvider.prototype,
+
+ _init: function() {
+ let interpretations = [Semantic.NFO_DOCUMENT];
+ ZeitgeistAsyncSearchProvider.prototype._init.call(this, _("DOCUMENTS"), interpretations);
+ }
+};
+
+function VideosAsyncSearchProvider() {
+ this._init();
+}
+
+VideosAsyncSearchProvider.prototype = {
+ __proto__: ZeitgeistAsyncSearchProvider.prototype,
+
+ _init: function() {
+ let interpretations = [Semantic.NFO_VIDEO];
+ ZeitgeistAsyncSearchProvider.prototype._init.call(this, _("VIDEOS"), interpretations);
+ }
+};
+
+function MusicAsyncSearchProvider() {
+ this._init();
+}
+
+MusicAsyncSearchProvider.prototype = {
+ __proto__: ZeitgeistAsyncSearchProvider.prototype,
+
+ _init: function() {
+ let interpretations = [
+ Semantic.NFO_AUDIO,
+ Semantic.NMM_MUSIC_PIECE];
+ ZeitgeistAsyncSearchProvider.prototype._init.call(this, _("MUSIC"), interpretations);
+ }
+};
+
+function PicturesAsyncSearchProvider() {
+ this._init();
+}
+
+PicturesAsyncSearchProvider.prototype = {
+ __proto__: ZeitgeistAsyncSearchProvider.prototype,
+
+ _init: function() {
+ let interpretations = [Semantic.NFO_IMAGE];
+ ZeitgeistAsyncSearchProvider.prototype._init.call(this, _("PICTURES"), interpretations);
+ }
+};
+
+function OtherAsyncSearchProvider() {
+ this._init();
+}
+
+OtherAsyncSearchProvider.prototype = {
+ __proto__: ZeitgeistAsyncSearchProvider.prototype,
+
+ _init: function() {
+ let interpretations = [
+ '!' + Semantic.NFO_IMAGE,
+ '!' + Semantic.NFO_DOCUMENT,
+ '!' + Semantic.NFO_VIDEO,
+ '!' + Semantic.NFO_AUDIO,
+ '!' + Semantic.NMM_MUSIC_PIECE];
+ ZeitgeistAsyncSearchProvider.prototype._init.call(this, _("OTHER"), interpretations);
+ },
+
+ _buildTemplates: function(interpretations) {
+ // Here we want to get everything matching all of the templates, and
+ // not just any of them. Therefore we need to AND the interpretations
+ // instead of OR'ing them; this is done by having an Event with
+ // different Subjects.
+ this.templates = [];
+ let subjects = [];
+ for (let i = 0; i < interpretations.length; i++) {
+ let subject = new Zeitgeist.Subject('', interpretations[i], '', '', '', '', '');
+ subjects.push(subject);
+ }
+ let event = new Zeitgeist.Event('', '', '', subjects, []);
+ this.templates.push(event);
+ }
+};
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]