[gnome-photos/wip/rishi/tracker-sparql-templates] Generate queries using SPARQL templates




commit 9d7113a50b130c51e420be09c8b9996d1fdd7e0b
Author: Sam Thursfield <sam afuera me uk>
Date:   Sun Jun 7 21:53:20 2020 +0200

    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 template substitution is used
    to build the SPARQL that's sent to Tracker.
    
    As a side effect, the SPARQL for the builtin "all" SearchType now uses
    a UNION of the equivalent SPARQLs for collections and items, instead of
    looking for all instances rdfs:Resource and then using a FILTER to weed
    out the irrelevant entries in the Tracker database.
    
    https://gitlab.gnome.org/GNOME/gnome-photos/-/merge_requests/163

 src/meson.build                              |   4 +
 src/photos-base-manager.c                    |  16 +++
 src/photos-base-manager.h                    |   5 +-
 src/photos-filterable.c                      |   8 --
 src/photos-filterable.h                      |   3 -
 src/photos-query-all.sparql.template         |  49 +++++++
 src/photos-query-builder.c                   | 188 +++++++++++----------------
 src/photos-query-collections.sparql.template |  33 +++++
 src/photos-query-favorites.sparql.template   |  27 ++++
 src/photos-query-photos.sparql.template      |  27 ++++
 src/photos-search-type-manager.c             | 134 ++++++-------------
 src/photos-search-type.c                     |  75 +++++------
 src/photos-search-type.h                     |   7 +-
 src/photos.gresource.xml                     |   7 +
 14 files changed, 321 insertions(+), 262 deletions(-)
---
diff --git a/src/meson.build b/src/meson.build
index d8fc4b6d..bf48e374 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -285,6 +285,10 @@ resource_data = files(
   'photos-main-window.ui',
   'photos-preview-menu.ui',
   'photos-primary-menu.ui',
+  'photos-query-all.sparql.template',
+  'photos-query-collections.sparql.template',
+  'photos-query-favorites.sparql.template',
+  'photos-query-photos.sparql.template',
   'photos-removable-devices-button.ui',
   'photos-removable-device-widget.ui',
   'photos-selection-menu.ui',
diff --git a/src/photos-base-manager.c b/src/photos-base-manager.c
index d49d19a5..73cb1d4b 100644
--- a/src/photos-base-manager.c
+++ b/src/photos-base-manager.c
@@ -243,6 +243,13 @@ photos_base_manager_default_get_previous_object (PhotosBaseManager *self, GObjec
 }
 
 
+static PhotosSparqlTemplate *
+photos_base_manager_default_get_sparql_template (PhotosBaseManager *self, gint flags)
+{
+  return NULL;
+}
+
+
 static gchar *
 photos_base_manager_default_get_where (PhotosBaseManager *self, gint flags)
 {
@@ -437,6 +444,7 @@ photos_base_manager_class_init (PhotosBaseManagerClass *class)
   class->get_next_object = photos_base_manager_default_get_next_object;
   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_sparql_template = photos_base_manager_default_get_sparql_template;
   class->get_where = photos_base_manager_default_get_where;
   class->remove_object_by_id = photos_base_manager_default_remove_object_by_id;
   class->set_active_object = photos_base_manager_default_set_active_object;
@@ -694,6 +702,14 @@ photos_base_manager_get_previous_object (PhotosBaseManager *self, GObject *objec
 }
 
 
+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);
+}
+
+
 const gchar *
 photos_base_manager_get_title (PhotosBaseManager *self)
 {
diff --git a/src/photos-base-manager.h b/src/photos-base-manager.h
index 99d203e9..4e0a9f89 100644
--- a/src/photos-base-manager.h
+++ b/src/photos-base-manager.h
@@ -23,7 +23,7 @@
 #ifndef PHOTOS_BASE_MANAGER_H
 #define PHOTOS_BASE_MANAGER_H
 
-#include <glib-object.h>
+#include "photos-sparql-template.h"
 
 G_BEGIN_DECLS
 
@@ -43,6 +43,7 @@ struct _PhotosBaseManagerClass
   GObject       *(*get_next_object)        (PhotosBaseManager *self, GObject *object);
   GObject       *(*get_object_by_id)       (PhotosBaseManager *self, const gchar *id);
   GObject       *(*get_previous_object)    (PhotosBaseManager *self, GObject *object);
+  PhotosSparqlTemplate *(*get_sparql_template) (PhotosBaseManager *self, gint flags);
   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);
@@ -76,6 +77,8 @@ guint               photos_base_manager_get_objects_count        (PhotosBaseMana
 
 GObject            *photos_base_manager_get_previous_object      (PhotosBaseManager *self, GObject *object);
 
+PhotosSparqlTemplate *photos_base_manager_get_sparql_template    (PhotosBaseManager *self, gint flags);
+
 const gchar        *photos_base_manager_get_title                (PhotosBaseManager *self);
 
 gchar              *photos_base_manager_get_where                (PhotosBaseManager *self, gint flags);
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-all.sparql.template b/src/photos-query-all.sparql.template
new file mode 100644
index 00000000..21efec24
--- /dev/null
+++ b/src/photos-query-all.sparql.template
@@ -0,0 +1,49 @@
+# 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/>.
+#
+
+SELECT {{projection}}
+{
+    {
+        SELECT ?urn
+        {
+            {
+                SELECT ?urn COUNT(?item) AS ?count
+                {
+                    ?urn a nfo:DataContainer.
+                    ?item a nmm:Photo; nie:isPartOf ?urn.
+                }
+                GROUP BY ?urn
+            }
+            OPTIONAL { ?urn nco:creator ?creator . }
+            OPTIONAL { ?urn nco:publisher ?publisher . }
+            FILTER (?count > 0 && {{collections_filter}} && {{search_match_filter}})
+        }
+    }
+    UNION
+    {
+        SELECT ?urn
+        {
+            ?urn a nmm:Photo .
+            OPTIONAL { ?urn nco:creator ?creator . }
+            OPTIONAL { ?urn nco:publisher ?publisher . }
+            {{item_where}}
+            FILTER ({{blocked_mime_types_filter}} && {{source_filter}} && {{search_match_filter}})
+        }
+    }
+}
+{{order}}
+{{offset_limit}}
diff --git a/src/photos-query-builder.c b/src/photos-query-builder.c
index 6b996811..b27ef9e1 100644
--- a/src/photos-query-builder.c
+++ b/src/photos-query-builder.c
@@ -33,43 +33,51 @@
 #include "photos-search-type-manager.h"
 
 
-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;
-
-  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);
+static const gchar *BLOCKED_MIME_TYPES_FILTER = "(nie:mimeType(?urn) != 'image/gif' && nie:mimeType(?urn) != 
'image/x-eps')";
 
-  return sparql;
-}
-
-
-static gchar *
-photos_query_builder_optional (void)
-{
-  return g_strdup ("OPTIONAL { ?urn nco:creator ?creator . } "
-                   "OPTIONAL { ?urn nco:publisher ?publisher . }");
-}
+static const gchar *COLLECTIONS_FILTER
+  = "(fn:starts-with (nao:identifier (?urn), '" PHOTOS_QUERY_COLLECTIONS_IDENTIFIER "')"
+    " || (?urn = nfo:image-category-screenshot))";
 
 
 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)
 {
+  PhotosSparqlTemplate *sparql_template;
+  const gchar *projection
+    = "?urn "
+      "nie:url (?urn) "
+      "nfo:fileName (?urn) "
+      "nie:mimeType (?urn) "
+      "nie:title (?urn) "
+      "tracker:coalesce (nco:fullname (?creator), nco:fullname (?publisher), '') "
+      "tracker:coalesce (nfo:fileLastModified (?urn), nie:contentLastModified (?urn)) AS ?mtime "
+      "nao:identifier (?urn) "
+      "rdf:type (?urn) "
+      "nie:dataSource(?urn) "
+      "( 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) ";
   g_autofree gchar *item_mngr_where = NULL;
+  g_autofree gchar *srch_mtch_mngr_filter = NULL;
+  g_autofree gchar *src_mngr_filter = 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);
+  sparql_template = photos_base_manager_get_sparql_template (state->srch_typ_mngr, flags);
 
   if (!(flags & PHOTOS_QUERY_FLAGS_UNFILTERED))
     {
@@ -79,59 +87,10 @@ photos_query_builder_inner_where (PhotosSearchContextState *state, gboolean glob
 
           item_mngr_where = photos_base_manager_get_where (state->item_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);
+      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);
+    }
 
   if (global && (flags & PHOTOS_QUERY_FLAGS_UNLIMITED) == 0)
     {
@@ -144,35 +103,20 @@ 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 (sparql_template,
+                                         "blocked_mime_types_filter", BLOCKED_MIME_TYPES_FILTER,
+                                         "collections_filter", COLLECTIONS_FILTER,
+                                         "item_where", item_mngr_where == NULL ? "" : item_mngr_where,
+                                         "order", "ORDER BY DESC (?mtime)",
+                                         "offset_limit", offset_limit ? offset_limit : "",
+                                         "projection", projection,
+                                         "search_match_filter", srch_mtch_mngr_filter == NULL ? "(true)" : 
srch_mtch_mngr_filter,
+                                         "source_filter", src_mngr_filter == NULL ? "(true)" : 
src_mngr_filter,
+                                         NULL);
 
   return sparql;
 }
@@ -232,11 +176,33 @@ PhotosQuery *
 photos_query_builder_count_query (PhotosSearchContextState *state, gint flags)
 {
   PhotosQuery *query;
+  PhotosSparqlTemplate *sparql_template;
+  g_autofree gchar *item_mngr_where = NULL;
+  g_autofree gchar *src_mngr_filter = NULL;
+  g_autofree gchar *srch_mtch_mngr_filter = NULL;
   g_autofree gchar *sparql = NULL;
-  g_autofree gchar *where_sparql = NULL;
 
-  where_sparql = photos_query_builder_where (state, TRUE, flags);
-  sparql = g_strconcat ("SELECT DISTINCT COUNT(?urn) ", where_sparql, NULL);
+  sparql_template = photos_base_manager_get_sparql_template (state->srch_typ_mngr, flags);
+
+  if ((flags & PHOTOS_QUERY_FLAGS_UNFILTERED) == 0)
+    {
+      item_mngr_where = photos_base_manager_get_where (state->item_mngr, flags);
+      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);
+    }
+
+  sparql
+    = photos_sparql_template_get_sparql (sparql_template,
+                                         "blocked_mime_types_filter", BLOCKED_MIME_TYPES_FILTER,
+                                         "collections_filter", COLLECTIONS_FILTER,
+                                         "item_where", item_mngr_where == NULL ? "" : item_mngr_where,
+                                         "order", "",
+                                         "offset_limit", "",
+                                         "projection", "COUNT(?urn)",
+                                         "search_match_filter", srch_mtch_mngr_filter == NULL ? "(true)" : 
srch_mtch_mngr_filter,
+                                         "source_filter", src_mngr_filter == NULL ? "(true)" : 
src_mngr_filter,
+                                         NULL);
+
   query = photos_query_new (state, sparql);
 
   return query;
diff --git a/src/photos-query-collections.sparql.template b/src/photos-query-collections.sparql.template
new file mode 100644
index 00000000..cbe0cce8
--- /dev/null
+++ b/src/photos-query-collections.sparql.template
@@ -0,0 +1,33 @@
+# 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/>.
+#
+
+SELECT {{projection}}
+{
+    {
+        SELECT ?urn COUNT(?item) AS ?count
+        {
+            ?urn a nfo:DataContainer.
+            ?item a nmm:Photo; nie:isPartOf ?urn.
+        }
+        GROUP BY ?urn
+    }
+    OPTIONAL { ?urn nco:creator ?creator . }
+    OPTIONAL { ?urn nco:publisher ?publisher . }
+    FILTER (?count > 0 && {{collections_filter}} && {{search_match_filter}})
+}
+{{order}}
+{{offset_limit}}
diff --git a/src/photos-query-favorites.sparql.template b/src/photos-query-favorites.sparql.template
new file mode 100644
index 00000000..61bd1d88
--- /dev/null
+++ b/src/photos-query-favorites.sparql.template
@@ -0,0 +1,27 @@
+# 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/>.
+#
+
+SELECT {{projection}}
+{
+    ?urn a nmm:Photo; nao:hasTag nao:predefined-tag-favorite .
+    OPTIONAL { ?urn nco:creator ?creator . }
+    OPTIONAL { ?urn nco:publisher ?publisher . }
+    {{item_where}}
+    FILTER ({{blocked_mime_types_filter}} && {{source_filter}} && {{search_match_filter}})
+}
+{{order}}
+{{offset_limit}}
diff --git a/src/photos-query-photos.sparql.template b/src/photos-query-photos.sparql.template
new file mode 100644
index 00000000..9abf1f35
--- /dev/null
+++ b/src/photos-query-photos.sparql.template
@@ -0,0 +1,27 @@
+# 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/>.
+#
+
+SELECT {{projection}}
+{
+    ?urn a nmm:Photo .
+    OPTIONAL { ?urn nco:creator ?creator . }
+    OPTIONAL { ?urn nco:publisher ?publisher . }
+    {{item_where}}
+    FILTER ({{blocked_mime_types_filter}} && {{source_filter}} && {{search_match_filter}})
+}
+{{order}}
+{{offset_limit}}
diff --git a/src/photos-search-type-manager.c b/src/photos-search-type-manager.c
index 0ea98aba..76a86fe0 100644
--- a/src/photos-search-type-manager.c
+++ b/src/photos-search-type-manager.c
@@ -26,7 +26,6 @@
 #include <glib.h>
 #include <glib/gi18n.h>
 
-#include "photos-filterable.h"
 #include "photos-query.h"
 #include "photos-search-type.h"
 #include "photos-search-type-manager.h"
@@ -41,18 +40,11 @@ struct _PhotosSearchTypeManager
 G_DEFINE_TYPE (PhotosSearchTypeManager, photos_search_type_manager, PHOTOS_TYPE_BASE_MANAGER);
 
 
-static const gchar *BLOCKED_MIME_TYPES[] =
-{
-  "image/gif",
-  "image/x-eps"
-};
-
-
-static gchar *
-photos_search_type_manager_get_filter (PhotosBaseManager *mngr, gint flags)
+static PhotosSparqlTemplate *
+photos_search_type_manager_get_sparql_template (PhotosBaseManager *mngr, gint flags)
 {
   GObject *search_type;
-  gchar *filter;
+  PhotosSparqlTemplate *sparql_template;
 
   if (flags & PHOTOS_QUERY_FLAGS_COLLECTIONS)
     search_type = photos_base_manager_get_object_by_id (mngr, PHOTOS_SEARCH_TYPE_STOCK_COLLECTIONS);
@@ -65,95 +57,53 @@ photos_search_type_manager_get_filter (PhotosBaseManager *mngr, gint flags)
   else
     search_type = photos_base_manager_get_object_by_id (mngr, PHOTOS_SEARCH_TYPE_STOCK_ALL);
 
-  filter = photos_filterable_get_filter (PHOTOS_FILTERABLE (search_type));
-  return filter;
+  sparql_template = photos_search_type_get_sparql_template (PHOTOS_SEARCH_TYPE (search_type));
+  return sparql_template;
 }
 
 
-static gchar *
-photos_search_type_manager_get_where (PhotosBaseManager *mngr, gint flags)
+static void
+photos_search_type_manager_init (PhotosSearchTypeManager *self)
 {
-  GObject *search_type;
+  PhotosSearchType *search_type;
 
-  if (flags & PHOTOS_QUERY_FLAGS_COLLECTIONS)
-    search_type = photos_base_manager_get_object_by_id (mngr, PHOTOS_SEARCH_TYPE_STOCK_COLLECTIONS);
-  else if (flags & PHOTOS_QUERY_FLAGS_FAVORITES)
-    search_type = photos_base_manager_get_object_by_id (mngr, PHOTOS_SEARCH_TYPE_STOCK_FAVORITES);
-  else if (flags & PHOTOS_QUERY_FLAGS_IMPORT || flags & PHOTOS_QUERY_FLAGS_OVERVIEW)
-    search_type = photos_base_manager_get_object_by_id (mngr, PHOTOS_SEARCH_TYPE_STOCK_PHOTOS);
-  else if (flags & PHOTOS_QUERY_FLAGS_SEARCH)
-    search_type = photos_base_manager_get_active_object (mngr);
-  else
-    search_type = photos_base_manager_get_object_by_id (mngr, PHOTOS_SEARCH_TYPE_STOCK_ALL);
+  {
+    g_autoptr (PhotosSparqlTemplate) sparql_template = NULL;
 
-  return photos_filterable_get_where (PHOTOS_FILTERABLE (search_type));
-}
+    sparql_template = photos_sparql_template_new ("resource:///org/gnome/Photos/query/all.sparql.template");
+    search_type = photos_search_type_new (PHOTOS_SEARCH_TYPE_STOCK_ALL, _("All"), sparql_template);
+    photos_base_manager_add_object (PHOTOS_BASE_MANAGER (self), G_OBJECT (search_type));
+    g_object_unref (search_type);
+  }
 
+  {
+    g_autoptr (PhotosSparqlTemplate) sparql_template = NULL;
 
-static void
-photos_search_type_manager_init (PhotosSearchTypeManager *self)
-{
-  PhotosSearchType *search_type;
-  gchar *item_filter;
-  gchar *all_filter;
-  gchar *blocked_mime_types_filter;
-  gchar *col_filter;
-  gchar **strv;
-  guint i;
-  guint n_elements;
-
-  n_elements = G_N_ELEMENTS (BLOCKED_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'", BLOCKED_MIME_TYPES[i]);
-
-  blocked_mime_types_filter = g_strjoinv (" && ", strv);
-
-  item_filter = g_strdup_printf ("(fn:contains (?type, 'nmm#Photo') && %s)", blocked_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 (PHOTOS_SEARCH_TYPE_STOCK_ALL,
-                                        _("All"),
-                                        "?urn a rdfs:Resource. "
-                                        "OPTIONAL {?item a nmm:Photo; nie:isPartOf ?urn}",
-                                        all_filter);
-  photos_base_manager_add_object (PHOTOS_BASE_MANAGER (self), G_OBJECT (search_type));
-  g_object_unref (search_type);
-
-  search_type = photos_search_type_new (PHOTOS_SEARCH_TYPE_STOCK_COLLECTIONS,
-                                        _("Albums"),
-                                        "?urn a nfo:DataContainer. "
-                                        "?item a nmm:Photo; nie:isPartOf ?urn.",
-                                        col_filter);
-  photos_base_manager_add_object (PHOTOS_BASE_MANAGER (self), G_OBJECT (search_type));
-  g_object_unref (search_type);
-
-  search_type = photos_search_type_new (PHOTOS_SEARCH_TYPE_STOCK_FAVORITES,
-                                        _("Favorites"),
-                                        "?urn a nmm:Photo; nao:hasTag nao:predefined-tag-favorite. ",
-                                        blocked_mime_types_filter);
-  photos_base_manager_add_object (PHOTOS_BASE_MANAGER (self), G_OBJECT (search_type));
-  g_object_unref (search_type);
-
-  search_type = photos_search_type_new (PHOTOS_SEARCH_TYPE_STOCK_PHOTOS,
-                                        _("Photos"),
-                                        "?urn a nmm:Photo",
-                                        blocked_mime_types_filter);
-  photos_base_manager_add_object (PHOTOS_BASE_MANAGER (self), G_OBJECT (search_type));
-  g_object_unref (search_type);
+    sparql_template = photos_sparql_template_new 
("resource:///org/gnome/Photos/query/collections.sparql.template");
+    search_type = photos_search_type_new (PHOTOS_SEARCH_TYPE_STOCK_COLLECTIONS, _("Albums"), 
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_autoptr (PhotosSparqlTemplate) sparql_template = NULL;
+
+    sparql_template = photos_sparql_template_new 
("resource:///org/gnome/Photos/query/favorites.sparql.template");
+    search_type = photos_search_type_new (PHOTOS_SEARCH_TYPE_STOCK_FAVORITES, _("Favorites"), 
sparql_template);
+    photos_base_manager_add_object (PHOTOS_BASE_MANAGER (self), G_OBJECT (search_type));
+    g_object_unref (search_type);
+  }
+
+  {
+    g_autoptr (PhotosSparqlTemplate) sparql_template = NULL;
 
-  g_free (item_filter);
-  g_free (all_filter);
-  g_free (blocked_mime_types_filter);
-  g_free (col_filter);
-  g_strfreev (strv);
+    sparql_template = photos_sparql_template_new 
("resource:///org/gnome/Photos/query/photos.sparql.template");
+    search_type = photos_search_type_new (PHOTOS_SEARCH_TYPE_STOCK_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);
 }
 
 
@@ -161,9 +111,7 @@ static void
 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 f03385aa..f0398949 100644
--- a/src/photos-search-type.c
+++ b/src/photos-search-type.c
@@ -30,19 +30,17 @@
 struct _PhotosSearchType
 {
   GObject parent_instance;
-  gchar *filter;
+  PhotosSparqlTemplate *sparql_template;
   gchar *id;
   gchar *name;
-  gchar *where;
 };
 
 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 +51,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,18 +59,28 @@ photos_search_type_get_id (PhotosFilterable *filterable)
 }
 
 
-static gchar *
-photos_search_type_get_where (PhotosFilterable *iface)
+static gboolean
+photos_search_type_is_search_criterion (PhotosFilterable *iface)
 {
-  PhotosSearchType *self = PHOTOS_SEARCH_TYPE (iface);
-  return g_strdup (self->where);
+  return TRUE;
 }
 
 
-static gboolean
-photos_search_type_is_search_criterion (PhotosFilterable *iface)
+PhotosSparqlTemplate *
+photos_search_type_get_sparql_template (PhotosSearchType *self)
 {
-  return TRUE;
+  return self->sparql_template;
+}
+
+
+static void
+photos_search_type_dispose (GObject *object)
+{
+  PhotosSearchType *self = PHOTOS_SEARCH_TYPE (object);
+
+  g_clear_object (&self->sparql_template);
+
+  G_OBJECT_CLASS (photos_search_type_parent_class)->dispose (object);
 }
 
 
@@ -89,10 +89,8 @@ 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_OBJECT_CLASS (photos_search_type_parent_class)->finalize (object);
 }
@@ -113,6 +111,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 +129,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 +137,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 = PHOTOS_SPARQL_TEMPLATE (g_value_dup_object (value));
       break;
 
     default:
@@ -161,18 +159,11 @@ photos_search_type_class_init (PhotosSearchTypeClass *class)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (class);
 
+  object_class->dispose = photos_search_type_dispose;
   object_class->finalize = photos_search_type_finalize;
   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 +181,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,20 +193,18 @@ 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;
 }
 
 
 PhotosSearchType *
-photos_search_type_new (const gchar *id, const gchar *name, const gchar *where, const gchar *filter)
+photos_search_type_new (const gchar *id, const gchar *name, PhotosSparqlTemplate *sparql_template)
+
 {
   return g_object_new (PHOTOS_TYPE_SEARCH_TYPE,
                        "id", id,
                        "name", name,
-                       "filter", filter,
-                       "where", where,
+                       "sparql-template", sparql_template,
                        NULL);
 }
diff --git a/src/photos-search-type.h b/src/photos-search-type.h
index bdf74489..6e9add2d 100644
--- a/src/photos-search-type.h
+++ b/src/photos-search-type.h
@@ -23,7 +23,7 @@
 #ifndef PHOTOS_SEARCH_TYPE_H
 #define PHOTOS_SEARCH_TYPE_H
 
-#include <glib-object.h>
+#include "photos-sparql-template.h"
 
 G_BEGIN_DECLS
 
@@ -37,8 +37,9 @@ G_DECLARE_FINAL_TYPE (PhotosSearchType, photos_search_type, PHOTOS, SEARCH_TYPE,
 
 PhotosSearchType    *photos_search_type_new                (const gchar *id,
                                                             const gchar *name,
-                                                            const gchar *where,
-                                                            const gchar *filter);
+                                                            PhotosSparqlTemplate *sparql_template);
+
+PhotosSparqlTemplate *photos_search_type_get_sparql_template (PhotosSearchType *self);
 
 G_END_DECLS
 
diff --git a/src/photos.gresource.xml b/src/photos.gresource.xml
index 1015b11d..88921af8 100644
--- a/src/photos.gresource.xml
+++ b/src/photos.gresource.xml
@@ -50,4 +50,11 @@
     <file alias="image-filter-symbolic.svg">../data/icons/image-filter-symbolic.svg</file>
     <file alias="image-sharpen-symbolic.svg">../data/icons/image-sharpen-symbolic.svg</file>
   </gresource>
+
+  <gresource prefix="/org/gnome/Photos/query">
+    <file alias="all.sparql.template">photos-query-all.sparql.template</file>
+    <file alias="collections.sparql.template">photos-query-collections.sparql.template</file>
+    <file alias="favorites.sparql.template">photos-query-favorites.sparql.template</file>
+    <file alias="photos.sparql.template">photos-query-photos.sparql.template</file>
+  </gresource>
 </gresources>


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