[gnome-photos/wip/rishi/tracker3] Port to Tracker 3




commit 9a015c793ea7df4044da1db123743876021b3995
Author: Sam Thursfield <sam afuera me uk>
Date:   Thu Mar 4 21:04:07 2021 +0100

    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
        filesystem miner's index of items at query time.
    
      * Inside Flatpak, the application 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 private instance of Tracker 3's
        filesystem miner when running on hosts without Tracker 3.
    
    Currently, nfo:fileName is absent from the tracker:Pictures graph [1],
    which leads to the following WARNING:
      gnome-photos-WARNING **: (../src/photos-local-item.c:91):
        photos_local_item_create_filename_fallback: code should not be
        reached
    
    Similarly, the built-in nfo:image-category-screenshot collection is
    also missing.
    
    [1] https://gitlab.gnome.org/GNOME/tracker/-/issues/221
    
    https://gitlab.gnome.org/GNOME/gnome-photos/-/issues/152

 data/meson.build                                   |   7 +-
 ....gnome.Photos.Tracker1.Miner.Extract.service.in |   8 -
 ...rg.gnome.Photos.Tracker1.Miner.Files.service.in |   8 -
 data/org.gnome.Photos.Tracker1.service.in          |   3 -
 ....gnome.Photos.Tracker3.Miner.Extract.service.in |   3 +
 ...rg.gnome.Photos.Tracker3.Miner.Files.service.in |   3 +
 data/org.gnome.Photos.rule.in                      |  12 +-
 flatpak/org.gnome.Photos.json                      |  44 +---
 meson.build                                        |   3 +-
 meson_post_install.py                              |   4 +-
 src/meson.build                                    |  15 +-
 src/org.freedesktop.Tracker3.Miner.Files.Index.xml |  11 +
 src/org.freedesktop.Tracker3.Miner.xml             |  56 +++++
 src/photos-application.c                           | 258 ++++++++++-----------
 src/photos-application.h                           |   5 +
 src/photos-base-item.c                             |   2 +-
 src/photos-indexing-notification.c                 | 118 +++++++---
 src/photos-item-manager.c                          |  55 +++--
 src/photos-item-manager.h                          |   3 +
 src/photos-quarks.c                                |  20 +-
 src/photos-query-all.sparql.template               |  73 ++++--
 src/photos-query-builder.c                         | 210 +++++++++++++----
 src/photos-query-collections.sparql.template       |  50 +++-
 src/photos-query-favorites.sparql.template         |  18 +-
 src/photos-query-photos.sparql.template            |  19 +-
 src/photos-search-match-manager.c                  |   2 +-
 src/photos-source.c                                |  14 +-
 src/photos-tracker-extract-priority.xml            |  30 ---
 src/photos-tracker-import-controller.c             |  37 +--
 src/photos-tracker-queue.c                         |  43 +++-
 src/photos-tracker-queue.h                         |   3 +
 src/photos-utils.c                                 |  28 ++-
 src/photos-utils.h                                 |   4 +-
 33 files changed, 752 insertions(+), 417 deletions(-)
---
diff --git a/data/meson.build b/data/meson.build
index 279dd536..96201dad 100644
--- a/data/meson.build
+++ b/data/meson.build
@@ -56,13 +56,12 @@ configure_file(
   output: domain_ontology_rule,
   configuration: tracker_domain_conf,
   install: true,
-  install_dir: join_paths(photos_datadir, 'tracker', 'domain-ontologies'),
+  install_dir: join_paths(photos_datadir, 'tracker3-miners', 'domain-ontologies'),
 )
 
 tracker_domain_services = [
-  'Tracker1',
-  'Tracker1.Miner.Extract',
-  'Tracker1.Miner.Files'
+  'Tracker3.Miner.Extract',
+  'Tracker3.Miner.Files'
 ]
 
 foreach service: tracker_domain_services
diff --git a/data/org.gnome.Photos.Tracker3.Miner.Extract.service.in 
b/data/org.gnome.Photos.Tracker3.Miner.Extract.service.in
new file mode 100644
index 00000000..54624264
--- /dev/null
+++ b/data/org.gnome.Photos.Tracker3.Miner.Extract.service.in
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=@application_id@.Tracker3.Miner.Extract
+Exec=@libexecdir@/tracker-extract-3 --domain-ontology @application_id@
diff --git a/data/org.gnome.Photos.Tracker3.Miner.Files.service.in 
b/data/org.gnome.Photos.Tracker3.Miner.Files.service.in
new file mode 100644
index 00000000..427d5d1c
--- /dev/null
+++ b/data/org.gnome.Photos.Tracker3.Miner.Files.service.in
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=@application_id@.Tracker3.Miner.Files
+Exec=@libexecdir@/tracker-miner-fs-3 --initial-sleep=0 --domain-ontology @application_id@
diff --git a/data/org.gnome.Photos.rule.in b/data/org.gnome.Photos.rule.in
index 38a4c397..bd908499 100644
--- a/data/org.gnome.Photos.rule.in
+++ b/data/org.gnome.Photos.rule.in
@@ -1,3 +1,7 @@
+# This is 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]
 # All locations accept
 # 1) Paths relative from a variable, the variables
@@ -14,14 +18,10 @@
 #
 
 # Location for the Tracker database (not optional)
-CacheLocation=$XDG_CACHE_HOME/gnome-photos/tracker
-
-# Location for the data journal, used in data recovery
-# situations (optional)
-JournalLocation=$XDG_DATA_HOME/gnome-photos/tracker/data
+CacheLocation=$XDG_CACHE_HOME/gnome-photos/tracker3/files
 
 # Name of the ontology to use, must be one located in
-# $(sharedir)/tracker/ontologies
+# $(sharedir)/tracker3/ontologies
 OntologyName=nepomuk
 
 # DBus name for the owner (not optional). Tracker will use
diff --git a/flatpak/org.gnome.Photos.json b/flatpak/org.gnome.Photos.json
index fe5c0e46..a7a3bae8 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,50 +264,19 @@
                 }
             ]
         },
-        {
-            "name": "tracker",
-            "buildsystem": "meson",
-            "cleanup": [ "/bin", "/etc", "/lib/girepository-1.0", "/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",
-                         "/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/glib-2.0/schemas/org.freedesktop.Tracker.Writeback.gschema.xml" ],
-            "config-opts": [ "-Dextract=true",
+            "cleanup": [ "/etc", "/share/dbus-1" ],
+            "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"
+                    "url": "https://gitlab.gnome.org/GNOME/tracker-miners.git";
                 }
             ]
         },
diff --git a/meson.build b/meson.build
index a949382c..2e290caf 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.1.90')
 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/meson_post_install.py b/meson_post_install.py
index 298a390e..ab3411cb 100644
--- a/meson_post_install.py
+++ b/meson_post_install.py
@@ -30,9 +30,9 @@ if not destdir:
     subprocess.call(['glib-compile-schemas', schemadir])
 
 dbusservicesdir = sys.argv[2]
-trackerdir = os.path.join(datadir, 'tracker', 'miners')
+trackerdir = os.path.join(datadir, 'tracker3', 'miners')
 
-miners = ["org.gnome.Photos.Tracker1.Miner.Extract.service", "org.gnome.Photos.Tracker1.Miner.Files.service"]
+miners = ["org.gnome.Photos.Tracker3.Miner.Extract.service", "org.gnome.Photos.Tracker3.Miner.Files.service"]
 
 os.makedirs(trackerdir, exist_ok=True)
 for miner in miners:
diff --git a/src/meson.build b/src/meson.build
index e25fb077..154f7d52 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -365,12 +365,18 @@ sources += gnome.gdbus_codegen(
   autocleanup: 'all',
 )
 
-tracker_extract_priority = 'photos-tracker-extract-priority'
+sources += gnome.gdbus_codegen(
+  'photos-tracker-miner',
+  'org.freedesktop.Tracker3.Miner.xml',
+  interface_prefix: 'org.freedesktop.Tracker3.',
+  namespace: 'Tracker',
+  autocleanup: 'all',
+)
 
 sources += gnome.gdbus_codegen(
-  tracker_extract_priority,
-  tracker_extract_priority + '.xml',
-  interface_prefix: 'org.freedesktop.Tracker1.',
+  'photos-tracker-miner-files-index',
+  'org.freedesktop.Tracker3.Miner.Files.Index.xml',
+  interface_prefix: 'org.freedesktop.Tracker3.',
   namespace: 'Tracker',
   autocleanup: 'all',
 )
@@ -390,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 09b2fbaf..a0122752 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 <tracker-sparql.h>
 
 #include "photos-application.h"
@@ -70,7 +69,7 @@
 #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-queue.h"
 #include "photos-utils.h"
 
 
@@ -129,10 +128,12 @@ struct _PhotosApplication
   PhotosSearchProvider *search_provider;
   PhotosSelectionController *sel_cntrlr;
   PhotosThumbnailFactory *factory;
-  TrackerMinerManager *miner_manager;
-  TrackerExtractPriority *extract_priority;
+  PhotosTrackerQueue *queue;
+  TrackerMinerFilesIndex *miner_files_index;
+  TrackerSparqlConnection *miner_files_connection;
   gboolean empty_results;
   gboolean main_window_deleted;
+  const gchar *miner_files_name;
   guint create_miners_count;
   guint init_fishes_id;
   guint use_count;
@@ -176,7 +177,11 @@ static const gchar *DESKTOP_KEY_PICTURE_OPTIONS = "picture-options";
 static const gchar *DESKTOP_KEY_COLOR_SHADING_TYPE = "color-shading-type";
 static const gchar *DESKTOP_KEY_PRIMARY_COLOR = "primary-color";
 static const gchar *DESKTOP_KEY_SECONDARY_COLOR = "secondary-color";
-static const gchar *MINER_FILES = "org.gnome.Photos.Tracker1.Miner.Files";
+static const gchar *MINER_FILES_NAME_PRIVATE = "org.gnome.Photos.Tracker3.Miner.Files";
+static const gchar *MINER_FILES_NAME_PRIVATE_CONTROL = "org.gnome.Photos.Tracker3.Miner.Files.Control";
+static const gchar *MINER_FILES_NAME_SESSION = "org.freedesktop.Tracker3.Miner.Files";
+static const gchar *MINER_FILES_NAME_SESSION_CONTROL = "org.freedesktop.Tracker3.Miner.Files.Control";
+static const gchar *MINER_FILES_OBJECT_PATH_CONTROL = "/org/freedesktop/Tracker3/Miner/Files/Control";
 
 typedef struct _PhotosApplicationCreateData PhotosApplicationCreateData;
 typedef struct _PhotosApplicationImportData PhotosApplicationImportData;
@@ -584,27 +589,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)
 {
@@ -641,16 +625,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);
-    }
 }
 
 
@@ -740,60 +714,6 @@ 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)
-{
-  PhotosApplication *self = PHOTOS_APPLICATION (user_data);
-  TrackerExtractPriority *extract_priority = TRACKER_EXTRACT_PRIORITY (source_object);
-
-  {
-    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));
-}
-
-
-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);
-
- out:
-  g_application_release (G_APPLICATION (self));
-}
-
-
 static gboolean
 photos_application_create_window (PhotosApplication *self)
 {
@@ -813,6 +733,8 @@ photos_application_create_window (PhotosApplication *self)
   gexiv2_registered_namespace = gexiv2_metadata_register_xmp_namespace ("http://www.gnome.org/xmp";, "gnome");
   g_return_val_if_fail (gexiv2_registered_namespace, FALSE);
 
+  photos_application_start_miners (self);
+
   self->main_window = photos_main_window_new (GTK_APPLICATION (self));
   g_signal_connect_object (self->main_window,
                            "delete-event",
@@ -827,16 +749,6 @@ photos_application_create_window (PhotosApplication *self)
   if (self->init_fishes_id == 0)
     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.gnome.Photos.Tracker1.Miner.Extract",
-                                              "/org/freedesktop/Tracker1/Extract/Priority",
-                                              self->create_window_cancellable,
-                                              photos_application_tracker_extract_priority,
-                                              self);
-
-  photos_application_start_miners (self);
   return TRUE;
 }
 
@@ -1113,18 +1025,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_files_index = 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_files_index, res, &error))
       {
         g_autofree gchar *uri = NULL;
 
@@ -1346,6 +1258,8 @@ photos_application_import_file_copy (GObject *source_object, GAsyncResult *res,
     }
   else
     {
+      const gchar *tracker_priority_graphs[] = { PHOTOS_PICTURES_GRAPH };
+      const gchar *tracker_index_location_flags[] = { };
       g_autofree gchar *destination_uri = NULL;
 
       g_assert_true (G_IS_FILE (destination));
@@ -1363,11 +1277,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 (self->miner_manager,
-                                                          destination,
-                                                          NULL,
-                                                          photos_application_import_index_file,
-                                                          g_object_ref (destination));
+      tracker_miner_files_index_call_index_location (self->miner_files_index,
+                                                     destination_uri,
+                                                     tracker_priority_graphs,
+                                                     tracker_index_location_flags,
+                                                     NULL,
+                                                     photos_application_import_index_location,
+                                                     g_object_ref (destination));
     }
 
  out:
@@ -1531,9 +1447,9 @@ photos_application_import (PhotosApplication *self)
   selection = photos_selection_controller_get_selection (self->sel_cntrlr);
   g_return_if_fail (selection != NULL);
 
-  if (self->miner_manager == NULL)
+  if (self->miner_files_index == NULL)
     {
-      g_warning ("No TrackerMinerManager, importing from attached devices won't work");
+      g_warning ("No TrackerMinerFilesIndex proxy, importing from attached devices won't work");
       goto out;
     }
 
@@ -2234,36 +2150,80 @@ photos_application_share_current (PhotosApplication *self)
 
 
 static void
-photos_application_start_miners (PhotosApplication *self)
+photos_application_start_miners_local (PhotosApplication *self)
 {
+  GDBusConnection *dbus_connection;
+  g_autoptr (TrackerNotifier) notifier = NULL;
+  const gchar *control_name;
+
+  self->miner_files_name = MINER_FILES_NAME_SESSION;
+  control_name = MINER_FILES_NAME_SESSION_CONTROL;
+  photos_debug (PHOTOS_DEBUG_TRACKER, "Connecting to %s", self->miner_files_name);
+
   {
     g_autoptr (GError) error = NULL;
 
-    self->miner_manager = tracker_miner_manager_new_full (TRUE, &error);
+    self->miner_files_connection = tracker_sparql_connection_bus_new (self->miner_files_name, NULL, NULL, 
&error);
     if (error != NULL)
-      g_warning ("Unable to create a TrackerMinerManager: %s", error->message);
+      {
+        g_warning ("Unable to create connection for session-wide Tracker indexer at %s: %s",
+                   self->miner_files_name,
+                   error->message);
+      }
   }
 
-  if (self->miner_manager != NULL)
+  if (self->miner_files_connection == NULL && photos_utils_is_flatpak ())
     {
-      GSList *available = NULL;
-      GSList *miner_files = NULL;
+      self->miner_files_name = MINER_FILES_NAME_PRIVATE;
+      control_name = MINER_FILES_NAME_PRIVATE_CONTROL;
+      photos_debug (PHOTOS_DEBUG_TRACKER, "Connecting to %s", self->miner_files_name);
 
-      available = tracker_miner_manager_get_available (self->miner_manager);
-      miner_files = g_slist_find_custom (available, MINER_FILES, (GCompareFunc) strcmp);
-      if (miner_files == NULL)
-        {
-          g_warning ("Unable to find miner %s", MINER_FILES);
-        }
-      else
-        {
-          if (!tracker_miner_manager_is_active (self->miner_manager, MINER_FILES))
-            g_warning ("Unable to activate miner %s", MINER_FILES);
-        }
+      {
+        g_autoptr (GError) error = NULL;
 
-      g_slist_free_full (available, g_free);
+        self->miner_files_connection = tracker_sparql_connection_bus_new (self->miner_files_name, NULL, 
NULL, &error);
+        if (error != NULL)
+          {
+            g_warning ("Unable to create connection for private Tracker indexer at %s: %s",
+                       self->miner_files_name,
+                       error->message);
+            self->miner_files_name = MINER_FILES_NAME_SESSION;
+          }
+      }
     }
 
+  if (self->miner_files_connection == NULL)
+    goto out;
+
+  {
+    g_autoptr (GError) error = NULL;
+
+    self->miner_files_index
+      = tracker_miner_files_index_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+                                                          G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS
+                                                          | G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
+                                                          control_name,
+                                                          MINER_FILES_OBJECT_PATH_CONTROL,
+                                                          NULL,
+                                                          &error);
+    if (error != NULL)
+      g_warning ("Unable to create TrackerMinerFilesIndex proxy: %s", error->message);
+  }
+
+  notifier = photos_tracker_queue_create_notifier (self->queue);
+  dbus_connection = g_application_get_dbus_connection (G_APPLICATION (self));
+  tracker_notifier_signal_subscribe (notifier, dbus_connection, self->miner_files_name, NULL, NULL);
+  photos_item_manager_set_notifier (PHOTOS_ITEM_MANAGER (self->state->item_mngr), notifier);
+
+ out:
+  return;
+}
+
+
+static void
+photos_application_start_miners (PhotosApplication *self)
+{
+  photos_application_start_miners_local (self);
   photos_application_create_online_miners (self);
 }
 
@@ -3023,8 +2983,9 @@ 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_manager);
+  g_clear_object (&self->queue);
+  g_clear_object (&self->miner_files_index);
+  g_clear_object (&self->miner_files_connection);
 
   if (self->state != NULL)
     {
@@ -3060,11 +3021,19 @@ photos_application_init (PhotosApplication *self)
   textdomain (GETTEXT_PACKAGE);
 
   g_set_application_name (_("Photos"));
-  tracker_sparql_connection_set_domain ("org.gnome.Photos");
 
   photos_utils_ensure_builtins ();
 
+  {
+    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);
+  }
+
   self->state = photos_search_context_state_new (PHOTOS_SEARCH_CONTEXT (self));
+  self->miner_files_name = MINER_FILES_NAME_SESSION;
   self->activation_timestamp = GDK_CURRENT_TIME;
 
   g_application_add_main_option_entries (G_APPLICATION (self), COMMAND_LINE_OPTIONS);
@@ -3116,6 +3085,23 @@ photos_application_new (void)
 }
 
 
+TrackerMinerFilesIndex *
+photos_application_dup_miner_files_index (PhotosApplication *self)
+{
+  TrackerMinerFilesIndex *ret_val = NULL;
+
+  g_return_val_if_fail (PHOTOS_IS_APPLICATION (self), NULL);
+
+  if (G_UNLIKELY (self->miner_files_index == NULL))
+    goto out;
+
+  ret_val = g_object_ref (self->miner_files_index);
+
+ out:
+  return ret_val;
+}
+
+
 gboolean
 photos_application_get_empty_results (PhotosApplication *self)
 {
@@ -3147,6 +3133,16 @@ photos_application_get_miner (PhotosApplication *self, const gchar *provider_typ
 }
 
 
+const gchar *
+photos_application_get_miner_files_name (PhotosApplication *self)
+{
+  g_return_val_if_fail (PHOTOS_IS_APPLICATION (self), NULL);
+  g_return_val_if_fail (self->miner_files_name != NULL, NULL);
+
+  return self->miner_files_name;
+}
+
+
 GList *
 photos_application_get_miners_running (PhotosApplication *self)
 {
diff --git a/src/photos-application.h b/src/photos-application.h
index ae28361c..50afe468 100644
--- a/src/photos-application.h
+++ b/src/photos-application.h
@@ -26,6 +26,7 @@
 #include <gtk/gtk.h>
 
 #include "photos-gom-miner.h"
+#include "photos-tracker-miner-files-index.h"
 
 G_BEGIN_DECLS
 
@@ -34,11 +35,15 @@ G_DECLARE_FINAL_TYPE (PhotosApplication, photos_application, PHOTOS, APPLICATION
 
 GApplication          *photos_application_new                    (void);
 
+TrackerMinerFilesIndex *photos_application_dup_miner_files_index (PhotosApplication *self);
+
 gboolean               photos_application_get_empty_results      (PhotosApplication *self);
 
 GomMiner              *photos_application_get_miner              (PhotosApplication *self,
                                                                   const gchar *provider_type);
 
+const gchar           *photos_application_get_miner_files_name   (PhotosApplication *self);
+
 GList                 *photos_application_get_miners_running     (PhotosApplication *self);
 
 gint                   photos_application_get_scale_factor       (PhotosApplication *self);
diff --git a/src/photos-base-item.c b/src/photos-base-item.c
index 0d72f9c5..f9d66865 100644
--- a/src/photos-base-item.c
+++ b/src/photos-base-item.c
@@ -3773,7 +3773,7 @@ photos_base_item_get_where (PhotosBaseItem *self)
   priv = photos_base_item_get_instance_private (self);
 
   if (priv->collection)
-    ret_val = g_strconcat ("{ ?urn nie:isPartOf <", priv->id, "> }", NULL);
+    ret_val = g_strconcat ("{ ?urn nie:isLogicalPartOf <", priv->id, "> }", NULL);
   else
     ret_val = g_strdup ("");
 
diff --git a/src/photos-indexing-notification.c b/src/photos-indexing-notification.c
index 72394983..fc0162d5 100644
--- a/src/photos-indexing-notification.c
+++ b/src/photos-indexing-notification.c
@@ -26,22 +26,23 @@
 #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-miner.h"
 
 
 struct _PhotosIndexingNotification
 {
   GtkGrid parent_instance;
+  GCancellable *cancellable;
   GtkWidget *ntfctn_mngr;
   GtkWidget *primary_label;
   GtkWidget *secondary_label;
   GtkWidget *spinner;
-  TrackerMinerManager *manager;
+  TrackerMiner *miner_files;
   gboolean closed;
   gboolean on_display;
   guint timeout_id;
@@ -56,8 +57,6 @@ enum
   REMOTE_MINER_TIMEOUT = 10 /* s */
 };
 
-static const gchar *MINER_FILES = "org.gnome.Photos.Tracker1.Miner.Files";
-
 
 static void
 photos_indexing_notification_remove_timeout (PhotosIndexingNotification *self)
@@ -173,23 +172,36 @@ photos_indexing_notification_timeout (gpointer user_data)
 
 
 static void
-photos_indexing_notification_check_notification (PhotosIndexingNotification *self)
+photos_indexing_notification_check_notification_get_progress (GObject *source_object,
+                                                              GAsyncResult *res,
+                                                              gpointer user_data)
 {
+  PhotosIndexingNotification *self;
   GApplication *app;
   GList *miners_running;
   GSList *running = NULL;
+  TrackerMiner *miner_files = TRACKER_MINER (source_object);
   gboolean is_indexing_local = FALSE;
   gboolean is_indexing_remote = FALSE;
+  gdouble progress;
 
-  running = tracker_miner_manager_get_running (self->manager);
-  if (g_slist_find_custom (running, (gconstpointer) MINER_FILES, (GCompareFunc) g_strcmp0) != NULL)
-    {
-      gdouble progress;
+  {
+    g_autoptr (GError) error = NULL;
 
-      tracker_miner_manager_get_status (self->manager, MINER_FILES, NULL, &progress, NULL);
-      if (progress < 1)
-        is_indexing_local = TRUE;
-    }
+    if (!tracker_miner_call_get_progress_finish (miner_files, &progress, res, &error))
+      {
+        if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+          goto out;
+
+        g_warning ("Unable to get indexing progress from TrackerMiner proxy: %s", error->message);
+        progress = 1.0;
+      }
+  }
+
+  self = PHOTOS_INDEXING_NOTIFICATION (user_data);
+
+  if (progress < 1)
+    is_indexing_local = TRUE;
 
   app = g_application_get_default ();
   miners_running = photos_application_get_miners_running (PHOTOS_APPLICATION (app));
@@ -210,10 +222,53 @@ photos_indexing_notification_check_notification (PhotosIndexingNotification *sel
   else
     photos_indexing_notification_destroy (self, FALSE);
 
+ out:
   g_slist_free_full (running, g_free);
 }
 
 
+static void
+photos_indexing_notification_check_notification (PhotosIndexingNotification *self)
+{
+  tracker_miner_call_get_progress (self->miner_files,
+                                   self->cancellable,
+                                   photos_indexing_notification_check_notification_get_progress,
+                                   self);
+}
+
+
+static void
+photos_indexing_notification_tracker_miner (GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+  PhotosIndexingNotification *self;
+  g_autoptr (TrackerMiner) miner_files = NULL;
+
+  {
+    g_autoptr (GError) error = NULL;
+
+    miner_files = tracker_miner_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 TrackerMiner proxy: %s", error->message);
+
+        goto out;
+      }
+  }
+
+  self = PHOTOS_INDEXING_NOTIFICATION (user_data);
+
+  self->miner_files = g_object_ref (miner_files);
+  g_signal_connect_swapped (self->miner_files,
+                            "progress",
+                            G_CALLBACK (photos_indexing_notification_check_notification),
+                            self);
+
+ out:
+  return;
+}
+
+
 static void
 photos_indexing_notification_dispose (GObject *object)
 {
@@ -221,8 +276,14 @@ photos_indexing_notification_dispose (GObject *object)
 
   photos_indexing_notification_remove_timeout (self);
 
+  if (self->cancellable != NULL)
+    {
+       g_cancellable_cancel (self->cancellable);
+       g_clear_object (&self->cancellable);
+    }
+
   g_clear_object (&self->ntfctn_mngr);
-  g_clear_object (&self->manager);
+  g_clear_object (&self->miner_files);
 
   G_OBJECT_CLASS (photos_indexing_notification_parent_class)->dispose (object);
 }
@@ -236,21 +297,9 @@ photos_indexing_notification_init (PhotosIndexingNotification *self)
   GtkWidget *close;
   GtkWidget *image;
   GtkWidget *labels;
+  const gchar *miner_files_name;
 
   app = g_application_get_default ();
-
-  {
-    g_autoptr (GError) error = NULL;
-
-    self->manager = tracker_miner_manager_new_full (TRUE, &error);
-    if (error != NULL)
-      {
-        g_warning ("Unable to create a TrackerMinerManager, indexing progress notification won't work: %s",
-                   error->message);
-        return;
-      }
-  }
-
   self->ntfctn_mngr = photos_notification_manager_dup_singleton ();
 
   self->spinner = gtk_spinner_new ();
@@ -287,16 +336,21 @@ photos_indexing_notification_init (PhotosIndexingNotification *self)
   gtk_container_add (GTK_CONTAINER (self), close);
   g_signal_connect_swapped (close, "clicked", G_CALLBACK (photos_indexing_notification_close_clicked), self);
 
+  /* TODO: should be proxied by the "control" daemon for Flatpaks */
+  miner_files_name = photos_application_get_miner_files_name (PHOTOS_APPLICATION (app));
+  tracker_miner_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+                                   G_DBUS_PROXY_FLAGS_NONE,
+                                   miner_files_name,
+                                   "/org/freedesktop/Tracker3/Miner/Files",
+                                   self->cancellable,
+                                   photos_indexing_notification_tracker_miner,
+                                   self);
+
   g_signal_connect_object (app,
                            "miners-changed",
                            G_CALLBACK (photos_indexing_notification_check_notification),
                            self,
                            G_CONNECT_SWAPPED);
-
-  g_signal_connect_swapped (self->manager,
-                            "miner-progress",
-                            G_CALLBACK (photos_indexing_notification_check_notification),
-                            self);
 }
 
 
diff --git a/src/photos-item-manager.c b/src/photos-item-manager.c
index 6bf4ef7b..f760c434 100644
--- a/src/photos-item-manager.c
+++ b/src/photos-item-manager.c
@@ -309,7 +309,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);
@@ -532,17 +532,11 @@ photos_item_manager_notifier_events_foreach (gpointer data, gpointer user_data)
   PhotosItemManager *self = PHOTOS_ITEM_MANAGER (user_data);
   TrackerNotifierEvent *event = (TrackerNotifierEvent *) data;
   TrackerNotifierEventType event_type;
-  const gchar *event_rdf_type;
   const gchar *event_urn;
 
-  event_rdf_type = tracker_notifier_event_get_type (event);
   event_type = tracker_notifier_event_get_event_type (event);
   event_urn = tracker_notifier_event_get_urn (event);
-  photos_debug (PHOTOS_DEBUG_TRACKER,
-                "Received TrackerNotifierEvent (%d): RDF type %s, URN %s",
-                event_type,
-                event_rdf_type,
-                event_urn);
+  photos_debug (PHOTOS_DEBUG_TRACKER, "Received TrackerNotifierEvent (%d): URN %s", event_type, event_urn);
 
   g_return_if_fail (event_urn != NULL && event_urn[0] != '\0');
 
@@ -584,9 +578,13 @@ photos_item_manager_notifier_events_foreach (gpointer data, gpointer user_data)
 
 
 static void
-photos_item_manager_notifier_events (PhotosItemManager *self, GPtrArray *events)
+photos_item_manager_notifier_events (PhotosItemManager *self,
+                                     const gchar *service,
+                                     const gchar *graph,
+                                     GPtrArray *events)
 {
-  g_ptr_array_foreach (events, photos_item_manager_notifier_events_foreach, self);
+  if (g_strcmp0 (graph, PHOTOS_PICTURES_GRAPH) == 0)
+    g_ptr_array_foreach (events, photos_item_manager_notifier_events_foreach, self);
 }
 
 
@@ -724,7 +722,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,
@@ -1100,17 +1098,6 @@ photos_item_manager_init (PhotosItemManager *self)
 
   self->mode = PHOTOS_WINDOW_MODE_NONE;
 
-  self->notifier = tracker_notifier_new (NULL,
-                                         TRACKER_NOTIFIER_FLAG_NOTIFY_UNEXTRACTED
-                                         | TRACKER_NOTIFIER_FLAG_QUERY_URN,
-                                         NULL,
-                                         NULL);
-  if (G_LIKELY (self->notifier != NULL))
-    g_signal_connect_swapped (self->notifier,
-                              "events",
-                              G_CALLBACK (photos_item_manager_notifier_events),
-                              self);
-
   {
     g_autoptr (GError) error = NULL;
 
@@ -1251,7 +1238,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');
@@ -1380,7 +1367,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));
@@ -1532,6 +1519,26 @@ photos_item_manager_set_constraints_for_mode (PhotosItemManager *self, gboolean
 }
 
 
+void
+photos_item_manager_set_notifier (PhotosItemManager *self, TrackerNotifier *notifier)
+{
+  g_return_if_fail (PHOTOS_IS_ITEM_MANAGER (self));
+  g_return_if_fail (notifier == NULL || TRACKER_IS_NOTIFIER (notifier));
+
+  if (self->notifier != NULL)
+    {
+      g_signal_handlers_disconnect_by_func (self->notifier, photos_item_manager_notifier_events, self);
+      g_clear_object (&self->notifier);
+    }
+
+  if (notifier != NULL)
+    {
+      self->notifier = g_object_ref (notifier);
+      g_signal_connect_swapped (self->notifier, "events", G_CALLBACK (photos_item_manager_notifier_events), 
self);
+    }
+}
+
+
 void
 photos_item_manager_unhide_item (PhotosItemManager *self, PhotosBaseItem *item)
 {
diff --git a/src/photos-item-manager.h b/src/photos-item-manager.h
index 99d13e5d..cc49861e 100644
--- a/src/photos-item-manager.h
+++ b/src/photos-item-manager.h
@@ -105,6 +105,9 @@ void                      photos_item_manager_set_constraints_for_mode     (Phot
                                                                             gboolean constrain,
                                                                             PhotosWindowMode mode);
 
+void                      photos_item_manager_set_notifier                 (PhotosItemManager *self,
+                                                                            TrackerNotifier *notifier);
+
 void                      photos_item_manager_wait_for_file_async          (PhotosItemManager *self,
                                                                             GFile *file,
                                                                             GCancellable *cancellable,
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-all.sparql.template b/src/photos-query-all.sparql.template
index d2dd7e2f..83949c48 100644
--- a/src/photos-query-all.sparql.template
+++ b/src/photos-query-all.sparql.template
@@ -16,33 +16,78 @@
 #
 
 SELECT {{projection}}
+FROM tracker:Pictures
 {
     {
-        SELECT ?urn
+        GRAPH tracker:Pictures
         {
+            SELECT {{projection_private}}
             {
-                SELECT ?urn COUNT(?item) AS ?count
                 {
-                    ?urn a nfo:DataContainer.
-                    ?item a nmm:Photo; nie:isPartOf ?urn.
-                    {{item_where}}
+                    SELECT ?urn COUNT(?item) AS ?count
+                    {
+                        {{values}}
+                        VALUES (?file ?filename) { ("" "") }
+                        ?urn a nfo:DataContainer .
+                        ?item a nmm:Photo ; nie:isLogicalPartOf ?urn .
+                    }
+                    GROUP BY (?urn)
                 }
-                GROUP BY (?urn)
+                {{item_where}}
+                OPTIONAL { ?urn nco:creator ?creator . }
+                OPTIONAL { ?urn nco:publisher ?publisher . }
+                FILTER (?count > 0 && {{collections_filter}} && {{search_match_filter}} && {{source_filter}})
             }
-            OPTIONAL { ?urn nco:creator ?creator . }
-            OPTIONAL { ?urn nco:publisher ?publisher . }
-            FILTER (?count > 0 && {{collections_filter}} && {{search_match_filter}} && {{source_filter}})
         }
     }
     UNION
     {
-        SELECT ?urn
+        SELECT {{projection_forwarded}}
         {
-            ?urn a nmm:Photo .
-            OPTIONAL { ?urn nco:creator ?creator . }
-            OPTIONAL { ?urn nco:publisher ?publisher . }
             {{item_where}}
-            FILTER ({{blocked_mime_types_filter}} && {{search_match_filter}} && {{source_filter}})
+            SERVICE <dbus:{{miner_files_name}}>
+            {
+                GRAPH tracker:Pictures
+                {
+                    SELECT {{projection_dbus}}
+                    {
+                        {
+                            SELECT ?urn COUNT(?item) AS ?count
+                            {
+                                {{values}}
+                                VALUES (?file ?filename) { ("" "") }
+                                ?urn a nfo:DataContainer .
+                                ?item a nmm:Photo ; nie:isLogicalPartOf ?urn .
+                            }
+                            GROUP BY (?urn)
+                        }
+                        OPTIONAL { ?urn nco:creator ?creator . }
+                        OPTIONAL { ?urn nco:publisher ?publisher . }
+                        FILTER (?count > 0 && {{collections_filter}} && {{search_match_filter}} && 
{{source_filter}})
+                    }
+                }
+            }
+        }
+    }
+    UNION
+    {
+        SELECT {{projection_forwarded}}
+        {
+            {{item_where}}
+            SERVICE <dbus:{{miner_files_name}}>
+            {
+                GRAPH tracker:Pictures
+                {
+                    SELECT {{projection_dbus}}
+                    {
+                        {{values}}
+                        ?urn a nmm:Photo ; nie:isStoredAs ?file .
+                        OPTIONAL { ?urn nco:creator ?creator . }
+                        OPTIONAL { ?urn nco:publisher ?publisher . }
+                        FILTER ({{blocked_mime_types_filter}} && {{search_match_filter}} && 
{{source_filter}})
+                    }
+                }
+            }
         }
     }
 }
diff --git a/src/photos-query-builder.c b/src/photos-query-builder.c
index 95ea1055..46eb973d 100644
--- a/src/photos-query-builder.c
+++ b/src/photos-query-builder.c
@@ -27,6 +27,7 @@
 
 #include <tracker-sparql.h>
 
+#include "photos-application.h"
 #include "photos-base-manager.h"
 #include "photos-query-builder.h"
 #include "photos-search-type.h"
@@ -45,46 +46,115 @@ static const gchar *COLLECTIONS_FILTER
 
 static gchar *
 photos_query_builder_query (PhotosSearchContextState *state,
-                            gboolean global,
+                            const gchar *values,
                             gint flags,
                             PhotosOffsetController *offset_cntrlr)
 {
+  GApplication *app;
   PhotosSparqlTemplate *sparql_template;
+  const gchar *miner_files_name;
+
+  /* These are the final list of properties used to create or update
+   * an item. It is a superset of the properties that come from the
+   * canonical source of an item. eg., an item's canonical source
+   * might be the D-Bus endpoint, but its nao:predefined-tag-favorite
+   * will always be in the private database.
+   */
   const gchar *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) "
+      "?file "
+      "?filename "
+      "?mimetype "
+      "?title "
+      "?author "
+      "?mtime "
+      "?identifier "
+      "?type "
+      "?datasource "
       "( 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) ";
+      "?has_contributor "
+      "?ctime "
+      "?width "
+      "?height "
+      "?equipment "
+      "?orientation "
+      "?exposure_time "
+      "?fnumber "
+      "?focal_length "
+      "?isospeed "
+      "?flash "
+      "?location ";
+
+  /* These properties come from the canonical source of an item. eg.,
+   * for local items the canonical source is the D-Bus endpoint, and
+   * for user-created collections it's the private database.
+   */
+  const gchar *projection_database
+    = "?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 "
+      "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 ";
+
+  /* This merely forwards the properties coming from the canonical
+   * source of an item until they can be aggregated into the final
+   * list that's used to create or update an item.
+   */
+  const gchar *projection_forwarded
+    = "?urn "
+      "?file "
+      "?filename "
+      "?mimetype "
+      "?title "
+      "?author "
+      "?mtime "
+      "?identifier "
+      "?type "
+      "?datasource "
+      "?has_contributor "
+      "?ctime "
+      "?width "
+      "?height "
+      "?equipment "
+      "?orientation "
+      "?exposure_time "
+      "?fnumber "
+      "?focal_length "
+      "?isospeed "
+      "?flash "
+      "?location ";
+
   g_autofree gchar *item_mngr_where = NULL;
   g_autofree gchar *offset_limit = NULL;
   g_autofree gchar *src_mngr_filter = NULL;
   g_autofree gchar *srch_mtch_mngr_filter = NULL;
   gchar *sparql;
 
+  app = g_application_get_default ();
+  miner_files_name = photos_application_get_miner_files_name (PHOTOS_APPLICATION (app));
+
   sparql_template = photos_base_manager_get_sparql_template (state->srch_typ_mngr, flags);
 
   if (!(flags & PHOTOS_QUERY_FLAGS_UNFILTERED))
     {
-      if (global)
+      if (values == NULL)
         {
           /* TODO: SearchCategoryManager */
 
@@ -95,7 +165,7 @@ photos_query_builder_query (PhotosSearchContextState *state,
       srch_mtch_mngr_filter = photos_base_manager_get_filter (state->srch_mtch_mngr, flags);
     }
 
-  if (global && (flags & PHOTOS_QUERY_FLAGS_UNLIMITED) == 0)
+  if (values == NULL && (flags & PHOTOS_QUERY_FLAGS_UNLIMITED) == 0)
     {
       gint offset = 0;
       gint step = 60;
@@ -114,13 +184,18 @@ photos_query_builder_query (PhotosSearchContextState *state,
                                          "blocked_mime_types_filter", BLOCKED_MIME_TYPES_FILTER,
                                          "collections_filter", COLLECTIONS_FILTER,
                                          "item_where", item_mngr_where == NULL ? "" : item_mngr_where,
+                                         "miner_files_name", miner_files_name,
                                          "order", "ORDER BY DESC (?mtime)",
                                          "offset_limit", offset_limit ? offset_limit : "",
                                          "projection", projection,
+                                         "projection_dbus", projection_database,
+                                         "projection_forwarded", projection_forwarded,
+                                         "projection_private", projection_database,
                                          "search_match_filter", srch_mtch_mngr_filter == NULL
                                                                 ? "(true)"
                                                                 : srch_mtch_mngr_filter,
                                          "source_filter", src_mngr_filter == NULL ? "(true)" : 
src_mngr_filter,
+                                         "values", values == NULL ? "" : values,
                                          NULL);
 
   return sparql;
@@ -153,7 +228,7 @@ photos_query_builder_create_collection_query (PhotosSearchContextState *state,
   tracker_resource_set_string (collection, "nie:title", name);
   tracker_resource_set_string (collection, "nao:identifier", identifier);
 
-  sparql = tracker_resource_print_sparql_update (collection, NULL, NULL);
+  sparql = tracker_resource_print_sparql_update (collection, NULL, "tracker:Pictures");
   query = photos_query_new (state, sparql);
 
   return query;
@@ -163,14 +238,28 @@ photos_query_builder_create_collection_query (PhotosSearchContextState *state,
 PhotosQuery *
 photos_query_builder_collection_icon_query (PhotosSearchContextState *state, const gchar *resource)
 {
+  GApplication *app;
   PhotosQuery *query;
+  const gchar *miner_files_name;
   g_autofree gchar *sparql = NULL;
 
-  sparql = g_strdup_printf ("SELECT ?urn "
-                            "tracker:coalesce(nfo:fileLastModified(?urn), nie:contentLastModified(?urn)) AS 
?mtime "
-                            "WHERE { ?urn nie:isPartOf <%s> } "
-                            "ORDER BY DESC (?mtime) LIMIT 4",
-                            resource);
+  app = g_application_get_default ();
+  miner_files_name = photos_application_get_miner_files_name (PHOTOS_APPLICATION (app));
+
+  sparql
+    = g_strdup_printf ("SELECT ?urn "
+                       "tracker:coalesce(nfo:fileLastModified(?file), nie:contentLastModified(?urn)) AS 
?mtime "
+                       "WHERE {"
+                       "  SERVICE <dbus:%s> {"
+                       "    GRAPH tracker:Pictures {"
+                       "      SELECT ?urn WHERE { ?urn a nmm:Photo ; nie:isStoredAs ?file . }"
+                       "    }"
+                       "  }"
+                       "  ?urn nie:isLogicalPartOf <%s> . "
+                       "}"
+                       "ORDER BY DESC (?mtime) LIMIT 4",
+                       miner_files_name,
+                       resource);
 
   query = photos_query_new (state, sparql);
 
@@ -181,13 +270,18 @@ photos_query_builder_collection_icon_query (PhotosSearchContextState *state, con
 PhotosQuery *
 photos_query_builder_count_query (PhotosSearchContextState *state, gint flags)
 {
+  GApplication *app;
   PhotosQuery *query;
   PhotosSparqlTemplate *sparql_template;
+  const gchar *miner_files_name;
   g_autofree gchar *item_mngr_where = NULL;
   g_autofree gchar *src_mngr_filter = NULL;
   g_autofree gchar *srch_mtch_mngr_filter = NULL;
   g_autofree gchar *sparql = NULL;
 
+  app = g_application_get_default ();
+  miner_files_name = photos_application_get_miner_files_name (PHOTOS_APPLICATION (app));
+
   sparql_template = photos_base_manager_get_sparql_template (state->srch_typ_mngr, flags);
 
   if ((flags & PHOTOS_QUERY_FLAGS_UNFILTERED) == 0)
@@ -202,13 +296,18 @@ photos_query_builder_count_query (PhotosSearchContextState *state, gint flags)
                                          "blocked_mime_types_filter", BLOCKED_MIME_TYPES_FILTER,
                                          "collections_filter", COLLECTIONS_FILTER,
                                          "item_where", item_mngr_where == NULL ? "" : item_mngr_where,
+                                         "miner_files_name", miner_files_name,
                                          "order", "",
                                          "offset_limit", "",
                                          "projection", "COUNT(?urn)",
+                                         "projection_dbus", "?urn",
+                                         "projection_forwarded", "?urn",
+                                         "projection_private", "?urn",
                                          "search_match_filter", srch_mtch_mngr_filter == NULL
                                                                 ? "(true)"
                                                                 : srch_mtch_mngr_filter,
                                          "source_filter", src_mngr_filter == NULL ? "(true)" : 
src_mngr_filter,
+                                         "values", "",
                                          NULL);
 
   query = photos_query_new (state, sparql);
@@ -251,7 +350,8 @@ photos_query_builder_fetch_collections_for_urn_query (PhotosSearchContextState *
   PhotosQuery *query;
   g_autofree gchar *sparql = NULL;
 
-  sparql = g_strdup_printf ("SELECT ?urn WHERE { ?urn a nfo:DataContainer . <%s> nie:isPartOf ?urn }", 
resource);
+  sparql = g_strdup_printf ("SELECT ?urn WHERE { ?urn a nfo:DataContainer . <%s> nie:isLogicalPartOf ?urn }",
+                            resource);
   query = photos_query_new (state, sparql);
 
   return query;
@@ -265,7 +365,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,
@@ -285,7 +385,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;
@@ -314,12 +414,24 @@ 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);
-  query = photos_query_new (state, sparql);
+  if (setting)
+    {
+      sparql = g_strdup_printf ("INSERT DATA { "
+                                "  GRAPH tracker:Pictures {"
+                                "    <%s> a nmm:Photo ; nie:isLogicalPartOf <%s> ."
+                                "  }"
+                                "}", item_urn, collection_urn);
+    }
+  else
+    {
+      sparql = g_strdup_printf ("DELETE DATA { "
+                                "  GRAPH tracker:Pictures {"
+                                "    <%s> nie:isLogicalPartOf <%s> "
+                                "  }"
+                                "}", item_urn, collection_urn);
+    }
 
+  query = photos_query_new (state, sparql);
   return query;
 }
 
@@ -327,19 +439,13 @@ 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;
 
-  tmp = photos_query_builder_query (state, FALSE, 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);
+  values = g_strdup_printf ("VALUES ?urn { <%s> }", resource);
+  sparql = photos_query_builder_query (state, values, flags, NULL);
   query = photos_query_new (state, sparql);
-
   return query;
 }
 
@@ -355,8 +461,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);
-  query = photos_query_new (state, sparql);
+  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-query-collections.sparql.template b/src/photos-query-collections.sparql.template
index 59155cc2..c9523d1b 100644
--- a/src/photos-query-collections.sparql.template
+++ b/src/photos-query-collections.sparql.template
@@ -16,18 +16,54 @@
 #
 
 SELECT {{projection}}
+FROM tracker:Pictures
 {
     {
-        SELECT ?urn COUNT(?item) AS ?count
+        GRAPH tracker:Pictures
         {
-            ?urn a nfo:DataContainer.
-            ?item a nmm:Photo; nie:isPartOf ?urn.
+            SELECT {{projection_private}}
+            {
+                {
+                    SELECT ?urn COUNT(?item) AS ?count
+                    {
+                        {{values}}
+                        VALUES (?file ?filename) { ("" "") }
+                        ?urn a nfo:DataContainer .
+                        ?item a nmm:Photo ; nie:isLogicalPartOf ?urn .
+                    }
+                    GROUP BY (?urn)
+                }
+                OPTIONAL { ?urn nco:creator ?creator . }
+                OPTIONAL { ?urn nco:publisher ?publisher . }
+                FILTER (?count > 0 && {{collections_filter}} && {{search_match_filter}} && {{source_filter}})
+            }
+        }
+    }
+    UNION
+    {
+        SERVICE <dbus:{{miner_files_name}}>
+        {
+            GRAPH tracker:Pictures
+            {
+                SELECT {{projection_dbus}}
+                {
+                    {
+                        SELECT ?urn COUNT(?item) AS ?count
+                        {
+                            {{values}}
+                            VALUES (?file ?filename) { ("" "") }
+                            ?urn a nfo:DataContainer .
+                            ?item a nmm:Photo ; nie:isLogicalPartOf ?urn .
+                        }
+                        GROUP BY (?urn)
+                    }
+                    OPTIONAL { ?urn nco:creator ?creator . }
+                    OPTIONAL { ?urn nco:publisher ?publisher . }
+                    FILTER (?count > 0 && {{collections_filter}} && {{search_match_filter}} && 
{{source_filter}})
+                }
+            }
         }
-        GROUP BY (?urn)
     }
-    OPTIONAL { ?urn nco:creator ?creator . }
-    OPTIONAL { ?urn nco:publisher ?publisher . }
-    FILTER (?count > 0 && {{collections_filter}} && {{search_match_filter}} && {{source_filter}})
 }
 {{order}}
 {{offset_limit}}
diff --git a/src/photos-query-favorites.sparql.template b/src/photos-query-favorites.sparql.template
index 23780d4e..8180d1b3 100644
--- a/src/photos-query-favorites.sparql.template
+++ b/src/photos-query-favorites.sparql.template
@@ -16,11 +16,23 @@
 #
 
 SELECT {{projection}}
+FROM tracker:Pictures
 {
     ?urn a nmm:Photo; nao:hasTag nao:predefined-tag-favorite .
-    OPTIONAL { ?urn nco:creator ?creator . }
-    OPTIONAL { ?urn nco:publisher ?publisher . }
-    FILTER ({{blocked_mime_types_filter}} && {{search_match_filter}} && {{source_filter}})
+    SERVICE <dbus:{{miner_files_name}}>
+    {
+        GRAPH tracker:Pictures
+        {
+            SELECT {{projection_dbus}}
+            {
+                {{values}}
+                ?urn a nmm:Photo ; nie:isStoredAs ?file .
+                OPTIONAL { ?urn nco:creator ?creator . }
+                OPTIONAL { ?urn nco:publisher ?publisher . }
+                FILTER ({{blocked_mime_types_filter}} && {{search_match_filter}} && {{source_filter}})
+            }
+        }
+    }
 }
 {{order}}
 {{offset_limit}}
diff --git a/src/photos-query-photos.sparql.template b/src/photos-query-photos.sparql.template
index 0973bbfb..2db00e6e 100644
--- a/src/photos-query-photos.sparql.template
+++ b/src/photos-query-photos.sparql.template
@@ -16,11 +16,22 @@
 #
 
 SELECT {{projection}}
+FROM tracker:Pictures
 {
-    ?urn a nmm:Photo .
-    OPTIONAL { ?urn nco:creator ?creator . }
-    OPTIONAL { ?urn nco:publisher ?publisher . }
-    FILTER ({{blocked_mime_types_filter}} && {{search_match_filter}} && {{source_filter}})
+    SERVICE <dbus:{{miner_files_name}}>
+    {
+        GRAPH tracker:Pictures
+        {
+            SELECT {{projection_dbus}}
+            {
+                {{values}}
+                ?urn a nmm:Photo ; nie:isStoredAs ?file .
+                OPTIONAL { ?urn nco:creator ?creator . }
+                OPTIONAL { ?urn nco:publisher ?publisher . }
+                FILTER ({{blocked_mime_types_filter}} && {{search_match_filter}} && {{source_filter}})
+            }
+        }
+    }
 }
 {{order}}
 {{offset_limit}}
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-import-controller.c b/src/photos-tracker-import-controller.c
index 9f130714..4c9cc30b 100644
--- a/src/photos-tracker-import-controller.c
+++ b/src/photos-tracker-import-controller.c
@@ -24,8 +24,8 @@
 #include "config.h"
 
 #include <gio/gio.h>
-#include <libtracker-control/tracker-control.h>
 
+#include "photos-application.h"
 #include "photos-base-manager.h"
 #include "photos-debug.h"
 #include "photos-device-item.h"
@@ -34,6 +34,7 @@
 #include "photos-query-builder.h"
 #include "photos-search-context.h"
 #include "photos-tracker-import-controller.h"
+#include "photos-tracker-miner-files-index.h"
 #include "photos-utils.h"
 
 
@@ -45,7 +46,7 @@ struct _PhotosTrackerImportController
   PhotosBaseManager *item_mngr;
   PhotosBaseManager *src_mngr;
   PhotosOffsetController *offset_cntrlr;
-  TrackerMinerManager *manager;
+  TrackerMinerFilesIndex *miner_files_index;
 };
 
 
@@ -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_files_index = 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_files_index, 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[] = { PHOTOS_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_files_index,
+                                                                       uri,
+                                                                       tracker_priority_graphs,
+                                                                       tracker_index_location_flags,
+                                                                       self->cancellable,
+                                                                       
photos_tracker_import_controller_index,
+                                                                       g_object_ref (file));
                         indexing = TRUE;
                       }
                   }
@@ -291,7 +296,7 @@ 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))
+      if (G_LIKELY (self->miner_files_index != NULL))
         {
           g_autoptr (GFile) root = NULL;
           g_autofree gchar *uri = NULL;
@@ -379,7 +384,7 @@ 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_clear_object (&self->miner_files_index);
 
   G_OBJECT_CLASS (photos_tracker_import_controller_parent_class)->dispose (object);
 }
@@ -421,13 +426,9 @@ 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 (TRUE, &error);
-    if (error != NULL)
-      g_warning ("Unable to create a TrackerMinerManager, indexing attached devices won't work: %s", 
error->message);
-  }
+  self->miner_files_index = photos_application_dup_miner_files_index (PHOTOS_APPLICATION (app));
+  if (G_UNLIKELY (self->miner_files_index == NULL))
+    g_warning ("No TrackerMinerFilesIndex proxy, indexing attached devices won't work");
 }
 
 
diff --git a/src/photos-tracker-queue.c b/src/photos-tracker-queue.c
index 6ac829cd..efd771a2 100644
--- a/src/photos-tracker-queue.c
+++ b/src/photos-tracker-queue.c
@@ -24,7 +24,6 @@
 #include "config.h"
 
 #include <glib.h>
-#include <tracker-sparql.h>
 
 #include "photos-debug.h"
 #include "photos-filterable.h"
@@ -189,7 +188,6 @@ photos_tracker_queue_check (PhotosTrackerQueue *self)
     case PHOTOS_TRACKER_QUERY_UPDATE:
       tracker_sparql_connection_update_async (self->connection,
                                               sparql,
-                                              G_PRIORITY_DEFAULT,
                                               data->cancellable,
                                               photos_tracker_queue_collector,
                                               g_object_ref (self));
@@ -198,7 +196,6 @@ photos_tracker_queue_check (PhotosTrackerQueue *self)
     case PHOTOS_TRACKER_QUERY_UPDATE_BLANK:
       tracker_sparql_connection_update_blank_async (self->connection,
                                                     sparql,
-                                                    G_PRIORITY_DEFAULT,
                                                     data->cancellable,
                                                     photos_tracker_queue_collector,
                                                     g_object_ref (self));
@@ -274,7 +271,12 @@ static gboolean
 photos_tracker_queue_initable_init (GInitable *initable, GCancellable *cancellable, GError **error)
 {
   PhotosTrackerQueue *self = PHOTOS_TRACKER_QUEUE (initable);
+  g_autoptr (GFile) ontology = NULL;
+  g_autoptr (GFile) store = NULL;
+  TrackerSparqlConnectionFlags tracker_flags;
   gboolean ret_val = FALSE;
+  const gchar *data_dir;
+  const gchar *store_path;
 
   G_LOCK (init_lock);
 
@@ -290,7 +292,28 @@ 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);
+  /* 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 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_STEMMER
+                  | TRACKER_SPARQL_CONNECTION_FLAGS_FTS_ENABLE_STOP_WORDS
+                  | TRACKER_SPARQL_CONNECTION_FLAGS_FTS_ENABLE_UNACCENT
+                  | TRACKER_SPARQL_CONNECTION_FLAGS_FTS_IGNORE_NUMBERS;
+
+  data_dir = g_get_user_data_dir ();
+  store = g_file_new_build_filename (data_dir, PACKAGE_TARNAME, "tracker3", "private", NULL);
+  store_path = g_file_peek_path (store);
+
+  ontology = tracker_sparql_get_ontology_nepomuk ();
+
+  photos_debug (PHOTOS_DEBUG_TRACKER, "Opening private database at %s", store_path);
+
+  self->connection = tracker_sparql_connection_new (tracker_flags,
+                                                    store,
+                                                    ontology,
+                                                    cancellable,
+                                                    &self->initialization_error);
   if (G_UNLIKELY (self->initialization_error != NULL))
     goto out;
 
@@ -326,6 +349,18 @@ photos_tracker_queue_dup_singleton (GCancellable *cancellable, GError **error)
 }
 
 
+TrackerNotifier *
+photos_tracker_queue_create_notifier (PhotosTrackerQueue *self)
+{
+  TrackerNotifier *notifier;
+
+  g_return_val_if_fail (PHOTOS_IS_TRACKER_QUEUE (self), NULL);
+
+  notifier = tracker_sparql_connection_create_notifier (self->connection);
+  return notifier;
+}
+
+
 void
 photos_tracker_queue_select (PhotosTrackerQueue *self,
                              PhotosQuery *query,
diff --git a/src/photos-tracker-queue.h b/src/photos-tracker-queue.h
index 93d97306..aab6c280 100644
--- a/src/photos-tracker-queue.h
+++ b/src/photos-tracker-queue.h
@@ -24,6 +24,7 @@
 #define PHOTOS_TRACKER_QUEUE_H
 
 #include <gio/gio.h>
+#include <tracker-sparql.h>
 
 #include "photos-query.h"
 
@@ -34,6 +35,8 @@ G_DECLARE_FINAL_TYPE (PhotosTrackerQueue, photos_tracker_queue, PHOTOS, TRACKER_
 
 PhotosTrackerQueue    *photos_tracker_queue_dup_singleton          (GCancellable *cancellable, GError 
**error);
 
+TrackerNotifier       *photos_tracker_queue_create_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 76e8f5e0..5cfddaa5 100644
--- a/src/photos-utils.c
+++ b/src/photos-utils.c
@@ -1333,7 +1333,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);
 
   {
@@ -1361,9 +1367,23 @@ 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 1e7a4cb7..8709537d 100644
--- a/src/photos-utils.h
+++ b/src/photos-utils.h
@@ -45,9 +45,9 @@ G_BEGIN_DECLS
 #define PHOTOS_TOOL_EXTENSION_POINT_NAME "photos-tool"
 #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";
+#define PHOTOS_COLLECTION_SCREENSHOT "http://tracker.api.gnome.org/ontology/v3/nfo#image-category-screenshot";
 #define PHOTOS_EXPORT_SUBPATH "Exports"
+#define PHOTOS_PICTURES_GRAPH "http://tracker.api.gnome.org/ontology/v3/tracker#Pictures";
 
 typedef enum
 {


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