[gnome-music/wip/mschraal/core: 118/118] albumsview: Make selection mode work and cleanup
- From: Marinus Schraal <mschraal src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-music/wip/mschraal/core: 118/118] albumsview: Make selection mode work and cleanup
- Date: Wed, 26 Jun 2019 13:09:55 +0000 (UTC)
commit 199ab02ef797ab82b1e9364728acba020efdc0ac
Author: Marinus Schraal <mschraal gnome org>
Date: Wed Jun 26 14:54:06 2019 +0200
albumsview: Make selection mode work and cleanup
Makes selection mode work, however the selected items count refers
to songs, not albums.
gnomemusic/corealbum.py | 23 +++++++-
gnomemusic/coredisc.py | 25 +++++++++
gnomemusic/coremodel.py | 6 +-
gnomemusic/coresong.py | 17 +++++-
gnomemusic/grilowrappers/grltrackersource.py | 7 +--
gnomemusic/views/albumsview.py | 82 +++++++---------------------
6 files changed, 85 insertions(+), 75 deletions(-)
---
diff --git a/gnomemusic/corealbum.py b/gnomemusic/corealbum.py
index 5081a451..40d4e19a 100644
--- a/gnomemusic/corealbum.py
+++ b/gnomemusic/corealbum.py
@@ -15,7 +15,6 @@ class CoreAlbum(GObject.GObject):
composer = GObject.Property(type=str, default=None)
duration = GObject.Property(type=int, default=0)
media = GObject.Property(type=Grl.Media)
- selected = GObject.Property(type=bool, default=False)
title = GObject.Property(type=str)
year = GObject.Property(type=str, default="----")
@@ -25,6 +24,7 @@ class CoreAlbum(GObject.GObject):
self._coremodel = coremodel
self._model = None
+ self._selected = False
self.update(media)
@log
@@ -47,8 +47,10 @@ class CoreAlbum(GObject.GObject):
return self._model
def _on_list_items_changed(self, model, pos, removed, added):
- for coredisc in model:
- coredisc.connect("notify::duration", self._on_duration_changed)
+ with self.freeze_notify():
+ for coredisc in model:
+ coredisc.connect("notify::duration", self._on_duration_changed)
+ coredisc.props.selected = self.props.selected
def _on_duration_changed(self, coredisc, duration):
duration = 0
@@ -57,3 +59,18 @@ class CoreAlbum(GObject.GObject):
duration += coredisc.props.duration
self.props.duration = duration
+
+ @GObject.Property(type=bool, default=False)
+ def selected(self):
+ return self._selected
+
+ @selected.setter
+ def selected(self, value):
+ self._selected = value
+
+ # The model is loaded on-demand, so the first time the model is
+ # returned it can still be empty. This is problem for returning
+ # a selection. Trigger loading of the model here if a selection
+ # is requested, it will trigger the filled model update as
+ # well.
+ self.props.model
diff --git a/gnomemusic/coredisc.py b/gnomemusic/coredisc.py
index 4c6bfbf1..a6d51854 100644
--- a/gnomemusic/coredisc.py
+++ b/gnomemusic/coredisc.py
@@ -19,6 +19,7 @@ class CoreDisc(GObject.GObject):
self._filter_model = None
self._model = None
self._old_album_ids = []
+ self._selected = False
self._sort_model = None
self.update(media)
@@ -40,16 +41,24 @@ class CoreDisc(GObject.GObject):
self._coremodel.get_model().connect(
"items-changed", self._on_core_changed)
+ self._model.connect("items-changed", self._on_disc_changed)
self._get_album_disc(
self.props.media, self.props.disc_nr, self._filter_model)
+ self._on_disc_changed(self._model, None, None, None)
+
return self._model
def _on_core_changed(self, model, position, removed, added):
self._get_album_disc(
self.props.media, self.props.disc_nr, self._filter_model)
+ def _on_disc_changed(self, model, position, removed, added):
+ with self.freeze_notify():
+ for coresong in model:
+ coresong.props.selected = self._selected
+
def _update_duration(self):
duration = 0
@@ -93,3 +102,19 @@ class CoreDisc(GObject.GObject):
self._coremodel._grilo.populate_album_disc_songs(
media, discnr, _callback)
+
+ @GObject.Property(
+ type=bool, default=False, flags=GObject.BindingFlags.SYNC_CREATE)
+ def selected(self):
+ return self._selected
+
+ @selected.setter
+ def selected(self, value):
+ self._selected = value
+
+ # The model is loaded on-demand, so the first time the model is
+ # returned it can still be empty. This is problem for returning
+ # a selection. Trigger loading of the model here if a selection
+ # is requested, it will trigger the filled model update as
+ # well.
+ self.props.model
diff --git a/gnomemusic/coremodel.py b/gnomemusic/coremodel.py
index a1ae199f..0d2b43bc 100644
--- a/gnomemusic/coremodel.py
+++ b/gnomemusic/coremodel.py
@@ -158,7 +158,8 @@ class CoreModel(GObject.GObject):
for disc in model:
for model_song in disc.props.model:
- song = CoreSong(model_song.props.media)
+ song = CoreSong(
+ model_song.props.media, self._coreselection)
self._playlist_model.append(song)
song.bind_property(
@@ -177,7 +178,8 @@ class CoreModel(GObject.GObject):
for artist_album in model:
for disc in artist_album.model:
for model_song in disc.model:
- song = CoreSong(model_song.props.media)
+ song = CoreSong(
+ model_song.props.media, self._coreselection)
self._playlist_model.append(song)
song.bind_property(
diff --git a/gnomemusic/coresong.py b/gnomemusic/coresong.py
index 530098e1..0fcb03de 100644
--- a/gnomemusic/coresong.py
+++ b/gnomemusic/coresong.py
@@ -18,17 +18,18 @@ class CoreSong(GObject.GObject):
duration = GObject.Property(type=int)
media = GObject.Property(type=Grl.Media)
play_count = GObject.Property(type=int)
- selected = GObject.Property(type=bool, default=False)
state = GObject.Property() # FIXME: How to set an IntEnum type?
title = GObject.Property(type=str)
track_number = GObject.Property(type=int)
url = GObject.Property(type=str)
@log
- def __init__(self, media):
+ def __init__(self, media, coreselection):
super().__init__()
+ self._coreselection = coreselection
self._favorite = False
+ self._selected = False
self.update(media)
@@ -52,6 +53,18 @@ class CoreSong(GObject.GObject):
self.props.media.set_favourite(self._favorite)
grilo.toggle_favorite(self.props.media, True)
+ @GObject.Property(type=bool, default=False)
+ def selected(self):
+ return self._selected
+
+ @selected.setter
+ def selected(self, value):
+ if self._selected == value:
+ return
+
+ self._selected = value
+ self._coreselection.update_selection(self, self._selected)
+
@log
def update(self, media):
self.props.media = media
diff --git a/gnomemusic/grilowrappers/grltrackersource.py b/gnomemusic/grilowrappers/grltrackersource.py
index 164a0937..957b5601 100644
--- a/gnomemusic/grilowrappers/grltrackersource.py
+++ b/gnomemusic/grilowrappers/grltrackersource.py
@@ -213,14 +213,12 @@ class GrlTrackerSource(GObject.GObject):
# print("NO MEDIA", source, op_id, media, error)
return
- song = CoreSong(media)
+ song = CoreSong(media, self._core_selection)
self._model.append(song)
self._hash[media.get_id()] = song
print("UPDATE ID", media.get_id(), media.get_title())
- song.connect("notify::selected", self._core_selection.update_selection)
-
def _on_source_removed(self, registry, source):
print("removed", source.props.source_id)
@@ -263,11 +261,10 @@ class GrlTrackerSource(GObject.GObject):
# print("NO MEDIA", source, op_id, media, error)
return
- song = CoreSong(media)
+ song = CoreSong(media, self._core_selection)
self._model.append(song)
self._hash[media.get_id()] = song
- song.connect("notify::selected", self._core_selection.update_selection)
# self._url_table[media.get_url()] = song
def _initial_albums_fill(self, source):
diff --git a/gnomemusic/views/albumsview.py b/gnomemusic/views/albumsview.py
index df41c40d..c769ccc1 100644
--- a/gnomemusic/views/albumsview.py
+++ b/gnomemusic/views/albumsview.py
@@ -51,8 +51,6 @@ class AlbumsView(BaseView):
self._album_widget.bind_property(
"selection-mode", self, "selection-mode",
GObject.BindingFlags.BIDIRECTIONAL)
- self._album_widget.bind_property(
- "selected-items-count", self, "selected-items-count")
self.add(self._album_widget)
self.albums_selected = []
@@ -104,6 +102,18 @@ class AlbumsView(BaseView):
def _create_widget(self, corealbum):
album_widget = AlbumCover(corealbum)
+ self.bind_property(
+ "selection-mode", album_widget, "selection-mode",
+ GObject.BindingFlags.SYNC_CREATE
+ | GObject.BindingFlags.BIDIRECTIONAL)
+
+ # NOTE: Adding SYNC_CREATE here will trigger all the nested
+ # models to be created. This will slow down initial start,
+ # but will improve initial 'selecte all' speed.
+ album_widget.bind_property(
+ "selected", corealbum, "selected",
+ GObject.BindingFlags.BIDIRECTIONAL)
+
return album_widget
@log
@@ -113,14 +123,14 @@ class AlbumsView(BaseView):
@log
def _on_child_activated(self, widget, child, user_data=None):
+ corealbum = child.props.corealbum
if self.props.selection_mode:
return
- item = child.props.corealbum
# Update and display the album widget if not in selection mode
- self._album_widget.update(item)
+ self._album_widget.update(corealbum)
- self._set_album_headerbar(item)
+ self._set_album_headerbar(corealbum)
self.set_visible_child(self._album_widget)
@log
@@ -136,72 +146,18 @@ class AlbumsView(BaseView):
self._init = True
self._view.show()
- @log
- def get_selected_songs(self, callback):
- # FIXME: we call into private objects with full knowledge of
- # what is there
- if self._headerbar.props.state == HeaderBar.State.CHILD:
- callback(self._album_widget.get_selected_songs())
- else:
- self.items_selected = []
- self.items_selected_callback = callback
- self.albums_index = 0
- if len(self.albums_selected):
- self._get_selected_album_songs()
-
- def _create_album_item(self, item):
- child = AlbumCover(item)
-
- child.connect('notify::selected', self._on_selection_changed)
-
- self.bind_property(
- 'selection-mode', child, 'selection-mode',
- GObject.BindingFlags.BIDIRECTIONAL)
-
- return child
-
- @log
- def _on_selection_changed(self, child, data=None):
- if (child.props.selected
- and child.props.media not in self.albums_selected):
- self.albums_selected.append(child.props.media)
- elif (not child.props.selected
- and child.props.media in self.albums_selected):
- self.albums_selected.remove(child.props.media)
-
- self.props.selected_items_count = len(self.albums_selected)
-
- @log
- def _get_selected_album_songs(self):
- grilo.populate_album_songs(
- self.albums_selected[self.albums_index],
- self._add_selected_item)
- self.albums_index += 1
-
- @log
- def _add_selected_item(self, source, param, item, remaining=0, data=None):
- if item:
- self.items_selected.append(item)
- if remaining == 0:
- if self.albums_index < self.props.selected_items_count:
- self._get_selected_album_songs()
- else:
- self.items_selected_callback(self.items_selected)
-
def _toggle_all_selection(self, selected):
"""
Selects or unselects all items without sending the notify::active
signal for performance purposes.
"""
- for child in self._view.get_children():
- child.props.selected = selected
+ with self._window._app._coreselection.freeze_notify():
+ for child in self._view.get_children():
+ child.props.selected = selected
+ child.props.corealbum.props.selected = selected
- @log
def select_all(self):
- self.albums_selected = list(self.all_items)
self._toggle_all_selection(True)
- @log
def unselect_all(self):
- self.albums_selected = []
self._toggle_all_selection(False)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]