[gnome-music/wip/mschraal/core] searchview: Very basic functional
- From: Marinus Schraal <mschraal src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-music/wip/mschraal/core] searchview: Very basic functional
- Date: Sat, 6 Jul 2019 23:04:20 +0000 (UTC)
commit 3980a6272926b7196e8897494991031defbbfbbf
Author: Marinus Schraal <mschraal gnome org>
Date: Sat Jul 6 17:04:44 2019 +0200
searchview: Very basic functional
gnomemusic/coremodel.py | 64 ++++
gnomemusic/grilowrappers/grltrackerplaylists.py | 449 ++++++++++++++++++++++++
gnomemusic/grilowrappers/grltrackersource.py | 3 +
gnomemusic/views/playlistsview.py | 67 ++--
4 files changed, 562 insertions(+), 21 deletions(-)
---
diff --git a/gnomemusic/coremodel.py b/gnomemusic/coremodel.py
index a895e689..8d7c4d78 100644
--- a/gnomemusic/coremodel.py
+++ b/gnomemusic/coremodel.py
@@ -1,3 +1,5 @@
+import math
+
import gi
gi.require_versions({'Dazzle': '1.0', 'Gfm': '0.1'})
from gi.repository import Dazzle, GObject, Gio, Gfm, Gtk
@@ -7,6 +9,7 @@ from gnomemusic import log
from gnomemusic.coreartist import CoreArtist
from gnomemusic.coregrilo import CoreGrilo
from gnomemusic.coresong import CoreSong
+from gnomemusic.grilowrappers.grltrackerplaylists import Playlist
from gnomemusic.player import PlayerPlaylist
from gnomemusic.songliststore import SongListStore
from gnomemusic.widgets.songwidget import SongWidget
@@ -68,6 +71,14 @@ class CoreModel(GObject.GObject):
self._artist_model)
self._artist_search_model.set_filter_func(lambda a: False)
+ self._playlists_model = Gio.ListStore.new(Playlist)
+ self._playlists_model_filter = Dazzle.ListModelFilter.new(
+ self._playlists_model)
+ self._playlists_model_sort = Gfm.SortListModel.new(
+ self._playlists_model_filter)
+ self._playlists_model_sort.set_sort_func(
+ self._wrap_list_store_sort_func(self._playlists_sort))
+
self._grilo = CoreGrilo(self, self._coreselection)
def _filter_selected(self, coresong):
@@ -81,6 +92,24 @@ class CoreModel(GObject.GObject):
name_b = artist_b.props.artist.casefold()
return name_a > name_b
+ def _playlists_sort(self, playlist_a, playlist_b):
+ if playlist_a.props.is_smart:
+ if not playlist_b.props.is_smart:
+ return -1
+ title_a = playlist_a.props.title.casefold()
+ title_b = playlist_b.props.title.casefold()
+ return title_a > title_b
+
+ if playlist_b.props.is_smart:
+ return 1
+
+ # cannot use GLib.DateTime.compare
+ # https://gitlab.gnome.org/GNOME/pygobject/issues/334
+ # newest first
+ date_diff = playlist_b.props.creation_date.difference(
+ playlist_a.props.creation_date)
+ return math.copysign(1, date_diff)
+
def _wrap_list_store_sort_func(self, func):
def wrap(a, b, *user_data):
@@ -232,6 +261,30 @@ class CoreModel(GObject.GObject):
"items-changed", _on_items_changed)
self.emit("playlist-loaded")
+ elif playlist_type == PlayerPlaylist.Type.PLAYLIST:
+ # if self._search_signal_id:
+ # self._song_search_model.disconnect(self._search_signal_id)
+
+ self._playlist_model.remove_all()
+
+ for model_song in model:
+ song = CoreSong(
+ model_song.props.media, self._coreselection,
+ self._grilo)
+
+ self._playlist_model.append(song)
+
+ if model_song is coresong:
+ song.props.state = SongWidget.State.PLAYING
+
+ song.bind_property(
+ "state", model_song, "state",
+ GObject.BindingFlags.SYNC_CREATE)
+
+ # self._search_signal_id = self._song_search_model.connect(
+ # "items-changed", _on_items_changed)
+
+ self.emit("playlist-loaded")
def search(self, text):
self._grilo.search(text)
@@ -296,3 +349,14 @@ class CoreModel(GObject.GObject):
type=Gtk.ListStore, default=None, flags=GObject.ParamFlags.READABLE)
def songs_gtkliststore(self):
return self._songliststore
+
+ @GObject.Property(
+ type=Gio.ListStore, default=None, flags=GObject.ParamFlags.READABLE)
+ def playlists(self):
+ return self._playlists_model
+
+ @GObject.Property(
+ type=Gfm.SortListModel, default=None,
+ flags=GObject.ParamFlags.READABLE)
+ def playlists_sort(self):
+ return self._playlists_model_sort
diff --git a/gnomemusic/grilowrappers/grltrackerplaylists.py b/gnomemusic/grilowrappers/grltrackerplaylists.py
new file mode 100644
index 00000000..5fff7493
--- /dev/null
+++ b/gnomemusic/grilowrappers/grltrackerplaylists.py
@@ -0,0 +1,449 @@
+import time
+
+from gettext import gettext as _
+
+import gi
+gi.require_versions({"Grl": "0.3", 'Tracker': "2.0"})
+from gi.repository import Gio, Grl, GLib, GObject
+
+from gnomemusic.coresong import CoreSong
+import gnomemusic.utils as utils
+
+
+class GrlTrackerPlaylists(GObject.GObject):
+
+ METADATA_KEYS = [
+ Grl.METADATA_KEY_ALBUM,
+ Grl.METADATA_KEY_ALBUM_ARTIST,
+ Grl.METADATA_KEY_ALBUM_DISC_NUMBER,
+ Grl.METADATA_KEY_ARTIST,
+ Grl.METADATA_KEY_CREATION_DATE,
+ Grl.METADATA_KEY_COMPOSER,
+ Grl.METADATA_KEY_DURATION,
+ Grl.METADATA_KEY_FAVOURITE,
+ Grl.METADATA_KEY_ID,
+ Grl.METADATA_KEY_PLAY_COUNT,
+ Grl.METADATA_KEY_THUMBNAIL,
+ Grl.METADATA_KEY_TITLE,
+ Grl.METADATA_KEY_TRACK_NUMBER,
+ Grl.METADATA_KEY_URL
+ ]
+
+ def __repr__(self):
+ return "<GrlTrackerPlaylists>"
+
+ def __init__(self, source, coremodel, coreselection, grilo):
+ super().__init__()
+
+ self._coremodel = coremodel
+ self._coreselection = coreselection
+ self._grilo = grilo
+ self._source = source
+ self._model = self._coremodel.props.playlists
+
+ self._fast_options = Grl.OperationOptions()
+ self._fast_options.set_resolution_flags(
+ Grl.ResolutionFlags.FAST_ONLY | Grl.ResolutionFlags.IDLE_RELAY)
+
+ self._initial_playlists_fill()
+
+ def _initial_playlists_fill(self):
+ smart_playlists = {
+ "MostPlayed": MostPlayed(),
+ "NeverPlayed": NeverPlayed(),
+ "RecentlyPlayed": RecentlyPlayed(),
+ "RecentlyAdded": RecentlyAdded(),
+ "Favorites": Favorites()
+ }
+
+ for playlist in smart_playlists.values():
+
+ def _add_to_model(
+ source, op_id, media, remaining, user_data, error):
+ if error:
+ print("ERROR", error)
+ return
+
+ if not media:
+ user_data.props.count = user_data.props.model.get_n_items()
+ return
+
+ coresong = CoreSong(media, self._coreselection, self._grilo)
+ user_data.props.model.append(coresong)
+
+ options = self._fast_options.copy()
+
+ self._source.query(
+ playlist.props.query, self.METADATA_KEYS, options,
+ _add_to_model, playlist)
+
+ self._model.append(playlist)
+
+ self._all_user_playlists()
+
+ def _all_user_playlists(self):
+ query = """
+ SELECT DISTINCT
+ rdf:type(?playlist)
+ tracker:id(?playlist) AS ?id
+ nie:title(?playlist) AS ?title
+ tracker:added(?playlist) AS ?creation_date
+ nfo:entryCounter(?playlist) AS ?childcount
+ WHERE
+ {
+ ?playlist a nmm:Playlist .
+ OPTIONAL { ?playlist nie:url ?url;
+ tracker:available ?available . }
+ FILTER ( !STRENDS(LCASE(?url), '.m3u')
+ && !STRENDS(LCASE(?url), '.m3u8')
+ && !STRENDS(LCASE(?url), '.pls')
+ || !BOUND(nfo:belongsToContainer(?playlist)) )
+ FILTER ( !BOUND(?tag) )
+ OPTIONAL { ?playlist nao:hasTag ?tag }
+ }
+ """.replace('\n', ' ').strip()
+
+ options = self._fast_options.copy()
+
+ self._source.query(
+ query, self.METADATA_KEYS, options, self._add_user_playlist)
+
+ def _add_user_playlist(
+ self, source, param, item, data, error):
+ if not item:
+ return
+
+ playlist = Playlist(
+ pl_id=item.get_id(), title=utils.get_media_title(item),
+ creation_date=item.get_creation_date(), source=self._source,
+ coremodel=self._coremodel, coreselection=self._coreselection,
+ grilo=self._grilo)
+
+ self._model.append(playlist)
+
+
+class Playlist(GObject.GObject):
+ """ Base class of all playlists """
+
+ METADATA_KEYS = [
+ Grl.METADATA_KEY_ALBUM,
+ Grl.METADATA_KEY_ALBUM_ARTIST,
+ Grl.METADATA_KEY_ALBUM_DISC_NUMBER,
+ Grl.METADATA_KEY_ARTIST,
+ Grl.METADATA_KEY_CREATION_DATE,
+ Grl.METADATA_KEY_COMPOSER,
+ Grl.METADATA_KEY_DURATION,
+ Grl.METADATA_KEY_FAVOURITE,
+ Grl.METADATA_KEY_ID,
+ Grl.METADATA_KEY_PLAY_COUNT,
+ Grl.METADATA_KEY_THUMBNAIL,
+ Grl.METADATA_KEY_TITLE,
+ Grl.METADATA_KEY_TRACK_NUMBER,
+ Grl.METADATA_KEY_URL
+ ]
+
+ count = GObject.Property(type=int, default=0)
+ creation_date = GObject.Property(type=GLib.DateTime, default=None)
+ is_smart = GObject.Property(type=bool, default=False)
+ pl_id = GObject.Property(type=str, default=None)
+ query = GObject.Property(type=str, default=None)
+ tag_text = GObject.Property(type=str, default=None)
+ title = GObject.Property(type=str, default=None)
+
+ def __repr__(self):
+ return "<Playlist>"
+
+ def __init__(
+ self, pl_id=None, query=None, tag_text=None, title=None,
+ creation_date=None, source=None, coremodel=None,
+ coreselection=None, grilo=None):
+ super().__init__()
+
+ self.props.pl_id = pl_id
+ self.props.query = query
+ self.props.tag_text = tag_text
+ self.props.title = title
+ self.props.creation_date = creation_date
+ self._model = None
+ self._source = source
+ self._coremodel = coremodel
+ self._coreselection = coreselection
+ self._grilo = grilo
+
+ @GObject.Property(type=Gio.ListStore, default=None)
+ def model(self):
+ if self._model is None:
+ self._model = Gio.ListStore()
+
+ self._populate_model()
+
+ return self._model
+
+ @model.setter
+ def model(self, value):
+ self._model = value
+
+ def _populate_model(self):
+ query = """
+ SELECT
+ rdf:type(?song)
+ ?song AS ?tracker_urn
+ tracker:id(?entry) AS ?id
+ nie:url(?song) AS ?url
+ nie:title(?song) AS ?title
+ nmm:artistName(nmm:performer(?song)) AS ?artist
+ nie:title(nmm:musicAlbum(?song)) AS ?album
+ nfo:duration(?song) AS ?duration
+ ?tag AS ?favourite
+ nie:contentAccessed(?song) AS ?last_played_time
+ nie:usageCounter(?song) AS ?play_count
+ WHERE {
+ ?playlist a nmm:Playlist ;
+ a nfo:MediaList ;
+ nfo:hasMediaFileListEntry ?entry .
+ ?entry a nfo:MediaFileListEntry ;
+ nfo:entryUrl ?url .
+ ?song a nmm:MusicPiece ;
+ a nfo:FileDataObject ;
+ nie:url ?url .
+ OPTIONAL {
+ ?song nao:hasTag ?tag .
+ FILTER( ?tag = nao:predefined-tag-favorite )
+ }
+ FILTER (
+ %(filter_clause)s
+ )
+ FILTER (
+ NOT EXISTS { ?song a nmm:Video }
+ && NOT EXISTS { ?song a nmm:Playlist }
+ )
+ }
+ ORDER BY nfo:listPosition(?entry)
+ """.replace('\n', ' ').strip() % {
+ 'filter_clause': 'tracker:id(?playlist) = ' + self.props.pl_id
+ }
+
+ def _add_to_playlist_cb(
+ source, op_id, media, remaining, user_data, error):
+ if not media:
+ self.props.count = self._model.get_n_items()
+ return
+
+ coresong = CoreSong(media, self._coreselection, self._grilo)
+ self._model.append(coresong)
+
+ options = Grl.OperationOptions()
+ options.set_resolution_flags(
+ Grl.ResolutionFlags.FAST_ONLY | Grl.ResolutionFlags.IDLE_RELAY)
+
+ self._source.query(
+ query, self.METADATA_KEYS, options, _add_to_playlist_cb, None)
+
+
+class SmartPlaylist(Playlist):
+ """Base class for smart playlists"""
+
+ def __repr__(self):
+ return "<SmartPlaylist>"
+
+ def __init__(self):
+ super().__init__()
+
+ self.props.is_smart = True
+
+ @GObject.Property(type=Gio.ListStore, default=None)
+ def model(self):
+ if self._model is None:
+ self._model = Gio.ListStore.new(CoreSong)
+
+ return self._model
+
+
+class MostPlayed(SmartPlaylist):
+ """Most Played smart playlist"""
+
+ def __init__(self):
+ super().__init__()
+
+ self.props.tag_text = "MOST_PLAYED"
+ # TRANSLATORS: this is a playlist name
+ self.props.title = _("Most Played")
+ self.props.query = """
+ SELECT
+ rdf:type(?song)
+ tracker:id(?song) AS ?id
+ ?song AS ?tracker_urn
+ nie:title(?song) AS ?title
+ nie:url(?song) AS ?url
+ nie:title(?song) AS ?title
+ nmm:artistName(nmm:performer(?song)) AS ?artist
+ nie:title(nmm:musicAlbum(?song)) AS ?album
+ nfo:duration(?song) AS ?duration
+ nie:usageCounter(?song) AS ?play_count
+ nmm:trackNumber(?song) AS ?track_number
+ nmm:setNumber(nmm:musicAlbumDisc(?song)) AS ?album_disc_number
+ ?tag AS ?favourite
+ WHERE {
+ ?song a nmm:MusicPiece ;
+ nie:usageCounter ?count .
+ OPTIONAL { ?song nao:hasTag ?tag .
+ FILTER (?tag = nao:predefined-tag-favorite) }
+ }
+ ORDER BY DESC(?count) LIMIT 50
+ """.replace('\n', ' ').strip()
+
+
+class NeverPlayed(SmartPlaylist):
+ """Never Played smart playlist"""
+
+ def __init__(self):
+ super().__init__()
+
+ self.props.tag_text = "NEVER_PLAYED"
+ # TRANSLATORS: this is a playlist name
+ self.props.title = _("Never Played")
+ self.props.query = """
+ SELECT
+ rdf:type(?song)
+ tracker:id(?song) AS ?id
+ ?song AS ?tracker_urn
+ nie:title(?song) AS ?title
+ nie:url(?song) AS ?url
+ nie:title(?song) AS ?title
+ nmm:artistName(nmm:performer(?song)) AS ?artist
+ nie:title(nmm:musicAlbum(?song)) AS ?album
+ nfo:duration(?song) AS ?duration
+ nie:usageCounter(?song) AS ?play_count
+ nmm:trackNumber(?song) AS ?track_number
+ nmm:setNumber(nmm:musicAlbumDisc(?song)) AS ?album_disc_number
+ ?tag AS ?favourite
+ WHERE {
+ ?song a nmm:MusicPiece ;
+ FILTER ( NOT EXISTS { ?song nie:usageCounter ?count .} )
+ OPTIONAL { ?song nao:hasTag ?tag .
+ FILTER (?tag = nao:predefined-tag-favorite) }
+ } ORDER BY nfo:fileLastAccessed(?song) LIMIT 50
+ """.replace('\n', ' ').strip()
+
+
+class RecentlyPlayed(SmartPlaylist):
+ """Recently Played smart playlist"""
+
+ def __init__(self):
+ super().__init__()
+
+ self.props.tag_text = "RECENTLY_PLAYED"
+ # TRANSLATORS: this is a playlist name
+ self.props.title = _("Recently Played")
+
+ sparql_midnight_dateTime_format = "%Y-%m-%dT00:00:00Z"
+ days_difference = 7
+ seconds_difference = days_difference * 86400
+ compare_date = time.strftime(
+ sparql_midnight_dateTime_format,
+ time.gmtime(time.time() - seconds_difference))
+ self.props.query = """
+ SELECT
+ rdf:type(?song)
+ tracker:id(?song) AS ?id
+ ?song AS ?tracker_urn
+ nie:title(?song) AS ?title
+ nie:url(?song) AS ?url
+ nie:title(?song) AS ?title
+ nmm:artistName(nmm:performer(?song)) AS ?artist
+ nie:title(nmm:musicAlbum(?song)) AS ?album
+ nfo:duration(?song) AS ?duration
+ nie:usageCounter(?song) AS ?play_count
+ nmm:trackNumber(?song) AS ?track_number
+ nmm:setNumber(nmm:musicAlbumDisc(?song)) AS ?album_disc_number
+ ?tag AS ?favourite
+ WHERE {
+ ?song a nmm:MusicPiece ;
+ nie:contentAccessed ?last_played .
+ FILTER ( ?last_played > '%(compare_date)s'^^xsd:dateTime
+ && EXISTS { ?song nie:usageCounter ?count .} )
+ OPTIONAL { ?song nao:hasTag ?tag .
+ FILTER (?tag = nao:predefined-tag-favorite) }
+ } ORDER BY DESC(?last_played) LIMIT 50
+ """.replace('\n', ' ').strip() % {
+ 'compare_date': compare_date
+ }
+
+
+class RecentlyAdded(SmartPlaylist):
+ """Recently Added smart playlist"""
+
+ def __init__(self):
+ super().__init__()
+
+ self.props.tag_text = "RECENTLY_ADDED"
+ # TRANSLATORS: this is a playlist name
+ self.props.title = _("Recently Added")
+
+ sparql_midnight_dateTime_format = "%Y-%m-%dT00:00:00Z"
+ days_difference = 7
+ seconds_difference = days_difference * 86400
+ compare_date = time.strftime(
+ sparql_midnight_dateTime_format,
+ time.gmtime(time.time() - seconds_difference))
+ self.props.query = """
+ SELECT
+ rdf:type(?song)
+ tracker:id(?song) AS ?id
+ ?song AS ?tracker_urn
+ nie:title(?song) AS ?title
+ nie:url(?song) AS ?url
+ nie:title(?song) AS ?title
+ nmm:artistName(nmm:performer(?song)) AS ?artist
+ nie:title(nmm:musicAlbum(?song)) AS ?album
+ nfo:duration(?song) AS ?duration
+ nie:usageCounter(?song) AS ?play_count
+ nmm:trackNumber(?song) AS ?track_number
+ nmm:setNumber(nmm:musicAlbumDisc(?song)) AS ?album_disc_number
+ ?tag AS ?favourite
+ WHERE {
+ ?song a nmm:MusicPiece ;
+ tracker:added ?added .
+ FILTER ( tracker:added(?song) > '%(compare_date)s'^^xsd:dateTime )
+ OPTIONAL { ?song nao:hasTag ?tag .
+ FILTER (?tag = nao:predefined-tag-favorite) }
+ } ORDER BY DESC(tracker:added(?song)) LIMIT 50
+ """.replace('\n', ' ').strip() % {
+ 'compare_date': compare_date,
+ }
+
+
+class Favorites(SmartPlaylist):
+ """Favorites smart playlist"""
+
+ def __init__(self):
+ super().__init__()
+
+ self.props.tag_text = "FAVORITES"
+ # TRANSLATORS: this is a playlist name
+ self.props.title = _("Favorite Songs")
+ self.props.query = """
+ SELECT
+ rdf:type(?song)
+ tracker:id(?song) AS ?id
+ ?song AS ?tracker_urn
+ nie:title(?song) AS ?title
+ nie:url(?song) AS ?url
+ nie:title(?song) AS ?title
+ nmm:artistName(nmm:performer(?song)) AS ?artist
+ nie:title(nmm:musicAlbum(?song)) AS ?album
+ nfo:duration(?song) AS ?duration
+ nie:usageCounter(?song) AS ?play_count
+ nmm:trackNumber(?song) AS ?track_number
+ nmm:setNumber(nmm:musicAlbumDisc(?song)) AS ?album_disc_number
+ nao:predefined-tag-favorite AS ?favourite
+ WHERE {
+ ?song a nmm:MusicPiece ;
+ nie:isStoredAs ?as ;
+ nao:hasTag nao:predefined-tag-favorite .
+ ?as nie:url ?url .
+ OPTIONAL { ?song nao:hasTag ?tag .
+ FILTER (?tag = nao:predefined-tag-favorite) }
+
+ } ORDER BY DESC(tracker:added(?song))
+ """.replace('\n', ' ').strip()
diff --git a/gnomemusic/grilowrappers/grltrackersource.py b/gnomemusic/grilowrappers/grltrackersource.py
index fcefcc2d..46e9b131 100644
--- a/gnomemusic/grilowrappers/grltrackersource.py
+++ b/gnomemusic/grilowrappers/grltrackersource.py
@@ -6,6 +6,7 @@ from gnomemusic.corealbum import CoreAlbum
from gnomemusic.coreartist import CoreArtist
from gnomemusic.coredisc import CoreDisc
from gnomemusic.coresong import CoreSong
+from gnomemusic.grilowrappers.grltrackerplaylists import GrlTrackerPlaylists
class GrlTrackerSource(GObject.GObject):
@@ -54,6 +55,8 @@ class GrlTrackerSource(GObject.GObject):
self._initial_albums_fill(self._source)
self._initial_artists_fill(self._source)
+ GrlTrackerPlaylists(source, coremodel, coreselection, grilo)
+
self._source.connect("content-changed", self._on_content_changed)
@GObject.Property(
diff --git a/gnomemusic/views/playlistsview.py b/gnomemusic/views/playlistsview.py
index 7a8c0747..c14ff88a 100644
--- a/gnomemusic/views/playlistsview.py
+++ b/gnomemusic/views/playlistsview.py
@@ -27,7 +27,6 @@ from gettext import gettext as _
from gi.repository import Gdk, Gio, GLib, GObject, Gtk, Pango
from gnomemusic import log
-from gnomemusic.grilo import grilo
from gnomemusic.player import ValidationStatus, PlayerPlaylist
from gnomemusic.playlists import Playlists
from gnomemusic.views.baseview import BaseView
@@ -36,6 +35,7 @@ from gnomemusic.widgets.playlistcontextmenu import PlaylistContextMenu
from gnomemusic.widgets.playlistcontrols import PlaylistControls
from gnomemusic.widgets.playlistdialog import PlaylistDialog
from gnomemusic.widgets.sidebarrow import SidebarRow
+from gnomemusic.widgets.songwidget import SongWidget
import gnomemusic.utils as utils
@@ -59,12 +59,14 @@ class PlaylistsView(BaseView):
super().__init__(
'playlists', _("Playlists"), window, sidebar_container)
+ self._coremodel = window._app.props.coremodel
+ self._model = self._coremodel.props.playlists
self._window = window
self.player = player
- self._view.get_style_context().add_class('songs-list')
+ # self._view.get_style_context().add_class('songs-list')
- self._add_list_renderers()
+ # self._add_list_renderers()
self._pl_ctrls = PlaylistControls()
self._pl_ctrls.connect('playlist-renamed', self._on_playlist_renamed)
@@ -134,7 +136,8 @@ class PlaylistsView(BaseView):
self._playlists_model = self._playlists.get_playlists_model()
self._sidebar.bind_model(
- self._playlists_model, self._add_playlist_to_sidebar)
+ self._coremodel.props.playlists_sort,
+ self._add_playlist_to_sidebar)
self._playlists_model.connect(
"items-changed", self._on_playlists_model_changed)
@@ -150,17 +153,19 @@ class PlaylistsView(BaseView):
view_container = Gtk.ScrolledWindow(hexpand=True, vexpand=True)
self._box.pack_start(view_container, True, True, 0)
- self._view = Gtk.TreeView()
- self._view.set_headers_visible(False)
- self._view.set_valign(Gtk.Align.START)
- self._view.set_model(self.model)
- self._view.set_activate_on_single_click(True)
- self._view.get_selection().set_mode(Gtk.SelectionMode.SINGLE)
+ self._view = Gtk.ListBox()
- self._view.connect('row-activated', self._on_song_activated)
- self._view.connect('drag-begin', self._drag_begin)
- self._view.connect('drag-end', self._drag_end)
- self._song_drag = {'active': False}
+ # self._view = Gtk.TreeView()
+ # self._view.set_headers_visible(False)
+ # self._view.set_valign(Gtk.Align.START)
+ # self._view.set_model(self.model)
+ # self._view.set_activate_on_single_click(True)
+ # self._view.get_selection().set_mode(Gtk.SelectionMode.SINGLE)
+
+ # self._view.connect('row-activated', self._on_song_activated)
+ # self._view.connect('drag-begin', self._drag_begin)
+ # self._view.connect('drag-end', self._drag_end)
+ # self._song_drag = {'active': False}
self._controller = Gtk.GestureMultiPress().new(self._view)
self._controller.props.propagation_phase = Gtk.PropagationPhase.CAPTURE
@@ -295,11 +300,11 @@ class PlaylistsView(BaseView):
if removed == 0:
return
- row_next = (self._sidebar.get_row_at_index(position)
- or self._sidebar.get_row_at_index(position - 1))
- if row_next:
- self._sidebar.select_row(row_next)
- row_next.emit("activate")
+ # row_next = (self._sidebar.get_row_at_index(position)
+ # or self._sidebar.get_row_at_index(position - 1))
+ # if row_next:
+ # self._sidebar.select_row(row_next)
+ # row_next.emit("activate")
@log
def _on_song_validated(self, player, index, status):
@@ -527,9 +532,12 @@ class PlaylistsView(BaseView):
if self.rename_active:
self._pl_ctrls.disable_rename_playlist()
+ self._view.bind_model(playlist.props.model, self._create_song_widget)
+
self._current_playlist = playlist
self._pl_ctrls.props.playlist_name = playlist_name
-
+ self._update_songs_count(playlist.props.count)
+ return
# if the active queue has been set by this playlist,
# use it as model, otherwise build the liststore
self._view.set_model(None)
@@ -538,7 +546,7 @@ class PlaylistsView(BaseView):
self._iter_to_clean_model = None
self._pl_ctrls.freeze_notify()
self._update_songs_count(0)
- grilo.populate_playlist_songs(playlist, self._add_song)
+ # grilo.populate_playlist_songs(playlist, self._add_song)
protected_pl = self._current_playlist.props.is_smart
self._playlist_delete_action.set_enabled(not protected_pl)
@@ -546,6 +554,23 @@ class PlaylistsView(BaseView):
self._remove_song_action.set_enabled(not protected_pl)
self._view.set_reorderable(not protected_pl)
+ def _create_song_widget(self, coresong):
+ song_widget = SongWidget(coresong)
+
+ song_widget.connect('button-release-event', self._song_activated)
+
+ return song_widget
+
+ def _song_activated(self, widget, event):
+ print(widget)
+ print(self._view.get_focus_child())
+ self._coremodel.set_playlist_model(
+ PlayerPlaylist.Type.PLAYLIST, widget.props.coresong,
+ self._current_playlist.props.model)
+ self.player.play()
+
+ return True
+
@log
def _add_song(self, source, param, song, remaining=0, data=None):
"""Grilo.populate_playlist_songs callback.
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]