[gnome-photos/sam/tracker3: 21/21] Port to Tracker 3




commit 88578de8585d10d7d8f4b0cb32f3428349253dc4
Author: Sam Thursfield <sam afuera me uk>
Date:   Sat May 23 13:36:25 2020 +0200

    Port to Tracker 3
    
    Notable changes:
    
      * User data (favourites, albums) is now stored in a private database in
        ~/.local/share/gnome-photos. This is combined with the Tracker Miner
        FS index of photos at query time.
      * Inside Flatpak, the app connects to Tracker via the new
        xdg-tracker-portal instead of talking directly over D-Bus. Access is
        limited by the portal so the app can only see the Pictures graph.
      * The Flatpak build can use a bundled version of Tracker Miners, if a
        suitable version is not available on the host.
      * Change detection is done using TrackerNotifier instead of watching
        the GraphUpdated D-Bus signal directly.
    
    Closes https://gitlab.gnome.org/GNOME/gnome-photos/-/issues/59
    Closes https://gitlab.gnome.org/GNOME/gnome-photos/-/issues/152

 data/meson.build                                   |   2 +
 data/tracker/meson.build                           |  33 ++
 ....gnome.Photos.Tracker3.Miner.Extract.service.in |   7 +
 ...rg.gnome.Photos.Tracker3.Miner.Files.service.in |   7 +
 data/tracker/org.gnome.Photos.domain.rule.in       |  20 +
 flatpak/org.gnome.Photos.json                      |  53 +--
 meson.build                                        |   3 +-
 src/meson.build                                    |  19 +-
 src/org.freedesktop.Tracker3.Miner.Files.Index.xml |  11 +
 src/org.freedesktop.Tracker3.Miner.xml             |  56 +++
 src/photos-application.c                           | 170 +++-----
 src/photos-base-item.c                             |   9 +
 src/photos-indexing-notification.c                 |  49 ++-
 src/photos-item-manager.c                          |  66 +--
 src/photos-quarks.c                                |  20 +-
 src/photos-query-builder.c                         | 148 ++++---
 src/photos-search-context.c                        |   3 +
 src/photos-search-context.h                        |   1 +
 src/photos-search-match-manager.c                  |   2 +-
 src/photos-source.c                                |  14 +-
 src/photos-tracker-change-event.c                  | 136 ------
 src/photos-tracker-change-event.h                  |  64 ---
 src/photos-tracker-change-monitor.c                | 468 ---------------------
 src/photos-tracker-change-monitor.h                |  42 --
 src/photos-tracker-controller.c                    |  12 +-
 src/photos-tracker-extract-priority.xml            |  30 --
 src/photos-tracker-import-controller.c             |  87 ++--
 src/photos-tracker-queue.c                         | 206 ++++++++-
 src/photos-tracker-queue.h                         |   7 +
 src/photos-tracker-resources.xml                   |  31 --
 src/photos-utils.c                                 |  24 +-
 src/photos-utils.h                                 |   2 +-
 src/queries/all.sparql.template                    |  34 +-
 src/queries/collections.sparql.template            |  20 +-
 src/queries/favorite-photos.sparql.template        |  20 +-
 src/queries/photos.sparql.template                 |  22 +-
 36 files changed, 741 insertions(+), 1157 deletions(-)
---
diff --git a/data/meson.build b/data/meson.build
index 534ef3e0..1a595c53 100644
--- a/data/meson.build
+++ b/data/meson.build
@@ -54,3 +54,5 @@ install_data(
   photos_namespace.to_lower() + '.gschema.xml',
   install_dir: join_paths(photos_datadir, 'glib-2.0', 'schemas'),
 )
+
+subdir('tracker')
diff --git a/data/tracker/meson.build b/data/tracker/meson.build
new file mode 100644
index 00000000..accc99c2
--- /dev/null
+++ b/data/tracker/meson.build
@@ -0,0 +1,33 @@
+# Files needed for running Tracker inside the Flatpak sandbox, for systems
+# which don't have a suitable version of Tracker in the host OS.
+#
+# We must export the .service files from the sandbox so they work on the
+# session bus. This means the Tracker domain name must correspond with the
+# application ID.
+
+
+domain_ontologies_dir = get_option('datadir') / 'tracker3' / 'domain-ontologies'
+dbus_services_dir = get_option('datadir') / 'dbus-1' / 'services'
+
+tracker_domain_config = configuration_data()
+tracker_domain_config.set('application_id', photos_namespace)
+tracker_domain_config.set('domain_rule', get_option('prefix') / domain_ontologies_dir / photos_namespace + 
'.domain.rule')
+
+configure_file(
+  input: 'org.gnome.Photos.domain.rule.in',
+  output: photos_namespace + '.domain.rule',
+  configuration: tracker_domain_config,
+  install_dir: domain_ontologies_dir)
+
+configure_file(
+  input: 'org.gnome.Photos.Tracker3.Miner.Extract.service.in',
+  output: photos_namespace + '.Tracker3.Miner.Extract.service',
+  configuration: tracker_domain_config,
+  install_dir: dbus_services_dir)
+
+configure_file(
+  input: 'org.gnome.Photos.Tracker3.Miner.Files.service.in',
+  output: photos_namespace + '.Tracker3.Miner.Files.service',
+  configuration: tracker_domain_config,
+  install_dir: dbus_services_dir)
+
diff --git a/data/tracker/org.gnome.Photos.Tracker3.Miner.Extract.service.in 
b/data/tracker/org.gnome.Photos.Tracker3.Miner.Extract.service.in
new file mode 100644
index 00000000..eb7a87aa
--- /dev/null
+++ b/data/tracker/org.gnome.Photos.Tracker3.Miner.Extract.service.in
@@ -0,0 +1,7 @@
+[D-BUS Service]
+Name=@application_id@.Tracker3.Miner.Extract
+Exec=/app/libexec/tracker-extract-3 --domain-ontology @domain_rule@
+
+# Miner details needed for tracker-control
+Path=/org/freedesktop/Tracker3/Miner/Extract
+NameSuffix=Miner.Files
diff --git a/data/tracker/org.gnome.Photos.Tracker3.Miner.Files.service.in 
b/data/tracker/org.gnome.Photos.Tracker3.Miner.Files.service.in
new file mode 100644
index 00000000..4fa7371d
--- /dev/null
+++ b/data/tracker/org.gnome.Photos.Tracker3.Miner.Files.service.in
@@ -0,0 +1,7 @@
+[D-BUS Service]
+Name=@application_id@.Tracker3.Miner.Files
+Exec=/app/libexec/tracker-miner-fs-3 --domain-ontology @domain_rule@ --initial-sleep 0
+
+# Miner details needed for tracker-control
+Path=/org/freedesktop/Tracker3/Miner/Files
+NameSuffix=Miner.Files
diff --git a/data/tracker/org.gnome.Photos.domain.rule.in b/data/tracker/org.gnome.Photos.domain.rule.in
new file mode 100644
index 00000000..8f5fc4a1
--- /dev/null
+++ b/data/tracker/org.gnome.Photos.domain.rule.in
@@ -0,0 +1,20 @@
+# This defines a private Tracker domain for GNOME Photos.
+#
+# It's used to run the Tracker indexer inside a Flatpak sandbox, when Photos is
+# running on a host that doesn't have a suitable version of Tracker installed.
+
+[DomainOntology]
+# Location for the Tracker database
+CacheLocation=$XDG_CACHE_HOME/gnome-photos/miner/files
+
+# Name of the ontology to use, must be one located in
+# $(sharedir)/tracker/ontologies
+OntologyName=nepomuk
+
+# DBus name for the owner (not optional). Tracker will use
+# the domain as the prefix of the DBus name for all the
+# services related to this domain ontology.
+Domain=@application_id@
+
+# List of miners we expect to run in this domain.
+Miners=Miner.Files;Miner.Extract
diff --git a/flatpak/org.gnome.Photos.json b/flatpak/org.gnome.Photos.json
index 52ac5c8a..ab010925 100644
--- a/flatpak/org.gnome.Photos.json
+++ b/flatpak/org.gnome.Photos.json
@@ -7,7 +7,7 @@
     "tags": [ "nightly" ],
     "desktop-file-name-prefix": "(Nightly) ",
     "finish-args": [
-        "--env=TRACKER_SPARQL_BACKEND=bus",
+        "--add-policy=Tracker3.dbus:org.freedesktop.Tracker3.Miner.Files=tracker:Pictures",
         "--filesystem=xdg-download",
         "--filesystem=xdg-pictures",
         "--metadata=X-DConf=migrate-path=/org/gnome/photos/",
@@ -17,8 +17,7 @@
         "--socket=wayland",
         "--socket=x11",
         "--talk-name=org.freedesktop.FileManager1",
-        "--talk-name=org.freedesktop.Tracker1",
-        "--talk-name=org.freedesktop.Tracker1.Miner.Extract",
+        "--talk-name=org.freedesktop.Tracker3.Miner.Files.Control",
         "--talk-name=com.intel.dleyna-renderer",
         "--talk-name=org.gnome.ControlCenter",
         "--talk-name=org.gnome.SettingsDaemon",
@@ -265,55 +264,22 @@
                 }
             ]
         },
-        {
-            "name": "tracker",
-            "buildsystem": "meson",
-            "cleanup": [ "/bin", "/etc", "/lib/girepository-1.0", "/libexec", "/share/dbus-1", 
"/share/gir-1.0" ],
-            "config-opts": [ "-Dbash_completion=no", "-Ddocs=false", "-Dsystemd_user_services=no" ],
-            "sources": [
-                {
-                    "type": "git",
-                    "url": "https://gitlab.gnome.org/GNOME/tracker.git";,
-                    "branch": "tracker-2.3"
-                }
-            ]
-        },
-        {
-            "name": "intltool",
-            "cleanup": [ "*" ],
-            "sources": [
-                {
-                    "type": "archive",
-                    "url": "https://launchpad.net/intltool/trunk/0.51.0/+download/intltool-0.51.0.tar.gz";,
-                    "sha256": "67c74d94196b153b774ab9f89b2fa6c6ba79352407037c8c14d5aeb334e959cd"
-                }
-            ]
-        },
         {
             "name": "tracker-miners",
             "buildsystem": "meson",
-            "cleanup": [ "/etc",
-                         "/lib",
-                         "/libexec",
-                         "/share/dbus-1/services/org.freedesktop.Tracker1.Miner.Extract.service",
-                         "/share/dbus-1/services/org.freedesktop.Tracker1.Writeback.service",
-                         "/share/tracker/miners/org.freedesktop.Tracker1.Miner.Applications.service",
-                         "/share/tracker/miners/org.freedesktop.Tracker1.Miner.Extract.service",
-                         "/share/tracker/miners/org.freedesktop.Tracker1.Miner.RSS.service",
-                         "/share/tracker-miners",
-                         "/share/glib-2.0/schemas/org.freedesktop.Tracker.Extract.gschema.xml",
-                         "/share/glib-2.0/schemas/org.freedesktop.Tracker.Writeback.gschema.xml" ],
-            "config-opts": [ "-Dextract=false",
-                             "-Dgeneric_media_extractor=none",
+            "cleanup": [ "/share/dbus-1/services/org.freedesktop.Tracker3.Miner.Extract.service",
+                         "/share/dbus-1/services/org.freedesktop.Tracker3.Miner.Files.service",
+                         "/share/dbus-1/services/org.freedesktop.Tracker3.Writeback.service" ],
+            "config-opts": [ "-Dman=false",
                              "-Dminer_fs=true",
                              "-Dminer_rss=false",
-                             "-Dsystemd_user_services=no",
+                             "-Dsystemd_user_services=false",
                              "-Dwriteback=false" ],
             "sources": [
                 {
                     "type": "git",
                     "url": "https://gitlab.gnome.org/GNOME/tracker-miners.git";,
-                    "branch": "tracker-miners-2.3"
+                    "branch": "master"
                 }
             ]
         },
@@ -325,7 +291,8 @@
                 {
                     "type": "git",
                     "url": "https://gitlab.gnome.org/GNOME/gnome-photos.git";,
-                    "disable-shallow-clone": "true"
+                    "disable-shallow-clone": "true",
+                    "branch": "sam/tracker3"
                 }
             ]
         }
diff --git a/meson.build b/meson.build
index 8e97e6a2..bc14d32d 100644
--- a/meson.build
+++ b/meson.build
@@ -175,8 +175,7 @@ libgfgraph_dep = dependency('libgfbgraph-0.2', version: '>= 0.2.1')
 libhandy_dep = dependency ('libhandy-1', version: '>= 1.0.0')
 libjpeg_dep = dependency('libjpeg')
 libpng_dep = dependency('libpng16')
-tracker_control_dep = dependency('tracker-control-2.0')
-tracker_sparql_dep = dependency('tracker-sparql-2.0')
+tracker_sparql_dep = dependency('tracker-sparql-3.0')
 
 dbus_dep = dependency('dbus-1')
 dbus_services_dir = dbus_dep.get_pkgconfig_variable(
diff --git a/src/meson.build b/src/meson.build
index 428583a8..92833eb2 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -205,8 +205,6 @@ sources = common_sources + files(
   'photos-tool-enhance.c',
   'photos-tool-filter-button.c',
   'photos-tool-filters.c',
-  'photos-tracker-change-event.c',
-  'photos-tracker-change-monitor.c',
   'photos-tracker-collection-view-controller.c',
   'photos-tracker-collections-controller.c',
   'photos-tracker-controller.c',
@@ -367,22 +365,18 @@ sources += gnome.gdbus_codegen(
   autocleanup: 'all',
 )
 
-tracker_extract_priority = 'photos-tracker-extract-priority'
-
 sources += gnome.gdbus_codegen(
-  tracker_extract_priority,
-  tracker_extract_priority + '.xml',
-  interface_prefix: 'org.freedesktop.Tracker1.',
+  'photos-tracker-miner',
+  'org.freedesktop.Tracker3.Miner.xml',
+  interface_prefix: 'org.freedesktop.Tracker3.',
   namespace: 'Tracker',
   autocleanup: 'all',
 )
 
-tracker_resources = 'photos-tracker-resources'
-
 sources += gnome.gdbus_codegen(
-  tracker_resources,
-  tracker_resources + '.xml',
-  interface_prefix: 'org.freedesktop.Tracker1.',
+  'photos-tracker-miner-index',
+  'org.freedesktop.Tracker3.Miner.Files.Index.xml',
+  interface_prefix: 'org.freedesktop.Tracker3.',
   namespace: 'Tracker',
   autocleanup: 'all',
 )
@@ -402,7 +396,6 @@ deps = common_deps + [
   libgfgraph_dep,
   libhandy_dep,
   m_dep,
-  tracker_control_dep,
   tracker_sparql_dep,
 ]
 
diff --git a/src/org.freedesktop.Tracker3.Miner.Files.Index.xml 
b/src/org.freedesktop.Tracker3.Miner.Files.Index.xml
new file mode 100644
index 00000000..e368f1e2
--- /dev/null
+++ b/src/org.freedesktop.Tracker3.Miner.Files.Index.xml
@@ -0,0 +1,11 @@
+<node>
+  <interface name='org.freedesktop.Tracker3.Miner.Files.Index'>
+    <method name='IndexLocation'>
+      <arg type='s' name='file_uri' direction='in' />
+      <arg type='as' name='graphs' direction='in' />
+      <arg type='as' name='flags' direction='in'>"
+        <doc:doc><doc:summary>Extension flags, no allowed values at the moment</doc:summary></doc:doc>
+      </arg>
+    </method>
+  </interface>
+</node>
diff --git a/src/org.freedesktop.Tracker3.Miner.xml b/src/org.freedesktop.Tracker3.Miner.xml
new file mode 100644
index 00000000..6fe09c84
--- /dev/null
+++ b/src/org.freedesktop.Tracker3.Miner.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<node name="/">
+  <interface name="org.freedesktop.Tracker3.Miner">
+    <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="_tracker_miner_dbus"/>
+    <method name="Start">
+      <annotation name="org.freedesktop.DBus.GLib.Async"  value="true"/>
+    </method>
+    <method name="GetStatus">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
+      <arg type="s" name="status" direction="out" />
+    </method>
+    <method name="GetProgress">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
+      <arg type="d" name="progress" direction="out" />
+    </method>
+    <method name="GetRemainingTime">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
+      <arg type="i" name="remaining_time" direction="out" />
+    </method>
+    <method name="GetPauseDetails">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
+      <arg type="as" name="pause_applications" direction="out" />
+      <arg type="as" name="pause_reasons" direction="out" />
+    </method>
+    <method name="Pause">
+      <annotation name="org.freedesktop.DBus.GLib.Async"  value="true"/>
+      <arg type="s" name="application" direction="in" />
+      <arg type="s" name="reason" direction="in" />
+      <arg type="i" name="cookie" direction="out" />
+    </method>
+    <method name="PauseForProcess">
+      <annotation name="org.freedesktop.DBus.GLib.Async"  value="true"/>
+      <arg type="s" name="application" direction="in" />
+      <arg type="s" name="reason" direction="in" />
+      <arg type="i" name="cookie" direction="out" />
+    </method>
+    <method name="Resume">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
+      <arg type="i" name="cookie" direction="in" />
+    </method>
+
+    <!-- Signals -->
+    <signal name="Started" />
+    <signal name="Stopped">
+      <arg type="b" name="interrupted" />
+    </signal>
+    <signal name="Paused" />
+    <signal name="Resumed" />
+    <signal name="Progress">
+      <arg type="s" name="status" />
+      <arg type="d" name="progress" />
+      <arg type="i" name="remaining_time" />
+    </signal>
+  </interface>
+</node>
diff --git a/src/photos-application.c b/src/photos-application.c
index b444b321..c7e19fdd 100644
--- a/src/photos-application.c
+++ b/src/photos-application.c
@@ -37,7 +37,6 @@
 #include <glib/gi18n.h>
 #include <grilo.h>
 #include <handy.h>
-#include <libtracker-control/tracker-control.h>
 
 #include "photos-application.h"
 #include "photos-base-item.h"
@@ -69,7 +68,8 @@
 #include "photos-share-notification.h"
 #include "photos-share-point-manager.h"
 #include "photos-thumbnail-factory.h"
-#include "photos-tracker-extract-priority.h"
+#include "photos-tracker-miner-index.h"
+#include "photos-tracker-queue.h"
 #include "photos-utils.h"
 
 
@@ -128,7 +128,7 @@ struct _PhotosApplication
   PhotosSearchProvider *search_provider;
   PhotosSelectionController *sel_cntrlr;
   PhotosThumbnailFactory *factory;
-  TrackerExtractPriority *extract_priority;
+  TrackerMinerFilesIndex *miner_control_proxy;
   gboolean empty_results;
   gboolean main_window_deleted;
   guint create_miners_count;
@@ -149,7 +149,6 @@ static guint signals[LAST_SIGNAL] = { 0 };
 
 static void photos_application_search_context_iface_init (PhotosSearchContextInterface *iface);
 
-
 G_DEFINE_TYPE_WITH_CODE (PhotosApplication, photos_application, GTK_TYPE_APPLICATION,
                          G_IMPLEMENT_INTERFACE (PHOTOS_TYPE_SEARCH_CONTEXT,
                                                 photos_application_search_context_iface_init));
@@ -196,7 +195,6 @@ struct _PhotosApplicationImportData
   GFile *import_sub_dir;
   GList *files;
   PhotosBaseItem *collection;
-  TrackerMinerManager *manager;
   gchar *collection_urn;
   gint64 ctime_latest;
 };
@@ -249,7 +247,6 @@ photos_application_create_data_free (PhotosApplicationCreateData *data)
 
 static PhotosApplicationImportData *
 photos_application_import_data_new (PhotosApplication *application,
-                                    TrackerMinerManager *manager,
                                     GList *files,
                                     gint64 ctime_latest)
 {
@@ -258,7 +255,6 @@ photos_application_import_data_new (PhotosApplication *application,
   data = g_slice_new0 (PhotosApplicationImportData);
   g_application_hold (G_APPLICATION (application));
   data->application = application;
-  data->manager = g_object_ref (manager);
   data->files = g_list_copy_deep (files, (GCopyFunc) g_object_ref, NULL);
   data->ctime_latest = ctime_latest;
   return data;
@@ -279,7 +275,6 @@ photos_application_import_data_free (PhotosApplicationImportData *data)
   g_clear_object (&data->destination);
   g_clear_object (&data->import_sub_dir);
   g_list_free_full (data->files, g_object_unref);
-  g_clear_object (&data->manager);
   g_free (data->collection_urn);
   g_slice_free (PhotosApplicationImportData, data);
 }
@@ -585,27 +580,6 @@ photos_application_actions_update (PhotosApplication *self)
 }
 
 
-static void
-photos_application_tracker_clear_rdf_types (GObject *source_object, GAsyncResult *res, gpointer user_data)
-{
-  PhotosApplication *self = PHOTOS_APPLICATION (user_data);
-  TrackerExtractPriority *extract_priority = TRACKER_EXTRACT_PRIORITY (source_object);
-
-  {
-    g_autoptr (GError) error = NULL;
-
-    if (!tracker_extract_priority_call_clear_rdf_types_finish (extract_priority, res, &error))
-      {
-        g_warning ("Unable to call ClearRdfTypes: %s", error->message);
-        goto out;
-      }
-  }
-
- out:
-  g_application_release (G_APPLICATION (self));
-}
-
-
 static gboolean
 photos_application_delete_event (PhotosApplication *self)
 {
@@ -642,16 +616,6 @@ photos_application_destroy (PhotosApplication *self)
   self->create_window_cancellable = g_cancellable_new ();
 
   photos_application_stop_miners (self);
-
-  if (self->extract_priority != NULL)
-    {
-      g_application_hold (G_APPLICATION (self));
-      tracker_extract_priority_call_clear_rdf_types (self->extract_priority,
-                                                     NULL,
-                                                     photos_application_tracker_clear_rdf_types,
-                                                     self);
-      g_clear_object (&self->extract_priority);
-    }
 }
 
 
@@ -741,57 +705,36 @@ photos_application_gegl_init_fishes_idle (gpointer user_data)
 }
 
 
-static void
-photos_application_tracker_set_rdf_types (GObject *source_object, GAsyncResult *res, gpointer user_data)
+static TrackerMinerFilesIndex *
+photos_application_get_miner_fs_control_proxy (GCancellable *cancellable)
 {
-  PhotosApplication *self = PHOTOS_APPLICATION (user_data);
-  TrackerExtractPriority *extract_priority = TRACKER_EXTRACT_PRIORITY (source_object);
+  g_autoptr (PhotosTrackerQueue) tracker_queue = NULL;
+  const gchar *miner_fs_control_busname;
+  g_autoptr (GError) error = NULL;
+  TrackerMinerFilesIndex *miner_control_proxy;
 
-  {
-    g_autoptr (GError) error = NULL;
-
-    if (!tracker_extract_priority_call_set_rdf_types_finish (extract_priority, res, &error))
-      {
-        if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
-          g_warning ("Unable to call SetRdfTypes: %s", error->message);
-
-        goto out;
-      }
-  }
-
- out:
-  g_application_release (G_APPLICATION (self));
-}
+  tracker_queue = photos_tracker_queue_dup_singleton (cancellable, &error);
 
+  if (!tracker_queue)
+    {
+      g_warning ("Error getting Tracker queue: %s. Import will not work.", error->message);
+      return NULL;
+    }
 
-static void
-photos_application_tracker_extract_priority (GObject *source_object, GAsyncResult *res, gpointer user_data)
-{
-  PhotosApplication *self = PHOTOS_APPLICATION (user_data);
-  const gchar *const rdf_types[] = {"nfo:Image", NULL};
-
-  {
-    g_autoptr (GError) error = NULL;
-
-    self->extract_priority = tracker_extract_priority_proxy_new_for_bus_finish (res, &error);
-    if (error != NULL)
-      {
-        if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
-          g_warning ("Unable to create TrackerExtractPriority proxy: %s", error->message);
-
-        goto out;
-      }
-  }
-
-  g_application_hold (G_APPLICATION (self));
-  tracker_extract_priority_call_set_rdf_types (self->extract_priority,
-                                               rdf_types,
-                                               self->create_window_cancellable,
-                                               photos_application_tracker_set_rdf_types,
-                                               self);
+  miner_fs_control_busname = photos_tracker_queue_get_miner_fs_control_busname (tracker_queue);
+  miner_control_proxy = tracker_miner_files_index_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+                                                                          G_DBUS_PROXY_FLAGS_NONE,
+                                                                          miner_fs_control_busname,
+                                                                          
"/org/freedesktop/Tracker3/Miner/Files/Control",
+                                                                          NULL,
+                                                                          &error);
+  if (!miner_control_proxy)
+    {
+      g_warning ("Error getting Tracker Miner FS control proxy: %s. Import will not work", error->message);
+      return NULL;
+    }
 
- out:
-  g_application_release (G_APPLICATION (self));
+  return miner_control_proxy;
 }
 
 
@@ -829,15 +772,10 @@ photos_application_create_window (PhotosApplication *self)
     self->init_fishes_id = g_idle_add (photos_application_gegl_init_fishes_idle, self);
 
   g_application_hold (G_APPLICATION (self));
-  tracker_extract_priority_proxy_new_for_bus (G_BUS_TYPE_SESSION,
-                                              G_DBUS_PROXY_FLAGS_NONE,
-                                              "org.freedesktop.Tracker1.Miner.Extract",
-                                              "/org/freedesktop/Tracker1/Extract/Priority",
-                                              self->create_window_cancellable,
-                                              photos_application_tracker_extract_priority,
-                                              self);
 
   photos_application_start_miners (self);
+
+  self->miner_control_proxy = photos_application_get_miner_fs_control_proxy (NULL);
   return TRUE;
 }
 
@@ -1114,18 +1052,18 @@ photos_application_get_state (PhotosSearchContext *context)
 
 
 static void
-photos_application_import_index_file (GObject *source_object, GAsyncResult *res, gpointer user_data)
+photos_application_import_index_location (GObject *source_object, GAsyncResult *res, gpointer user_data)
 {
   PhotosApplication *self;
   g_autoptr (GFile) file = G_FILE (user_data);
-  TrackerMinerManager *manager = TRACKER_MINER_MANAGER (source_object);
+  TrackerMinerFilesIndex *miner_control_proxy = TRACKER_MINER_FILES_INDEX (source_object);
 
   self = PHOTOS_APPLICATION (g_application_get_default ());
 
   {
     g_autoptr (GError) error = NULL;
 
-    if (!tracker_miner_manager_index_file_for_process_finish (manager, res, &error))
+    if (!tracker_miner_files_index_call_index_location_finish (miner_control_proxy, res, &error))
       {
         g_autofree gchar *uri = NULL;
 
@@ -1324,7 +1262,6 @@ photos_application_import_file_copy (GObject *source_object, GAsyncResult *res,
   PhotosApplication *self = data->application;
   g_autoptr (GFile) destination = NULL;
   GFile *source = G_FILE (source_object);
-  TrackerMinerManager *manager = data->manager;
 
   {
     g_autoptr (GError) error = NULL;
@@ -1349,6 +1286,8 @@ photos_application_import_file_copy (GObject *source_object, GAsyncResult *res,
   else
     {
       g_autofree gchar *destination_uri = NULL;
+      const gchar *tracker_priority_graphs[] = { TRACKER_PICTURES_GRAPH };
+      const gchar *tracker_index_location_flags[] = { };
 
       g_assert_true (G_IS_FILE (destination));
       g_set_object (&data->destination, destination);
@@ -1365,11 +1304,13 @@ photos_application_import_file_copy (GObject *source_object, GAsyncResult *res,
 
       g_application_hold (G_APPLICATION (self));
       g_application_mark_busy (G_APPLICATION (self));
-      tracker_miner_manager_index_file_for_process_async (manager,
-                                                          destination,
-                                                          NULL,
-                                                          photos_application_import_index_file,
-                                                          g_object_ref (destination));
+      tracker_miner_files_index_call_index_location (self->miner_control_proxy,
+                                                     destination_uri,
+                                                     tracker_priority_graphs,
+                                                     tracker_index_location_flags,
+                                                     NULL,
+                                                     photos_application_import_index_location,
+                                                     g_object_ref (destination));
     }
 
  out:
@@ -1520,7 +1461,6 @@ photos_application_import (PhotosApplication *self)
   GtkWidget *dialog;
   g_autoptr (PhotosApplicationImportData) data = NULL;
   PhotosSource *source;
-  TrackerMinerManager *manager = NULL; /* TODO: use g_autoptr */
   gint64 ctime_latest = -1;
 
   source = PHOTOS_SOURCE (photos_base_manager_get_active_object (self->state->src_mngr));
@@ -1534,17 +1474,11 @@ photos_application_import (PhotosApplication *self)
   selection = photos_selection_controller_get_selection (self->sel_cntrlr);
   g_return_if_fail (selection != NULL);
 
-  {
-    g_autoptr (GError) error = NULL;
-
-    manager = tracker_miner_manager_new_full (FALSE, &error);
-    if (error != NULL)
-      {
-        g_warning ("Unable to create a TrackerMinerManager, importing from attached devices won't work: %s",
-                   error->message);
-        goto out;
-      }
-  }
+  if (!self->miner_control_proxy)
+    {
+      g_warning ("No Tracker3.Miner.Files.Index proxy, importing from attached devices won't work");
+      goto out;
+    }
 
   for (l = selection; l != NULL; l = l->next)
     {
@@ -1573,14 +1507,14 @@ photos_application_import (PhotosApplication *self)
   dialog = photos_import_dialog_new (GTK_WINDOW (self->main_window), ctime_latest);
   gtk_widget_show_all (dialog);
 
-  data = photos_application_import_data_new (self, manager, files, ctime_latest);
+  data = photos_application_import_data_new (self, files, ctime_latest);
+
   g_signal_connect (dialog,
                     "response",
                     G_CALLBACK (photos_application_import_response),
                     g_steal_pointer (&data));
 
  out:
-  g_clear_object (&manager);
   g_list_free_full (files, g_object_unref);
 }
 
@@ -2977,6 +2911,7 @@ photos_application_dispose (GObject *object)
   g_clear_object (&self->insta_action);
   g_clear_object (&self->load_next_action);
   g_clear_object (&self->load_previous_action);
+  g_clear_object (&self->miner_control_proxy);
   g_clear_object (&self->open_action);
   g_clear_object (&self->preview_menu_action);
   g_clear_object (&self->primary_menu_action);
@@ -3005,7 +2940,7 @@ photos_application_dispose (GObject *object)
   g_clear_object (&self->camera_cache);
   g_clear_object (&self->sel_cntrlr);
   g_clear_object (&self->factory);
-  g_clear_object (&self->extract_priority);
+  g_clear_object (&self->miner_control_proxy);
 
   if (self->state != NULL)
     {
@@ -3133,8 +3068,7 @@ photos_application_get_miners_running (PhotosApplication *self)
   return self->miners_running;
 }
 
-
-gint
+int
 photos_application_get_scale_factor (PhotosApplication *self)
 {
   GList *windows;
diff --git a/src/photos-base-item.c b/src/photos-base-item.c
index 0d72f9c5..1f6b31ce 100644
--- a/src/photos-base-item.c
+++ b/src/photos-base-item.c
@@ -2756,6 +2756,15 @@ photos_base_item_update_info_from_type (PhotosBaseItem *self)
 }
 
 
+static gdouble
+get_double_with_default (TrackerSparqlCursor *cursor, PhotosQueryColumns column, gdouble default_value)
+{
+  if (tracker_sparql_cursor_is_bound (cursor, column))
+    return tracker_sparql_cursor_get_double (cursor, column);
+  else
+    return default_value;
+}
+
 static void
 photos_base_item_populate_from_cursor (PhotosBaseItem *self, TrackerSparqlCursor *cursor)
 {
diff --git a/src/photos-indexing-notification.c b/src/photos-indexing-notification.c
index 7b2ea7dd..ad25ecd0 100644
--- a/src/photos-indexing-notification.c
+++ b/src/photos-indexing-notification.c
@@ -26,12 +26,13 @@
 #include <gio/gio.h>
 #include <glib.h>
 #include <glib/gi18n.h>
-#include <libtracker-control/tracker-control.h>
 
 #include "photos-application.h"
 #include "photos-gom-miner.h"
 #include "photos-indexing-notification.h"
 #include "photos-notification-manager.h"
+#include "photos-tracker-queue.h"
+#include "photos-tracker-miner.h"
 
 
 struct _PhotosIndexingNotification
@@ -41,7 +42,7 @@ struct _PhotosIndexingNotification
   GtkWidget *primary_label;
   GtkWidget *secondary_label;
   GtkWidget *spinner;
-  TrackerMinerManager *manager;
+  TrackerMiner *miner_fs_proxy;
   gboolean closed;
   gboolean on_display;
   guint timeout_id;
@@ -56,8 +57,6 @@ enum
   REMOTE_MINER_TIMEOUT = 10 /* s */
 };
 
-static const gchar *MINER_FILES = "org.freedesktop.Tracker1.Miner.Files";
-
 
 static void
 photos_indexing_notification_remove_timeout (PhotosIndexingNotification *self)
@@ -180,13 +179,18 @@ photos_indexing_notification_check_notification (PhotosIndexingNotification *sel
   GSList *running = NULL;
   gboolean is_indexing_local = FALSE;
   gboolean is_indexing_remote = FALSE;
+  GError *error = NULL;
+  gdouble progress;
 
-  running = tracker_miner_manager_get_running (self->manager);
-  if (g_slist_find_custom (running, (gconstpointer) MINER_FILES, (GCompareFunc) g_strcmp0) != NULL)
+  tracker_miner_call_get_progress_sync (self->miner_fs_proxy, &progress, NULL, &error);
+  if (error)
     {
-      gdouble progress;
+      g_warning ("Couldn't get indexing progress from Tracker Miner FS: %s", error->message);
 
-      tracker_miner_manager_get_status (self->manager, MINER_FILES, NULL, &progress, NULL);
+      g_clear_error (&error);
+    }
+  else
+    {
       if (progress < 1)
         is_indexing_local = TRUE;
     }
@@ -222,7 +226,6 @@ photos_indexing_notification_dispose (GObject *object)
   photos_indexing_notification_remove_timeout (self);
 
   g_clear_object (&self->ntfctn_mngr);
-  g_clear_object (&self->manager);
 
   G_OBJECT_CLASS (photos_indexing_notification_parent_class)->dispose (object);
 }
@@ -240,13 +243,26 @@ photos_indexing_notification_init (PhotosIndexingNotification *self)
   app = g_application_get_default ();
 
   {
+    g_autoptr (PhotosTrackerQueue) tracker_queue;
     g_autoptr (GError) error = NULL;
+    const gchar *miner_fs_busname;
+
+    tracker_queue = photos_tracker_queue_dup_singleton (NULL, &error);
+
+    if (tracker_queue)
+      {
+        miner_fs_busname = photos_tracker_queue_get_miner_fs_busname (tracker_queue);
+        self->miner_fs_proxy = tracker_miner_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+                                                                     G_DBUS_PROXY_FLAGS_NONE,
+                                                                     miner_fs_busname,
+                                                                     "/org/freedesktop/Tracker3/Miner/Files",
+                                                                     NULL,
+                                                                     &error);
+      }
 
-    self->manager = tracker_miner_manager_new_full (FALSE, &error);
     if (error != NULL)
       {
-        g_warning ("Unable to create a TrackerMinerManager, indexing progress notification won't work: %s",
-                   error->message);
+        g_warning ("Unable to create proxy for Tracker Miner FS, indexing progress notification won't work");
         return;
       }
   }
@@ -293,10 +309,11 @@ photos_indexing_notification_init (PhotosIndexingNotification *self)
                            self,
                            G_CONNECT_SWAPPED);
 
-  g_signal_connect_swapped (self->manager,
-                            "miner-progress",
-                            G_CALLBACK (photos_indexing_notification_check_notification),
-                            self);
+  g_signal_connect_object (self->miner_fs_proxy,
+                           "progress",
+                           G_CALLBACK (photos_indexing_notification_check_notification),
+                           self,
+                           G_CONNECT_SWAPPED);
 }
 
 
diff --git a/src/photos-item-manager.c b/src/photos-item-manager.c
index 337891c1..7312a668 100644
--- a/src/photos-item-manager.c
+++ b/src/photos-item-manager.c
@@ -41,12 +41,9 @@
 #include "photos-query.h"
 #include "photos-search-context.h"
 #include "photos-single-item-job.h"
-#include "photos-tracker-change-event.h"
-#include "photos-tracker-change-monitor.h"
 #include "photos-tracker-queue.h"
 #include "photos-utils.h"
 
-
 struct _PhotosItemManager
 {
   PhotosBaseManager parent_instance;
@@ -60,7 +57,7 @@ struct _PhotosItemManager
   PhotosBaseItem *active_collection;
   PhotosBaseManager **item_mngr_chldrn;
   PhotosLoadState load_state;
-  PhotosTrackerChangeMonitor *monitor;
+  TrackerNotifier *notifier;
   PhotosTrackerQueue *queue;
   PhotosWindowMode mode;
   gboolean fullscreen;
@@ -311,7 +308,7 @@ photos_item_manager_add_cursor_for_mode (PhotosItemManager *self,
   g_return_if_fail (base_item_type == G_TYPE_NONE
                     || (base_item_type != PHOTOS_TYPE_BASE_ITEM
                         && g_type_is_a (base_item_type, PHOTOS_TYPE_BASE_ITEM)));
-  g_return_if_fail (TRACKER_SPARQL_IS_CURSOR (cursor));
+  g_return_if_fail (TRACKER_IS_SPARQL_CURSOR (cursor));
   g_return_if_fail (mode != PHOTOS_WINDOW_MODE_NONE);
   g_return_if_fail (mode != PHOTOS_WINDOW_MODE_EDIT);
   g_return_if_fail (mode != PHOTOS_WINDOW_MODE_PREVIEW);
@@ -529,21 +526,23 @@ photos_item_manager_item_created (PhotosItemManager *self, const gchar *urn)
 
 
 static void
-photos_item_manager_changes_pending_foreach (gpointer key, gpointer value, gpointer user_data)
+photos_item_manager_changes_pending_foreach (gpointer data,
+                                             gpointer user_data)
 {
   PhotosItemManager *self = PHOTOS_ITEM_MANAGER (user_data);
-  PhotosTrackerChangeEvent *change_event = (PhotosTrackerChangeEvent *) value;
-  PhotosTrackerChangeEventType change_type;
+  TrackerNotifierEvent *event = (TrackerNotifierEvent *) data;
+  TrackerNotifierEventType change_type;
   const gchar *change_urn;
 
-  change_type = photos_tracker_change_event_get_type (change_event);
-  change_urn = photos_tracker_change_event_get_urn (change_event);
+  change_type = tracker_notifier_event_get_event_type (event);
+  change_urn = tracker_notifier_event_get_urn (event);
 
-  if (change_type == PHOTOS_TRACKER_CHANGE_EVENT_CHANGED)
+  if (change_type == TRACKER_NOTIFIER_EVENT_UPDATE)
     {
       GObject *object;
 
       object = photos_base_manager_get_object_by_id (PHOTOS_BASE_MANAGER (self), change_urn);
+      g_message ("UPDATE event for %s, object %p", change_urn, object);
       if (object != NULL)
         {
           photos_base_item_refresh (PHOTOS_BASE_ITEM (object));
@@ -557,15 +556,17 @@ photos_item_manager_changes_pending_foreach (gpointer key, gpointer value, gpoin
             }
         }
     }
-  else if (change_type == PHOTOS_TRACKER_CHANGE_EVENT_CREATED)
+  else if (change_type == TRACKER_NOTIFIER_EVENT_CREATE)
     {
+      g_message ("CREATE event for %s", change_urn);
       photos_item_manager_item_created (self, change_urn);
     }
-  else if (change_type == PHOTOS_TRACKER_CHANGE_EVENT_DELETED)
+  else if (change_type == TRACKER_NOTIFIER_EVENT_DELETE)
     {
       GObject *object;
 
       object = photos_base_manager_get_object_by_id (PHOTOS_BASE_MANAGER (self), change_urn);
+      g_message ("DELETE event for %s, object %p", change_urn, object);
       if (object != NULL)
         {
           photos_base_item_destroy (PHOTOS_BASE_ITEM (object));
@@ -577,9 +578,14 @@ photos_item_manager_changes_pending_foreach (gpointer key, gpointer value, gpoin
 
 
 static void
-photos_item_manager_changes_pending (PhotosItemManager *self, GHashTable *changes)
+photos_item_manager_changes_pending (PhotosItemManager *self,
+                                     const gchar       *service,
+                                     const gchar       *graph,
+                                     GPtrArray         *events,
+                                     gpointer           user_data)
 {
-  g_hash_table_foreach (changes, photos_item_manager_changes_pending_foreach, self);
+  if (g_str_equal (graph, TRACKER_PICTURES_GRAPH))
+    g_ptr_array_foreach (events, photos_item_manager_changes_pending_foreach, self);
 }
 
 
@@ -717,7 +723,7 @@ photos_item_manager_wait_for_changes_timeout (gpointer user_data)
       g_autoptr (PhotosQuery) query = NULL;
       g_autofree gchar *sparql = NULL;
 
-      sparql = g_strdup_printf ("SELECT ?urn nie:url (?urn) WHERE { ?urn nie:url '%s' }", uri);
+      sparql = g_strdup_printf ("SELECT ?urn nie:isStoredAs (?urn) WHERE { ?urn nie:isStoredAs '%s' }", uri);
       query = photos_query_new (NULL, sparql);
       photos_tracker_queue_select (self->queue,
                                    query,
@@ -1038,7 +1044,7 @@ photos_item_manager_dispose (GObject *object)
   g_clear_object (&self->active_object);
   g_clear_object (&self->loader_cancellable);
   g_clear_object (&self->active_collection);
-  g_clear_object (&self->monitor);
+  g_clear_object (&self->notifier);
   g_clear_object (&self->queue);
 
   G_OBJECT_CLASS (photos_item_manager_parent_class)->dispose (object);
@@ -1093,20 +1099,24 @@ photos_item_manager_init (PhotosItemManager *self)
 
   self->mode = PHOTOS_WINDOW_MODE_NONE;
 
-  self->monitor = photos_tracker_change_monitor_dup_singleton (NULL, NULL);
-  if (G_LIKELY (self->monitor != NULL))
-    g_signal_connect_object (self->monitor,
-                             "changes-pending",
-                             G_CALLBACK (photos_item_manager_changes_pending),
-                             self,
-                             G_CONNECT_SWAPPED);
-
   {
     g_autoptr (GError) error = NULL;
 
     self->queue = photos_tracker_queue_dup_singleton (NULL, &error);
     if (G_UNLIKELY (error != NULL))
-      g_warning ("Unable to create PhotosTrackerQueue: %s", error->message);
+      {
+        g_warning ("Unable to create PhotosTrackerQueue: %s", error->message);
+        self->notifier = NULL;
+      }
+    else
+      {
+        self->notifier = photos_tracker_queue_get_notifier (self->queue);
+        g_signal_connect_object (self->notifier,
+                                 "events",
+                                 G_CALLBACK (photos_item_manager_changes_pending),
+                                 self,
+                                 G_CONNECT_SWAPPED);
+      }
   }
 
   self->fullscreen = FALSE;
@@ -1241,7 +1251,7 @@ photos_item_manager_add_item (PhotosItemManager *self,
   g_return_if_fail (base_item_type == G_TYPE_NONE
                     || (base_item_type != PHOTOS_TYPE_BASE_ITEM
                         && g_type_is_a (base_item_type, PHOTOS_TYPE_BASE_ITEM)));
-  g_return_if_fail (TRACKER_SPARQL_IS_CURSOR (cursor));
+  g_return_if_fail (TRACKER_IS_SPARQL_CURSOR (cursor));
 
   id = tracker_sparql_cursor_get_string (cursor, PHOTOS_QUERY_COLUMNS_URN, NULL);
   g_return_if_fail (id != NULL && id[0] != '\0');
@@ -1370,7 +1380,7 @@ photos_item_manager_create_item (PhotosItemManager *self,
   g_return_val_if_fail (base_item_type == G_TYPE_NONE
                         || (base_item_type != PHOTOS_TYPE_BASE_ITEM
                             && g_type_is_a (base_item_type, PHOTOS_TYPE_BASE_ITEM)), NULL);
-  g_return_val_if_fail (TRACKER_SPARQL_IS_CURSOR (cursor), NULL);
+  g_return_val_if_fail (TRACKER_IS_SPARQL_CURSOR (cursor), NULL);
 
   id = tracker_sparql_cursor_get_string (cursor, PHOTOS_QUERY_COLUMNS_URN, NULL);
   item = PHOTOS_BASE_ITEM (photos_base_manager_get_object_by_id (PHOTOS_BASE_MANAGER (self), id));
diff --git a/src/photos-quarks.c b/src/photos-quarks.c
index 0870ef62..5ee25745 100644
--- a/src/photos-quarks.c
+++ b/src/photos-quarks.c
@@ -25,68 +25,68 @@
 GQuark
 photos_quarks_flash_off_quark (void)
 {
-  return g_quark_from_static_string ("http://www.tracker-project.org/temp/nmm#flash-off";);
+  return g_quark_from_static_string ("http://tracker.api.gnome.org/ontology/v3/nmm#flash-off";);
 }
 
 
 GQuark
 photos_quarks_flash_on_quark (void)
 {
-  return g_quark_from_static_string ("http://www.tracker-project.org/temp/nmm#flash-on";);
+  return g_quark_from_static_string ("http://tracker.api.gnome.org/ontology/v3/nmm#flash-on";);
 }
 
 
 GQuark
 photos_quarks_orientation_bottom_quark (void)
 {
-  return g_quark_from_static_string 
("http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#orientation-bottom";);
+  return g_quark_from_static_string ("http://tracker.api.gnome.org/ontology/v3/nfo#orientation-bottom";);
 }
 
 
 GQuark
 photos_quarks_orientation_bottom_mirror_quark (void)
 {
-  return g_quark_from_static_string 
("http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#orientation-bottom-mirror";);
+  return g_quark_from_static_string 
("http://tracker.api.gnome.org/ontology/v3/nfo#orientation-bottom-mirror";);
 }
 
 
 GQuark
 photos_quarks_orientation_left_quark (void)
 {
-  return g_quark_from_static_string 
("http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#orientation-left";);
+  return g_quark_from_static_string ("http://tracker.api.gnome.org/ontology/v3/nfo#orientation-left";);
 }
 
 
 GQuark
 photos_quarks_orientation_left_mirror_quark (void)
 {
-  return g_quark_from_static_string 
("http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#orientation-left-mirror";);
+  return g_quark_from_static_string ("http://tracker.api.gnome.org/ontology/v3/nfo#orientation-left-mirror";);
 }
 
 
 GQuark
 photos_quarks_orientation_right_quark (void)
 {
-  return g_quark_from_static_string 
("http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#orientation-right";);
+  return g_quark_from_static_string ("http://tracker.api.gnome.org/ontology/v3/nfo#orientation-right";);
 }
 
 
 GQuark
 photos_quarks_orientation_right_mirror_quark (void)
 {
-  return g_quark_from_static_string 
("http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#orientation-right-mirror";);
+  return g_quark_from_static_string 
("http://tracker.api.gnome.org/ontology/v3/nfo#orientation-right-mirror";);
 }
 
 
 GQuark
 photos_quarks_orientation_top_quark (void)
 {
-  return g_quark_from_static_string 
("http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#orientation-top";);
+  return g_quark_from_static_string ("http://tracker.api.gnome.org/ontology/v3/nfo#orientation-top";);
 }
 
 
 GQuark
 photos_quarks_orientation_top_mirror_quark (void)
 {
-  return g_quark_from_static_string 
("http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#orientation-top-mirror";);
+  return g_quark_from_static_string ("http://tracker.api.gnome.org/ontology/v3/nfo#orientation-top-mirror";);
 }
diff --git a/src/photos-query-builder.c b/src/photos-query-builder.c
index e0735bde..46d65e8f 100644
--- a/src/photos-query-builder.c
+++ b/src/photos-query-builder.c
@@ -25,6 +25,7 @@
 
 #include <string.h>
 
+#include "photos-application.h"
 #include "photos-base-manager.h"
 #include "photos-query.h"
 #include "photos-query-builder.h"
@@ -32,6 +33,7 @@
 #include "photos-source-manager.h"
 #include "photos-search-match-manager.h"
 #include "photos-search-type-manager.h"
+#include "photos-tracker-queue.h"
 
 #define PHOTOS_QUERY_COLLECTIONS_IDENTIFIER "photos:collection:"
 #define PHOTOS_QUERY_LOCAL_COLLECTIONS_IDENTIFIER "photos:collection:local:"
@@ -48,12 +50,14 @@ const gchar *photos_default_filter = \
 
 static gchar *
 photos_query_builder_query (PhotosSearchContextState *state,
-                            gboolean global,
+                            const gchar *values,
                             gint flags,
                             PhotosOffsetController *offset_cntrlr)
 {
   PhotosSparqlTemplate *template;
-  const gchar *projection = NULL;
+  const gchar *miner_fs_busname = NULL;
+  const gchar *main_projection = NULL;
+  const gchar *second_projection = NULL;
   g_autofree gchar *item_pattern = NULL;
   g_autofree gchar *search_filter = NULL;
   g_autofree gchar *source_filter = NULL;
@@ -63,29 +67,35 @@ photos_query_builder_query (PhotosSearchContextState *state,
 
   template = photos_base_manager_get_sparql_template (state->srch_typ_mngr, flags);
 
-  projection = "?urn "
-               "nie:url (?urn) "
-               "nfo:fileName (?urn) "
-               "nie:mimeType (?urn) "
-               "nie:title (?urn) "
-               "tracker:coalesce (nco:fullname (?creator), nco:fullname (?publisher), '') "
-               "tracker:coalesce (nfo:fileLastModified (?urn), nie:contentLastModified (?urn)) AS ?mtime "
-               "nao:identifier (?urn) "
-               "rdf:type (?urn) "
-               "nie:dataSource(?urn) "
-               "( EXISTS { ?urn nao:hasTag nao:predefined-tag-favorite } ) "
-               "( EXISTS { ?urn nco:contributor ?contributor FILTER ( ?contributor != ?creator ) } ) "
-               "tracker:coalesce(nfo:fileCreated (?urn), nie:contentCreated (?urn)) "
-               "nfo:width (?urn) "
-               "nfo:height (?urn) "
-               "nfo:equipment (?urn) "
-               "nfo:orientation (?urn) "
-               "nmm:exposureTime (?urn) "
-               "nmm:fnumber (?urn) "
-               "nmm:focalLength (?urn) "
-               "nmm:isoSpeed (?urn) "
-               "nmm:flash (?urn) "
-               "slo:location (?urn) ";
+  miner_fs_busname = photos_tracker_queue_get_miner_fs_busname (state->queue);
+
+  main_projection = "?urn "
+                    "?file "
+                    "nfo:fileName (?file) AS ?filename "
+                    "nie:mimeType (?urn) AS ?mimetype "
+                    "nie:title (?urn) AS ?title "
+                    "tracker:coalesce (nco:fullname (?creator), nco:fullname (?publisher), '') AS 
?author_name "
+                    "tracker:coalesce (nfo:fileLastModified (?file), 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 
?has_contributor "
+                    "tracker:coalesce(nfo:fileCreated (?file), nie:contentCreated (?urn)) AS ?ctime "
+                    "nfo:width (?urn) AS ?width "
+                    "nfo:height (?urn) AS ?height "
+                    "nfo:equipment (?urn) AS ?equipment "
+                    "nfo:orientation (?urn) AS ?orientation "
+                    "nmm:exposureTime (?urn) AS ?exposure_time "
+                    "nmm:fnumber (?urn) AS ?fnumber "
+                    "nmm:focalLength (?urn) AS ?focal_length "
+                    "nmm:isoSpeed (?urn) AS ?isospeed "
+                    "nmm:flash (?urn) AS ?flash "
+                    "slo:location (?urn) AS ?location ";
+
+  second_projection = "?urn ?file ?filename ?mimetype ?title ?author_name ?mtime ?identifier ?type 
?datasource "
+                      "( EXISTS { ?urn nao:hasTag nao:predefined-tag-favorite } ) AS ?is_favorite "
+                      "?has_contributor ?ctime ?width ?height ?equipment ?orientation ?exposure_time 
?fnumber "
+                      "?focal_length ?isospeed ?flash ?location ";
 
   item_pattern = photos_base_manager_get_where (state->item_mngr, flags);
 
@@ -97,7 +107,7 @@ photos_query_builder_query (PhotosSearchContextState *state,
 
   order = "ORDER BY DESC (?mtime)";
 
-  if (global && (flags & PHOTOS_QUERY_FLAGS_UNLIMITED) == 0)
+  if (values == NULL && (flags & PHOTOS_QUERY_FLAGS_UNLIMITED) == 0)
     {
       gint offset = 0;
       gint step = 60;
@@ -112,12 +122,16 @@ photos_query_builder_query (PhotosSearchContextState *state,
     }
 
   sparql = photos_sparql_template_get_sparql (template,
-                                              "projection", projection,
+                                              "miner_fs_busname", miner_fs_busname,
+                                              "main_projection", main_projection,
+                                              "second_projection", second_projection,
+                                              "final_projection", second_projection,
+                                              "values", values ? values : "",
                                               "collections_default_filter", collections_default_filter,
                                               "item_pattern", item_pattern,
                                               "photos_default_filter", photos_default_filter,
-                                              "source_filter", source_filter ? source_filter : "",
-                                              "search_filter", search_filter ? search_filter : "",
+                                              "source_filter", source_filter ? source_filter : "(true)",
+                                              "search_filter", search_filter ? search_filter : "(true)",
                                               "order", order,
                                               "offset_limit", offset_limit ? offset_limit : "",
                                               NULL);
@@ -133,6 +147,7 @@ photos_query_builder_create_collection_query (PhotosSearchContextState *state,
 {
   g_autoptr (GDateTime) now = NULL;
   PhotosQuery *query;
+  g_autoptr (TrackerResource) collection = NULL;
   g_autofree gchar *identifier = NULL;
   g_autofree gchar *sparql = NULL;
   g_autofree gchar *time = NULL;
@@ -144,13 +159,14 @@ photos_query_builder_create_collection_query (PhotosSearchContextState *state,
   now = g_date_time_new_now_utc ();
   time = g_date_time_format_iso8601 (now);
 
-  sparql = g_strdup_printf ("INSERT { _:res a nfo:DataContainer ; a nie:DataObject ; "
-                            "nie:contentLastModified '%s' ; "
-                            "nie:title '%s' ; "
-                            "nao:identifier '%s' }",
-                            time,
-                            name,
-                            identifier);
+  collection = tracker_resource_new ("_:res");
+  tracker_resource_add_uri (collection, "rdf:type", "nfo:DataContainer");
+  tracker_resource_add_uri (collection, "rdf:type", "nie:DataObject");
+  tracker_resource_set_string (collection, "nie:contentLastModified", time);
+  tracker_resource_set_string (collection, "nie:title", name);
+  tracker_resource_set_string (collection, "nao:identifier", identifier);
+
+  sparql = tracker_resource_print_sparql_update (collection, NULL, "tracker:Pictures");
 
   query = photos_query_new (state, sparql);
 
@@ -180,7 +196,9 @@ PhotosQuery *
 photos_query_builder_count_query (PhotosSearchContextState *state, gint flags)
 {
   PhotosSparqlTemplate *template;
-  const gchar *projection = NULL;
+  const gchar *miner_fs_busname = NULL;
+  const gchar *count_projection = NULL;
+  const gchar *value_projection = NULL;
   g_autofree gchar *item_pattern = NULL;
   g_autofree gchar *search_filter = NULL;
   g_autofree gchar *source_filter = NULL;
@@ -189,7 +207,10 @@ photos_query_builder_count_query (PhotosSearchContextState *state, gint flags)
 
   template = photos_base_manager_get_sparql_template (state->srch_typ_mngr, flags);
 
-  projection = "COUNT(?urn) ";
+  miner_fs_busname = photos_tracker_queue_get_miner_fs_busname (state->queue);
+
+  value_projection = "?urn ";
+  count_projection = "COUNT(?urn) ";
 
   item_pattern = photos_base_manager_get_where (state->item_mngr, flags);
 
@@ -200,12 +221,16 @@ photos_query_builder_count_query (PhotosSearchContextState *state, gint flags)
     }
 
   sparql = photos_sparql_template_get_sparql (template,
-                                              "projection", projection,
+                                              "miner_fs_busname", miner_fs_busname,
+                                              "main_projection", value_projection,
+                                              "second_projection", value_projection,
+                                              "final_projection", count_projection,
+                                              "values", "",
                                               "collections_default_filter", collections_default_filter,
                                               "item_pattern", item_pattern,
                                               "photos_default_filter", photos_default_filter,
-                                              "source_filter", source_filter ? source_filter : "",
-                                              "search_filter", search_filter ? search_filter : "",
+                                              "source_filter", source_filter ? source_filter : "(true)",
+                                              "search_filter", search_filter ? search_filter : "(true)",
                                               "order", "",
                                               "offset_limit", "",
                                               NULL);
@@ -264,7 +289,7 @@ photos_query_builder_fetch_collections_local (PhotosSearchContextState *state)
   g_autofree gchar *sparql = NULL;
 
   sparql = photos_query_builder_query (state,
-                                       TRUE,
+                                       NULL,
                                        PHOTOS_QUERY_FLAGS_COLLECTIONS
                                        | PHOTOS_QUERY_FLAGS_LOCAL
                                        | PHOTOS_QUERY_FLAGS_UNLIMITED,
@@ -284,7 +309,7 @@ photos_query_builder_global_query (PhotosSearchContextState *state,
   PhotosQuery *query;
   g_autofree gchar *sparql = NULL;
 
-  sparql = photos_query_builder_query (state, TRUE, flags, offset_cntrlr);
+  sparql = photos_query_builder_query (state, NULL, flags, offset_cntrlr);
   query = photos_query_new (state, sparql);
 
   return query;
@@ -313,10 +338,19 @@ photos_query_builder_set_collection_query (PhotosSearchContextState *state,
   PhotosQuery *query;
   g_autofree gchar *sparql = NULL;
 
-  sparql = g_strdup_printf ("%s { <%s> nie:isPartOf <%s> }",
-                            setting ? "INSERT" : "DELETE",
-                            item_urn,
-                            collection_urn);
+  if (setting)
+    sparql = g_strdup_printf ("INSERT DATA { "
+                              "  GRAPH tracker:Pictures {"
+                              "    <%s> a nie:DataObject , nmm:Photo ; "
+                              "      nie:isPartOf <%s> "
+                              "  }"
+                              "}", item_urn, collection_urn);
+  else
+    sparql = g_strdup_printf ("DELETE DATA { "
+                              "  GRAPH tracker:Pictures {"
+                              "    <%s> nie:isPartOf <%s> "
+                              "  }"
+                              "}", item_urn, collection_urn);
   query = photos_query_new (state, sparql);
 
   return query;
@@ -326,17 +360,14 @@ photos_query_builder_set_collection_query (PhotosSearchContextState *state,
 PhotosQuery *
 photos_query_builder_single_query (PhotosSearchContextState *state, gint flags, const gchar *resource)
 {
-  g_autoptr (GRegex) regex = NULL;
   PhotosQuery *query;
-  g_autofree gchar *replacement = NULL;
   g_autofree gchar *sparql = NULL;
-  g_autofree gchar *tmp = NULL;
+  g_autofree gchar *values = NULL;
+
+  values = g_strdup_printf ("VALUES ?urn { <%s> }", resource);
 
-  tmp = photos_query_builder_query (state, FALSE, flags, NULL);
+  sparql = photos_query_builder_query (state, values, flags, NULL);
 
-  regex = g_regex_new ("\\?urn", 0, 0, NULL);
-  replacement = g_strconcat ("<", resource, ">", NULL);
-  sparql = g_regex_replace (regex, tmp, -1, 0, replacement, 0, NULL);
   query = photos_query_new (state, sparql);
 
   return query;
@@ -354,7 +385,14 @@ photos_query_builder_update_mtime_query (PhotosSearchContextState *state, const
   now = g_date_time_new_now_utc ();
   time = g_date_time_format_iso8601 (now);
 
-  sparql = g_strdup_printf ("INSERT OR REPLACE { <%s> nie:contentLastModified '%s' }", resource, time);
+  sparql = g_strdup_printf ("WITH tracker:Pictures "
+                            "DELETE { <%s> nie:contentLastModified ?time } "
+                            "INSERT { "
+                            "  <%s> a nmm:Photo ; "
+                            "    nie:contentLastModified '%s' "
+                            "}"
+                            "WHERE { <%s> nie:contentLastModified ?time }",
+                            resource, resource, time, resource);
   query = photos_query_new (state, sparql);
 
   return query;
diff --git a/src/photos-search-context.c b/src/photos-search-context.c
index 4b503798..6f8694bc 100644
--- a/src/photos-search-context.c
+++ b/src/photos-search-context.c
@@ -31,6 +31,7 @@
 #include "photos-search-match-manager.h"
 #include "photos-search-type-manager.h"
 #include "photos-source-manager.h"
+#include "photos-tracker-queue.h"
 
 
 G_DEFINE_INTERFACE (PhotosSearchContext, photos_search_context, G_TYPE_OBJECT);
@@ -54,6 +55,7 @@ photos_search_context_state_new (PhotosSearchContext *self)
   state->srch_cntrlr = photos_search_controller_new ();
   state->srch_mtch_mngr = photos_search_match_manager_new (state->srch_cntrlr);
   state->srch_typ_mngr = photos_search_type_manager_new ();
+  state->queue = photos_tracker_queue_dup_singleton (NULL, NULL);
 
   return state;
 }
@@ -68,6 +70,7 @@ photos_search_context_state_free (PhotosSearchContextState *state)
   g_object_unref (state->srch_mtch_mngr);
   g_object_unref (state->srch_typ_mngr);
   g_object_unref (state->srch_cntrlr);
+  g_clear_object (&state->queue);
   g_slice_free (PhotosSearchContextState, state);
 }
 
diff --git a/src/photos-search-context.h b/src/photos-search-context.h
index 2af6cf96..5a18d386 100644
--- a/src/photos-search-context.h
+++ b/src/photos-search-context.h
@@ -41,6 +41,7 @@ struct _PhotosSearchContextState
   gpointer srch_typ_mngr;
   gpointer offset_cntrlr;
   gpointer srch_cntrlr;
+  gpointer queue;
 };
 
 PhotosSearchContextState      *photos_search_context_state_new      (PhotosSearchContext *self);
diff --git a/src/photos-search-match-manager.c b/src/photos-search-match-manager.c
index e6dc429a..2ba1fd0f 100644
--- a/src/photos-search-match-manager.c
+++ b/src/photos-search-match-manager.c
@@ -148,7 +148,7 @@ photos_search_match_manager_init (PhotosSearchMatchManager *self)
                   "  tracker:case-fold (tracker:coalesce (nco:fullname (?creator), 
nco:fullname(?publisher))),"
                   "  \"%s\")";
   title_filter = "fn:contains ("
-                 "  tracker:case-fold (tracker:coalesce (nie:title (?urn), nfo:fileName(?urn))),"
+                 "  tracker:case-fold (tracker:coalesce (nie:title (?urn), nfo:fileName(?file))),"
                  "  \"%s\")";
 
   search_match = photos_search_match_new (PHOTOS_SEARCH_MATCH_STOCK_ALL,
diff --git a/src/photos-source.c b/src/photos-source.c
index db6f2de9..5219652c 100644
--- a/src/photos-source.c
+++ b/src/photos-source.c
@@ -62,7 +62,7 @@ G_DEFINE_TYPE_WITH_CODE (PhotosSource, photos_source, G_TYPE_OBJECT,
 DZL_DEFINE_COUNTER (instances, "PhotosSource", "Instances", "Number of PhotosSource instances")
 
 
-static const gchar *TRACKER_SCHEMA = "org.freedesktop.Tracker.Miner.Files";
+static const gchar *TRACKER_SCHEMA = "org.freedesktop.Tracker3.Miner.Files";
 static const gchar *TRACKER_KEY_RECURSIVE_DIRECTORIES = "index-recursive-directories";
 
 
@@ -94,7 +94,7 @@ photos_source_build_filter_local (void)
         continue;
 
       tracker_uri = photos_utils_convert_path_to_uri (tracker_dirs[i]);
-      g_string_append_printf (tracker_filter, " || fn:contains (nie:url (?urn), '%s')", tracker_uri);
+      g_string_append_printf (tracker_filter, " || fn:contains (nie:isStoredAs (?urn), '%s')", tracker_uri);
     }
 
   path = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP);
@@ -109,11 +109,11 @@ photos_source_build_filter_local (void)
   export_path = g_build_filename (path, PHOTOS_EXPORT_SUBPATH, NULL);
   export_uri = photos_utils_convert_path_to_uri (export_path);
 
-  filter = g_strdup_printf ("(((fn:contains (nie:url (?urn), '%s')"
-                            "   || fn:contains (nie:url (?urn), '%s')"
-                            "   || fn:contains (nie:url (?urn), '%s')"
+  filter = g_strdup_printf ("(((fn:contains (nie:isStoredAs (?urn), '%s')"
+                            "   || fn:contains (nie:isStoredAs (?urn), '%s')"
+                            "   || fn:contains (nie:isStoredAs (?urn), '%s')"
                             "   %s)"
-                            "  && !fn:contains (nie:url (?urn), '%s'))"
+                            "  && !fn:contains (nie:isStoredAs (?urn), '%s'))"
                             " || fn:starts-with (nao:identifier (?urn), '%s')"
                             " || (?urn = nfo:image-category-screenshot))",
                             desktop_uri,
@@ -146,7 +146,7 @@ photos_source_build_filter_resource (PhotosSource *self)
 
       root = g_mount_get_root (self->mount);
       uri = g_file_get_uri (root);
-      filter = g_strdup_printf ("(fn:starts-with (nie:url (?urn), '%s'))", uri);
+      filter = g_strdup_printf ("(fn:starts-with (nie:isStoredAs (?urn), '%s'))", uri);
     }
   else
     {
diff --git a/src/photos-tracker-controller.c b/src/photos-tracker-controller.c
index 525e4ee0..54f714e0 100644
--- a/src/photos-tracker-controller.c
+++ b/src/photos-tracker-controller.c
@@ -294,6 +294,12 @@ photos_tracker_controller_perform_current_query (PhotosTrackerController *self)
 
   priv = photos_tracker_controller_get_instance_private (self);
 
+  if (G_UNLIKELY (priv->queue == NULL))
+    {
+      photos_tracker_controller_query_error (self, priv->queue_error);
+      goto out;
+    }
+
   g_clear_object (&priv->current_query);
   priv->current_query = PHOTOS_TRACKER_CONTROLLER_GET_CLASS (self)->get_query (self);
   g_return_if_fail (priv->current_query != NULL);
@@ -305,12 +311,6 @@ photos_tracker_controller_perform_current_query (PhotosTrackerController *self)
   g_object_unref (priv->cancellable);
   priv->cancellable = g_cancellable_new ();
 
-  if (G_UNLIKELY (priv->queue == NULL))
-    {
-      photos_tracker_controller_query_error (self, priv->queue_error);
-      goto out;
-    }
-
   photos_tracker_queue_select (priv->queue,
                                priv->current_query,
                                priv->cancellable,
diff --git a/src/photos-tracker-import-controller.c b/src/photos-tracker-import-controller.c
index 085ace3a..0366b5e8 100644
--- a/src/photos-tracker-import-controller.c
+++ b/src/photos-tracker-import-controller.c
@@ -24,7 +24,6 @@
 #include "config.h"
 
 #include <gio/gio.h>
-#include <libtracker-control/tracker-control.h>
 
 #include "photos-base-manager.h"
 #include "photos-debug.h"
@@ -34,6 +33,8 @@
 #include "photos-query-builder.h"
 #include "photos-search-context.h"
 #include "photos-tracker-import-controller.h"
+#include "photos-tracker-miner-index.h"
+#include "photos-tracker-queue.h"
 #include "photos-utils.h"
 
 
@@ -45,7 +46,7 @@ struct _PhotosTrackerImportController
   PhotosBaseManager *item_mngr;
   PhotosBaseManager *src_mngr;
   PhotosOffsetController *offset_cntrlr;
-  TrackerMinerManager *manager;
+  TrackerMinerFilesIndex *miner_control_proxy;
 };
 
 
@@ -76,12 +77,12 @@ static void
 photos_tracker_import_controller_index (GObject *source_object, GAsyncResult *res, gpointer user_data)
 {
   g_autoptr (GFile) file = G_FILE (user_data);
-  TrackerMinerManager *manager = TRACKER_MINER_MANAGER (source_object);
+  TrackerMinerFilesIndex *miner_control_proxy = TRACKER_MINER_FILES_INDEX (source_object);
 
   {
     g_autoptr (GError) error = NULL;
 
-    if (!tracker_miner_manager_index_file_for_process_finish (manager, res, &error))
+    if (!tracker_miner_files_index_call_index_location_finish (miner_control_proxy, res, &error))
       {
         if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
           {
@@ -102,6 +103,8 @@ photos_tracker_import_controller_next_files (GObject *source_object, GAsyncResul
   GFileEnumerator *enumerator = G_FILE_ENUMERATOR (source_object);
   GList *infos = NULL;
   GList *l;
+  const gchar *tracker_priority_graphs[] = { TRACKER_PICTURES_GRAPH };
+  const gchar *tracker_index_location_flags[] = { };
 
   {
     g_autoptr (GError) error = NULL;
@@ -187,11 +190,13 @@ photos_tracker_import_controller_next_files (GObject *source_object, GAsyncResul
                     if (g_content_type_equals (mime_type, IMPORTABLE_MIME_TYPES[i])
                         || g_content_type_is_a (mime_type, IMPORTABLE_MIME_TYPES[i]))
                       {
-                        tracker_miner_manager_index_file_for_process_async (self->manager,
-                                                                            file,
-                                                                            self->cancellable,
-                                                                            
photos_tracker_import_controller_index,
-                                                                            g_object_ref (file));
+                        tracker_miner_files_index_call_index_location (self->miner_control_proxy,
+                                                                       uri,
+                                                                       tracker_priority_graphs,
+                                                                       tracker_index_location_flags,
+                                                                       self->cancellable,
+                                                                       
photos_tracker_import_controller_index,
+                                                                       g_object_ref (file));
                         indexing = TRUE;
                       }
                   }
@@ -291,28 +296,6 @@ photos_tracker_import_controller_source_active_changed (PhotosTrackerImportContr
     {
       g_return_if_fail (g_queue_is_empty (self->pending_directories));
 
-      if (G_LIKELY (self->manager != NULL))
-        {
-          g_autoptr (GFile) root = NULL;
-          g_autofree gchar *uri = NULL;
-
-          root = g_mount_get_root (mount);
-          g_queue_push_tail (self->pending_directories, g_object_ref (root));
-
-          uri = g_file_get_uri (root);
-          photos_debug (PHOTOS_DEBUG_IMPORT, "Enumerating device directory %s", uri);
-
-          g_file_enumerate_children_async (root,
-                                           G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE","
-                                           G_FILE_ATTRIBUTE_STANDARD_NAME","
-                                           G_FILE_ATTRIBUTE_STANDARD_TYPE,
-                                           G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
-                                           G_PRIORITY_DEFAULT,
-                                           self->cancellable,
-                                           photos_tracker_import_controller_enumerate_children,
-                                           self);
-        }
-
       photos_tracker_controller_refresh_for_object (PHOTOS_TRACKER_CONTROLLER (self));
     }
 }
@@ -379,7 +362,6 @@ photos_tracker_import_controller_dispose (GObject *object)
 
   g_clear_object (&self->src_mngr);
   g_clear_object (&self->offset_cntrlr);
-  g_clear_object (&self->manager);
 
   G_OBJECT_CLASS (photos_tracker_import_controller_parent_class)->dispose (object);
 }
@@ -397,6 +379,39 @@ photos_tracker_import_controller_finalize (GObject *object)
 }
 
 
+static TrackerMinerFilesIndex *
+photos_tracker_import_controller_get_miner_fs_control_proxy (GCancellable *cancellable)
+{
+  g_autoptr (PhotosTrackerQueue) tracker_queue = NULL;
+  const gchar *miner_fs_control_busname;
+  g_autoptr (GError) error = NULL;
+  TrackerMinerFilesIndex *miner_control_proxy;
+
+  tracker_queue = photos_tracker_queue_dup_singleton (cancellable, &error);
+
+  if (!tracker_queue)
+    {
+      g_warning ("Error getting Tracker queue: %s. Import will not work.", error->message);
+      return NULL;
+    }
+
+  miner_fs_control_busname = photos_tracker_queue_get_miner_fs_control_busname (tracker_queue);
+  miner_control_proxy = tracker_miner_files_index_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+                                                                          G_DBUS_PROXY_FLAGS_NONE,
+                                                                          miner_fs_control_busname,
+                                                                          
"/org/freedesktop/Tracker3/Miner/Files/Control",
+                                                                          NULL,
+                                                                          &error);
+  if (!miner_control_proxy)
+    {
+      g_warning ("Error getting Tracker Miner FS control proxy: %s. Import will not work", error->message);
+      return NULL;
+    }
+
+  return miner_control_proxy;
+}
+
+
 static void
 photos_tracker_import_controller_init (PhotosTrackerImportController *self)
 {
@@ -421,13 +436,7 @@ photos_tracker_import_controller_init (PhotosTrackerImportController *self)
 
   self->offset_cntrlr = photos_offset_import_controller_dup_singleton ();
 
-  {
-    g_autoptr (GError) error = NULL;
-
-    self->manager = tracker_miner_manager_new_full (FALSE, &error);
-    if (error != NULL)
-      g_warning ("Unable to create a TrackerMinerManager, indexing attached devices won't work: %s", 
error->message);
-  }
+  self->miner_control_proxy = photos_tracker_import_controller_get_miner_fs_control_proxy (NULL);
 }
 
 
diff --git a/src/photos-tracker-queue.c b/src/photos-tracker-queue.c
index 6ac829cd..a5f4c91a 100644
--- a/src/photos-tracker-queue.c
+++ b/src/photos-tracker-queue.c
@@ -37,9 +37,20 @@ struct _PhotosTrackerQueue
   GObject parent_instance;
   GError *initialization_error;
   GQueue *queue;
-  TrackerSparqlConnection *connection;
+  TrackerSparqlConnection *local_connection;
+  TrackerSparqlConnection *miner_fs_connection;
   gboolean is_initialized;
   gboolean running;
+  gboolean miner_fs_ready;
+  const gchar *miner_fs_busname;
+  const gchar *miner_fs_control_busname;
+};
+
+enum
+{
+  PROP_0,
+  PROP_MINER_FS_READY,
+  PROP_MINER_FS_BUSNAME
 };
 
 static void photos_tracker_queue_initable_iface_init (GInitableIface *iface);
@@ -90,7 +101,6 @@ photos_tracker_queue_data_free (PhotosTrackerQueueData *data)
 
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (PhotosTrackerQueueData, photos_tracker_queue_data_free);
 
-
 static PhotosTrackerQueueData *
 photos_tracker_queue_data_new (PhotosQuery *query,
                                PhotosTrackerQueryType query_type,
@@ -179,7 +189,7 @@ photos_tracker_queue_check (PhotosTrackerQueue *self)
   switch (data->query_type)
     {
     case PHOTOS_TRACKER_QUERY_SELECT:
-      tracker_sparql_connection_query_async (self->connection,
+      tracker_sparql_connection_query_async (self->local_connection,
                                              sparql,
                                              data->cancellable,
                                              photos_tracker_queue_collector,
@@ -187,18 +197,16 @@ photos_tracker_queue_check (PhotosTrackerQueue *self)
       break;
 
     case PHOTOS_TRACKER_QUERY_UPDATE:
-      tracker_sparql_connection_update_async (self->connection,
+      tracker_sparql_connection_update_async (self->local_connection,
                                               sparql,
-                                              G_PRIORITY_DEFAULT,
                                               data->cancellable,
                                               photos_tracker_queue_collector,
                                               g_object_ref (self));
       break;
 
     case PHOTOS_TRACKER_QUERY_UPDATE_BLANK:
-      tracker_sparql_connection_update_blank_async (self->connection,
+      tracker_sparql_connection_update_blank_async (self->local_connection,
                                                     sparql,
-                                                    G_PRIORITY_DEFAULT,
                                                     data->cancellable,
                                                     photos_tracker_queue_collector,
                                                     g_object_ref (self));
@@ -211,6 +219,53 @@ photos_tracker_queue_check (PhotosTrackerQueue *self)
 }
 
 
+static gboolean
+photos_tracker_queue_start_session_miner_fs (PhotosTrackerQueue *self, GError **error)
+{
+  const gchar *busname = "org.freedesktop.Tracker3.Miner.Files";
+  const gchar *control_busname = "org.freedesktop.Tracker3.Miner.Files.Control";
+
+  photos_debug (PHOTOS_DEBUG_TRACKER, "Connecting to %s", busname);
+  self->miner_fs_connection = tracker_sparql_connection_bus_new (busname, NULL, NULL, error);
+  if (*error)
+    {
+      g_warning ("Unable to create connection for session-wide Tracker indexer at %s: %s", busname, 
(*error)->message);
+      return FALSE;
+    }
+
+  self->miner_fs_busname = busname;
+  self->miner_fs_control_busname = control_busname;
+
+  return TRUE;
+}
+
+
+static gboolean
+photos_tracker_queue_start_local_miner_fs (PhotosTrackerQueue *self, GError **error)
+{
+  const gchar *busname = "org.gnome.Photos.Tracker3.Miner.Files";
+  const gchar *control_busname = "org.gnome.Photos.Tracker3.Miner.Files.Control";
+
+  photos_debug (PHOTOS_DEBUG_TRACKER, "Connecting to %s", busname);
+  self->miner_fs_connection = tracker_sparql_connection_bus_new (busname, NULL, NULL, error);
+  if (*error)
+    {
+      g_critical ("Could not start local Tracker indexer at %s: %s", busname, (*error)->message);
+      return FALSE;
+    }
+
+  self->miner_fs_busname = busname;
+  self->miner_fs_control_busname = control_busname;
+
+  return TRUE;
+}
+
+static gboolean
+inside_flatpak (void)
+{
+    return g_file_test ("/.flatpak-info", G_FILE_TEST_EXISTS);
+}
+
 static GObject *
 photos_tracker_queue_constructor (GType type, guint n_construct_params, GObjectConstructParam 
*construct_params)
 {
@@ -234,7 +289,8 @@ photos_tracker_queue_dispose (GObject *object)
 {
   PhotosTrackerQueue *self = PHOTOS_TRACKER_QUEUE (object);
 
-  g_clear_object (&self->connection);
+  g_clear_object (&self->local_connection);
+  g_clear_object (&self->miner_fs_connection);
 
   G_OBJECT_CLASS (photos_tracker_queue_parent_class)->dispose (object);
 }
@@ -258,6 +314,38 @@ photos_tracker_queue_init (PhotosTrackerQueue *self)
   self->queue = g_queue_new ();
 }
 
+static void
+photos_tracker_queue_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+  PhotosTrackerQueue *self = PHOTOS_TRACKER_QUEUE (object);
+
+  switch (prop_id)
+    {
+    case PROP_MINER_FS_READY:
+      g_value_set_boolean (value, self->miner_fs_ready);
+      break;
+
+    case PROP_MINER_FS_BUSNAME:
+      g_value_set_string (value, self->miner_fs_busname);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+photos_tracker_queue_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+  switch (prop_id)
+    {
+    /* All properties are read only */
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
 
 static void
 photos_tracker_queue_class_init (PhotosTrackerQueueClass *class)
@@ -267,6 +355,24 @@ photos_tracker_queue_class_init (PhotosTrackerQueueClass *class)
   object_class->constructor = photos_tracker_queue_constructor;
   object_class->dispose = photos_tracker_queue_dispose;
   object_class->finalize = photos_tracker_queue_finalize;
+  object_class->get_property = photos_tracker_queue_get_property;
+  object_class->set_property = photos_tracker_queue_set_property;
+
+  g_object_class_install_property (object_class,
+                                   PROP_MINER_FS_READY,
+                                   g_param_spec_boolean ("tracker-miner-fs-ready",
+                                                         "Tracker Miner FS ready",
+                                                         "TRUE if it is possible to query Tracker indexer",
+                                                         FALSE,
+                                                         G_PARAM_READABLE));
+
+  g_object_class_install_property (object_class,
+                                   PROP_MINER_FS_BUSNAME,
+                                   g_param_spec_string ("tracker-miner-fs-busname",
+                                                        "Tracker Miner FS busname",
+                                                        "D-Bus name of the Tracker indexer daemon",
+                                                        "",
+                                                        G_PARAM_READABLE));
 }
 
 
@@ -274,13 +380,16 @@ static gboolean
 photos_tracker_queue_initable_init (GInitable *initable, GCancellable *cancellable, GError **error)
 {
   PhotosTrackerQueue *self = PHOTOS_TRACKER_QUEUE (initable);
+  TrackerSparqlConnectionFlags tracker_flags;
+  g_autoptr (GFile) store = NULL;
   gboolean ret_val = FALSE;
+  gboolean miner_ok = FALSE;
 
   G_LOCK (init_lock);
 
   if (self->is_initialized)
     {
-      if (self->connection != NULL)
+      if (self->local_connection != NULL && self->miner_fs_connection != NULL)
         ret_val = TRUE;
       else
         g_assert_nonnull (self->initialization_error);
@@ -290,11 +399,49 @@ photos_tracker_queue_initable_init (GInitable *initable, GCancellable *cancellab
 
   g_assert_no_error (self->initialization_error);
 
-  self->connection = tracker_sparql_connection_get (cancellable, &self->initialization_error);
+  /* Connect to the local database which stores user data.
+   *
+   * Same flags that tracker-miner-fs uses by default. See:
+   * https://gitlab.gnome.org/GNOME/tracker-miners/-/blob/master/src/miners/fs/tracker-main.c#L735 and
+   * 
https://gitlab.gnome.org/GNOME/tracker-miners/-/blob/master/data/org.freedesktop.Tracker.FTS.gschema.xml */
+  tracker_flags = TRACKER_SPARQL_CONNECTION_FLAGS_FTS_ENABLE_UNACCENT |
+                  TRACKER_SPARQL_CONNECTION_FLAGS_FTS_ENABLE_STOP_WORDS |
+                  TRACKER_SPARQL_CONNECTION_FLAGS_FTS_IGNORE_NUMBERS;
+
+  store = g_file_new_build_filename (g_get_user_data_dir (), "gnome-photos", NULL);
+
+  photos_debug (PHOTOS_DEBUG_TRACKER, "Opening local database at %s", g_file_peek_path (store));
+  self->local_connection = tracker_sparql_connection_new (tracker_flags,
+                                                          store,
+                                                          tracker_sparql_get_ontology_nepomuk (),
+                                                          cancellable,
+                                                          &self->initialization_error);
+
   if (G_UNLIKELY (self->initialization_error != NULL))
     goto out;
 
-  ret_val = TRUE;
+  /* Connect to filesystem indexer. */
+  miner_ok = photos_tracker_queue_start_session_miner_fs (self, &self->initialization_error);
+
+  if (!miner_ok && inside_flatpak ())
+    {
+      g_clear_error (&self->initialization_error);
+      miner_ok = photos_tracker_queue_start_local_miner_fs (self, &self->initialization_error);
+    }
+
+  if (miner_ok)
+    {
+      photos_debug (PHOTOS_DEBUG_TRACKER, "Using %s as tracker-miner-fs", self->miner_fs_busname);
+      ret_val = TRUE;
+    }
+  else
+    {
+      photos_debug (PHOTOS_DEBUG_TRACKER, "Initialization failed due to %s", 
self->initialization_error->message);
+      g_clear_object (&self->miner_fs_connection);
+      g_clear_object (&self->local_connection);
+      ret_val = FALSE;
+    }
+
 
  out:
   self->is_initialized = TRUE;
@@ -319,10 +466,44 @@ photos_tracker_queue_initable_iface_init (GInitableIface *iface)
 PhotosTrackerQueue *
 photos_tracker_queue_dup_singleton (GCancellable *cancellable, GError **error)
 {
+  GObject *singleton;
+
   g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
-  return g_initable_new (PHOTOS_TYPE_TRACKER_QUEUE, cancellable, error, NULL);
+  singleton = g_object_new (PHOTOS_TYPE_TRACKER_QUEUE, NULL);
+
+  if (g_initable_init (G_INITABLE (singleton), cancellable, error))
+      return PHOTOS_TRACKER_QUEUE (singleton);
+
+  /* On error we deliberately don't unref the object so that we won't try
+   * and re-initialize Tracker when called again.
+   */
+  return NULL;
+}
+
+
+const gchar *
+photos_tracker_queue_get_miner_fs_busname (PhotosTrackerQueue *self)
+{
+  return self->miner_fs_busname;
+}
+
+
+const gchar *
+photos_tracker_queue_get_miner_fs_control_busname (PhotosTrackerQueue *self)
+{
+  return self->miner_fs_control_busname;
+}
+
+
+TrackerNotifier *
+photos_tracker_queue_get_notifier (PhotosTrackerQueue *self)
+{
+  /* We want notifications on filesystem changes, we don't need them for the
+   * local database which we manage ourselves.
+   */
+  return tracker_sparql_connection_create_notifier (self->miner_fs_connection);
 }
 
 
@@ -351,6 +532,7 @@ photos_tracker_queue_select (PhotosTrackerQueue *self,
 }
 
 
+
 void
 photos_tracker_queue_update (PhotosTrackerQueue *self,
                              PhotosQuery *query,
diff --git a/src/photos-tracker-queue.h b/src/photos-tracker-queue.h
index 93d97306..6e31ecf6 100644
--- a/src/photos-tracker-queue.h
+++ b/src/photos-tracker-queue.h
@@ -24,16 +24,23 @@
 #define PHOTOS_TRACKER_QUEUE_H
 
 #include <gio/gio.h>
+#include <libtracker-sparql/tracker-sparql.h>
 
 #include "photos-query.h"
 
 G_BEGIN_DECLS
 
+#define TRACKER_PICTURES_GRAPH "http://tracker.api.gnome.org/ontology/v3/tracker#Pictures";
+
 #define PHOTOS_TYPE_TRACKER_QUEUE (photos_tracker_queue_get_type ())
 G_DECLARE_FINAL_TYPE (PhotosTrackerQueue, photos_tracker_queue, PHOTOS, TRACKER_QUEUE, GObject);
 
 PhotosTrackerQueue    *photos_tracker_queue_dup_singleton          (GCancellable *cancellable, GError 
**error);
 
+const gchar *          photos_tracker_queue_get_miner_fs_busname         (PhotosTrackerQueue *self);
+const gchar *          photos_tracker_queue_get_miner_fs_control_busname (PhotosTrackerQueue *self);
+TrackerNotifier *      photos_tracker_queue_get_notifier                 (PhotosTrackerQueue *self);
+
 void                   photos_tracker_queue_select                 (PhotosTrackerQueue *self,
                                                                     PhotosQuery *query,
                                                                     GCancellable *cancellable,
diff --git a/src/photos-utils.c b/src/photos-utils.c
index 1d7be577..4e65f9f8 100644
--- a/src/photos-utils.c
+++ b/src/photos-utils.c
@@ -1323,7 +1323,13 @@ photos_utils_set_edited_name (const gchar *urn, const gchar *title)
   g_autoptr (PhotosTrackerQueue) queue = NULL;
   g_autofree gchar *sparql = NULL;
 
-  sparql = g_strdup_printf ("INSERT OR REPLACE { <%s> nie:title \"%s\" }", urn, title);
+  sparql = g_strdup_printf ("WITH tracker:Pictures "
+                            "DELETE { <%s> nie:title ?title } "
+                            "INSERT { "
+                            "  <%s> a nmm:Photo ; "
+                            "    nie:title \"%s\" . "
+                            "}"
+                            "WHERE { <%s> nie:title ?title }", urn, urn, title, urn);
   query = photos_query_new (NULL, sparql);
 
   {
@@ -1351,9 +1357,19 @@ photos_utils_set_favorite (const gchar *urn, gboolean is_favorite)
   g_autoptr (PhotosTrackerQueue) queue = NULL;
   g_autofree gchar *sparql = NULL;
 
-  sparql = g_strdup_printf ("%s { <%s> nao:hasTag nao:predefined-tag-favorite }",
-                            (is_favorite) ? "INSERT OR REPLACE" : "DELETE",
-                            urn);
+  if (is_favorite)
+    sparql = g_strdup_printf ("INSERT DATA { "
+                              "  GRAPH tracker:Pictures {"
+                              "    <%s> a nmm:Photo ; "
+                              "      nao:hasTag nao:predefined-tag-favorite "
+                              "  } "
+                              "}", urn);
+  else
+    sparql = g_strdup_printf ("DELETE DATA {"
+                              "  GRAPH tracker:Pictures {"
+                              "    <%s> nao:hasTag nao:predefined-tag-favorite "
+                              "  } "
+                              "}", urn);
   query = photos_query_new (NULL, sparql);
 
   {
diff --git a/src/photos-utils.h b/src/photos-utils.h
index a4d69abf..57069892 100644
--- a/src/photos-utils.h
+++ b/src/photos-utils.h
@@ -46,7 +46,7 @@ G_BEGIN_DECLS
 #define PHOTOS_TRACKER_CONTROLLER_EXTENSION_POINT_NAME "photos-tracker-controller"
 
 #define PHOTOS_COLLECTION_SCREENSHOT \
-  "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#image-category-screenshot";
+  "http://tracker.api.gnome.org/ontology/v3/nfo#image-category-screenshot";
 #define PHOTOS_EXPORT_SUBPATH "Exports"
 
 typedef enum
diff --git a/src/queries/all.sparql.template b/src/queries/all.sparql.template
index 1cef98e8..14e08027 100644
--- a/src/queries/all.sparql.template
+++ b/src/queries/all.sparql.template
@@ -1,30 +1,42 @@
-SELECT {{projection}}
+SELECT {{final_projection}}
+FROM NAMED tracker:Pictures
 {
     {
-        SELECT {{projection}}
+        SELECT {{main_projection}}
         {
             {
                 SELECT ?urn COUNT(?item) AS ?count
                 {
+                    {{values}}
+                    VALUES (?file ?filename ?creator ?publisher) { ("" "" "" "") }
                     ?urn a nfo:DataContainer.
-                    ?item a nmm:Photo; nie:isPartOf ?urn.
-                } GROUP BY ?urn
+                    ?item a nmm:Photo ;
+                       nie:isPartOf ?urn .
+                    {{item_pattern}}
+                }
+                GROUP BY ?urn
             }
             FILTER (?count > 0 && {{collections_default_filter}} && {{search_filter}})
         }
-        GROUP BY ?urn
     }
     UNION
     {
-        SELECT {{projection}}
+        SELECT {{second_projection}}
         {
-            ?urn a nmm:Photo .
-            OPTIONAL { ?urn nco:creator ?creator . }
-            OPTIONAL { ?urn nco:publisher ?publisher . }
             {{item_pattern}}
-            FILTER ({{photos_default_filter}} && {{source_filter}} && {{search_filter}})
+            SERVICE <dbus:{{miner_fs_busname}}>
+            {
+                SELECT {{main_projection}}
+                {
+                    {{values}}
+                    ?urn a nmm:Photo ;
+                        nie:isStoredAs ?file .
+                    OPTIONAL { ?urn nco:creator ?creator . }
+                    OPTIONAL { ?urn nco:publisher ?publisher . }
+                    FILTER ({{photos_default_filter}} && {{source_filter}} && {{search_filter}})
+                }
+            }
         }
-        GROUP BY ?urn
     }
 }
 {{order}}
diff --git a/src/queries/collections.sparql.template b/src/queries/collections.sparql.template
index 20b35cd6..4dfb345a 100644
--- a/src/queries/collections.sparql.template
+++ b/src/queries/collections.sparql.template
@@ -1,14 +1,20 @@
-SELECT {{projection}}
+SELECT {{final_projection}}
 {
+    SELECT {{main_projection}}
     {
-        SELECT ?urn COUNT(?item) AS ?count
         {
-            ?urn a nfo:DataContainer.
-            ?item a nmm:Photo; nie:isPartOf ?urn.
-        } GROUP BY ?urn
+            SELECT ?urn COUNT(?item) AS ?count
+            {
+                {{values}}
+                VALUES (?file ?filename ?creator ?publisher) { ("" "" "" "") }
+                ?urn a nfo:DataContainer .
+                ?item a nmm:Photo ;
+                   nie:isPartOf ?urn .
+            }
+            GROUP BY ?urn
+        }
+        FILTER (?count > 0 && {{collections_default_filter}} && {{search_filter}})
     }
-    FILTER (?count > 0 && {{collections_default_filter}} && {{search_filter}})
 }
-GROUP BY ?urn
 {{order}}
 {{offset_limit}}
diff --git a/src/queries/favorite-photos.sparql.template b/src/queries/favorite-photos.sparql.template
index 0885a08a..9a0d7806 100644
--- a/src/queries/favorite-photos.sparql.template
+++ b/src/queries/favorite-photos.sparql.template
@@ -1,12 +1,20 @@
-SELECT {{projection}}
+SELECT {{final_projection}}
+FROM tracker:Pictures
 {
     ?urn a nmm:Photo .
     ?urn a nmm:Photo; nao:hasTag nao:predefined-tag-favorite .
-    OPTIONAL { ?urn nco:creator ?creator . }
-    OPTIONAL { ?urn nco:publisher ?publisher . }
-    {{item_pattern}}
-    FILTER ({{photos_default_filter}} && {{source_filter}} && {{search_filter}})
+    SERVICE <dbus:{{miner_fs_busname}}>
+    {
+        SELECT {{main_projection}}
+        {
+            ?urn a nmm:Photo ;
+                nie:isStoredAs ?file .
+            OPTIONAL { ?urn nco:creator ?creator . }
+            OPTIONAL { ?urn nco:publisher ?publisher . }
+            {{item_pattern}}
+            FILTER ({{photos_default_filter}} && {{source_filter}} && {{search_filter}})
+        }
+    }
 }
-GROUP BY ?urn
 {{order}}
 {{offset_limit}}
diff --git a/src/queries/photos.sparql.template b/src/queries/photos.sparql.template
index 4eb10b74..6ade35e2 100644
--- a/src/queries/photos.sparql.template
+++ b/src/queries/photos.sparql.template
@@ -1,11 +1,19 @@
-SELECT {{projection}}
+SELECT {{final_projection}}
+FROM tracker:Pictures
 {
-    ?urn a nmm:Photo .
-    OPTIONAL { ?urn nco:creator ?creator . }
-    OPTIONAL { ?urn nco:publisher ?publisher . }
-    {{item_pattern}}
-    FILTER ({{photos_default_filter}} && {{source_filter}} && {{search_filter}})
+    SERVICE <dbus:{{miner_fs_busname}}>
+    {
+        SELECT {{main_projection}}
+        {
+            {{values}}
+            ?urn a nmm:Photo ;
+                nie:isStoredAs ?file .
+            OPTIONAL { ?urn nco:creator ?creator . }
+            OPTIONAL { ?urn nco:publisher ?publisher . }
+            {{item_pattern}}
+            FILTER ({{photos_default_filter}} && {{source_filter}} && {{search_filter}})
+        }
+    }
 }
-GROUP BY ?urn
 {{order}}
 {{offset_limit}}


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