summaryrefslogtreecommitdiff
path: root/gnomemusic/views/searchview.py
diff options
context:
space:
mode:
Diffstat (limited to 'gnomemusic/views/searchview.py')
-rw-r--r--gnomemusic/views/searchview.py239
1 files changed, 59 insertions, 180 deletions
diff --git a/gnomemusic/views/searchview.py b/gnomemusic/views/searchview.py
index bea60950..cd7cf3f9 100644
--- a/gnomemusic/views/searchview.py
+++ b/gnomemusic/views/searchview.py
@@ -28,9 +28,10 @@ from gettext import gettext as _
from typing import Optional
import typing
-from gi.repository import Gdk, GObject, Gtk
+from gi.repository import GObject, Gtk
from gnomemusic.search import Search
+from gnomemusic.utils import ArtSize
from gnomemusic.widgets.albumcover import AlbumCover
from gnomemusic.widgets.albumwidget import AlbumWidget
from gnomemusic.widgets.headerbar import HeaderBar
@@ -40,6 +41,7 @@ from gnomemusic.widgets.songwidget import SongWidget
from gnomemusic.widgets.songwidgetmenu import SongWidgetMenu
if typing.TYPE_CHECKING:
from gnomemusic.application import Application
+ from gnomemusic.corealbum import CoreAlbum
from gnomemusic.coresong import CoreSong
@@ -78,7 +80,6 @@ class SearchView(Gtk.Stack):
_search_results = Gtk.Template.Child()
_songs_header = Gtk.Template.Child()
_songs_listbox = Gtk.Template.Child()
- _songs_listbox_ctrlr = Gtk.Template.Child()
_view_all_albums = Gtk.Template.Child()
_view_all_artists = Gtk.Template.Child()
@@ -94,41 +95,32 @@ class SearchView(Gtk.Stack):
self._application = application
self._coremodel = application.props.coremodel
self._model = self._coremodel.props.songs_search
- self._album_model = self._coremodel.props.albums_search
- self._album_filter = self._coremodel.props.albums_search_filter
- self._album_filter.set_filter_func(
- self._core_filter, self._album_model, 12)
+ self._player = self._application.props.player
+ self._window = application.props.window
+ self._headerbar = self._window.props.headerbar
+ self._album_model = self._coremodel.props.albums_search
self._artist_model = self._coremodel.props.artists_search
- self._artist_filter = self._coremodel.props.artists_search_filter
- self._artist_filter.set_filter_func(
- self._core_filter, self._artist_model, 6)
+
+ self._album_slice = Gtk.SliceListModel.new(self._album_model, 0, 8)
+ self._artist_slice = Gtk.SliceListModel.new(self._artist_model, 0, 6)
self._model.connect_after(
"items-changed", self._on_model_items_changed)
self._songs_listbox.bind_model(self._model, self._create_song_widget)
self._on_model_items_changed(self._model, 0, 0, 0)
- self._album_filter.connect_after(
+ self._album_slice.connect_after(
"items-changed", self._on_album_model_items_changed)
self._album_flowbox.bind_model(
- self._album_filter, self._create_album_widget)
- self._album_flowbox.connect(
- "size-allocate", self._on_album_flowbox_size_allocate)
- self._on_album_model_items_changed(self._album_filter, 0, 0, 0)
+ self._album_slice, self._create_album_cover)
+ self._application.props.window.connect(
+ "notify::default-width", self._on_window_width_change)
- self._artist_filter.connect_after(
+ self._artist_slice.connect_after(
"items-changed", self._on_artist_model_items_changed)
self._artist_flowbox.bind_model(
- self._artist_filter, self._create_artist_widget)
- self._artist_flowbox.connect(
- "size-allocate", self._on_artist_flowbox_size_allocate)
- self._on_artist_model_items_changed(self._artist_filter, 0, 0, 0)
-
- self._player = self._application.props.player
-
- self._window = application.props.window
- self._headerbar = self._window._headerbar
+ self._artist_slice, self._create_artist_widget)
self.connect("notify::selection-mode", self._on_selection_mode_changed)
@@ -140,7 +132,8 @@ class SearchView(Gtk.Stack):
self._album_widget.bind_property(
"selection-mode", self, "selection-mode",
GObject.BindingFlags.BIDIRECTIONAL)
- self._scrolled_album_widget.add(self._album_widget)
+ viewport = self._scrolled_album_widget.get_first_child()
+ viewport.set_child(self._album_widget)
self._scrolled_artist_window: Optional[Gtk.ScrolledWindow] = None
@@ -169,23 +162,23 @@ class SearchView(Gtk.Stack):
return song_widget
- def _create_album_widget(self, corealbum):
- album_widget = AlbumCover(corealbum)
- album_widget.retrieve()
+ def _create_album_cover(self, corealbum: CoreAlbum) -> AlbumCover:
+ album_cover = AlbumCover(corealbum)
+ album_cover.retrieve()
self.bind_property(
- "selection-mode", album_widget, "selection-mode",
+ "selection-mode", album_cover, "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 'select all' speed.
- album_widget.bind_property(
+ album_cover.bind_property(
"selected", corealbum, "selected",
GObject.BindingFlags.BIDIRECTIONAL)
- return album_widget
+ return album_cover
def _create_artist_widget(self, coreartist):
artist_tile = ArtistSearchTile(coreartist)
@@ -206,11 +199,6 @@ class SearchView(Gtk.Stack):
nr_albums = self._album_model.get_n_items()
self._view_all_albums.props.visible = (nr_albums > model.get_n_items())
- def set_child_visible(child):
- child.props.visible = True
-
- self._album_flowbox.foreach(set_child_visible)
-
def _on_artist_model_items_changed(self, model, position, removed, added):
items_found = model.get_n_items() > 0
self._artist_header.props.visible = items_found
@@ -221,11 +209,6 @@ class SearchView(Gtk.Stack):
self._view_all_artists.props.visible = (
nr_artists > model.get_n_items())
- def set_child_visible(child):
- child.props.visible = True
-
- self._artist_flowbox.foreach(set_child_visible)
-
def _on_model_items_changed(self, model, position, removed, added):
items_found = model.get_n_items() > 0
self._songs_header.props.visible = items_found
@@ -247,124 +230,26 @@ class SearchView(Gtk.Stack):
@Gtk.Template.Callback()
def _song_activated(
self, list_box: Gtk.ListBox, song_widget: SongWidget) -> bool:
- if song_widget.props.select_click:
- song_widget.props.select_click = False
- return True
-
- event = Gtk.get_current_event()
- (_, state) = event.get_state()
- mod_mask = Gtk.accelerator_get_default_mod_mask()
- if ((state & mod_mask) == Gdk.ModifierType.CONTROL_MASK
- and not self.props.selection_mode):
- self.props.selection_mode = True
- song_widget.props.select_click = True
- song_widget.props.coresong.props.selected = True
- return True
-
+ coresong = song_widget.props.coresong
if self.props.selection_mode:
- song_widget.props.select_click = True
- selection_state = song_widget.props.selected
+ selection_state = coresong.props.selected
song_widget.props.selected = not selection_state
- song_widget.props.coresong.props.selected = not selection_state
+ coresong.props.selected = not selection_state
return True
- (_, button) = event.get_button()
- if (button == Gdk.BUTTON_PRIMARY
- and not self.props.selection_mode):
- coresong = song_widget.props.coresong
- self._coremodel.props.active_core_object = coresong
- self._player.play(coresong)
+ self._coremodel.props.active_core_object = coresong
+ self._player.play(coresong)
return True
- @Gtk.Template.Callback()
- def _songs_listbox_right_click(
- self, gesture: Gtk.GestureMultiPress, n_press: int, x: int,
- y: int) -> None:
- song_widget = self._songs_listbox.get_row_at_y(y)
-
- _, y0 = song_widget.translate_coordinates(self._songs_listbox, 0, 0)
- row_height = song_widget.get_allocated_height()
- rect = Gdk.Rectangle()
- rect.x = x
- rect.y = y0 + 0.5 * row_height
-
- song_context_menu = SongWidgetMenu(
- self._application, song_widget, song_widget.props.coresong)
- song_context_menu.props.relative_to = self._songs_listbox
- song_context_menu.props.pointing_to = rect
- song_context_menu.popup()
-
- def _on_album_flowbox_size_allocate(self, widget, allocation, data=None):
- nb_children = self._album_filter.get_n_items()
- if nb_children == 0:
- return
-
- first_child = self._album_flowbox.get_child_at_index(0)
- child_height = first_child.get_allocation().height
- if allocation.height > 2.5 * child_height:
- for i in range(nb_children - 1, -1, -1):
- child = self._album_flowbox.get_child_at_index(i)
- if child.props.visible is True:
- child.props.visible = False
- return
-
- children_hidden = False
- for idx in range(nb_children):
- child = self._album_flowbox.get_child_at_index(idx)
- if not child.props.visible:
- children_hidden = True
- break
- if children_hidden is False:
- return
-
- last_visible_child = self._album_flowbox.get_child_at_index(idx - 1)
- first_row_last = self._album_flowbox.get_child_at_index((idx - 1) // 2)
- second_row_pos = last_visible_child.get_allocation().x
- first_row_pos = first_row_last.get_allocation().x
- child_width = last_visible_child.get_allocation().width
- nb_children_to_add = (first_row_pos - second_row_pos) // child_width
- nb_children_to_add = min(nb_children_to_add + idx, nb_children)
- for i in range(idx, nb_children_to_add):
- child = self._album_flowbox.get_child_at_index(i)
- child.props.visible = True
-
- def _on_artist_flowbox_size_allocate(self, widget, allocation, data=None):
- nb_children = self._artist_filter.get_n_items()
- if nb_children == 0:
- return
-
- first_child = self._artist_flowbox.get_child_at_index(0)
- # FIXME: It looks like it is possible that the widget is not
- # yet created, resulting in a crash with first_child being
- # None.
- # Look for a cleaner solution.
- if first_child is None:
- return
+ def _on_window_width_change(self, widget, value):
+ allocation = self._album_flowbox.get_allocation()
+ # FIXME: Just a bit of guesswork here.
+ padding = 32
+ items_per_row = allocation.width // (ArtSize.MEDIUM.width + padding)
- child_height = first_child.get_allocation().height
- if allocation.height > 1.5 * child_height:
- for i in range(nb_children - 1, -1, -1):
- child = self._artist_flowbox.get_child_at_index(i)
- if child.props.visible is True:
- child.props.visible = False
- return
-
- children_hidden = False
- for idx in range(nb_children):
- child = self._artist_flowbox.get_child_at_index(idx)
- if not child.props.visible:
- children_hidden = True
- break
- if children_hidden is False:
- return
-
- last_child = self._artist_flowbox.get_child_at_index(idx - 1)
- last_child_allocation = last_child.get_allocation()
- child_width = last_child_allocation.width
- if (last_child_allocation.x + 2 * child_width) < allocation.width:
- child = self._artist_flowbox.get_child_at_index(idx)
- child.props.visible = True
+ self._album_slice.props.size = 2 * items_per_row
+ self._artist_slice.props.size = items_per_row
@Gtk.Template.Callback()
def _on_album_activated(self, widget, child, user_data=None):
@@ -378,8 +263,8 @@ class SearchView(Gtk.Stack):
self.props.state = SearchView.State.ALBUM
self._headerbar.props.state = HeaderBar.State.SEARCH
- self._headerbar.props.title = corealbum.props.title
- self._headerbar.props.subtitle = corealbum.props.artist
+ self._headerbar.set_label_title(
+ corealbum.props.title, corealbum.props.artist)
self.set_visible_child(self._scrolled_album_widget)
self.props.search_mode_active = False
@@ -390,15 +275,15 @@ class SearchView(Gtk.Stack):
if self.props.selection_mode:
return
- artist_albums_widget = ArtistAlbumsWidget(
- coreartist, self._application)
+ artist_albums_widget = ArtistAlbumsWidget(self._application)
+ artist_albums_widget.props.coreartist = coreartist
# FIXME: Recreating a view here. Alternate solution is used
# in AlbumsView: one view created and an update function.
# Settle on one design.
self._scrolled_artist_window = Gtk.ScrolledWindow()
- self._scrolled_artist_window.add(artist_albums_widget)
+ self._scrolled_artist_window.props.child = artist_albums_widget
self._scrolled_artist_window.props.visible = True
- self.add(self._scrolled_artist_window)
+ self.add_child(self._scrolled_artist_window)
artist_albums_widget.show()
self.bind_property(
@@ -407,18 +292,16 @@ class SearchView(Gtk.Stack):
self.props.state = SearchView.State.ARTIST
self._headerbar.props.state = HeaderBar.State.SEARCH
- self._headerbar.props.title = coreartist.props.artist
- self._headerbar.props.subtitle = None
+ self._headerbar.set_label_title(coreartist.props.artist, "")
self.set_visible_child(self._scrolled_artist_window)
self.props.search_mode_active = False
@Gtk.Template.Callback()
- def _on_all_artists_clicked(self, widget, event, user_data=None):
+ def _on_all_artists_clicked(self, widget, user_data=None):
self.props.state = SearchView.State.ALL_ARTISTS
self._headerbar.props.state = HeaderBar.State.SEARCH
- self._headerbar.props.title = _("Artists Results")
- self._headerbar.props.subtitle = None
+ self._headerbar.set_label_title(_("Artists Results"), "")
self._artist_all_flowbox.props.visible = True
self._album_all_flowbox.props.visible = False
@@ -429,38 +312,36 @@ class SearchView(Gtk.Stack):
self.props.search_mode_active = False
@Gtk.Template.Callback()
- def _on_all_albums_clicked(self, widget, event, user_data=None):
+ def _on_all_albums_clicked(self, widget, user_data=None):
self.props.state = SearchView.State.ALL_ALBUMS
self._headerbar.props.state = HeaderBar.State.SEARCH
- self._headerbar.props.title = _("Albums Results")
- self._headerbar.props.subtitle = None
+ self._headerbar.set_label_title(_("Albums Results"), "")
self._artist_all_flowbox.props.visible = False
self._album_all_flowbox.props.visible = True
self._album_all_flowbox.bind_model(
- self._album_model, self._create_album_widget)
+ self._album_model, self._create_album_cover)
self.props.visible_child = self._all_search_results
self.props.search_mode_active = False
- def _select_all(self, value):
- def child_select(child):
- child.props.selected = value
-
+ def _select_all(self, value: bool) -> None:
if self.props.state == SearchView.State.MAIN:
with self._model.freeze_notify():
- def song_select(child):
- child.props.coresong.props.selected = value
-
- self._songs_listbox.foreach(song_select)
- self._album_flowbox.foreach(child_select)
- self._artist_flowbox.foreach(child_select)
+ for coresong in self._model:
+ coresong.props.selected = value
+ for corealbum in self._album_model:
+ corealbum.props.selected = value
+ for coreartist in self._artist_model:
+ coreartist.props.selected = value
elif self.props.state == SearchView.State.ALL_ALBUMS:
with self._model.freeze_notify():
- self._album_all_flowbox.foreach(child_select)
+ for corealbum in self._album_model:
+ corealbum.props.selected = value
elif self.props.state == SearchView.State.ALL_ARTISTS:
with self._model.freeze_notify():
- self._artist_all_flowbox.foreach(child_select)
+ for corealbum in self._album_model:
+ corealbum.props.selected = value
elif self.props.state == SearchView.State.ALBUM:
view = self._album_widget
if value is True:
@@ -485,8 +366,6 @@ class SearchView(Gtk.Stack):
return
elif self.get_visible_child() == self._scrolled_artist_window:
self.remove(self._scrolled_artist_window)
- self._scrolled_artist_window.destroy()
- self._scrolled_artist_window = None
self.set_visible_child(self._search_results)
self.props.search_mode_active = True