[gnome-music/wip/mschraal/core: 159/177] searchview: Add artists results



commit 6e07811db4f64197ae8d6d51ad93f7367b6fecbe
Author: Marinus Schraal <mschraal gnome org>
Date:   Mon Jul 1 14:11:34 2019 +0200

    searchview: Add artists results

 gnomemusic/coremodel.py                      |  7 ++++
 gnomemusic/grilowrappers/grltrackersource.py | 55 ++++++++++++++++++++++++++++
 gnomemusic/views/searchview.py               | 45 +++++++++++++++++++++++
 3 files changed, 107 insertions(+)
---
diff --git a/gnomemusic/coremodel.py b/gnomemusic/coremodel.py
index 59674123..02dbe01c 100644
--- a/gnomemusic/coremodel.py
+++ b/gnomemusic/coremodel.py
@@ -60,6 +60,10 @@ class CoreModel(GObject.GObject):
             self._album_model)
         self._album_search_model.set_filter_func(lambda a: False)
 
+        self._artist_search_model = Dazzle.ListModelFilter.new(
+            self._artist_model)
+        self._artist_search_model.set_filter_func(lambda a: False)
+
         print("PLAYLIST_MODEL", self._playlist_model)
         self._grilo = CoreGrilo(
             self, self._model, self._album_model, self._artist_model,
@@ -205,5 +209,8 @@ class CoreModel(GObject.GObject):
     def get_album_search_model(self):
         return self._album_search_model
 
+    def get_artist_search_model(self):
+        return self._artist_search_model
+
     def search(self, text):
         self._grilo.search(text)
diff --git a/gnomemusic/grilowrappers/grltrackersource.py b/gnomemusic/grilowrappers/grltrackersource.py
index 8af63a3e..621a932e 100644
--- a/gnomemusic/grilowrappers/grltrackersource.py
+++ b/gnomemusic/grilowrappers/grltrackersource.py
@@ -46,6 +46,7 @@ class GrlTrackerSource(GObject.GObject):
         self._hash = {}
         self._song_search_model = song_search_model
         self._album_search_model = album_search_model
+        self._artist_search_model = self._coremodel.get_artist_search_model()
 
         self._fast_options = Grl.OperationOptions()
         self._fast_options.set_resolution_flags(
@@ -584,3 +585,57 @@ class GrlTrackerSource(GObject.GObject):
 
         self._source.query(
             query, self.METADATA_KEYS, options, albums_search_cb)
+
+        # Artist search
+
+        query = """
+        SELECT DISTINCT
+            rdf:type(?artist)
+            tracker:id(?artist) AS ?id
+        {
+            ?song a nmm:MusicPiece ;
+                    nmm:musicAlbum ?album ;
+                    nmm:performer ?artist .
+            BIND(tracker:normalize(
+                nie:title(nmm:musicAlbum(?song)), 'nfkd') AS ?match1) .
+            BIND(tracker:normalize(
+                nmm:artistName(nmm:performer(?song)), 'nfkd') AS ?match2) .
+            BIND(tracker:normalize(nie:title(?song), 'nfkd') AS ?match3) .
+            BIND(tracker:normalize(nmm:composer(?song), 'nfkd') AS ?match4) .
+            FILTER (
+                CONTAINS(tracker:case-fold(
+                    tracker:unaccent(?match1)), "%(name)s")
+                || CONTAINS(tracker:case-fold(?match1), "%(name)s")
+                || CONTAINS(tracker:case-fold(
+                    tracker:unaccent(?match2)), "%(name)s")
+                || CONTAINS(tracker:case-fold(?match2), "%(name)s")
+                || CONTAINS(tracker:case-fold(
+                    tracker:unaccent(?match3)), "%(name)s")
+                || CONTAINS(tracker:case-fold(?match3), "%(name)s")
+                || CONTAINS(tracker:case-fold(
+                    tracker:unaccent(?match4)), "%(name)s")
+                || CONTAINS(tracker:case-fold(?match4), "%(name)s")
+            )
+        }
+        """.replace('\n', ' ').strip() % {'name': term}
+
+        artist_filter_ids = []
+
+        def artist_filter(coreartist):
+            return coreartist.media.get_id() in artist_filter_ids
+
+        def artist_search_cb(source, op_id, media, data, error):
+            if error:
+                print("ERROR", error)
+                return
+
+            if not media:
+                self._artist_search_model.set_filter_func(artist_filter)
+                return
+
+            artist_filter_ids.append(media.get_id())
+
+        options = self._fast_options.copy()
+
+        self._source.query(
+            query, self.METADATA_KEYS, options, artist_search_cb)
diff --git a/gnomemusic/views/searchview.py b/gnomemusic/views/searchview.py
index c871ff1d..cf23693d 100644
--- a/gnomemusic/views/searchview.py
+++ b/gnomemusic/views/searchview.py
@@ -55,6 +55,7 @@ class SearchView(BaseView):
         self._coremodel = window._app._coremodel
         self._model = self._coremodel.get_songs_search_model()
         self._album_model = self._coremodel.get_album_search_model()
+        self._artist_model = self._coremodel.get_artist_search_model()
         super().__init__('search', None, window)
 
         # self._add_list_renderers()
@@ -107,8 +108,13 @@ class SearchView(BaseView):
         self._album_flowbox.connect(
             "child-activated", self._on_album_activated)
 
+        self._artist_listbox = Gtk.ListBox()
+        self._artist_listbox.bind_model(
+            self._artist_model, self._create_artist_widget)
+
         self._all_results_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
         self._all_results_box.pack_start(self._album_flowbox, True, True, 0)
+        self._all_results_box.pack_start(self._artist_listbox, True, True, 0)
         self._all_results_box.pack_start(self._songs_listbox, True, True, 0)
 
         # self._ctrl = Gtk.GestureMultiPress().new(self._view)
@@ -164,6 +170,26 @@ class SearchView(BaseView):
 
         return album_widget
 
+    def _create_artist_widget(self, coresong):
+        # FIXME: Hacky quick 'artist' widget. Needs its own tile.
+        song_widget = SongWidget(coresong.props.media)
+        song_widget._title_label.props.label = coresong.props.artist
+        song_widget.props.show_duration = False
+        song_widget.props.show_favorite = False
+        song_widget.props.show_song_number = False
+        song_widget.coreartist = coresong
+
+        self.bind_property(
+            "selection-mode", song_widget, "selection-mode",
+            GObject.BindingFlags.BIDIRECTIONAL
+            | GObject.BindingFlags.SYNC_CREATE)
+
+        song_widget.connect('button-release-event', self._artist_activated)
+
+        song_widget.show_all()
+
+        return song_widget
+
     def _song_activated(self, widget, event):
         mod_mask = Gtk.accelerator_get_default_mod_mask()
         if ((event.get_state() & mod_mask) == Gdk.ModifierType.CONTROL_MASK
@@ -202,6 +228,25 @@ class SearchView(BaseView):
 
         self.set_visible_child(self._album_widget)
 
+    def _artist_activated(self, widget, event):
+        mod_mask = Gtk.accelerator_get_default_mod_mask()
+        if ((event.get_state() & mod_mask) == Gdk.ModifierType.CONTROL_MASK
+                and not self.props.selection_mode):
+            self.props.selection_mode = True
+            return
+
+        (_, button) = event.get_button()
+        if (button == Gdk.BUTTON_PRIMARY
+                and not self.props.selection_mode):
+            # self.emit('song-activated', widget)
+            pass
+
+        # FIXME: Need to ignore the event from the checkbox.
+        # if self.props.selection_mode:
+        #     widget.props.selected = not widget.props.selected
+
+        return True
+
     def _child_select(self, child, value):
         widget = child.get_child()
         widget.props.selected = value


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