[gnome-shell/zeitgeist: 20/22] Add support for Zeitgeist search providers



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]