Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Leap:15.6:Update
gnome-documents
35.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 35.patch of Package gnome-documents
From 38fc56ab890c9272498ad3c5043147e537dc6575 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho <carlosg@gnome.org> Date: Sun, 17 Jan 2021 16:21:26 +0100 Subject: [PATCH 1/8] search: Don't inspect Tracker settings In a sandboxed environment it's no possible (or shouldn't be!) to inspect tracker settings. This is just used to include results from custom folders in addition to Documents/Downloads/Desktop folders, however these are not accessible within the sandbox anymore. Drop this code, and stick to the given XDG folders, if support for custom folders is desirable, should go through the org.freedesktop.Tracker3.Miner.Files.Index interface. --- src/search.js | 36 +----------------------------------- 1 file changed, 1 insertion(+), 35 deletions(-) diff --git a/src/search.js b/src/search.js index df5907c5..738ca336 100644 --- a/src/search.js +++ b/src/search.js @@ -279,9 +279,6 @@ var SearchSourceStock = { LOCAL: 'local' }; -const TRACKER_SCHEMA = 'org.freedesktop.Tracker.Miner.Files'; -const TRACKER_KEY_RECURSIVE_DIRECTORIES = 'index-recursive-directories'; - const Source = class Source { constructor(params) { this.id = null; @@ -310,35 +307,6 @@ const Source = class Source { return []; } - _getTrackerLocations() { - let settings = new Gio.Settings({ schema_id: TRACKER_SCHEMA }); - let locations = settings.get_strv(TRACKER_KEY_RECURSIVE_DIRECTORIES); - let files = []; - - locations.forEach((location) => { - // ignore special XDG placeholders, since we handle those internally - if (location[0] == '&' || location[0] == '$') - return; - - let trackerFile = Gio.file_new_for_commandline_arg(location); - - // also ignore XDG locations if they are present with their full path - for (let idx = 0; idx < GLib.UserDirectory.N_DIRECTORIES; idx++) { - let path = GLib.get_user_special_dir(idx); - if (!path) - continue; - - let file = Gio.file_new_for_path(path); - if (trackerFile.equal(file)) - return; - } - - files.push(trackerFile); - }); - - return files; - } - _getBuiltinLocations() { let files = []; let xdgDirs = [GLib.UserDirectory.DIRECTORY_DESKTOP, @@ -356,9 +324,7 @@ const Source = class Source { _buildFilterLocal() { let locations = this._getBuiltinLocations(); - locations = locations.concat( - this._getTrackerLocations(), - this._getGettingStartedLocations()); + locations = locations.concat(this._getGettingStartedLocations()); let filters = []; locations.forEach((location) => { -- GitLab From 613c214f98451a756b819c0da0b239c69253fecc Mon Sep 17 00:00:00 2001 From: Carlos Garnacho <carlosg@gnome.org> Date: Sun, 17 Jan 2021 16:26:05 +0100 Subject: [PATCH 2/8] application: Drop unused import This library does not exist anymore in Tracker3, and is besides unused here. --- src/application.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/application.js b/src/application.js index eadcd43f..86bb1eff 100644 --- a/src/application.js +++ b/src/application.js @@ -30,7 +30,6 @@ const Gtk = imports.gi.Gtk; const GLib = imports.gi.GLib; const GObject = imports.gi.GObject; const Tracker = imports.gi.Tracker; -const TrackerControl = imports.gi.TrackerControl; const ChangeMonitor = imports.changeMonitor; const Format = imports.format; -- GitLab From f4a6d68538b2efead616d2e2d26e5c037878d1ad Mon Sep 17 00:00:00 2001 From: Carlos Garnacho <carlosg@gnome.org> Date: Sun, 17 Jan 2021 16:41:57 +0100 Subject: [PATCH 3/8] notification: Delete indexing notification This relies on libtracker-control, which is no longer a thing. It might make sense to track indexing state, but that goes together with requests to index specific locations. --- src/notifications.js | 159 ------------------------------------------- 1 file changed, 159 deletions(-) diff --git a/src/notifications.js b/src/notifications.js index 4629b832..7d77f40b 100644 --- a/src/notifications.js +++ b/src/notifications.js @@ -23,7 +23,6 @@ const Gd = imports.gi.Gd; const Gettext = imports.gettext; const GObject = imports.gi.GObject; const Gtk = imports.gi.Gtk; -const TrackerControl = imports.gi.TrackerControl; const _ = imports.gettext.gettext; const Application = imports.application; @@ -155,161 +154,6 @@ var PrintNotification = class PrintNotification { } } -const REMOTE_MINER_TIMEOUT = 10; // seconds -const TRACKER_MINER_FILES_NAME = 'org.freedesktop.Tracker1.Miner.Files'; - -const IndexingNotification = class IndexingNotification { - constructor() { - this._closed = false; - this._timeoutId = 0; - - try { - this._manager = TrackerControl.MinerManager.new_full(false); - this._manager.connect('miner-progress', this._checkNotification.bind(this)); - } catch(e) { - logError(e, 'Unable to create a TrackerMinerManager, indexing progress ' + - 'notification won\'t work'); - return; - } - - Application.application.connect('miners-changed', this._checkNotification.bind(this)); - Application.modeController.connect('window-mode-changed', this._checkNotification.bind(this)); - } - - _checkNotification() { - if (Application.modeController.getWindowMode() == WindowMode.WindowMode.PREVIEW_EV) { - this._destroy(false); - return; - } - - let isIndexingLocal = false; - let isIndexingRemote = false; - - if (this._manager) { - let running = this._manager.get_running(); - if (running.indexOf(TRACKER_MINER_FILES_NAME) != -1) { - let [res, status, progress, time] = this._manager.get_status(TRACKER_MINER_FILES_NAME); - - if (progress < 1) - isIndexingLocal = true; - } - } - - if (Application.application.minersRunning.length > 0) - isIndexingRemote = true; - - if (isIndexingLocal) { - this._display(_("Your documents are being indexed"), - _("Some documents might not be available during this process")); - } else if (isIndexingRemote) { - this._removeTimeout(); - this._timeoutId = Mainloop.timeout_add_seconds(REMOTE_MINER_TIMEOUT, this._onTimeoutExpired.bind(this)); - } else { - this._destroy(false); - } - } - - _onTimeoutExpired() { - this._timeoutId = 0; - - let primary = null; - let miner = null; - - if (Application.application.minersRunning.length == 1) { - miner = Application.application.minersRunning[0]; - } - - if (miner && miner.DisplayName) { - // Translators: %s refers to an online account provider, e.g. - // "Google", or "Windows Live". - primary = _("Fetching documents from %s").format(miner.DisplayName); - } else { - primary = _("Fetching documents from online accounts"); - } - - this._display(primary, null); - - return false; - } - - _removeTimeout() { - if (this._timeoutId != 0) { - Mainloop.source_remove(this._timeoutId); - this._timeoutId = 0; - } - } - - _buildWidget() { - this.widget = new Gtk.Grid({ orientation: Gtk.Orientation.HORIZONTAL, - column_spacing: 12 }); - - let spinner = new Gtk.Spinner({ width_request: 16, - height_request: 16 }); - spinner.start(); - this.widget.add(spinner); - - let labels = new Gtk.Grid({ orientation: Gtk.Orientation.VERTICAL, - row_spacing: 3 }); - this.widget.add(labels); - - this._primaryLabel = new Gtk.Label({ halign: Gtk.Align.START }); - labels.add(this._primaryLabel); - - this._secondaryLabel = new Gtk.Label({ halign: Gtk.Align.START }); - this._secondaryLabel.get_style_context().add_class('dim-label'); - labels.add(this._secondaryLabel); - - let close = new Gtk.Button({ image: new Gtk.Image({ icon_name: 'window-close-symbolic', - pixel_size: 16, - margin_top: 2, - margin_bottom: 2 }), - valign: Gtk.Align.CENTER, - focus_on_click: false, - relief: Gtk.ReliefStyle.NONE }); - close.connect('clicked', () => { - this._destroy(true); - }); - this.widget.add(close); - - Application.notificationManager.addNotification(this); - } - - _update(primaryText, secondaryText) { - this._primaryLabel.label = primaryText; - this._secondaryLabel.label = secondaryText; - - if (secondaryText) { - this._primaryLabel.vexpand = false; - this._secondaryLabel.show(); - } else { - this._primaryLabel.vexpand = true; - this._secondaryLabel.hide(); - } - } - - _display(primaryText, secondaryText) { - if (this._closed) { - return; - } - - if (!this.widget) - this._buildWidget(); - - this._update(primaryText, secondaryText); - } - - _destroy(closed) { - this._removeTimeout(); - - if (this.widget) { - this.widget.destroy(); - this.widget = null; - } - - this._closed = closed; - } -} - var NotificationManager = GObject.registerClass(class NotificationManager extends Gtk.Revealer { _init() { super._init({ halign: Gtk.Align.CENTER, @@ -323,9 +167,6 @@ var NotificationManager = GObject.registerClass(class NotificationManager extend row_spacing: 6 }); frame.add(this._grid); - - // add indexing monitor notification - this._indexingNotification = new IndexingNotification(); } addNotification(notification) { -- GitLab From 442616018c83c620619e7ea1b462b08cb664f930 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho <carlosg@gnome.org> Date: Sun, 17 Jan 2021 16:54:46 +0100 Subject: [PATCH 4/8] application: Use org.freedesktop.Tracker3.Miner.Files.Control for index control This new request allows prioritising graphs on index folders, so request the tracker:Documents graph on the Documents folder here. --- src/application.js | 44 +++++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/src/application.js b/src/application.js index 86bb1eff..d1a1d454 100644 --- a/src/application.js +++ b/src/application.js @@ -71,20 +71,21 @@ var trackerCollectionsController = null; var trackerDocumentsController = null; var trackerSearchController = null; -const TrackerExtractPriorityIface = '<node> \ -<interface name="org.freedesktop.Tracker1.Extract.Priority"> \ - <method name="ClearRdfTypes" /> \ - <method name="SetRdfTypes"> \ - <arg name="rdf_types" type="as" /> \ +const TrackerMinerFilesIndexIface = '<node> \ +<interface name="org.freedesktop.Tracker3.Miner.Files.Index"> \ + <method name="IndexLocation"> \ + <arg name="file_uri" type="s" /> \ + <arg name="graphs" type="as" /> \ + <arg name="flags" type="as" /> \ </method> \ </interface> \ </node>'; -var TrackerExtractPriorityProxy = Gio.DBusProxy.makeProxyWrapper(TrackerExtractPriorityIface); -function TrackerExtractPriority() { - return new TrackerExtractPriorityProxy(Gio.DBus.session, - 'org.freedesktop.Tracker1.Miner.Extract', - '/org/freedesktop/Tracker1/Extract/Priority'); +var TrackerMinerFilesControlProxy = Gio.DBusProxy.makeProxyWrapper(TrackerMinerFilesIndexIface); +function TrackerMinerFilesControl() { + return new TrackerMinerFilesControlProxy(Gio.DBus.session, + 'org.freedesktop.Tracker3.Miner.Files.Control', + '/org/freedesktop/Tracker3/Miner/Files/Index'); } const MINER_REFRESH_TIMEOUT = 60; /* seconds */ @@ -99,6 +100,7 @@ var Application = GObject.registerClass({ this._activationTimestamp = Gdk.CURRENT_TIME; this._extractPriority = null; this._searchProvider = null; + this._minerControl = null; let appid; GLib.set_application_name(_("Documents")); @@ -115,8 +117,6 @@ var Application = GObject.registerClass({ } _initGettingStarted() { - let manager = TrackerControl.MinerManager.new_full(false); - let languages = GLib.get_language_names(); let files = languages.map( function(language) { @@ -138,7 +138,7 @@ var Application = GObject.registerClass({ this.gettingStartedLocation = files[i].get_parent(); try { - manager.index_file(files[i], null); + this._minerControl.IndexLocationRemote(files[i].get_path(), ['tracker:Documents'], []); } catch (e) { logError(e, 'Error indexing the getting started PDF'); } @@ -388,19 +388,20 @@ var Application = GObject.registerClass({ if (this._mainWindow) return; + try { + this._minerControl = TrackerMinerFilesControl(); + this._minerControl.IndexLocationRemote(GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DOCUMENTS), + ['tracker:Documents'], []); + } catch (e) { + logError(e, 'Unable to connect to the tracker extractor'); + } + this._initGettingStarted(); notificationManager = new Notifications.NotificationManager(); this._mainWindow = new MainWindow.MainWindow(this); this._mainWindow.connect('destroy', this._onWindowDestroy.bind(this)); - try { - this._extractPriority = TrackerExtractPriority(); - this._extractPriority.SetRdfTypesRemote(['nfo:Document']); - } catch (e) { - logError(e, 'Unable to connect to the tracker extractor'); - } - // start miners this._startMiners(); } @@ -475,9 +476,6 @@ var Application = GObject.registerClass({ // stop miners this._stopMiners(); - - if (this._extractPriority) - this._extractPriority.ClearRdfTypesRemote(); } _onWindowDestroy(window) { -- GitLab From e4b48b1227b7cdff28abfc77dfafe6a83e286aa9 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho <carlosg@gnome.org> Date: Sun, 17 Jan 2021 17:02:04 +0100 Subject: [PATCH 5/8] changeMonitor: Rewrite to use TrackerNotifier The GraphUpdated DBus signal became superseded by TrackerNotifier in 2.x, and completely removed on 3.x. Use TrackerNotifier here for event tracking. --- src/changeMonitor.js | 182 +++++++++---------------------------------- 1 file changed, 36 insertions(+), 146 deletions(-) diff --git a/src/changeMonitor.js b/src/changeMonitor.js index 5308b042..0172cd65 100644 --- a/src/changeMonitor.js +++ b/src/changeMonitor.js @@ -20,167 +20,57 @@ */ const Gio = imports.gi.Gio; +const Lang = imports.lang; const Mainloop = imports.mainloop; const Signals = imports.signals; +const Tracker = imports.gi.Tracker; const Application = imports.application; -const TrackerResourcesServiceIface = '<node> \ -<interface name="org.freedesktop.Tracker1.Resources"> \ - <signal name="GraphUpdated"> \ - <arg name="className" type="s" /> \ - <arg name="deleteEvents" type="a(iiii)" /> \ - <arg name="insertEvents" type="a(iiii)" /> \ - </signal> \ -</interface> \ -</node>'; - -var TrackerResourcesServiceProxy = Gio.DBusProxy.makeProxyWrapper(TrackerResourcesServiceIface); -function TrackerResourcesService() { - return new TrackerResourcesServiceProxy(Gio.DBus.session, - 'org.freedesktop.Tracker1', - '/org/freedesktop/Tracker1/Resources'); -} - var ChangeEventType = { CHANGED: 0, CREATED: 1, DELETED: 2 }; -const _RDF_TYPE = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"; - -const ChangeEvent = class ChangeEvent { - constructor(urnId, predicateId, isDelete) { - this.urnId = urnId; - this.predicateId = predicateId; - - if (isDelete) - this.type = ChangeEventType.DELETED; - else - this.type = ChangeEventType.CREATED; - } +const ChangeEvent = new Lang.Class({ + Name: 'ChangeEvent', - setResolvedValues(urn, predicate) { + _init: function(type, urn) { this.urn = urn; - this.predicate = predicate; - if (predicate != _RDF_TYPE) + if (type == Tracker.NotifierEventType.CREATE) + this.type = ChangeEventType.CREATED; + else if (type == Tracker.NotifierEventType.DELETE) + this.type = ChangeEventType.DELETED; + else if (type == Tracker.NotifierEventType.UPDATE) this.type = ChangeEventType.CHANGED; } - - merge(event) { - // deletions or creations override the current type - if (event.type == ChangeEventType.DELETED || - event.type == ChangeEventType.CREATED) { - this.type = event.type; - } - } -} - -const CHANGE_MONITOR_TIMEOUT = 500; // msecs -const CHANGE_MONITOR_MAX_ITEMS = 500; // items - -var TrackerChangeMonitor = class TrackerChangeMonitor { - constructor() { - this._pendingChanges = {}; - this._unresolvedIds = {}; - - this._pendingEvents = []; - this._pendingEventsId = 0; - - this._resourceService = new TrackerResourcesService(); - this._resourceService.connectSignal('GraphUpdated', this._onGraphUpdated.bind(this)); - } - - _onGraphUpdated(proxy, senderName, [className, deleteEvents, insertEvents]) { - deleteEvents.forEach((event) => { - this._addPendingEvent(event, true); - }); - - insertEvents.forEach((event) => { - this._addPendingEvent(event, false); - }); - } - - _addPendingEvent(event, isDelete) { - if (this._pendingEventsId != 0) - Mainloop.source_remove(this._pendingEventsId); - - this._unresolvedIds[event[1]] = event[1]; - this._unresolvedIds[event[2]] = event[2]; - this._pendingEvents.push(new ChangeEvent(event[1], event[2], isDelete)); - - if (this._pendingEvents.length >= CHANGE_MONITOR_MAX_ITEMS) - this._processEvents(); - else - this._pendingEventsId = - Mainloop.timeout_add(CHANGE_MONITOR_TIMEOUT, this._processEvents.bind(this)); - } - - _processEvents() { - let events = this._pendingEvents; - let idTable = this._unresolvedIds; - - this._pendingEventsId = 0; - this._pendingEvents = []; - this._unresolvedIds = {}; - - let sparql = 'SELECT'; - Object.keys(idTable).forEach((unresolvedId) => { - sparql += (' tracker:uri(%d)').format(unresolvedId); - }); - sparql += ' {}'; - - // resolve all the unresolved IDs we got so far - Application.connectionQueue.add(sparql, null, (object, res) => { - let cursor = object.query_finish(res); - - cursor.next_async(null, (object, res) => { - let valid = false; - try { - valid = cursor.next_finish(res); - } catch(e) { - logError(e, 'Unable to resolve item URNs for graph changes'); - } - - if (valid) { - let idx = 0; - Object.keys(idTable).forEach((unresolvedId) => { - idTable[unresolvedId] = cursor.get_string(idx)[0]; - idx++; - }); - - this._sendEvents(events, idTable); - } - - cursor.close(); - }); - }); - - return false; - } - - _addEvent(event) { - let urn = event.urn; - let oldEvent = this._pendingChanges[urn]; - - if (oldEvent != null) { - oldEvent.merge(event); - this._pendingChanges[urn] = oldEvent; - } else { - this._pendingChanges[urn] = event; - } - } - - _sendEvents(events, idTable) { - events.forEach((event) => { - event.setResolvedValues(idTable[event.urnId], idTable[event.predicateId]); - this._addEvent(event); - }); - - this.emit('changes-pending', this._pendingChanges); - this._pendingChanges = {}; +}); + +var TrackerChangeMonitor = new Lang.Class({ + Name: 'TrackerChangeMonitor', + + _init: function() { + this._notifier = Application.connection.create_notifier(); + this._notifier.signal_subscribe(Gio.DBus.session, + 'org.freedesktop.Tracker3.Miner.Files', + null, + 'http://tracker.api.gnome.org/ontology/v3/tracker#Documents'); + this._notifier.connect('events', Lang.bind(this, this._onNotifierEvents)); + }, + + _onNotifierEvents: function(notifier, service, graph, events) { + let pendingChanges = {}; + + events.forEach(Lang.bind(this, + function(event) { + let urn = event.get_urn(); + let changeEvent = new ChangeEvent(event.get_event_type(), urn); + pendingChanges[urn] = changeEvent; + })); + + this.emit('changes-pending', pendingChanges); } -} +}); Signals.addSignalMethods(TrackerChangeMonitor.prototype); -- GitLab From 3296833675ff48f7c578ac766aeac346e7911d68 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho <carlosg@gnome.org> Date: Sun, 17 Jan 2021 17:03:14 +0100 Subject: [PATCH 6/8] Port queries to Tracker3 Use new Tracker.SparqlConnection constructors, and rework the queries so that it: 1) Observes the data layout in use in Tracker Miners 3.x 2) Uses a private database for the data considered writeable: - collections - titles 3) Queries g-o-m miners specifically, alongside local data All queries happen on the local connection, optionally including data from tracker-miner-fs and g-o-m miners via SERVICE{} clauses, this is just not the case for collection queries, since collections are stored in the private documents database. --- meson.build | 4 +- src/application.js | 8 ++- src/documents.js | 2 +- src/main.js | 3 +- src/query.js | 136 ++++++++++++++++++++++++++++++++------- src/search.js | 4 +- src/trackerController.js | 4 +- src/trackerUtils.js | 2 +- 8 files changed, 127 insertions(+), 36 deletions(-) diff --git a/meson.build b/meson.build index 7a6d1ad0..1f63b310 100644 --- a/meson.build +++ b/meson.build @@ -54,7 +54,6 @@ endforeach add_project_arguments('-DHAVE_CONFIG_H', language: 'c') evince_req_version = '>= 3.13.3' -tracker_req_version = '>= 0.17.3' gjs_dep = dependency('gjs-1.0', version: '>= 1.48.0') gjs_console = gjs_dep.get_pkgconfig_variable('gjs_console') @@ -68,8 +67,7 @@ documents_deps = [ dependency('gobject-introspection-1.0', version: '>= 1.31.6'), dependency('gtk+-3.0', version: '>= 3.22.15'), dependency('libsoup-2.4', version: '>= 2.41.3'), - dependency('tracker-control-2.0', version: tracker_req_version), - dependency('tracker-sparql-2.0', version: tracker_req_version), + dependency('tracker-sparql-3.0'), dependency('webkit2gtk-4.0', version: '>= 2.6.0'), cc.find_library('m') ] diff --git a/src/application.js b/src/application.js index d1a1d454..73cd2da1 100644 --- a/src/application.js +++ b/src/application.js @@ -337,9 +337,13 @@ var Application = GObject.registerClass({ // connect to tracker try { - connection = Tracker.SparqlConnection.get(null); + let cacheDir = GLib.build_filenamev([GLib.get_user_cache_dir(), 'org.gnome.Documents', 'db']); + let nepomuk = Tracker.sparql_get_ontology_nepomuk(); + connection = Tracker.SparqlConnection.new(Tracker.SparqlConnectionFlags.NONE, + Gio.File.new_for_path(cacheDir), + nepomuk, null); } catch (e) { - logError(e, 'Unable to connect to the tracker database'); + logError(e, 'Unable to set up the tracker database'); return; } diff --git a/src/documents.js b/src/documents.js index 752b5714..d2ad55f9 100644 --- a/src/documents.js +++ b/src/documents.js @@ -776,7 +776,7 @@ const DocCommon = class DocCommon { let retval = ''; if (this.collection) - retval = '{ ?urn nie:isPartOf <' + this.id + '> }'; + retval = '{ ?urn nie:isLogicalPartOf <' + this.id + '> }'; return retval; } diff --git a/src/main.js b/src/main.js index b4afb261..9094f889 100644 --- a/src/main.js +++ b/src/main.js @@ -33,8 +33,7 @@ pkg.require({ 'EvinceDocument': '3.0', 'Goa': '1.0', 'Gtk': '3.0', 'GObject': '2.0', - 'Tracker': '2.0', - 'TrackerControl': '2.0', + 'Tracker': '3.0', 'WebKit2': '4.0' }); const Application = imports.application; diff --git a/src/query.js b/src/query.js index 6ab1a462..4f5142ea 100644 --- a/src/query.js +++ b/src/query.js @@ -90,9 +90,6 @@ var QueryBuilder = class QueryBuilder { part += this._buildOptional(); if ((flags & QueryFlags.UNFILTERED) == 0) { - if (global) - part += this._context.documentManager.getWhere(); - part += this._buildFilterString(currentType, flags, ftsQuery.length > 0); } @@ -141,6 +138,18 @@ var QueryBuilder = class QueryBuilder { } _buildQueryInternal(global, flags, offsetController, sortBy) { + let selectClauses = + ' (COALESCE (nie:url(?urn), nie:isStoredAs(?urn)) AS ?uri) ' + + ' (COALESCE (nfo:fileName(?urn), tracker:string-from-filename(nie:isStoredAs(?urn))) AS ?filename) ' + + ' (nie:mimeType(?urn) AS ?mimetype) ' + + ' (nie:title(?urn) AS ?title) ' + + ' (tracker:coalesce(nco:fullname(?creator), nco:fullname(?publisher), \'\') AS ?author) ' + + ' (nie:contentLastModified(?urn) AS ?mtime) ' + + ' (nao:identifier(?urn) AS ?identifier) ' + + ' (rdf:type(?urn) AS ?type) ' + + ' (nie:dataSource(?urn) AS ?datasource ) ' + + ' (( EXISTS { ?urn nco:contributor ?contributor FILTER ( ?contributor != ?creator ) } ) AS ?shared) ' + + ' (nie:contentCreated(?urn) AS ?created) '; let whereSparql = this._buildWhere(global, flags); let tailSparql = ''; @@ -175,19 +184,61 @@ var QueryBuilder = class QueryBuilder { } let sparql = - 'SELECT DISTINCT ?urn ' + // urn - 'nie:url(?urn) ' + // uri - 'nfo:fileName(?urn) AS ?filename ' + // filename - 'nie:mimeType(?urn)' + // mimetype - 'nie:title(?urn) AS ?title ' + // title - 'tracker:coalesce(nco:fullname(?creator), nco:fullname(?publisher), \'\') AS ?author ' + // author - 'tracker:coalesce(nfo:fileLastModified(?urn), nie:contentLastModified(?urn)) AS ?mtime ' + // mtime - 'nao:identifier(?urn) ' + // identifier - 'rdf:type(?urn) ' + // type - 'nie:dataSource(?urn) ' + // resource URN - '( EXISTS { ?urn nco:contributor ?contributor FILTER ( ?contributor != ?creator ) } ) ' + // shared - 'tracker:coalesce(nfo:fileCreated(?urn), nie:contentCreated(?urn)) ' + // date created - whereSparql + tailSparql; + 'SELECT ?urn ' + + ' ?uri ' + + ' ?filename ' + + ' ?mimetype ' + + ' COALESCE (?localTitle, ?title, ?filename) AS ?t ' + + ' ?author ' + + ' ?mtime ' + + ' ?identifier ' + + ' ?type ' + + ' ?datasource ' + + ' ?shared ' + + ' ?created ' + + 'WHERE { '; + + // Collections queries are local + if (flags & QueryFlags.COLLECTIONS) { + sparql += + 'SELECT DISTINCT ?urn ' + + selectClauses + + whereSparql; + } else { + let services = ['org.freedesktop.Tracker3.Miner.Files']; + let serviceQueries = []; + + if (this._context.sourceManager.hasProviderType('google')) + services.push('org.gnome.OnlineMiners.GData'); + if (this._context.sourceManager.hasProviderType('owncloud')) + services.push('org.gnome.OnlineMiners.Owncloud'); + if (this._context.sourceManager.hasProviderType('windows_live')) + services.push('org.gnome.OnlineMiners.Zpj'); + + services.forEach((service) => { + let serviceQuery = + '{' + + ' SERVICE SILENT <dbus:' + service + '> {' + + ' GRAPH tracker:Documents { ' + + ' SELECT DISTINCT ?urn ' + + selectClauses + + whereSparql + + ' }' + + ' }' + + '}'; + + serviceQueries.push(serviceQuery); + }); + + sparql += serviceQueries.join(' UNION '); + sparql += 'OPTIONAL { ?urn nie:title ?localTitle } . '; + + if (global && (flags & QueryFlags.UNFILTERED) == 0) + sparql += this._context.documentManager.getWhere(); + } + + sparql += '}'; + sparql += tailSparql; return sparql; } @@ -204,8 +255,39 @@ var QueryBuilder = class QueryBuilder { } buildCountQuery(flags) { - let sparql = 'SELECT DISTINCT COUNT(?urn) ' + - this._buildWhere(true, flags); + let sparql; + if (flags & QueryFlags.COLLECTIONS) { + sparql = 'SELECT DISTINCT COUNT(?urn) AS ?c ' + + this._buildWhere(true, flags); + } else { + let services = ['org.freedesktop.Tracker3.Miner.Files']; + let countQueries = []; + + if (this._context.sourceManager.hasProviderType('google')) + services.push('org.gnome.OnlineMiners.GData'); + if (this._context.sourceManager.hasProviderType('owncloud')) + services.push('org.gnome.OnlineMiners.Owncloud'); + if (this._context.sourceManager.hasProviderType('windows_live')) + services.push('org.gnome.OnlineMiners.Zpj'); + + sparql = 'SELECT SUM(?c) {'; + + services.forEach((service) => { + let countQuery = + '{ ' + + ' SERVICE SILENT <dbus:' + service + '> { ' + + ' GRAPH tracker:Documents { ' + + ' SELECT DISTINCT COUNT(?urn) AS ?c ' + + this._buildWhere(true, flags) + + ' }' + + ' }' + + '}'; + countQueries.push(countQuery); + }); + + sparql += countQueries.join(' UNION '); + sparql += '}'; + } return this._createQuery(sparql); } @@ -215,8 +297,8 @@ var QueryBuilder = class QueryBuilder { let sparql = ('SELECT ' + '?urn ' + - 'tracker:coalesce(nfo:fileLastModified(?urn), nie:contentLastModified(?urn)) AS ?mtime ' + - 'WHERE { ?urn nie:isPartOf ?collUrn } ' + + 'nie:contentLastModified(?urn) AS ?mtime ' + + 'WHERE { ?urn nie:isLogicalPartOf ?collUrn } ' + 'ORDER BY DESC (?mtime)' + 'LIMIT 4').replace(/\?collUrn/, '<' + resource + '>'); @@ -228,7 +310,7 @@ var QueryBuilder = class QueryBuilder { let sparql = ('SELECT ' + '?urn ' + - 'WHERE { ?urn a nfo:DataContainer . ?docUrn nie:isPartOf ?urn }' + 'WHERE { ?urn a nfo:DataContainer . ?docUrn nie:isLogicalPartOf ?urn }' ).replace(/\?docUrn/, '<' + resource + '>'); return this._createQuery(sparql); @@ -236,15 +318,21 @@ var QueryBuilder = class QueryBuilder { // adds or removes the given item to the given collection buildSetCollectionQuery(itemUrn, collectionUrn, setting) { - let sparql = ('%s { <%s> nie:isPartOf <%s> }' - ).format((setting ? 'INSERT' : 'DELETE'), itemUrn, collectionUrn); + let sparql; + if (setting) { + sparql = ('INSERT DATA { <%s> a nie:InformationElement; nie:isLogicalPartOf <%s> }' + ).format(itemUrn, collectionUrn); + } else { + sparql = ('DELETE DATA { <%s> nie:isLogicalPartOf <%s> }' + ).format(itemUrn, collectionUrn); + } return this._createQuery(sparql); } // bumps the mtime to current time for the given resource buildUpdateMtimeQuery(resource) { let time = GdPrivate.iso8601_from_timestamp(GLib.get_real_time() / GLib.USEC_PER_SEC); - let sparql = ('INSERT OR REPLACE { <%s> nie:contentLastModified \"%s\" }' + let sparql = ('INSERT OR REPLACE { <%s> a nie:InformationElement; nie:contentLastModified \"%s\" }' ).format(resource, time); return this._createQuery(sparql); diff --git a/src/search.js b/src/search.js index 738ca336..557c7a0a 100644 --- a/src/search.js +++ b/src/search.js @@ -19,6 +19,8 @@ * */ +imports.gi.versions.Tracker = '3.0'; + const Application = imports.application; const Documents = imports.documents; const Manager = imports.manager; @@ -328,7 +330,7 @@ const Source = class Source { let filters = []; locations.forEach((location) => { - filters.push('(fn:contains (nie:url(?urn), "%s"))'.format(location.get_uri())); + filters.push('(fn:contains (nie:isStoredAs(?urn), "%s"))'.format(location.get_uri())); }); filters.push('(fn:starts-with (nao:identifier(?urn), "gd:collection:local:"))'); diff --git a/src/trackerController.js b/src/trackerController.js index 23e1c137..169ddcb5 100644 --- a/src/trackerController.js +++ b/src/trackerController.js @@ -86,10 +86,10 @@ var TrackerConnectionQueue = class TrackerConnectionQueue { Application.connection.query_async(params.query, params.cancellable, this._queueCollector.bind(this, params)); else if (params.queryType == QueryType.UPDATE) - Application.connection.update_async(params.query, GLib.PRIORITY_DEFAULT, params.cancellable, + Application.connection.update_async(params.query, params.cancellable, this._queueCollector.bind(this, params)); else if (params.queryType == QueryType.UPDATE_BLANK) - Application.connection.update_blank_async(params.query, GLib.PRIORITY_DEFAULT, params.cancellable, + Application.connection.update_blank_async(params.query, params.cancellable, this._queueCollector.bind(this, params)); } diff --git a/src/trackerUtils.js b/src/trackerUtils.js index 007568c1..1ed63f2e 100644 --- a/src/trackerUtils.js +++ b/src/trackerUtils.js @@ -22,7 +22,7 @@ const Application = imports.application; function setEditedName(newTitle, docId, callback) { - let sparql = ('INSERT OR REPLACE { <%s> nie:title \"%s\" }'.format(docId, newTitle)); + let sparql = ('INSERT OR REPLACE { <%s> a nie:InformationElement ; nie:title \"%s\" }'.format(docId, newTitle)); Application.connectionQueue.update(sparql, null, function(object, res) { -- GitLab From f2721143344fbb0f1836a70a0efbaa7c246ae8dc Mon Sep 17 00:00:00 2001 From: Carlos Garnacho <carlosg@gnome.org> Date: Fri, 22 Jan 2021 18:00:55 +0100 Subject: [PATCH 7/8] flatpak: Update reference to use Tracker3 Use the Tracker3 policy to specify the accessed graph, drop the builtin tracker copy, and change tracker-miners build parameters so we can run our own internal copy. In code, first check whether there is access to the stock miner, then attempt this internal miner. This is a fallback for systems that do not have tracker3 installed. --- flatpak/org.gnome.Documents.json | 35 +++++++++----------------------- src/application.js | 11 ++++++++++ src/query.js | 4 ++-- 3 files changed, 23 insertions(+), 27 deletions(-) diff --git a/flatpak/org.gnome.Documents.json b/flatpak/org.gnome.Documents.json index 5c2e3116..325d1e73 100644 --- a/flatpak/org.gnome.Documents.json +++ b/flatpak/org.gnome.Documents.json @@ -17,9 +17,8 @@ /* Needs to talk to the network: */ "--share=network", "--talk-name=org.gnome.Mutter.DisplayConfig", - /* Tracker access */ - "--talk-name=org.freedesktop.Tracker1", - "--talk-name=org.freedesktop.Tracker1.Miner.Extract", + /* Tracker3 graph access */ + "--add-policy=Tracker3.dbus:org.freedesktop.Tracker3.Miner.Files=tracker:Documents", /* Needed for dconf to work */ "--filesystem=xdg-run/dconf", "--filesystem=~/.config/dconf:ro", "--talk-name=ca.desrt.dconf", "--env=DCONF_USER_CONFIG_DIR=.config/dconf" @@ -157,35 +156,21 @@ } ] }, - { - "name": "tracker", - "buildsystem": "meson", - "cleanup": [ "/bin", "/etc", "/lib/systemd", "/libexec", "/share/dbus-1/services" ], - "config-opts": [ "--default-library=shared", "-Dbash-completion=no", "-Ddocs=false" ], - "sources": [ - { - "type": "git", - "url": "https://gitlab.gnome.org/GNOME/tracker.git", - "branch": "tracker-2.3" - } - ] - }, { "name": "tracker-miners", "buildsystem": "meson", - "cleanup": [ "/bin", "/etc", "/lib/systemd", "/libexec" ], - "config-opts": [ "--default-library=shared", - "-Dminer_apps=false", + "config-opts": [ "-Ddefault_index_single_directories=&DOWNLOADS", + "-Ddefault_index_recursive_directories=&DOCUMENTS", + "-Ddomain_prefix=org.gnome.Documents", + "-Dman=false", + "-Dminer_fs=true", + "-Dminer_fs_cache_location=$XDG_CACHE_HOME/org.gnome.Documents/miner/files", "-Dminer_rss=false", - "-Dextract=false", - "-Dgeneric_media_extractor=none", - "-Dwriteback=false", - "-Dminer_fs=true" ], + "-Dsystemd_user_services=false" ], "sources": [ { "type": "git", - "url": "https://gitlab.gnome.org/GNOME/tracker-miners.git", - "branch": "tracker-miners-2.3" + "url": "https://gitlab.gnome.org/GNOME/tracker-miners.git" } ] }, diff --git a/src/application.js b/src/application.js index 73cd2da1..1fa75b79 100644 --- a/src/application.js +++ b/src/application.js @@ -70,6 +70,7 @@ var sourceManager = null; var trackerCollectionsController = null; var trackerDocumentsController = null; var trackerSearchController = null; +var trackerMinerService = null; const TrackerMinerFilesIndexIface = '<node> \ <interface name="org.freedesktop.Tracker3.Miner.Files.Index"> \ @@ -347,6 +348,16 @@ var Application = GObject.registerClass({ return; } + // test access to global tracker daemon + try { + let busConn = Tracker.SparqlConnection.bus_new('org.freedesktop.Tracker3.Miner.Files', + null, Gio.DBus.session); + trackerMinerService = 'org.freedesktop.Tracker3.Miner.Files'; + } catch (e) { + // if the daemon is not available, run our own copy (for the sandboxed case) + trackerMinerService = this.get_application_id() + '.Tracker3.Miner.Files'; + } + try { goaClient = Goa.Client.new_sync(null); } catch (e) { diff --git a/src/query.js b/src/query.js index 4f5142ea..ef90754e 100644 --- a/src/query.js +++ b/src/query.js @@ -205,7 +205,7 @@ var QueryBuilder = class QueryBuilder { selectClauses + whereSparql; } else { - let services = ['org.freedesktop.Tracker3.Miner.Files']; + let services = [this._context.trackerMinerService]; let serviceQueries = []; if (this._context.sourceManager.hasProviderType('google')) @@ -260,7 +260,7 @@ var QueryBuilder = class QueryBuilder { sparql = 'SELECT DISTINCT COUNT(?urn) AS ?c ' + this._buildWhere(true, flags); } else { - let services = ['org.freedesktop.Tracker3.Miner.Files']; + let services = [this._context.trackerMinerService]; let countQueries = []; if (this._context.sourceManager.hasProviderType('google')) -- GitLab From 912235ec6243eb34c27517f119e88ce8eb495a55 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho <carlosg@gnome.org> Date: Tue, 26 Jan 2021 16:48:29 +0100 Subject: [PATCH 8/8] flatpak: Update flatpak reference Drop gspell, and update to meson build in evince. Just needed for CI to pass, and build flatpaks. --- .gitlab-ci.yml | 1 - flatpak/org.gnome.Documents.json | 23 ++++++----------------- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e2d7ce78..774a9834 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -4,7 +4,6 @@ variables: GIT_SUBMODULE_STRATEGY: normal flatpak-documents: - image: 'registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:3.32' variables: BUNDLE: "gnome-documents-dev.flatpak" MANIFEST_PATH: "flatpak/org.gnome.Documents.json" diff --git a/flatpak/org.gnome.Documents.json b/flatpak/org.gnome.Documents.json index 325d1e73..309cf6cb 100644 --- a/flatpak/org.gnome.Documents.json +++ b/flatpak/org.gnome.Documents.json @@ -1,7 +1,7 @@ { "app-id": "org.gnome.Documents", "runtime": "org.gnome.Platform", - "runtime-version": "3.32", + "runtime-version": "master", "sdk": "org.gnome.Sdk", "command": "gnome-documents", "tags": [ "nightly" ], @@ -130,25 +130,14 @@ } ] }, - { - "name": "gspell", - "cleanup": [ - "/bin" - ], - "sources": [ - { - "type": "git", - "url": "https://gitlab.gnome.org/GNOME/gspell.git" - } - ] - }, { "name": "evince", + "buildsystem": "meson", "cleanup": [ "/share/GConf", "/share/help" ], - "config-opts": [ "--disable-nautilus", "--disable-viewer", - "--disable-previewer", "--disable-dbus", - "--disable-browser-plugin", "--enable-introspection", - "--disable-comics" ], + "config-opts": [ "-Dnautilus=false", "-Dviewer=false", + "-Dpreviewer=false", "-Ddbus=false", + "-Dbrowser-plugin=false", "-Dintrospection=true", + "-Dcomics=disabled" ], "sources": [ { "type": "git", -- GitLab
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor