Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
07c39959d9 | ||
|
23d1d18619 | ||
|
23bf5db80c | ||
|
550e9973b7 | ||
|
e4e6b26e15 | ||
|
9551e1c2f5 | ||
|
a70ea12be8 | ||
|
fb5a3a53fa | ||
|
30eac56691 | ||
|
cb6f3a0836 | ||
|
8e579024b1 | ||
|
41c70293df | ||
|
4b015903bc |
@ -10,7 +10,9 @@ nobase_dist_js_DATA = \
|
||||
misc/history.js \
|
||||
misc/modemManager.js \
|
||||
misc/params.js \
|
||||
misc/semantic.js \
|
||||
misc/util.js \
|
||||
misc/zeitgeist.js \
|
||||
perf/core.js \
|
||||
ui/altTab.js \
|
||||
ui/appDisplay.js \
|
||||
@ -22,7 +24,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 +65,5 @@ nobase_dist_js_DATA = \
|
||||
ui/workspaceThumbnail.js \
|
||||
ui/workspacesView.js \
|
||||
ui/workspaceSwitcherPopup.js \
|
||||
ui/xdndHandler.js
|
||||
ui/xdndHandler.js \
|
||||
ui/zeitgeistSearch.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);
|
||||
|
43
js/misc/semantic.js
Normal file
43
js/misc/semantic.js
Normal file
@ -0,0 +1,43 @@
|
||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*-
|
||||
*
|
||||
* Semantic-desktop interpretations for various data types
|
||||
*
|
||||
* Authors: Federico Mena Quintero <federico@gnome.org>
|
||||
*
|
||||
* 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 NFO_AUDIO = "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#Audio";
|
||||
const NFO_DOCUMENT = "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#Document";
|
||||
const NFO_HTML_DOCUMENT = "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#HtmlDocument";
|
||||
const NFO_IMAGE = "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#Image";
|
||||
const NFO_MEDIA = "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#Media";
|
||||
const NFO_MIND_MAP = "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#MindMap";
|
||||
const NFO_PAGINATED_TEXT_DOCUMENT = "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#PaginatedTextDocument";
|
||||
const NFO_PLAIN_TEXT_DOCUMENT = "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#PlainTextDocument";
|
||||
const NFO_PRESENTATION = "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#Presentation";
|
||||
const NFO_RASTER_IMAGE = "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#RasterImage";
|
||||
const NFO_SOURCE_CODE = "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#SourceCode";
|
||||
const NFO_SPREADSHEET = "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#Spreadsheet";
|
||||
const NFO_TEXT_DOCUMENT = "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#TextDocument";
|
||||
const NFO_VECTOR_IMAGE = "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#VectorImage";
|
||||
const NFO_VIDEO = "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#Video";
|
||||
|
||||
const NMM_CURSOR = "http://www.semanticdesktop.org/ontologies/2009/02/19/nmm#Cursor";
|
||||
const NMM_ICON = "http://www.semanticdesktop.org/ontologies/2009/02/19/nmm#Icon";
|
||||
const NMM_MOVIE = "http://www.semanticdesktop.org/ontologies/2009/02/19/nmm#Movie";
|
||||
const NMM_MUSIC_PIECE = "http://www.semanticdesktop.org/ontologies/2009/02/19/nmm#MusicPiece";
|
||||
const NMM_TV_SHOW = "http://www.semanticdesktop.org/ontologies/2009/02/19/nmm#TVShow";
|
264
js/misc/zeitgeist.js
Normal file
264
js/misc/zeitgeist.js
Normal file
@ -0,0 +1,264 @@
|
||||
/* -*- 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 DBus = imports.dbus;
|
||||
|
||||
const SIG_EVENT = '(asaasay)';
|
||||
const MAX_TIMESTAMP = 9999999999999;
|
||||
|
||||
// Number of results given by fullTextSearch; 100 is probably enough.
|
||||
// Note: We can't currently increase this number to anything above 132, due to
|
||||
// https://bugs.launchpad.net/zeitgeist-extensions/+bug/716503
|
||||
const MAX_RESULTS = 100;
|
||||
|
||||
const ResultType = {
|
||||
// http://zeitgeist-project.com/docs/0.6/datamodel.html#resulttype
|
||||
// It's unfortunate to have to define these by hand; maybe if D-Bus had a way to introspect enums...
|
||||
MOST_RECENT_EVENTS : 0,
|
||||
LEAST_RECENT_EVENTS : 1,
|
||||
MOST_RECENT_SUBJECTS : 2,
|
||||
LEAST_RECENT_SUBJECTS : 3,
|
||||
MOST_POPULAR_SUBJECTS : 4,
|
||||
LEAST_POPULAR_SUBJECTS : 5,
|
||||
MOST_POPULAR_ACTOR : 6,
|
||||
LEAST_POPULAR_ACTOR : 7,
|
||||
MOST_RECENT_ACTOR : 8,
|
||||
LEAST_RECENT_ACTOR : 9,
|
||||
MOST_RECENT_ORIGIN : 10,
|
||||
LEAST_RECENT_ORIGIN : 11,
|
||||
MOST_POPULAR_ORIGIN : 12,
|
||||
LEAST_POPULAR_ORIGIN : 13,
|
||||
OLDEST_ACTOR : 14,
|
||||
MOST_RECENT_SUBJECT_INTERPRETATION : 15,
|
||||
LEAST_RECENT_SUBJECT_INTERPRETATION : 16,
|
||||
MOST_POPULAR_SUBJECT_INTERPRETATION : 17,
|
||||
LEAST_POPULAR_SUBJECT_INTERPRETATION : 18,
|
||||
MOST_RECENT_MIME_TYPE : 19,
|
||||
LEAST_RECENT_MIME_TYPE : 20,
|
||||
MOST_POPULAR_MIME_TYPE : 21,
|
||||
LEAST_POPULAR_MIME_TYPE : 22
|
||||
};
|
||||
|
||||
const StorageState = {
|
||||
// http://zeitgeist-project.com/docs/0.6/datamodel.html#storagestate
|
||||
// As with ResultType, it would be nice if we could introspect enums through D-Bus
|
||||
NOT_AVAILABLE : 0,
|
||||
AVAILABLE : 1,
|
||||
ANY : 2
|
||||
};
|
||||
|
||||
/* Zeitgeist Subjects (files, people, etc.) */
|
||||
|
||||
function Subject(uri, interpretation, manifestation, origin, mimetype, text, storage) {
|
||||
this._init(uri, interpretation, manifestation, origin, mimetype, text, storage);
|
||||
};
|
||||
|
||||
Subject.prototype = {
|
||||
_init: function(uri, interpretation, manifestation, origin, mimetype, text, storage) {
|
||||
this.uri = uri;
|
||||
this.interpretation = interpretation;
|
||||
this.manifestation = manifestation;
|
||||
this.origin = origin;
|
||||
this.mimetype = mimetype;
|
||||
this.text = text;
|
||||
this.storage = storage;
|
||||
},
|
||||
};
|
||||
|
||||
Subject.fromPlain = function(rawSubject) {
|
||||
return new Subject(rawSubject[0], // uri
|
||||
rawSubject[1], // interpretation
|
||||
rawSubject[2], // manifestation
|
||||
rawSubject[3], // origin
|
||||
rawSubject[4], // mimetype
|
||||
rawSubject[5], // text
|
||||
rawSubject[6]); // storage
|
||||
};
|
||||
|
||||
Subject.toPlain = function(subject) {
|
||||
let rawSubject = [];
|
||||
rawSubject[0] = subject.uri;
|
||||
rawSubject[1] = subject.interpretation;
|
||||
rawSubject[2] = subject.manifestation
|
||||
rawSubject[3] = subject.origin;
|
||||
rawSubject[4] = subject.mimetype;
|
||||
rawSubject[5] = subject.text;
|
||||
rawSubject[6] = subject.storage;
|
||||
return rawSubject;
|
||||
};
|
||||
|
||||
/* Zeitgeist Events */
|
||||
|
||||
function Event(interpretation, manifestation, actor, subjects, payload) {
|
||||
this._init(interpretation, manifestation, actor, subjects, payload);
|
||||
};
|
||||
|
||||
Event.prototype = {
|
||||
_init: function(interpretation, manifestation, actor, subjects, payload) {
|
||||
this.id = 0;
|
||||
this.timestamp = 0;
|
||||
this.actor = actor;
|
||||
this.interpretation = interpretation;
|
||||
this.manifestation = manifestation;
|
||||
this.actor = actor;
|
||||
this.payload = payload;
|
||||
this.subjects = subjects;
|
||||
},
|
||||
};
|
||||
|
||||
Event.fromPlain = function(rawEvent) {
|
||||
let subjects = rawEvent[1].map(Subject.fromPlain);
|
||||
let event = new Event(rawEvent[0][2], // interpretation
|
||||
rawEvent[0][3], // manifestation
|
||||
rawEvent[0][4], // actor
|
||||
subjects, // subjects
|
||||
rawEvent[2]);// payload
|
||||
event.id = rawEvent[0][0]; // id
|
||||
event.timestamp = parseInt(rawEvent[0][1], 10); // timestamp - it comes as a string over d-bus (yuck)
|
||||
return event;
|
||||
};
|
||||
|
||||
Event.toPlain = function(event) {
|
||||
let rawEvent = [];
|
||||
rawEvent[0] = [];
|
||||
rawEvent[0][0] = event.id.toString();
|
||||
rawEvent[0][1] = event.timestamp.toString();
|
||||
rawEvent[0][2] = event.interpretation;
|
||||
rawEvent[0][3] = event.manifestation;
|
||||
rawEvent[0][4] = event.actor;
|
||||
rawEvent[1] = event.subjects.map(Subject.toPlain);
|
||||
rawEvent[2] = event.payload;
|
||||
return rawEvent;
|
||||
};
|
||||
|
||||
// Zeitgeist D-Bus interface definitions. Note that most of these are
|
||||
// incomplete, and only cover the methods/properties/signals that
|
||||
// we're currently using.
|
||||
|
||||
/* Zeitgeist D-Bus Interface */
|
||||
|
||||
const LOG_NAME = 'org.gnome.zeitgeist.Engine';
|
||||
const LOG_PATH = '/org/gnome/zeitgeist/log/activity';
|
||||
const LogIface = {
|
||||
name: 'org.gnome.zeitgeist.Log',
|
||||
methods: [
|
||||
{ name: 'GetEvents',
|
||||
inSignature: 'au',
|
||||
outSignature: 'a'+SIG_EVENT },
|
||||
{ name: 'FindRelatedUris',
|
||||
inSignature: 'au',
|
||||
outSignature: '(xx)a(' + SIG_EVENT + ')a'+ SIG_EVENT + 'uuu' },
|
||||
{ name: 'FindEventIds',
|
||||
inSignature: '(xx)a' + SIG_EVENT + 'uuu',
|
||||
outSignature: 'au' },
|
||||
{ name: 'FindEvents',
|
||||
inSignature: '(xx)a' + SIG_EVENT + 'uuu',
|
||||
outSignature: 'a' + SIG_EVENT },
|
||||
{ name: 'InsertEvents',
|
||||
inSignature: 'a' + SIG_EVENT,
|
||||
outSignature: 'au' },
|
||||
{ name: 'DeleteEvents',
|
||||
inSignature: 'au',
|
||||
outSignature: '(xx)' },
|
||||
{ name: 'DeleteLog',
|
||||
inSignature: '',
|
||||
outSignature: '' },
|
||||
{ name: 'Quit',
|
||||
inSignature: '',
|
||||
outSignature: '' },
|
||||
// FIXME: Add missing DBus Methods
|
||||
// - InstallMonitor
|
||||
// - RemoveMonitor
|
||||
],
|
||||
properties: [
|
||||
{ name: 'Get',
|
||||
inSignature: 'ss',
|
||||
outSignature: 'v',
|
||||
access: 'read' },
|
||||
{ name: 'Set',
|
||||
inSignature: 'ssv',
|
||||
outSignature: '',
|
||||
access: 'read' },
|
||||
{ name: 'GetAll',
|
||||
inSignature: 's',
|
||||
outSignature: 'a{sv}',
|
||||
access: 'read' },
|
||||
]
|
||||
};
|
||||
|
||||
const Log = DBus.makeProxyClass(LogIface);
|
||||
const _log = new Log(DBus.session, LOG_NAME, LOG_PATH);
|
||||
|
||||
function findEvents(timeRange, eventTemplates, storageState, numEvents, resultType, callback) {
|
||||
function handler(results, error) {
|
||||
if (error != null)
|
||||
log("Error querying Zeitgeist for events: "+error);
|
||||
else
|
||||
callback(results.map(Event.fromPlain));
|
||||
}
|
||||
_log.FindEventsRemote(timeRange, eventTemplates.map(Event.toPlain),
|
||||
storageState, numEvents, resultType, handler);
|
||||
}
|
||||
|
||||
/* Zeitgeist Full-Text-Search Interface */
|
||||
|
||||
const INDEX_NAME = 'org.gnome.zeitgeist.Engine';
|
||||
const INDEX_PATH = '/org/gnome/zeitgeist/index/activity';
|
||||
const IndexIface = {
|
||||
name: 'org.gnome.zeitgeist.Index',
|
||||
methods: [
|
||||
{ name: 'Search',
|
||||
inSignature: 's(xx)a'+SIG_EVENT+'uuu',
|
||||
outSignature: 'a'+SIG_EVENT+'u' },
|
||||
],
|
||||
};
|
||||
|
||||
const Index = DBus.makeProxyClass(IndexIface);
|
||||
const _index = new Index(DBus.session, INDEX_NAME, INDEX_PATH);
|
||||
|
||||
/**
|
||||
* fullTextSearch:
|
||||
*
|
||||
* Asynchronously search Zeitgeist's index for events relating to the query.
|
||||
*
|
||||
* @param query The query string, using asterisks for wildcards. Wildcards must
|
||||
* be used at the start and/or end of a string to get relevant information.
|
||||
* @param eventTemplates Zeitgeist event templates, see
|
||||
* http://zeitgeist-project.com/docs/0.6/datamodel.html#event for more
|
||||
* information
|
||||
* @param callback The callback, takes a list containing Zeitgeist.Event
|
||||
* objects
|
||||
*/
|
||||
function fullTextSearch(query, eventTemplates, callback) {
|
||||
function handler(results, error) {
|
||||
if (error != null)
|
||||
log("Error searching with Zeitgeist FTS: "+error);
|
||||
else
|
||||
callback(results[0].map(Event.fromPlain));
|
||||
}
|
||||
_index.SearchRemote(query, [0, MAX_TIMESTAMP],
|
||||
eventTemplates.map(Event.toPlain),
|
||||
0, // offset into the search results
|
||||
MAX_RESULTS,
|
||||
ResultType.MOST_POPULAR_SUBJECTS, handler);
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gio = imports.gi.Gio;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Lang = imports.lang;
|
||||
@ -13,6 +14,7 @@ const _ = Gettext.gettext;
|
||||
|
||||
const AppFavorites = imports.ui.appFavorites;
|
||||
const DND = imports.ui.dnd;
|
||||
const DocInfo = imports.misc.docInfo;
|
||||
const IconGrid = imports.ui.iconGrid;
|
||||
const Main = imports.ui.main;
|
||||
const Overview = imports.ui.overview;
|
||||
@ -21,6 +23,7 @@ const Search = imports.ui.search;
|
||||
const Tweener = imports.ui.tweener;
|
||||
const Workspace = imports.ui.workspace;
|
||||
const Params = imports.misc.params;
|
||||
const Zeitgeist = imports.misc.zeitgeist;
|
||||
|
||||
const MENU_POPUP_TIMEOUT = 600;
|
||||
const SCROLL_TIME = 0.1;
|
||||
@ -582,6 +585,7 @@ AppIconMenu.prototype = {
|
||||
this.blockSourceEvents = true;
|
||||
|
||||
this._source = source;
|
||||
this._eventTemplate = new Zeitgeist.Event('', '', "application://" + this._source.app.get_id(), [], []);
|
||||
|
||||
this.connect('activate', Lang.bind(this, this._onActivate));
|
||||
this.connect('open-state-changed', Lang.bind(this, this._onOpenStateChanged));
|
||||
@ -628,6 +632,63 @@ AppIconMenu.prototype = {
|
||||
this._toggleFavoriteMenuItem = this._appendMenuItem(isFavorite ? _("Remove from Favorites")
|
||||
: _("Add to Favorites"));
|
||||
|
||||
Zeitgeist.findEvents([new Date().getTime() - 86400000*90, Zeitgeist.MAX_TIMESTAMP],
|
||||
[this._eventTemplate],
|
||||
Zeitgeist.StorageState.ANY,
|
||||
100,
|
||||
Zeitgeist.ResultType.MOST_RECENT_SUBJECTS,
|
||||
Lang.bind(this, this._appendJumplist));
|
||||
},
|
||||
|
||||
_appendJumplist: function (events) {
|
||||
let fetchedUris = [];
|
||||
let hasJumplist = false;
|
||||
|
||||
function appendEvents(events2, count, type) {
|
||||
if (count == null) {
|
||||
count = 3;
|
||||
}
|
||||
if (type == null) {
|
||||
type = "emblem-favorite";
|
||||
}
|
||||
let j = 0;
|
||||
if (events.length > 0) {
|
||||
for (let i in events) {
|
||||
let uri = events[i].subjects[0].uri.replace('file://', '');
|
||||
uri = uri.replace(/\%20/g, ' '); // FIXME: properly unescape, or get the display name otherwise
|
||||
if (fetchedUris.indexOf(uri) == -1 &&
|
||||
(GLib.file_test(uri, GLib.FileTest.EXISTS) || this._source.app.get_id() == "tomboy.desktop")) {
|
||||
if (!hasJumplist) {
|
||||
this._appendSeparator();
|
||||
hasJumplist = true;
|
||||
}
|
||||
this._appendJumplistItem(events[i], type);
|
||||
fetchedUris.push(uri);
|
||||
j++;
|
||||
if (j >= count)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
appendEvents.call(this, events, 4, "document-open-recent");
|
||||
Zeitgeist.findEvents([new Date().getTime() - 86400000*90, Zeitgeist.MAX_TIMESTAMP],
|
||||
[this._eventTemplate],
|
||||
Zeitgeist.StorageState.ANY,
|
||||
100,
|
||||
Zeitgeist.ResultType.MOST_POPULAR_SUBJECTS,
|
||||
Lang.bind(this, appendEvents));
|
||||
},
|
||||
|
||||
_appendJumplistItem: function (event, type) {
|
||||
let info = new DocInfo.ZeitgeistItemInfo(event);
|
||||
let item = new PopupMenu.PopupImageMenuItem(info.name, type);
|
||||
this.addMenuItem(item);
|
||||
item.connect('activate', Lang.bind(this, function () {
|
||||
let app = new Gio.DesktopAppInfo.new(this._source.app.get_id());
|
||||
app.launch_uris([info.uri], null);
|
||||
}));
|
||||
},
|
||||
|
||||
_appendSeparator: function () {
|
||||
|
@ -1,50 +0,0 @@
|
||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const DocInfo = imports.misc.docInfo;
|
||||
const Params = imports.misc.params;
|
||||
const Search = imports.ui.search;
|
||||
|
||||
|
||||
function DocSearchProvider() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
DocSearchProvider.prototype = {
|
||||
__proto__: Search.SearchProvider.prototype,
|
||||
|
||||
_init: function(name) {
|
||||
Search.SearchProvider.prototype._init.call(this, _("RECENT ITEMS"));
|
||||
this._docManager = DocInfo.getDocManager();
|
||||
},
|
||||
|
||||
getResultMeta: function(resultId) {
|
||||
let docInfo = this._docManager.lookupByUri(resultId);
|
||||
if (!docInfo)
|
||||
return null;
|
||||
return { 'id': resultId,
|
||||
'name': docInfo.name,
|
||||
'createIcon': function(size) {
|
||||
return docInfo.createIcon(size);
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
activateResult: function(id, params) {
|
||||
params = Params.parse(params, { workspace: null,
|
||||
timestamp: null });
|
||||
|
||||
let docInfo = this._docManager.lookupByUri(id);
|
||||
docInfo.launch(params.workspace ? params.workspace.index() : -1);
|
||||
},
|
||||
|
||||
getInitialResultSet: function(terms) {
|
||||
return this._docManager.initialSearch(terms);
|
||||
},
|
||||
|
||||
getSubsearchResultSet: function(previousResults, terms) {
|
||||
return this._docManager.subsearch(previousResults, terms);
|
||||
}
|
||||
};
|
@ -26,11 +26,13 @@ var commandHeader = 'const Clutter = imports.gi.Clutter; ' +
|
||||
'const Gtk = imports.gi.Gtk; ' +
|
||||
'const Mainloop = imports.mainloop; ' +
|
||||
'const Meta = imports.gi.Meta; ' +
|
||||
'const Semantic = imports.misc.semantic' +
|
||||
'const Shell = imports.gi.Shell; ' +
|
||||
'const Tp = imports.gi.TelepathyGLib; ' +
|
||||
'const Main = imports.ui.main; ' +
|
||||
'const Lang = imports.lang; ' +
|
||||
'const Tweener = imports.ui.tweener; ' +
|
||||
'const Zeitgeist = imports.misc.zeitgeist; ' +
|
||||
/* Utility functions...we should probably be able to use these
|
||||
* in the shell core code too. */
|
||||
'const stage = global.stage; ' +
|
||||
|
@ -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;
|
||||
@ -25,6 +24,7 @@ const Tweener = imports.ui.tweener;
|
||||
const ViewSelector = imports.ui.viewSelector;
|
||||
const WorkspacesView = imports.ui.workspacesView;
|
||||
const WorkspaceThumbnail = imports.ui.workspaceThumbnail;
|
||||
const ZeitgeistSearch = imports.ui.zeitgeistSearch;
|
||||
|
||||
// Time for initial animation going into Overview mode
|
||||
const ANIMATION_TIME = 0.25;
|
||||
@ -192,7 +192,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();
|
||||
|
@ -115,6 +115,43 @@ function SearchProvider(title) {
|
||||
SearchProvider.prototype = {
|
||||
_init: function(title) {
|
||||
this.title = title;
|
||||
this.searchSystem = null;
|
||||
this.searchAsync = false;
|
||||
},
|
||||
|
||||
_asyncCancelled: function() {
|
||||
},
|
||||
|
||||
startAsync: function() {
|
||||
this.searchAsync = true;
|
||||
},
|
||||
|
||||
tryCancelAsync: function() {
|
||||
if (!this.searchAsync)
|
||||
return;
|
||||
this._asyncCancelled();
|
||||
this.searchAsync = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* addItems:
|
||||
* @items: an array of result identifier strings representing
|
||||
* items which match the last given search terms.
|
||||
*
|
||||
* This should be used for something that requires a bit more
|
||||
* logic; it's designed to be an asyncronous way to add a result
|
||||
* to the current search.
|
||||
*/
|
||||
addItems: function( items) {
|
||||
if (!this.searchSystem)
|
||||
throw new Error('Search provider not registered');
|
||||
|
||||
if (!items.length)
|
||||
return;
|
||||
|
||||
this.tryCancelAsync();
|
||||
|
||||
this.searchSystem.addProviderItems(this, items);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -212,6 +249,7 @@ SearchProvider.prototype = {
|
||||
};
|
||||
Signals.addSignalMethods(SearchProvider.prototype);
|
||||
|
||||
|
||||
function OpenSearchSystem() {
|
||||
this._init();
|
||||
}
|
||||
@ -324,6 +362,7 @@ SearchSystem.prototype = {
|
||||
},
|
||||
|
||||
registerProvider: function (provider) {
|
||||
provider.searchSystem = this;
|
||||
this._providers.push(provider);
|
||||
},
|
||||
|
||||
@ -340,13 +379,30 @@ SearchSystem.prototype = {
|
||||
this._previousResults = [];
|
||||
},
|
||||
|
||||
addProviderItems: function(provider, items) {
|
||||
let index = this._providers.indexOf(provider);
|
||||
let [provider2, results] = this._previousResults[index];
|
||||
if (provider !== provider2)
|
||||
return;
|
||||
|
||||
results.push.apply(results, items);
|
||||
this.emit('results-updated', this._previousResults);
|
||||
},
|
||||
|
||||
updateSearch: function(searchString) {
|
||||
searchString = searchString.replace(/^\s+/g, '').replace(/\s+$/g, '');
|
||||
if (searchString == '')
|
||||
return [];
|
||||
return;
|
||||
|
||||
let terms = searchString.split(/\s+/);
|
||||
let isSubSearch = terms.length == this._previousTerms.length;
|
||||
this.updateSearchResults(terms);
|
||||
},
|
||||
|
||||
updateSearchResults: function(terms) {
|
||||
let isSubSearch = false;
|
||||
|
||||
if (terms) {
|
||||
isSubSearch = terms.length == this._previousTerms.length;
|
||||
if (isSubSearch) {
|
||||
for (let i = 0; i < terms.length; i++) {
|
||||
if (terms[i].indexOf(this._previousTerms[i]) != 0) {
|
||||
@ -355,14 +411,17 @@ SearchSystem.prototype = {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
terms = this._previousTerms;
|
||||
}
|
||||
|
||||
let results = [];
|
||||
if (isSubSearch) {
|
||||
for (let i = 0; i < this._previousResults.length; i++) {
|
||||
for (let i = 0; i < this._providers.length; i++) {
|
||||
let [provider, previousResults] = this._previousResults[i];
|
||||
provider.tryCancelAsync();
|
||||
try {
|
||||
let providerResults = provider.getSubsearchResultSet(previousResults, terms);
|
||||
if (providerResults.length > 0)
|
||||
results.push([provider, providerResults]);
|
||||
} catch (error) {
|
||||
global.log ('A ' + error.name + ' has occured in ' + provider.title + ': ' + error.message);
|
||||
@ -371,9 +430,9 @@ SearchSystem.prototype = {
|
||||
} else {
|
||||
for (let i = 0; i < this._providers.length; i++) {
|
||||
let provider = this._providers[i];
|
||||
provider.tryCancelAsync();
|
||||
try {
|
||||
let providerResults = provider.getInitialResultSet(terms);
|
||||
if (providerResults.length > 0)
|
||||
results.push([provider, providerResults]);
|
||||
} catch (error) {
|
||||
global.log ('A ' + error.name + ' has occured in ' + provider.title + ': ' + error.message);
|
||||
@ -383,8 +442,7 @@ SearchSystem.prototype = {
|
||||
|
||||
this._previousTerms = terms;
|
||||
this._previousResults = results;
|
||||
|
||||
return results;
|
||||
}
|
||||
this.emit('results-updated', results);
|
||||
},
|
||||
};
|
||||
Signals.addSignalMethods(SearchSystem.prototype);
|
||||
|
@ -182,6 +182,7 @@ function SearchResults(searchSystem, openSearchSystem) {
|
||||
SearchResults.prototype = {
|
||||
_init: function(searchSystem, openSearchSystem) {
|
||||
this._searchSystem = searchSystem;
|
||||
this._searchSystem.connect('results-updated', Lang.bind(this, this._updateResults));
|
||||
this._openSearchSystem = openSearchSystem;
|
||||
|
||||
this.actor = new St.BoxLayout({ name: 'searchResults',
|
||||
@ -216,9 +217,11 @@ SearchResults.prototype = {
|
||||
this._selectedProvider = -1;
|
||||
this._providers = this._searchSystem.getProviders();
|
||||
this._providerMeta = [];
|
||||
for (let i = 0; i < this._providers.length; i++)
|
||||
this._providerMetaResults = {};
|
||||
for (let i = 0; i < this._providers.length; i++) {
|
||||
this.createProviderMeta(this._providers[i]);
|
||||
|
||||
this._providerMetaResults[this.providers[i].title] = [];
|
||||
}
|
||||
this._searchProvidersBox = new St.BoxLayout({ style_class: 'search-providers-box' });
|
||||
this.actor.add(this._searchProvidersBox);
|
||||
|
||||
@ -297,6 +300,12 @@ SearchResults.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
_clearDisplayForProvider: function(index) {
|
||||
let meta = this._providerMeta[index];
|
||||
meta.resultDisplay.clear();
|
||||
meta.actor.hide();
|
||||
},
|
||||
|
||||
reset: function() {
|
||||
this._searchSystem.reset();
|
||||
this._statusText.hide();
|
||||
@ -311,15 +320,15 @@ SearchResults.prototype = {
|
||||
this._statusText.show();
|
||||
},
|
||||
|
||||
doSearch: function (searchString) {
|
||||
this._searchSystem.updateSearch(searchString);
|
||||
},
|
||||
|
||||
_metaForProvider: function(provider) {
|
||||
return this._providerMeta[this._providers.indexOf(provider)];
|
||||
},
|
||||
|
||||
updateSearch: function (searchString) {
|
||||
let results = this._searchSystem.updateSearch(searchString);
|
||||
|
||||
this._clearDisplay();
|
||||
|
||||
_updateResults: function(searchSystem, results) {
|
||||
if (results.length == 0) {
|
||||
this._statusText.set_text(_("No matching results."));
|
||||
this._statusText.show();
|
||||
@ -329,15 +338,23 @@ SearchResults.prototype = {
|
||||
this._statusText.hide();
|
||||
}
|
||||
|
||||
let terms = this._searchSystem.getTerms();
|
||||
let terms = searchSystem.getTerms();
|
||||
this._openSearchSystem.setSearchTerms(terms);
|
||||
|
||||
for (let i = 0; i < results.length; i++) {
|
||||
let [provider, providerResults] = results[i];
|
||||
if (providerResults.length == 0)
|
||||
this._clearDisplayForProvider(i)
|
||||
else {
|
||||
if (this._providerMetaResults[provider.title] != providerResults) {
|
||||
this._providerMetaResults[provider.title] = providerResults;
|
||||
this._clearDisplayForProvider(i);
|
||||
let meta = this._metaForProvider(provider);
|
||||
meta.actor.show();
|
||||
meta.resultDisplay.renderResults(providerResults, terms);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this._selectedOpenSearchButton == -1)
|
||||
this.selectDown(false);
|
||||
|
@ -290,7 +290,7 @@ SearchTab.prototype = {
|
||||
_doSearch: function () {
|
||||
this._searchTimeoutId = 0;
|
||||
let text = this._text.get_text().replace(/^\s+/g, '').replace(/\s+$/g, '');
|
||||
this._searchResults.updateSearch(text);
|
||||
this._searchResults.doSearch(text);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
202
js/ui/zeitgeistSearch.js
Normal file
202
js/ui/zeitgeistSearch.js
Normal file
@ -0,0 +1,202 @@
|
||||
/* -*- 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,
|
||||
'createIcon': function (size) {
|
||||
return ZeitgeistSubjectCache[resultId].createIcon(size);
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
Loading…
Reference in New Issue
Block a user