void-packages/srcpkgs/gnome-photos/patches/tracker3.patch

4152 lines
157 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

From 4673c40a7c006ccb6de203ec2b25ca39a74782d9 Mon Sep 17 00:00:00 2001
From: Sam Thursfield <sam@afuera.me.uk>
Date: Wed, 27 May 2020 13:07:58 +0200
Subject: [PATCH 1/3] Fix build failure due to undefined M_PI constant
The <math.h> header needs to be included.
Previously I suppose libtracker-sparql.h pulled this in.
---
src/photos-utils.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/photos-utils.c b/src/photos-utils.c
index 1d7be577..d659b47d 100644
--- a/src/photos-utils.c
+++ b/src/photos-utils.c
@@ -32,6 +32,7 @@
#include <glib.h>
#include <tracker-sparql.h>
#include <libgd/gd.h>
+#include <math.h>
#include "photos-application.h"
#include "photos-device-item.h"
--
GitLab
From 18f126a67a37d1f6efe546e42eef22ae15da7642 Mon Sep 17 00:00:00 2001
From: Sam Thursfield <sam@afuera.me.uk>
Date: Sun, 7 Jun 2020 21:53:20 +0200
Subject: [PATCH 2/3] Generate queries using SPARQL templates
The code to generate SPARQL queries was split across many different
source files, making it difficult to make big changes. Now the
queries are written out as templates and we use template substitution
to build the SPARQL that we send to Tracker.
---
src/meson.build | 5 +
src/photos-base-manager.c | 15 ++
src/photos-base-manager.h | 4 +
src/photos-filterable.c | 8 -
src/photos-filterable.h | 3 -
src/photos-query-builder.c | 207 +++++++++-----------
src/photos-search-type-manager.c | 59 +-----
src/photos-search-type.c | 67 +++----
src/photos-search-type.h | 6 +-
src/photos-sparql-template.c | 187 ++++++++++++++++++
src/photos-sparql-template.h | 38 ++++
src/photos.gresource.xml | 4 +
src/queries/all.sparql.template | 31 +++
src/queries/collections.sparql.template | 14 ++
src/queries/favorite-photos.sparql.template | 12 ++
src/queries/photos.sparql.template | 11 ++
16 files changed, 446 insertions(+), 225 deletions(-)
create mode 100644 src/photos-sparql-template.c
create mode 100644 src/photos-sparql-template.h
create mode 100644 src/queries/all.sparql.template
create mode 100644 src/queries/collections.sparql.template
create mode 100644 src/queries/favorite-photos.sparql.template
create mode 100644 src/queries/photos.sparql.template
diff --git a/src/meson.build b/src/meson.build
index 9919f0cf..b5b2759c 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -195,6 +195,7 @@ sources = common_sources + files(
'photos-source.c',
'photos-source-manager.c',
'photos-source-notification.c',
+ 'photos-sparql-template.c',
'photos-spinner-box.c',
'photos-thumbnail-factory.c',
'photos-tool.c',
@@ -290,6 +291,10 @@ resource_data = files(
'photos-selection-toolbar.ui',
'photos-share-dialog.ui',
'photos-zoom-controls.ui',
+ 'queries/all.sparql.template',
+ 'queries/collections.sparql.template',
+ 'queries/favorite-photos.sparql.template',
+ 'queries/photos.sparql.template',
)
sources += gnome.compile_resources(
diff --git a/src/photos-base-manager.c b/src/photos-base-manager.c
index d49d19a5..052638d5 100644
--- a/src/photos-base-manager.c
+++ b/src/photos-base-manager.c
@@ -250,6 +250,12 @@ photos_base_manager_default_get_where (PhotosBaseManager *self, gint flags)
}
+static PhotosSparqlTemplate *
+photos_base_manager_default_get_sparql_template (PhotosBaseManager *self, gint flags)
+{
+ return NULL;
+}
+
static void
photos_base_manager_default_remove_object_by_id (PhotosBaseManager *self, const gchar *id)
{
@@ -438,6 +444,7 @@ photos_base_manager_class_init (PhotosBaseManagerClass *class)
class->get_object_by_id = photos_base_manager_default_get_object_by_id;
class->get_previous_object = photos_base_manager_default_get_previous_object;
class->get_where = photos_base_manager_default_get_where;
+ class->get_sparql_template = photos_base_manager_default_get_sparql_template;
class->remove_object_by_id = photos_base_manager_default_remove_object_by_id;
class->set_active_object = photos_base_manager_default_set_active_object;
@@ -714,6 +721,14 @@ photos_base_manager_get_where (PhotosBaseManager *self, gint flags)
}
+PhotosSparqlTemplate *
+photos_base_manager_get_sparql_template (PhotosBaseManager *self, gint flags)
+{
+ g_return_val_if_fail (PHOTOS_IS_BASE_MANAGER (self), NULL);
+ return PHOTOS_BASE_MANAGER_GET_CLASS (self)->get_sparql_template (self, flags);
+}
+
+
void
photos_base_manager_process_new_objects (PhotosBaseManager *self, GHashTable *new_objects)
{
diff --git a/src/photos-base-manager.h b/src/photos-base-manager.h
index 99d203e9..04cfa7db 100644
--- a/src/photos-base-manager.h
+++ b/src/photos-base-manager.h
@@ -24,6 +24,7 @@
#define PHOTOS_BASE_MANAGER_H
#include <glib-object.h>
+#include "photos-sparql-template.h"
G_BEGIN_DECLS
@@ -46,6 +47,7 @@ struct _PhotosBaseManagerClass
gchar *(*get_where) (PhotosBaseManager *self, gint flags);
void (*remove_object_by_id) (PhotosBaseManager *self, const gchar *id);
gboolean (*set_active_object) (PhotosBaseManager *self, GObject *object);
+ PhotosSparqlTemplate *(*get_sparql_template) (PhotosBaseManager *self, gint flags);
/* signals */
void (*active_changed) (PhotosBaseManager *self, GObject *object);
@@ -80,6 +82,8 @@ const gchar *photos_base_manager_get_title (PhotosBaseMana
gchar *photos_base_manager_get_where (PhotosBaseManager *self, gint flags);
+PhotosSparqlTemplate *photos_base_manager_get_sparql_template (PhotosBaseManager *self, gint flags);
+
void photos_base_manager_process_new_objects (PhotosBaseManager *self, GHashTable *new_objects);
void photos_base_manager_remove_object (PhotosBaseManager *self, GObject *object);
diff --git a/src/photos-filterable.c b/src/photos-filterable.c
index 361b1c29..aaa4109c 100644
--- a/src/photos-filterable.c
+++ b/src/photos-filterable.c
@@ -69,14 +69,6 @@ photos_filterable_get_id (PhotosFilterable *self)
}
-gchar *
-photos_filterable_get_where (PhotosFilterable *self)
-{
- g_return_val_if_fail (PHOTOS_IS_FILTERABLE (self), NULL);
- return PHOTOS_FILTERABLE_GET_IFACE (self)->get_where (self);
-}
-
-
gboolean
photos_filterable_is_search_criterion (PhotosFilterable *self)
{
diff --git a/src/photos-filterable.h b/src/photos-filterable.h
index e768bca0..8a3415fc 100644
--- a/src/photos-filterable.h
+++ b/src/photos-filterable.h
@@ -37,7 +37,6 @@ struct _PhotosFilterableInterface
gboolean (*get_builtin) (PhotosFilterable *self);
gchar *(*get_filter) (PhotosFilterable *self);
const gchar *(*get_id) (PhotosFilterable *self);
- gchar *(*get_where) (PhotosFilterable *self);
gboolean (*is_search_criterion) (PhotosFilterable *self);
};
@@ -47,8 +46,6 @@ gchar *photos_filterable_get_filter (PhotosFilterable *self
const gchar *photos_filterable_get_id (PhotosFilterable *self);
-gchar *photos_filterable_get_where (PhotosFilterable *self);
-
gboolean photos_filterable_is_search_criterion (PhotosFilterable *self);
G_END_DECLS
diff --git a/src/photos-query-builder.c b/src/photos-query-builder.c
index 2c52a130..5d9d8a5a 100644
--- a/src/photos-query-builder.c
+++ b/src/photos-query-builder.c
@@ -26,112 +26,76 @@
#include <string.h>
#include "photos-base-manager.h"
+#include "photos-query.h"
#include "photos-query-builder.h"
#include "photos-search-type.h"
#include "photos-source-manager.h"
#include "photos-search-match-manager.h"
#include "photos-search-type-manager.h"
+#define PHOTOS_QUERY_COLLECTIONS_IDENTIFIER "photos:collection:"
+#define PHOTOS_QUERY_LOCAL_COLLECTIONS_IDENTIFIER "photos:collection:local:"
-static gchar *
-photos_query_builder_filter (PhotosSearchContextState *state, gint flags)
-{
- gchar *sparql;
- g_autofree gchar *src_mngr_filter = NULL;
- g_autofree gchar *srch_mtch_mngr_filter = NULL;
- g_autofree gchar *srch_typ_mngr_filter = NULL;
+const gchar *collections_default_filter = \
+ "(fn:starts-with (nao:identifier (?urn), '" PHOTOS_QUERY_COLLECTIONS_IDENTIFIER "')"
+ " || (?urn = nfo:image-category-screenshot))";
- src_mngr_filter = photos_base_manager_get_filter (state->src_mngr, flags);
- srch_mtch_mngr_filter = photos_base_manager_get_filter (state->srch_mtch_mngr, flags);
- srch_typ_mngr_filter = photos_base_manager_get_filter (state->srch_typ_mngr, flags);
- sparql = g_strdup_printf ("FILTER (%s && %s && %s)",
- src_mngr_filter,
- srch_mtch_mngr_filter,
- srch_typ_mngr_filter);
-
- return sparql;
-}
+/* This includes mimetype blocklist */
+const gchar *photos_default_filter = \
+ "(nie:mimeType(?urn) != 'image/gif' && nie:mimeType(?urn) != 'image/x-eps')";
static gchar *
-photos_query_builder_optional (void)
-{
- return g_strdup ("OPTIONAL { ?urn nco:creator ?creator . } "
- "OPTIONAL { ?urn nco:publisher ?publisher . }");
-}
-
-
-static gchar *
-photos_query_builder_inner_where (PhotosSearchContextState *state, gboolean global, gint flags)
+photos_query_builder_query (PhotosSearchContextState *state,
+ gboolean global,
+ gint flags,
+ PhotosOffsetController *offset_cntrlr)
{
- g_autofree gchar *item_mngr_where = NULL;
+ PhotosSparqlTemplate *template;
+ const gchar *projection = NULL;
+ g_autofree gchar *item_pattern = NULL;
+ g_autofree gchar *search_filter = NULL;
+ g_autofree gchar *source_filter = NULL;
+ const gchar *order = NULL;
+ g_autofree gchar *offset_limit = NULL;
gchar *sparql;
- g_autofree gchar *srch_typ_mngr_where = NULL;
- srch_typ_mngr_where = photos_base_manager_get_where (state->srch_typ_mngr, flags);
+ 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) ";
+
+ item_pattern = photos_base_manager_get_where (state->item_mngr, flags);
if (!(flags & PHOTOS_QUERY_FLAGS_UNFILTERED))
{
- if (global)
- {
- /* TODO: SearchCategoryManager */
-
- item_mngr_where = photos_base_manager_get_where (state->item_mngr, flags);
- }
+ source_filter = photos_base_manager_get_filter (state->src_mngr, flags);
+ search_filter = photos_base_manager_get_filter (state->srch_mtch_mngr, flags);
}
- sparql = g_strdup_printf ("WHERE { %s %s }",
- srch_typ_mngr_where,
- (item_mngr_where != NULL) ? item_mngr_where : "");
-
- return sparql;
-}
-
-
-static gchar *
-photos_query_builder_where (PhotosSearchContextState *state, gboolean global, gint flags)
-{
- const gchar *count_items = "COUNT (?item) AS ?count";
- gboolean item_defined;
- g_autofree gchar *filter = NULL;
- g_autofree gchar *optional = NULL;
- gchar *sparql;
- g_autofree gchar *where_sparql = NULL;
-
- where_sparql = photos_query_builder_inner_where (state, global, flags);
- item_defined = strstr (where_sparql, "?item") != NULL;
-
- optional = photos_query_builder_optional ();
-
- if (!(flags & PHOTOS_QUERY_FLAGS_UNFILTERED))
- filter = photos_query_builder_filter (state, flags);
-
- sparql = g_strdup_printf ("WHERE {{"
- " SELECT ?urn rdf:type (?urn) AS ?type %s %s GROUP BY (?urn)"
- " }"
- " %s %s"
- "}",
- item_defined ? count_items : "",
- where_sparql,
- optional,
- (filter != NULL) ? filter : "");
-
- return sparql;
-}
-
-
-static gchar *
-photos_query_builder_query (PhotosSearchContextState *state,
- gboolean global,
- gint flags,
- PhotosOffsetController *offset_cntrlr)
-{
- gchar *sparql;
- g_autofree gchar *tail_sparql = NULL;
- g_autofree gchar *where_sparql = NULL;
-
- where_sparql = photos_query_builder_where (state, global, flags);
+ order = "ORDER BY DESC (?mtime)";
if (global && (flags & PHOTOS_QUERY_FLAGS_UNLIMITED) == 0)
{
@@ -144,35 +108,19 @@ photos_query_builder_query (PhotosSearchContextState *state,
step = photos_offset_controller_get_step (offset_cntrlr);
}
- tail_sparql = g_strdup_printf ("ORDER BY DESC (?mtime) LIMIT %d OFFSET %d", step, offset);
+ offset_limit = g_strdup_printf ("LIMIT %d OFFSET %d", step, offset);
}
- sparql = g_strconcat ("SELECT ?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) ",
- where_sparql,
- tail_sparql,
- NULL);
+ sparql = photos_sparql_template_get_sparql (template,
+ "projection", projection,
+ "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 : "",
+ "order", order,
+ "offset_limit", offset_limit ? offset_limit : "",
+ NULL);
return sparql;
}
@@ -234,12 +182,37 @@ photos_query_builder_collection_icon_query (PhotosSearchContextState *state, con
PhotosQuery *
photos_query_builder_count_query (PhotosSearchContextState *state, gint flags)
{
- PhotosQuery *query;
+ PhotosSparqlTemplate *template;
+ const gchar *projection = NULL;
+ g_autofree gchar *item_pattern = NULL;
+ g_autofree gchar *search_filter = NULL;
+ g_autofree gchar *source_filter = NULL;
g_autofree gchar *sparql = NULL;
- g_autofree gchar *where_sparql = NULL;
+ PhotosQuery *query;
+
+ template = photos_base_manager_get_sparql_template (state->srch_typ_mngr, flags);
+
+ projection = "COUNT(?urn) ";
+
+ item_pattern = photos_base_manager_get_where (state->item_mngr, flags);
+
+ if (! (flags & PHOTOS_QUERY_FLAGS_UNFILTERED))
+ {
+ source_filter = photos_base_manager_get_filter (state->src_mngr, flags);
+ search_filter = photos_base_manager_get_filter (state->srch_mtch_mngr, flags);
+ }
+
+ sparql = photos_sparql_template_get_sparql (template,
+ "projection", projection,
+ "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 : "",
+ "order", "",
+ "offset_limit", "",
+ NULL);
- where_sparql = photos_query_builder_where (state, TRUE, flags);
- sparql = g_strconcat ("SELECT DISTINCT COUNT(?urn) ", where_sparql, NULL);
query = photos_query_new (state, sparql);
return query;
diff --git a/src/photos-search-type-manager.c b/src/photos-search-type-manager.c
index 87f441ed..5c87d4a4 100644
--- a/src/photos-search-type-manager.c
+++ b/src/photos-search-type-manager.c
@@ -41,13 +41,6 @@ struct _PhotosSearchTypeManager
G_DEFINE_TYPE (PhotosSearchTypeManager, photos_search_type_manager, PHOTOS_TYPE_BASE_MANAGER);
-static const gchar *BLACKLISTED_MIME_TYPES[] =
-{
- "image/gif",
- "image/x-eps"
-};
-
-
static gchar *
photos_search_type_manager_get_filter (PhotosBaseManager *mngr, gint flags)
{
@@ -69,9 +62,8 @@ photos_search_type_manager_get_filter (PhotosBaseManager *mngr, gint flags)
return filter;
}
-
-static gchar *
-photos_search_type_manager_get_where (PhotosBaseManager *mngr, gint flags)
+static PhotosSparqlTemplate *
+photos_search_type_manager_get_sparql_template (PhotosBaseManager *mngr, gint flags)
{
GObject *search_type;
@@ -86,74 +78,39 @@ photos_search_type_manager_get_where (PhotosBaseManager *mngr, gint flags)
else
search_type = photos_base_manager_get_object_by_id (mngr, PHOTOS_SEARCH_TYPE_STOCK_ALL);
- return photos_filterable_get_where (PHOTOS_FILTERABLE (search_type));
+ return photos_search_type_get_sparql_template (PHOTOS_SEARCH_TYPE (search_type));
}
-
static void
photos_search_type_manager_init (PhotosSearchTypeManager *self)
{
PhotosSearchType *search_type;
- gchar *item_filter;
- gchar *all_filter;
- gchar *blacklisted_mime_types_filter;
- gchar *col_filter;
- gchar **strv;
- guint i;
- guint n_elements;
-
- n_elements = G_N_ELEMENTS (BLACKLISTED_MIME_TYPES);
- strv = (gchar **) g_malloc0_n (n_elements + 1, sizeof (gchar *));
- for (i = 0; i < n_elements; i++)
- strv[i] = g_strdup_printf ("nie:mimeType(?urn) != '%s'", BLACKLISTED_MIME_TYPES[i]);
-
- blacklisted_mime_types_filter = g_strjoinv (" && ", strv);
-
- item_filter = g_strdup_printf ("(fn:contains (?type, 'nmm#Photo') && %s)", blacklisted_mime_types_filter);
- col_filter = g_strdup_printf ("(fn:contains (?type, 'nfo#DataContainer')"
- " && ?count > 0"
- " && (fn:starts-with (nao:identifier (?urn), '%s')"
- " || (?urn = nfo:image-category-screenshot)))",
- PHOTOS_QUERY_COLLECTIONS_IDENTIFIER);
- all_filter = g_strdup_printf ("(%s || %s)", col_filter, item_filter);
search_type = photos_search_type_new_full (PHOTOS_SEARCH_TYPE_STOCK_ALL,
_("All"),
- "?urn a rdfs:Resource. "
- "OPTIONAL {?item a nmm:Photo; nie:isPartOf ?urn}",
- all_filter);
+ "resource:///org/gnome/Photos/all.sparql.template");
photos_base_manager_add_object (PHOTOS_BASE_MANAGER (self), G_OBJECT (search_type));
g_object_unref (search_type);
search_type = photos_search_type_new_full (PHOTOS_SEARCH_TYPE_STOCK_COLLECTIONS,
_("Albums"),
- "?urn a nfo:DataContainer. "
- "?item a nmm:Photo; nie:isPartOf ?urn.",
- col_filter);
+ "resource:///org/gnome/Photos/collections.sparql.template");
photos_base_manager_add_object (PHOTOS_BASE_MANAGER (self), G_OBJECT (search_type));
g_object_unref (search_type);
search_type = photos_search_type_new_full (PHOTOS_SEARCH_TYPE_STOCK_FAVORITES,
_("Favorites"),
- "?urn a nmm:Photo; nao:hasTag nao:predefined-tag-favorite. ",
- blacklisted_mime_types_filter);
+ "resource:///org/gnome/Photos/favorite-photos.sparql.template");
photos_base_manager_add_object (PHOTOS_BASE_MANAGER (self), G_OBJECT (search_type));
g_object_unref (search_type);
search_type = photos_search_type_new_full (PHOTOS_SEARCH_TYPE_STOCK_PHOTOS,
_("Photos"),
- "?urn a nmm:Photo",
- blacklisted_mime_types_filter);
+ "resource:///org/gnome/Photos/photos.sparql.template");
photos_base_manager_add_object (PHOTOS_BASE_MANAGER (self), G_OBJECT (search_type));
g_object_unref (search_type);
photos_base_manager_set_active_object_by_id (PHOTOS_BASE_MANAGER (self), PHOTOS_SEARCH_TYPE_STOCK_ALL);
-
- g_free (item_filter);
- g_free (all_filter);
- g_free (blacklisted_mime_types_filter);
- g_free (col_filter);
- g_strfreev (strv);
}
@@ -163,7 +120,7 @@ photos_search_type_manager_class_init (PhotosSearchTypeManagerClass *class)
PhotosBaseManagerClass *base_manager_class = PHOTOS_BASE_MANAGER_CLASS (class);
base_manager_class->get_filter = photos_search_type_manager_get_filter;
- base_manager_class->get_where = photos_search_type_manager_get_where;
+ base_manager_class->get_sparql_template = photos_search_type_manager_get_sparql_template;
}
diff --git a/src/photos-search-type.c b/src/photos-search-type.c
index 44dc60eb..f3bbae15 100644
--- a/src/photos-search-type.c
+++ b/src/photos-search-type.c
@@ -25,24 +25,23 @@
#include "photos-filterable.h"
#include "photos-search-type.h"
+#include "photos-sparql-template.h"
struct _PhotosSearchType
{
GObject parent_instance;
- gchar *filter;
gchar *id;
gchar *name;
- gchar *where;
+ PhotosSparqlTemplate *sparql_template;
};
enum
{
PROP_0,
- PROP_FILTER,
PROP_ID,
PROP_NAME,
- PROP_WHERE,
+ PROP_SPARQL_TEMPLATE,
};
static void photos_search_type_filterable_iface_init (PhotosFilterableInterface *iface);
@@ -53,14 +52,6 @@ G_DEFINE_TYPE_WITH_CODE (PhotosSearchType, photos_search_type, G_TYPE_OBJECT,
photos_search_type_filterable_iface_init));
-static gchar *
-photos_search_type_get_filter (PhotosFilterable *iface)
-{
- PhotosSearchType *self = PHOTOS_SEARCH_TYPE (iface);
- return g_strdup (self->filter);
-}
-
-
static const gchar *
photos_search_type_get_id (PhotosFilterable *filterable)
{
@@ -69,14 +60,6 @@ photos_search_type_get_id (PhotosFilterable *filterable)
}
-static gchar *
-photos_search_type_get_where (PhotosFilterable *iface)
-{
- PhotosSearchType *self = PHOTOS_SEARCH_TYPE (iface);
- return g_strdup (self->where);
-}
-
-
static gboolean
photos_search_type_is_search_criterion (PhotosFilterable *iface)
{
@@ -84,15 +67,20 @@ photos_search_type_is_search_criterion (PhotosFilterable *iface)
}
+PhotosSparqlTemplate *
+photos_search_type_get_sparql_template (PhotosSearchType *self)
+{
+ return self->sparql_template;
+}
+
static void
photos_search_type_finalize (GObject *object)
{
PhotosSearchType *self = PHOTOS_SEARCH_TYPE (object);
- g_free (self->filter);
g_free (self->id);
g_free (self->name);
- g_free (self->where);
+ g_clear_object (&self->sparql_template);
G_OBJECT_CLASS (photos_search_type_parent_class)->finalize (object);
}
@@ -113,6 +101,10 @@ photos_search_type_get_property (GObject *object, guint prop_id, GValue *value,
g_value_set_string (value, self->name);
break;
+ case PROP_SPARQL_TEMPLATE:
+ g_value_set_object (value, self->sparql_template);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -127,10 +119,6 @@ photos_search_type_set_property (GObject *object, guint prop_id, const GValue *v
switch (prop_id)
{
- case PROP_FILTER:
- self->filter = g_value_dup_string (value);
- break;
-
case PROP_ID:
self->id = g_value_dup_string (value);
break;
@@ -139,8 +127,8 @@ photos_search_type_set_property (GObject *object, guint prop_id, const GValue *v
self->name = g_value_dup_string (value);
break;
- case PROP_WHERE:
- self->where = g_value_dup_string (value);
+ case PROP_SPARQL_TEMPLATE:
+ self->sparql_template = g_object_ref (g_value_get_object (value));
break;
default:
@@ -165,14 +153,6 @@ photos_search_type_class_init (PhotosSearchTypeClass *class)
object_class->get_property = photos_search_type_get_property;
object_class->set_property = photos_search_type_set_property;
- g_object_class_install_property (object_class,
- PROP_FILTER,
- g_param_spec_string ("filter",
- "",
- "",
- "(true)",
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
-
g_object_class_install_property (object_class,
PROP_ID,
g_param_spec_string ("id",
@@ -190,11 +170,11 @@ photos_search_type_class_init (PhotosSearchTypeClass *class)
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
g_object_class_install_property (object_class,
- PROP_WHERE,
- g_param_spec_string ("where",
- "",
+ PROP_SPARQL_TEMPLATE,
+ g_param_spec_object ("sparql-template",
"",
"",
+ PHOTOS_TYPE_SPARQL_TEMPLATE,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
}
@@ -202,9 +182,7 @@ photos_search_type_class_init (PhotosSearchTypeClass *class)
static void
photos_search_type_filterable_iface_init (PhotosFilterableInterface *iface)
{
- iface->get_filter = photos_search_type_get_filter;
iface->get_id = photos_search_type_get_id;
- iface->get_where = photos_search_type_get_where;
iface->is_search_criterion = photos_search_type_is_search_criterion;
}
@@ -217,12 +195,13 @@ photos_search_type_new (const gchar *id, const gchar *name)
PhotosSearchType *
-photos_search_type_new_full (const gchar *id, const gchar *name, const gchar *where, const gchar *filter)
+photos_search_type_new_full (const gchar *id, const gchar *name, const gchar *template_path)
{
+ g_autoptr (PhotosSparqlTemplate) template = photos_sparql_template_new (template_path);
+
return g_object_new (PHOTOS_TYPE_SEARCH_TYPE,
"id", id,
"name", name,
- "filter", filter,
- "where", where,
+ "sparql-template", template,
NULL);
}
diff --git a/src/photos-search-type.h b/src/photos-search-type.h
index 2f7135bd..7d699dd4 100644
--- a/src/photos-search-type.h
+++ b/src/photos-search-type.h
@@ -24,6 +24,7 @@
#define PHOTOS_SEARCH_TYPE_H
#include <glib-object.h>
+#include "photos-sparql-template.h"
G_BEGIN_DECLS
@@ -39,8 +40,9 @@ PhotosSearchType *photos_search_type_new (const gchar *id, con
PhotosSearchType *photos_search_type_new_full (const gchar *id,
const gchar *name,
- const gchar *where,
- const gchar *filter);
+ const gchar *template_path);
+
+PhotosSparqlTemplate *photos_search_type_get_sparql_template (PhotosSearchType *self);
G_END_DECLS
diff --git a/src/photos-sparql-template.c b/src/photos-sparql-template.c
new file mode 100644
index 00000000..b32437c0
--- /dev/null
+++ b/src/photos-sparql-template.c
@@ -0,0 +1,187 @@
+/*
+ * Photos - access, organize and share your photos on GNOME
+ * Copyright © 2020 Sam Thursfield <sam@afuera.me.uk>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <gio/gio.h>
+
+#include "photos-sparql-template.h"
+
+#define MAX_SPARQL_TEMPLATE_SIZE (1024 * 10)
+
+struct _PhotosSparqlTemplate {
+ GObject parent_instance;
+ gchar *template_path;
+ gchar *template_text;
+};
+
+G_DEFINE_TYPE (PhotosSparqlTemplate, photos_sparql_template, G_TYPE_OBJECT)
+
+enum {
+ PROP_0,
+ PROP_TEMPLATE_PATH,
+ N_PROPS
+};
+
+PhotosSparqlTemplate *
+photos_sparql_template_new (const gchar *template_path)
+{
+ return g_object_new (PHOTOS_TYPE_SPARQL_TEMPLATE, "template-path", template_path, NULL);
+}
+
+static void
+photos_sparql_template_constructed (GObject *object)
+{
+ PhotosSparqlTemplate *self = PHOTOS_SPARQL_TEMPLATE (object);
+ g_autoptr (GFile) file = NULL;
+ g_autoptr (GFileInputStream) stream = NULL;
+ gchar buffer[MAX_SPARQL_TEMPLATE_SIZE + 1];
+ gsize bytes_read;
+ g_autoptr (GError) error = NULL;
+
+ G_OBJECT_CLASS (photos_sparql_template_parent_class)->constructed (object);
+
+ file = g_file_new_for_uri (self->template_path);
+
+ stream = g_file_read (file, NULL, &error);
+
+ if (!stream)
+ {
+ g_critical ("Failed to open template %s: %s", self->template_path, error->message);
+ }
+
+ g_input_stream_read_all (G_INPUT_STREAM (stream), buffer, MAX_SPARQL_TEMPLATE_SIZE, &bytes_read, NULL, &error);
+
+ if (error)
+ {
+ g_critical ("Failed to read template %s: %s", self->template_path, error->message);
+ }
+
+ buffer[bytes_read] = '\0';
+
+ self->template_text = g_strdup (buffer);
+}
+
+static void
+photos_sparql_template_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (photos_sparql_template_parent_class)->finalize (object);
+}
+
+static void
+photos_sparql_template_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ PhotosSparqlTemplate *self = PHOTOS_SPARQL_TEMPLATE (object);
+
+ switch (prop_id)
+ {
+ case PROP_TEMPLATE_PATH:
+ g_value_set_string (value, self->template_path);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+photos_sparql_template_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ PhotosSparqlTemplate *self = PHOTOS_SPARQL_TEMPLATE (object);
+
+ switch (prop_id)
+ {
+ case PROP_TEMPLATE_PATH:
+ self->template_path = g_value_dup_string (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+photos_sparql_template_class_init (PhotosSparqlTemplateClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructed = photos_sparql_template_constructed;
+ object_class->finalize = photos_sparql_template_finalize;
+ object_class->get_property = photos_sparql_template_get_property;
+ object_class->set_property = photos_sparql_template_set_property;
+
+ g_object_class_install_property (object_class,
+ PROP_TEMPLATE_PATH,
+ g_param_spec_string ("template-path",
+ "Template path",
+ "Path to the template file.",
+ NULL,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
+}
+
+static void
+photos_sparql_template_init (PhotosSparqlTemplate *self)
+{
+}
+
+
+gchar *
+photos_sparql_template_get_sparql (PhotosSparqlTemplate *self,
+ const gchar *first_binding_name, ...)
+{
+ va_list va;
+ gchar *sparql;
+
+ sparql = self->template_text;
+
+ /* FIXME: this is an inefficent way to do template substitutions
+ * because we allocate and free a copy of the string for each binding.
+ * We should check https://gitlab.gnome.org/GNOME/template-glib/
+ */
+ if (first_binding_name)
+ {
+ GRegex *regex;
+ gchar *name_regex;
+ const gchar *name;
+ const gchar *value;
+
+ va_start (va, first_binding_name);
+ name = first_binding_name;
+ do {
+ value = va_arg (va, const gchar *);
+
+ if (value == NULL)
+ {
+ g_critical ("Missing value for argument \"%s\"", name);
+ break;
+ }
+
+ name_regex = g_strdup_printf ("{{\\s?%s\\s?}}", name);
+ regex = g_regex_new (name_regex, 0, 0, NULL);
+ sparql = g_regex_replace_literal (regex, sparql, -1, 0, value, 0, NULL) ;
+ } while ((name = va_arg (va, const gchar *)));
+
+ va_end (va);
+ }
+
+ return sparql;
+}
diff --git a/src/photos-sparql-template.h b/src/photos-sparql-template.h
new file mode 100644
index 00000000..66351b38
--- /dev/null
+++ b/src/photos-sparql-template.h
@@ -0,0 +1,38 @@
+/*
+ * Photos - access, organize and share your photos on GNOME
+ * Copyright © 2020 Sam Thursfield <sam@afuera.me.uk>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define PHOTOS_TYPE_SPARQL_TEMPLATE (photos_sparql_template_get_type())
+
+G_DECLARE_FINAL_TYPE (PhotosSparqlTemplate, photos_sparql_template, PHOTOS, SPARQL_TEMPLATE, GObject)
+
+struct _PhotosSparqlTemplateClass
+{
+ GObjectClass parent_class;
+};
+
+PhotosSparqlTemplate *photos_sparql_template_new (const gchar *template_path);
+
+gchar *photos_sparql_template_get_sparql (PhotosSparqlTemplate *self, const gchar *first_binding_name, ...) G_GNUC_NULL_TERMINATED;
+
+G_END_DECLS
diff --git a/src/photos.gresource.xml b/src/photos.gresource.xml
index 1015b11d..39e6d842 100644
--- a/src/photos.gresource.xml
+++ b/src/photos.gresource.xml
@@ -35,6 +35,10 @@
<file alias="selection-toolbar.ui" preprocess="xml-stripblanks" compressed="true">photos-selection-toolbar.ui</file>
<file alias="share-dialog.ui" preprocess="xml-stripblanks" compressed="true">photos-share-dialog.ui</file>
<file alias="zoom-controls.ui" preprocess="xml-stripblanks" compressed="true">photos-zoom-controls.ui</file>
+ <file alias="all.sparql.template">queries/all.sparql.template</file>
+ <file alias="collections.sparql.template">queries/collections.sparql.template</file>
+ <file alias="favorite-photos.sparql.template">queries/favorite-photos.sparql.template</file>
+ <file alias="photos.sparql.template">queries/photos.sparql.template</file>
</gresource>
<gresource prefix="/org/gnome/Photos/gtk">
diff --git a/src/queries/all.sparql.template b/src/queries/all.sparql.template
new file mode 100644
index 00000000..1cef98e8
--- /dev/null
+++ b/src/queries/all.sparql.template
@@ -0,0 +1,31 @@
+SELECT {{projection}}
+{
+ {
+ SELECT {{projection}}
+ {
+ {
+ SELECT ?urn COUNT(?item) AS ?count
+ {
+ ?urn a nfo:DataContainer.
+ ?item a nmm:Photo; nie:isPartOf ?urn.
+ } GROUP BY ?urn
+ }
+ FILTER (?count > 0 && {{collections_default_filter}} && {{search_filter}})
+ }
+ GROUP BY ?urn
+ }
+ UNION
+ {
+ SELECT {{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}})
+ }
+ GROUP BY ?urn
+ }
+}
+{{order}}
+{{offset_limit}}
diff --git a/src/queries/collections.sparql.template b/src/queries/collections.sparql.template
new file mode 100644
index 00000000..20b35cd6
--- /dev/null
+++ b/src/queries/collections.sparql.template
@@ -0,0 +1,14 @@
+SELECT {{projection}}
+{
+ {
+ SELECT ?urn COUNT(?item) AS ?count
+ {
+ ?urn a nfo:DataContainer.
+ ?item a nmm:Photo; nie:isPartOf ?urn.
+ } GROUP BY ?urn
+ }
+ 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
new file mode 100644
index 00000000..0885a08a
--- /dev/null
+++ b/src/queries/favorite-photos.sparql.template
@@ -0,0 +1,12 @@
+SELECT {{projection}}
+{
+ ?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}})
+}
+GROUP BY ?urn
+{{order}}
+{{offset_limit}}
diff --git a/src/queries/photos.sparql.template b/src/queries/photos.sparql.template
new file mode 100644
index 00000000..4eb10b74
--- /dev/null
+++ b/src/queries/photos.sparql.template
@@ -0,0 +1,11 @@
+SELECT {{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}})
+}
+GROUP BY ?urn
+{{order}}
+{{offset_limit}}
--
GitLab
From dbbb76f228bad33334e0574784c34efb7071f950 Mon Sep 17 00:00:00 2001
From: Sam Thursfield <sam@afuera.me.uk>
Date: Sat, 23 May 2020 13:36:25 +0200
Subject: [PATCH 3/3] 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 ++
...e.Photos.Tracker3.Miner.Extract.service.in | 7 +
...ome.Photos.Tracker3.Miner.Files.service.in | 7 +
data/tracker/org.gnome.Photos.domain.rule.in | 20 +
flatpak/org.gnome.Photos.json | 49 +-
meson.build | 3 +-
src/meson.build | 19 +-
...freedesktop.Tracker3.Miner.Files.Index.xml | 11 +
src/org.freedesktop.Tracker3.Miner.xml | 56 +++
src/photos-application.c | 176 ++-----
src/photos-base-item.c | 10 +
src/photos-indexing-notification.c | 53 +-
src/photos-item-manager.c | 69 +--
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 | 2 +-
src/photos-tracker-import-controller.c | 85 ++--
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, 736 insertions(+), 1142 deletions(-)
create mode 100644 data/tracker/meson.build
create mode 100644 data/tracker/org.gnome.Photos.Tracker3.Miner.Extract.service.in
create mode 100644 data/tracker/org.gnome.Photos.Tracker3.Miner.Files.service.in
create mode 100644 data/tracker/org.gnome.Photos.domain.rule.in
create mode 100644 src/org.freedesktop.Tracker3.Miner.Files.Index.xml
create mode 100644 src/org.freedesktop.Tracker3.Miner.xml
delete mode 100644 src/photos-tracker-change-event.c
delete mode 100644 src/photos-tracker-change-event.h
delete mode 100644 src/photos-tracker-change-monitor.c
delete mode 100644 src/photos-tracker-change-monitor.h
delete mode 100644 src/photos-tracker-resources.xml
diff --git a/data/meson.build b/data/meson.build
index f51a4511..9b528c96 100644
--- a/data/meson.build
+++ b/data/meson.build
@@ -83,3 +83,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 4d3ac2a8..adfdaf34 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,8 @@
"--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",
+ "--talk-name=org.freedesktop.Tracker3.Miner.Files.Index",
"--talk-name=com.intel.dleyna-renderer",
"--talk-name=org.gnome.ControlCenter",
"--talk-name=org.gnome.SettingsDaemon",
@@ -248,50 +248,22 @@
}
]
},
- {
- "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": [ "/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"
}
]
},
@@ -303,7 +275,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 ead63250..d20e1289 100644
--- a/meson.build
+++ b/meson.build
@@ -172,8 +172,7 @@ libgdata_dep = dependency('libgdata', version: '>= 0.15.2')
libgfgraph_dep = dependency('libgfbgraph-0.2', version: '>= 0.2.1')
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 b5b2759c..6b3b7f01 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',
)
@@ -401,7 +395,6 @@ deps = common_deps + [
libgdata_dep,
libgfgraph_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 f7b4b56e..7d6758cd 100644
--- a/src/photos-application.c
+++ b/src/photos-application.c
@@ -36,7 +36,6 @@
#include <glib.h>
#include <glib/gi18n.h>
#include <grilo.h>
-#include <libtracker-control/tracker-control.h>
#include "photos-application.h"
#include "photos-base-item.h"
@@ -68,7 +67,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"
@@ -127,8 +127,7 @@ struct _PhotosApplication
PhotosSearchProvider *search_provider;
PhotosSelectionController *sel_cntrlr;
PhotosThumbnailFactory *factory;
- TrackerMinerManager *miner_manager;
- TrackerExtractPriority *extract_priority;
+ TrackerMinerFilesIndex *miner_control_proxy;
gboolean empty_results;
gboolean main_window_deleted;
guint create_miners_count;
@@ -149,7 +148,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));
@@ -174,7 +172,6 @@ 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";
typedef struct _PhotosApplicationCreateData PhotosApplicationCreateData;
typedef struct _PhotosApplicationImportData PhotosApplicationImportData;
@@ -582,27 +579,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)
{
@@ -639,16 +615,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);
- }
}
@@ -738,57 +704,34 @@ 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 (GError) error = NULL;
+ g_autoptr (PhotosTrackerQueue) tracker_queue = NULL;
+ const gchar *miner_fs_control_busname;
+ g_autoptr (GError) error = NULL;
+ TrackerMinerFilesIndex *miner_control_proxy;
- 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);
+ tracker_queue = photos_tracker_queue_dup_singleton (cancellable, &error);
- goto out;
- }
+ if (!tracker_queue) {
+ g_warning ("Error getting Tracker queue: %s. Import will not work.", error->message);
+ return NULL;
}
- 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;
- }
+ 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;
}
- 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));
+ return miner_control_proxy;
}
@@ -826,15 +769,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.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);
+
+ self->miner_control_proxy = photos_application_get_miner_fs_control_proxy (NULL);
return TRUE;
}
@@ -1111,18 +1049,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;
@@ -1345,6 +1283,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[] = { "for-process" };
g_assert_true (G_IS_FILE (destination));
g_set_object (&data->destination, destination);
@@ -1361,11 +1301,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_control_proxy,
+ destination_uri,
+ tracker_priority_graphs,
+ tracker_index_location_flags,
+ NULL,
+ photos_application_import_index_location,
+ g_object_ref (destination));
}
out:
@@ -1529,9 +1471,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_control_proxy)
{
- g_warning ("No TrackerMinerManager, importing from attached devices won't work");
+ g_warning ("No Tracker3.Miner.Files.Index proxy, importing from attached devices won't work");
goto out;
}
@@ -1563,6 +1505,7 @@ photos_application_import (PhotosApplication *self)
gtk_widget_show_all (dialog);
data = photos_application_import_data_new (self, files, ctime_latest);
+
g_signal_connect (dialog,
"response",
G_CALLBACK (photos_application_import_response),
@@ -2234,35 +2177,7 @@ photos_application_share_current (PhotosApplication *self)
static void
photos_application_start_miners (PhotosApplication *self)
{
- {
- g_autoptr (GError) error = NULL;
-
- self->miner_manager = tracker_miner_manager_new_full (TRUE, &error);
- if (error != NULL)
- g_warning ("Unable to create a TrackerMinerManager: %s", error->message);
- }
-
- if (self->miner_manager != NULL)
- {
- GSList *available = NULL;
- GSList *miner_files = NULL;
-
- 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_slist_free_full (available, g_free);
- }
-
- photos_application_create_online_miners (self);
+ photos_application_create_online_miners (self);
}
@@ -2991,6 +2906,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);
@@ -3019,8 +2935,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_manager);
+ g_clear_object (&self->miner_control_proxy);
if (self->state != NULL)
{
@@ -3148,8 +3063,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..4ef69224 100644
--- a/src/photos-base-item.c
+++ b/src/photos-base-item.c
@@ -2756,6 +2756,16 @@ 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 72394983..122d0d91 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.gnome.Photos.Tracker1.Miner.Files";
-
static void
photos_indexing_notification_remove_timeout (PhotosIndexingNotification *self)
@@ -180,16 +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)
- {
- gdouble progress;
+ tracker_miner_call_get_progress_sync (self->miner_fs_proxy, &progress, NULL, &error);
+ if (error) {
+ 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);
- if (progress < 1)
- is_indexing_local = TRUE;
- }
+ g_clear_error (&error);
+ } else {
+ if (progress < 1)
+ is_indexing_local = TRUE;
+ }
app = g_application_get_default ();
miners_running = photos_application_get_miners_running (PHOTOS_APPLICATION (app));
@@ -222,7 +223,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 +240,25 @@ 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 (TRUE, &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 +305,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..4dfe3c7e 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,15 @@ photos_item_manager_changes_pending_foreach (gpointer key, gpointer value, gpoin
static void
-photos_item_manager_changes_pending (PhotosItemManager *self, GHashTable *changes)
-{
- g_hash_table_foreach (changes, photos_item_manager_changes_pending_foreach, self);
+photos_item_manager_changes_pending (PhotosItemManager *self,
+ const gchar *service,
+ const gchar *graph,
+ GPtrArray *events,
+ gpointer user_data)
+{
+ if (g_str_equal (graph, TRACKER_PICTURES_GRAPH)) {
+ g_ptr_array_foreach (events, photos_item_manager_changes_pending_foreach, self);
+ }
}
@@ -717,7 +724,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 +1045,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 +1100,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 +1252,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 +1381,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 5d9d8a5a..9b1baf29 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,
{
GTimeVal tv;
PhotosQuery *query;
+ g_autoptr (TrackerResource) collection = NULL;
g_autofree gchar *identifier = NULL;
g_autofree gchar *sparql = NULL;
g_autofree gchar *time = NULL;
@@ -147,13 +162,14 @@ photos_query_builder_create_collection_query (PhotosSearchContextState *state,
tv.tv_usec = 0;
time = g_time_val_to_iso8601 (&tv);
- 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);
@@ -183,7 +199,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;
@@ -192,7 +210,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);
@@ -203,12 +224,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);
@@ -267,7 +292,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,
@@ -287,7 +312,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;
@@ -316,10 +341,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;
@@ -329,17 +363,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;
@@ -360,7 +391,14 @@ photos_query_builder_update_mtime_query (PhotosSearchContextState *state, const
tv.tv_usec = 0;
time = g_time_val_to_iso8601 (&tv);
- 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-change-event.c b/src/photos-tracker-change-event.c
deleted file mode 100644
index d5c74ebc..00000000
--- a/src/photos-tracker-change-event.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Photos - access, organize and share your photos on GNOME
- * Copyright © 2012 2019 Red Hat, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/* Based on code from:
- * + Documents
- */
-
-
-#include "config.h"
-
-#include "photos-tracker-change-event.h"
-
-
-struct _PhotosTrackerChangeEvent
-{
- PhotosTrackerChangeEventType type;
- gchar *predicate;
- gchar *urn;
- gint32 predicate_id;
- gint32 urn_id;
-};
-
-
-static const gchar *RDF_TYPE = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type";
-
-
-void
-photos_tracker_change_event_free (PhotosTrackerChangeEvent *self)
-{
- g_free (self->predicate);
- g_free (self->urn);
- g_slice_free (PhotosTrackerChangeEvent, self);
-}
-
-
-PhotosTrackerChangeEvent *
-photos_tracker_change_event_new (gint32 urn_id, gint32 predicate_id, gboolean is_delete)
-{
- PhotosTrackerChangeEvent *self;
-
- self = g_slice_new0 (PhotosTrackerChangeEvent);
- self->urn_id = urn_id;
- self->predicate_id = predicate_id;
-
- if (is_delete)
- self->type = PHOTOS_TRACKER_CHANGE_EVENT_DELETED;
- else
- self->type = PHOTOS_TRACKER_CHANGE_EVENT_CREATED;
-
- return self;
-}
-
-
-PhotosTrackerChangeEvent *
-photos_tracker_change_event_copy (PhotosTrackerChangeEvent *event)
-{
- PhotosTrackerChangeEvent *self;
-
- self = g_slice_new0 (PhotosTrackerChangeEvent);
- self->type = event->type;
- self->predicate = g_strdup (event->predicate);
- self->urn = g_strdup (event->urn);
- self->predicate_id = event->predicate_id;
- self->urn_id = event->urn_id;
-
- return self;
-}
-
-
-PhotosTrackerChangeEventType
-photos_tracker_change_event_get_type (PhotosTrackerChangeEvent *self)
-{
- return self->type;
-}
-
-
-gint32
-photos_tracker_change_event_get_predicate_id (PhotosTrackerChangeEvent *self)
-{
- return self->predicate_id;
-}
-
-
-const gchar *
-photos_tracker_change_event_get_urn (PhotosTrackerChangeEvent *self)
-{
- return self->urn;
-}
-
-
-gint32
-photos_tracker_change_event_get_urn_id (PhotosTrackerChangeEvent *self)
-{
- return self->urn_id;
-}
-
-
-void
-photos_tracker_change_event_merge (PhotosTrackerChangeEvent *self, PhotosTrackerChangeEvent *event)
-{
- g_return_if_fail (g_strcmp0 (self->urn, event->urn) == 0);
-
- if (event->type == PHOTOS_TRACKER_CHANGE_EVENT_DELETED || event->type == PHOTOS_TRACKER_CHANGE_EVENT_CREATED)
- self->type = event->type;
-}
-
-
-void
-photos_tracker_change_event_set_resolved_values (PhotosTrackerChangeEvent *self,
- const gchar *urn,
- const gchar *predicate)
-{
- g_return_if_fail (self->predicate == NULL);
- g_return_if_fail (self->urn == NULL);
-
- self->urn = g_strdup (urn);
- self->predicate = g_strdup (predicate);
-
- if (g_strcmp0 (predicate, RDF_TYPE) != 0)
- self->type = PHOTOS_TRACKER_CHANGE_EVENT_CHANGED;
-}
diff --git a/src/photos-tracker-change-event.h b/src/photos-tracker-change-event.h
deleted file mode 100644
index eee4f40c..00000000
--- a/src/photos-tracker-change-event.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Photos - access, organize and share your photos on GNOME
- * Copyright © 2012 2019 Red Hat, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/* Based on code from:
- * + Documents
- */
-
-#ifndef PHOTOS_TRACKER_CHANGE_EVENT_H
-#define PHOTOS_TRACKER_CHANGE_EVENT_H
-
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-typedef enum
-{
- PHOTOS_TRACKER_CHANGE_EVENT_CHANGED,
- PHOTOS_TRACKER_CHANGE_EVENT_CREATED,
- PHOTOS_TRACKER_CHANGE_EVENT_DELETED
-} PhotosTrackerChangeEventType;
-
-typedef struct _PhotosTrackerChangeEvent PhotosTrackerChangeEvent;
-
-PhotosTrackerChangeEvent *photos_tracker_change_event_new (gint32 urn_id,
- gint32 predicate_id,
- gboolean is_delete);
-
-PhotosTrackerChangeEvent *photos_tracker_change_event_copy (PhotosTrackerChangeEvent *event);
-
-void photos_tracker_change_event_free (PhotosTrackerChangeEvent *self);
-
-PhotosTrackerChangeEventType photos_tracker_change_event_get_type (PhotosTrackerChangeEvent *self);
-
-gint32 photos_tracker_change_event_get_predicate_id (PhotosTrackerChangeEvent *self);
-
-const gchar *photos_tracker_change_event_get_urn (PhotosTrackerChangeEvent *self);
-
-gint32 photos_tracker_change_event_get_urn_id (PhotosTrackerChangeEvent *self);
-
-void photos_tracker_change_event_merge (PhotosTrackerChangeEvent *self,
- PhotosTrackerChangeEvent *event);
-
-void photos_tracker_change_event_set_resolved_values (PhotosTrackerChangeEvent *self,
- const gchar *urn,
- const gchar *predicate);
-
-G_END_DECLS
-
-#endif /* PHOTOS_TRACKER_CHANGE_EVENT_H */
diff --git a/src/photos-tracker-change-monitor.c b/src/photos-tracker-change-monitor.c
deleted file mode 100644
index 44c9ffe7..00000000
--- a/src/photos-tracker-change-monitor.c
+++ /dev/null
@@ -1,468 +0,0 @@
-/*
- * Photos - access, organize and share your photos on GNOME
- * Copyright © 2012 2019 Red Hat, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/* Based on code from:
- * + Documents
- */
-
-
-#include "config.h"
-
-#include <glib.h>
-#include <tracker-sparql.h>
-
-#include "photos-tracker-change-event.h"
-#include "photos-tracker-change-monitor.h"
-#include "photos-tracker-queue.h"
-#include "photos-tracker-resources.h"
-#include "photos-query.h"
-
-
-struct _PhotosTrackerChangeMonitor
-{
- GObject parent_instance;
- GHashTable *pending_changes;
- GHashTable *unresolved_ids;
- GQueue *pending_events;
- PhotosTrackerQueue *queue;
- TrackerResources *resource_service;
- guint outstanding_ops;
- guint pending_events_id;
-};
-
-enum
-{
- CHANGES_PENDING,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-static void photos_tracker_change_monitor_initable_iface_init (GInitableIface *iface);
-
-
-G_DEFINE_TYPE_EXTENDED (PhotosTrackerChangeMonitor, photos_tracker_change_monitor, G_TYPE_OBJECT, 0,
- G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, photos_tracker_change_monitor_initable_iface_init));
-
-
-enum
-{
- CHANGE_MONITOR_TIMEOUT = 500, /* ms */
- CHANGE_MONITOR_MAX_ITEMS = 500
-};
-
-
-typedef struct _PhotosTrackerChangeMonitorQueryData PhotosTrackerChangeMonitorQueryData;
-typedef struct _TrackerResourcesEvent TrackerResourcesEvent;
-
-struct _PhotosTrackerChangeMonitorQueryData
-{
- PhotosTrackerChangeMonitor *self;
- GHashTable *id_table;
- GQueue *events;
-};
-
-struct _TrackerResourcesEvent
-{
- gint32 graph;
- gint32 subject;
- gint32 predicate;
- gint32 object;
-};
-
-
-static void
-photos_tracker_change_monitor_query_data_free (PhotosTrackerChangeMonitorQueryData *data)
-{
- g_clear_object (&data->self);
-
- if (data->id_table != NULL)
- g_hash_table_unref (data->id_table);
-
- if (data->events != NULL)
- g_queue_free_full (data->events, (GDestroyNotify) photos_tracker_change_event_free);
-
- g_slice_free (PhotosTrackerChangeMonitorQueryData, data);
-}
-
-
-static PhotosTrackerChangeMonitorQueryData *
-photos_tracker_change_monitor_query_data_new (PhotosTrackerChangeMonitor *self,
- GHashTable *id_table,
- GQueue *events)
-{
- PhotosTrackerChangeMonitorQueryData *data;
-
- data = g_slice_new0 (PhotosTrackerChangeMonitorQueryData);
- data->self = g_object_ref (self);
- data->id_table = id_table;
- data->events = events;
-
- return data;
-}
-
-
-static void
-photos_tracker_change_monitor_add_event (PhotosTrackerChangeMonitor *self, PhotosTrackerChangeEvent *change_event)
-{
- PhotosTrackerChangeEvent *old_change_event;
- const gchar *urn;
-
- urn = photos_tracker_change_event_get_urn (change_event);
- old_change_event = (PhotosTrackerChangeEvent *) g_hash_table_lookup (self->pending_changes, urn);
-
- if (old_change_event != NULL)
- photos_tracker_change_event_merge (old_change_event, change_event);
- else
- g_hash_table_insert (self->pending_changes, g_strdup (urn), photos_tracker_change_event_copy (change_event));
-}
-
-
-static void
-photos_tracker_change_monitor_remove_timeout (PhotosTrackerChangeMonitor *self)
-{
- if (self->pending_events_id != 0)
- {
- g_source_remove (self->pending_events_id);
- self->pending_events_id = 0;
- }
-}
-
-
-static void
-photos_tracker_change_monitor_send_events (PhotosTrackerChangeMonitor *self, GHashTable *id_table, GQueue *events)
-{
- GList *l;
-
- for (l = events->head; l != NULL; l = l->next)
- {
- PhotosTrackerChangeEvent *change_event = (PhotosTrackerChangeEvent *) l->data;
- const gchar *predicate;
- const gchar *urn;
- gint32 predicate_id;
- gint32 urn_id;
-
- predicate_id = photos_tracker_change_event_get_predicate_id (change_event);
- urn_id = photos_tracker_change_event_get_urn_id (change_event);
-
- predicate = (gchar *) g_hash_table_lookup (id_table, GINT_TO_POINTER (predicate_id));
- if (G_UNLIKELY (predicate == NULL))
- continue;
-
- urn = (gchar *) g_hash_table_lookup (id_table, GINT_TO_POINTER (urn_id));
- if (G_UNLIKELY (urn == NULL))
- continue;
-
- photos_tracker_change_event_set_resolved_values (change_event, urn, predicate);
- photos_tracker_change_monitor_add_event (self, change_event);
- }
-
- g_signal_emit (self, signals[CHANGES_PENDING], 0, self->pending_changes);
- g_hash_table_remove_all (self->pending_changes);
-}
-
-
-static void
-photos_tracker_change_monitor_cursor_next (GObject *source_object, GAsyncResult *res, gpointer user_data)
-{
- PhotosTrackerChangeMonitorQueryData *data = (PhotosTrackerChangeMonitorQueryData *) user_data;
- PhotosTrackerChangeMonitor *self = data->self;
- TrackerSparqlCursor *cursor = TRACKER_SPARQL_CURSOR (source_object);
- GHashTableIter iter;
- gboolean valid;
-
- {
- g_autoptr (GError) error = NULL;
-
- valid = tracker_sparql_cursor_next_finish (cursor, res, &error);
- if (error != NULL)
- g_warning ("Unable to resolve item URNs for graph changes: %s", error->message);
- }
-
- if (valid)
- {
- guint idx;
-
- idx = 0;
- g_hash_table_iter_init (&iter, data->id_table);
- while (g_hash_table_iter_next (&iter, NULL, NULL))
- {
- const gchar *str;
-
- str = tracker_sparql_cursor_get_string (cursor, idx, NULL);
- g_hash_table_iter_replace (&iter, g_strdup (str));
- idx++;
- }
-
- photos_tracker_change_monitor_send_events (self, data->id_table, data->events);
- }
-
- tracker_sparql_cursor_close (cursor);
- photos_tracker_change_monitor_query_data_free (data);
-}
-
-
-static void
-photos_tracker_change_monitor_query_executed (GObject *source_object, GAsyncResult *res, gpointer user_data)
-{
- PhotosTrackerChangeMonitorQueryData *data = (PhotosTrackerChangeMonitorQueryData *) user_data;
- TrackerSparqlConnection *connection = TRACKER_SPARQL_CONNECTION (source_object);
- TrackerSparqlCursor *cursor; /* TODO: Use g_autoptr */
-
- {
- g_autoptr (GError) error = NULL;
-
- cursor = tracker_sparql_connection_query_finish (connection, res, &error);
- if (error != NULL)
- {
- g_warning ("Unable to resolve item URNs for graph changes: %s", error->message);
- photos_tracker_change_monitor_query_data_free (data);
- return;
- }
- }
-
- tracker_sparql_cursor_next_async (cursor, NULL, photos_tracker_change_monitor_cursor_next, data);
- g_object_unref (cursor);
-}
-
-
-static gboolean
-photos_tracker_change_monitor_process_events (PhotosTrackerChangeMonitor *self)
-{
- GHashTable *id_table;
- GHashTableIter iter;
- GQueue *events;
- g_autoptr (GString) sparql = NULL;
- PhotosTrackerChangeMonitorQueryData *data;
- g_autoptr (PhotosQuery) query = NULL;
- gpointer id;
-
- events = self->pending_events;
- self->pending_events = g_queue_new ();
-
- id_table = self->unresolved_ids;
- self->unresolved_ids = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
-
- self->pending_events_id = 0;
-
- sparql = g_string_new ("SELECT");
-
- g_hash_table_iter_init (&iter, id_table);
- while (g_hash_table_iter_next (&iter, &id, NULL))
- g_string_append_printf (sparql, " tracker:uri(%d)", GPOINTER_TO_INT (id));
-
- g_string_append (sparql, " {}");
-
- query = photos_query_new (NULL, sparql->str);
-
- data = photos_tracker_change_monitor_query_data_new (self, id_table, events);
- photos_tracker_queue_select (self->queue,
- query,
- NULL,
- photos_tracker_change_monitor_query_executed,
- data,
- NULL);
-
- return G_SOURCE_REMOVE;
-}
-
-
-static void
-photos_tracker_change_monitor_add_pending_event (PhotosTrackerChangeMonitor *self,
- const TrackerResourcesEvent *event,
- gboolean is_delete)
-{
- PhotosTrackerChangeEvent *change_event;
-
- photos_tracker_change_monitor_remove_timeout (self);
-
- g_hash_table_insert (self->unresolved_ids, GINT_TO_POINTER (event->subject), NULL);
- g_hash_table_insert (self->unresolved_ids, GINT_TO_POINTER (event->predicate), NULL);
-
- change_event = photos_tracker_change_event_new (event->subject, event->predicate, is_delete);
- g_queue_push_tail (self->pending_events, change_event);
-
- if (self->pending_events->length >= CHANGE_MONITOR_MAX_ITEMS)
- photos_tracker_change_monitor_process_events (self);
- else
- self->pending_events_id = g_timeout_add (CHANGE_MONITOR_TIMEOUT,
- (GSourceFunc) photos_tracker_change_monitor_process_events,
- self);
-}
-
-
-static void
-photos_tracker_change_monitor_graph_updated (TrackerResources *resource_service,
- const gchar *class_name,
- GVariant *delete_events,
- GVariant *insert_events,
- gpointer user_data)
-{
- PhotosTrackerChangeMonitor *self = PHOTOS_TRACKER_CHANGE_MONITOR (user_data);
- const TrackerResourcesEvent *events;
- gsize i;
- gsize n_elements;
-
- events = (const TrackerResourcesEvent *) g_variant_get_fixed_array (delete_events,
- &n_elements,
- sizeof (TrackerResourcesEvent));
- for (i = 0; i < n_elements; i++)
- photos_tracker_change_monitor_add_pending_event (self, &events[i], TRUE);
-
- events = (const TrackerResourcesEvent *) g_variant_get_fixed_array (insert_events,
- &n_elements,
- sizeof (TrackerResourcesEvent));
- for (i = 0; i < n_elements; i++)
- photos_tracker_change_monitor_add_pending_event (self, &events[i], FALSE);
-}
-
-
-static GObject *
-photos_tracker_change_monitor_constructor (GType type,
- guint n_construct_params,
- GObjectConstructParam *construct_params)
-{
- static GObject *self = NULL;
-
- if (self == NULL)
- {
- self = G_OBJECT_CLASS (photos_tracker_change_monitor_parent_class)->constructor (type,
- n_construct_params,
- construct_params);
- g_object_add_weak_pointer (self, (gpointer) &self);
- return self;
- }
-
- return g_object_ref (self);
-}
-
-
-static void
-photos_tracker_change_monitor_dispose (GObject *object)
-{
- PhotosTrackerChangeMonitor *self = PHOTOS_TRACKER_CHANGE_MONITOR (object);
-
- photos_tracker_change_monitor_remove_timeout (self);
-
- g_clear_object (&self->queue);
- g_clear_object (&self->resource_service);
-
- G_OBJECT_CLASS (photos_tracker_change_monitor_parent_class)->dispose (object);
-}
-
-
-static void
-photos_tracker_change_monitor_finalize (GObject *object)
-{
- PhotosTrackerChangeMonitor *self = PHOTOS_TRACKER_CHANGE_MONITOR (object);
-
- g_hash_table_unref (self->pending_changes);
- g_hash_table_unref (self->unresolved_ids);
-
- g_queue_free_full (self->pending_events, (GDestroyNotify) photos_tracker_change_event_free);
-
- G_OBJECT_CLASS (photos_tracker_change_monitor_parent_class)->finalize (object);
-}
-
-
-static void
-photos_tracker_change_monitor_init (PhotosTrackerChangeMonitor *self)
-{
- self->pending_changes = g_hash_table_new_full (g_str_hash,
- g_str_equal,
- g_free,
- (GDestroyNotify) photos_tracker_change_event_free);
-
- self->unresolved_ids = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
-
- self->pending_events = g_queue_new ();
-}
-
-
-static void
-photos_tracker_change_monitor_class_init (PhotosTrackerChangeMonitorClass *class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (class);
-
- object_class->constructor = photos_tracker_change_monitor_constructor;
- object_class->dispose = photos_tracker_change_monitor_dispose;
- object_class->finalize = photos_tracker_change_monitor_finalize;
-
- signals[CHANGES_PENDING] = g_signal_new ("changes-pending",
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, /*accumulator */
- NULL, /*accu_data */
- g_cclosure_marshal_VOID__BOXED,
- G_TYPE_NONE,
- 1,
- G_TYPE_HASH_TABLE);
-}
-
-
-static gboolean
-photos_tracker_change_monitor_initable_init (GInitable *initable, GCancellable *cancellable, GError **error)
-{
- PhotosTrackerChangeMonitor *self = PHOTOS_TRACKER_CHANGE_MONITOR (initable);
- gboolean ret_val = TRUE;
-
- if (G_LIKELY (self->queue != NULL && self->resource_service != NULL))
- goto out;
-
- self->queue = photos_tracker_queue_dup_singleton (cancellable, error);
- if (G_UNLIKELY (self->queue == NULL))
- {
- ret_val = FALSE;
- goto out;
- }
-
- self->resource_service = tracker_resources_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
- G_DBUS_PROXY_FLAGS_NONE,
- "org.gnome.Photos.Tracker1",
- "/org/freedesktop/Tracker1/Resources",
- cancellable,
- error);
- if (G_UNLIKELY (self->resource_service == NULL))
- {
- ret_val = FALSE;
- goto out;
- }
-
- g_signal_connect (self->resource_service,
- "graph-updated",
- G_CALLBACK (photos_tracker_change_monitor_graph_updated),
- self);
-
- out:
- return ret_val;
-}
-
-
-static void
-photos_tracker_change_monitor_initable_iface_init (GInitableIface *iface)
-{
- iface->init = photos_tracker_change_monitor_initable_init;
-}
-
-
-PhotosTrackerChangeMonitor *
-photos_tracker_change_monitor_dup_singleton (GCancellable *cancellable, GError **error)
-{
- return g_initable_new (PHOTOS_TYPE_TRACKER_CHANGE_MONITOR, cancellable, error, NULL);
-}
diff --git a/src/photos-tracker-change-monitor.h b/src/photos-tracker-change-monitor.h
deleted file mode 100644
index 9740b046..00000000
--- a/src/photos-tracker-change-monitor.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Photos - access, organize and share your photos on GNOME
- * Copyright © 2012 2019 Red Hat, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/* Based on code from:
- * + Documents
- */
-
-#ifndef PHOTOS_TRACKER_CHANGE_MONITOR_H
-#define PHOTOS_TRACKER_CHANGE_MONITOR_H
-
-#include <gio/gio.h>
-
-G_BEGIN_DECLS
-
-#define PHOTOS_TYPE_TRACKER_CHANGE_MONITOR (photos_tracker_change_monitor_get_type ())
-G_DECLARE_FINAL_TYPE (PhotosTrackerChangeMonitor,
- photos_tracker_change_monitor,
- PHOTOS,
- TRACKER_CHANGE_MONITOR,
- GObject);
-
-PhotosTrackerChangeMonitor *photos_tracker_change_monitor_dup_singleton (GCancellable *cancellable,
- GError **error);
-
-G_END_DECLS
-
-#endif /* PHOTOS_TRACKER_CHANGE_MONITOR_H */
diff --git a/src/photos-tracker-controller.c b/src/photos-tracker-controller.c
index a02db077..6d0053a1 100644
--- a/src/photos-tracker-controller.c
+++ b/src/photos-tracker-controller.c
@@ -292,6 +292,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);
@@ -303,12 +309,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-extract-priority.xml b/src/photos-tracker-extract-priority.xml
index 7e3b9b0c..2b562299 100644
--- a/src/photos-tracker-extract-priority.xml
+++ b/src/photos-tracker-extract-priority.xml
@@ -21,7 +21,7 @@
-->
<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
- <interface name="org.freedesktop.Tracker1.Extract.Priority">
+ <interface name="org.freedesktop.Tracker3.Extract.Priority">
<method name="ClearRdfTypes" />
<method name="SetRdfTypes">
<arg name="rdf_types" type="as" direction="in" />
diff --git a/src/photos-tracker-import-controller.c b/src/photos-tracker-import-controller.c
index 9f130714..d7ed9b20 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[] = { "for-process" };
{
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,37 @@ 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 +434,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 (TRUE, &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 76d25d5d..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,13 +399,49 @@ photos_tracker_queue_initable_init (GInitable *initable, GCancellable *cancellab
g_assert_no_error (self->initialization_error);
- tracker_sparql_connection_set_domain ("org.gnome.Photos");
+ /* 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);
- self->connection = tracker_sparql_connection_get (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;
@@ -321,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);
}
@@ -353,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-tracker-resources.xml b/src/photos-tracker-resources.xml
deleted file mode 100644
index 18177aa0..00000000
--- a/src/photos-tracker-resources.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<!DOCTYPE node PUBLIC
-"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
-"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
-
-<!--
- Photos - access, organize and share your photos on GNOME
- Copyright © 2012 2019 Red Hat, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
--->
-
-<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
- <interface name="org.freedesktop.Tracker1.Resources">
- <signal name="GraphUpdated">
- <arg name="className" type="s" />
- <arg name="deleteEvents" type="a(iiii)" />
- <arg name="insertEvents" type="a(iiii)" />
- </signal>
- </interface>
-</node>
diff --git a/src/photos-utils.c b/src/photos-utils.c
index d659b47d..72d2e98b 100644
--- a/src/photos-utils.c
+++ b/src/photos-utils.c
@@ -1324,7 +1324,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);
{
@@ -1352,9 +1358,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}}
--
GitLab