Expand/collapse for artists

This commit is contained in:
Sumner Evans
2020-05-20 07:45:37 -06:00
parent 7e626b0cc3
commit 4cf1d9d7e1
5 changed files with 124 additions and 66 deletions

View File

@@ -515,7 +515,7 @@ class FilesystemAdapter(CachingAdapter):
"year": getattr(api_album, "year", None),
"genre": ingest_genre_data(g) if (g := api_album.genre) else None,
"artist": ingest_artist_data(ar) if (ar := api_album.artist) else None,
"songs": [
"_songs": [
ingest_song_data(s, fill_album=False) for s in api_album.songs or []
],
"_cover_art": self._do_ingest_new_data(

View File

@@ -108,6 +108,15 @@ class Album(BaseModel):
except Exception:
return None
@property
def songs(self) -> List["Song"]:
albums = Album.select()
artists = Album.select()
return sorted(
prefetch(self._songs, albums, artists),
key=lambda s: (s.disc_number or 1, s.track),
)
class AlbumQueryResult(BaseModel):
query_hash = TextField(primary_key=True)
@@ -144,7 +153,7 @@ class Song(BaseModel):
duration = DurationField(null=True)
parent_id = TextField(null=True)
album = ForeignKeyField(Album, null=True, backref="songs")
album = ForeignKeyField(Album, null=True, backref="_songs")
artist = ForeignKeyField(Artist, null=True)
genre = ForeignKeyField(Genre, null=True, backref="songs")

View File

@@ -64,12 +64,17 @@
margin: 10px 15px 0 10px;
}
#artist-info-panel {
margin-bottom: 10px;
}
#playlist-name, #artist-detail-panel #artist-name {
font-size: 40px;
margin-bottom: 10px;
}
#playlist-name.collapsed {
#playlist-name.collapsed,
#artist-detail-panel #artist-name.collapsed {
font-size: 30px;
}
@@ -204,9 +209,7 @@
}
#artist-album-artwork {
margin: 10px;
min-width: 300px;
min-height: 300px;
margin: 10px 15px 0 10px;
}
#artist-album-list-artwork {

View File

@@ -1,6 +1,6 @@
from datetime import timedelta
from random import randint
from typing import Any, List, Sequence
from typing import List, Sequence
from gi.repository import Gio, GLib, GObject, Gtk, Pango
@@ -36,6 +36,9 @@ class ArtistsPanel(Gtk.Paned):
self.artist_detail_panel.connect(
"song-clicked", lambda _, *args: self.emit("song-clicked", *args),
)
self.artist_detail_panel.connect(
"refresh-window", lambda _, *args: self.emit("refresh-window", *args),
)
self.pack2(self.artist_detail_panel, True, False)
def update(self, app_config: AppConfiguration, force: bool = False):
@@ -145,7 +148,7 @@ class ArtistList(Gtk.Box):
self.loading_indicator.hide()
class ArtistDetailPanel(Gtk.ScrolledWindow):
class ArtistDetailPanel(Gtk.Box):
"""Defines the artists list."""
__gsignals__ = {
@@ -154,19 +157,30 @@ class ArtistDetailPanel(Gtk.ScrolledWindow):
GObject.TYPE_NONE,
(int, object, object),
),
"refresh-window": (
GObject.SignalFlags.RUN_FIRST,
GObject.TYPE_NONE,
(object, bool),
),
}
update_order_token = 0
artist_details_expanded = False
def __init__(self, *args, **kwargs):
super().__init__(*args, name="artist-detail-panel", **kwargs)
super().__init__(
*args,
name="artist-detail-panel",
orientation=Gtk.Orientation.VERTICAL,
**kwargs,
)
self.albums: Sequence[API.Album] = []
self.artist_id = None
artist_info_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
# Artist info panel
self.big_info_panel = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
self.big_info_panel = Gtk.Box(
orientation=Gtk.Orientation.HORIZONTAL, name="artist-info-panel"
)
self.artist_artwork = SpinnerImage(
loading=False,
@@ -179,22 +193,6 @@ class ArtistDetailPanel(Gtk.ScrolledWindow):
# Action buttons, name, comment, number of songs, etc.
artist_details_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
# Action buttons (note we are packing end here, so we have to put them
# in right-to-left).
self.artist_action_buttons = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
view_refresh_button = IconButton("view-refresh-symbolic", "Refresh artist info")
view_refresh_button.connect("clicked", self.on_view_refresh_click)
self.artist_action_buttons.pack_end(view_refresh_button, False, False, 5)
download_all_btn = IconButton(
"folder-download-symbolic", "Download all songs by this artist"
)
download_all_btn.connect("clicked", self.on_download_all_click)
self.artist_action_buttons.pack_end(download_all_btn, False, False, 5)
artist_details_box.pack_start(self.artist_action_buttons, False, False, 5)
artist_details_box.pack_start(Gtk.Box(), True, False, 0)
self.artist_indicator = self.make_label(name="artist-indicator")
@@ -246,35 +244,55 @@ class ArtistDetailPanel(Gtk.ScrolledWindow):
self.big_info_panel.pack_start(artist_details_box, True, True, 10)
artist_info_box.pack_start(self.big_info_panel, False, True, 0)
# Action buttons
action_buttons_container = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
self.artist_action_buttons = Gtk.Box(
orientation=Gtk.Orientation.HORIZONTAL, spacing=10
)
download_all_btn = IconButton(
"folder-download-symbolic", "Download all songs by this artist"
)
download_all_btn.connect("clicked", self.on_download_all_click)
self.artist_action_buttons.add(download_all_btn)
view_refresh_button = IconButton("view-refresh-symbolic", "Refresh artist info")
view_refresh_button.connect("clicked", self.on_view_refresh_click)
self.artist_action_buttons.add(view_refresh_button)
action_buttons_container.pack_start(
self.artist_action_buttons, False, False, 10
)
action_buttons_container.pack_start(Gtk.Box(), True, True, 0)
expand_button_container = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
self.expand_collapse_button = IconButton(
"pan-up-symbolic", "Expand playlist details"
)
self.expand_collapse_button.connect("clicked", self.on_expand_collapse_click)
expand_button_container.pack_end(self.expand_collapse_button, False, False, 0)
action_buttons_container.add(expand_button_container)
self.big_info_panel.pack_start(action_buttons_container, False, False, 5)
self.pack_start(self.big_info_panel, False, True, 0)
self.album_list_scrolledwindow = Gtk.ScrolledWindow()
self.albums_list = AlbumsListWithSongs()
self.albums_list.connect(
"song-clicked", lambda _, *args: self.emit("song-clicked", *args),
)
artist_info_box.pack_start(self.albums_list, True, True, 0)
self.add(artist_info_box)
self.album_list_scrolledwindow.add(self.albums_list)
self.pack_start(self.album_list_scrolledwindow, True, True, 0)
def update(self, app_config: AppConfiguration):
self.artist_id = app_config.state.selected_artist_id
if app_config.state.selected_artist_id is None:
self.artist_action_buttons.hide()
self.artist_indicator.set_text("")
self.artist_name.set_markup("")
self.artist_stats.set_markup("")
self.artist_bio.set_markup("")
self.similar_artists_scrolledwindow.hide()
self.play_shuffle_buttons.hide()
self.artist_artwork.set_from_file(None)
self.albums = []
self.albums_list.update(None)
self.hide()
else:
self.update_order_token += 1
self.artist_action_buttons.show()
self.show()
self.update_artist_view(
app_config.state.selected_artist_id,
app_config=app_config,
@@ -296,8 +314,22 @@ class ArtistDetailPanel(Gtk.ScrolledWindow):
if order_token != self.update_order_token:
return
self.artist_indicator.set_text("ARTIST")
if app_config:
self.artist_details_expanded = app_config.state.artist_details_expanded
up_down = "up" if self.artist_details_expanded else "down"
self.expand_collapse_button.set_icon(f"pan-{up_down}-symbolic")
self.expand_collapse_button.set_tooltip_text(
"Collapse" if self.artist_details_expanded else "Expand"
)
self.artist_name.set_markup(util.esc(f"<b>{artist.name}</b>"))
self.artist_name.set_tooltip_text(artist.name)
if self.artist_details_expanded:
self.show_all()
self.artist_artwork.set_image_size(300)
self.artist_indicator.set_text("ARTIST")
self.artist_stats.set_markup(self.format_stats(artist))
self.artist_bio.set_markup(util.esc(artist.biography))
@@ -319,6 +351,14 @@ class ArtistDetailPanel(Gtk.ScrolledWindow):
self.similar_artists_scrolledwindow.show_all()
else:
self.similar_artists_scrolledwindow.hide()
else:
self.artist_name.get_style_context().add_class("collapsed")
self.show_all()
self.artist_artwork.set_image_size(70)
self.artist_indicator.hide()
self.artist_stats.hide()
self.artist_bio.hide()
self.similar_artists_scrolledwindow.hide()
self.play_shuffle_buttons.show_all()
@@ -353,7 +393,7 @@ class ArtistDetailPanel(Gtk.ScrolledWindow):
self.artist_id, force=True, order_token=self.update_order_token,
)
def on_download_all_click(self, btn: Any):
def on_download_all_click(self, _):
AdapterManager.batch_download_songs(
self.get_artist_song_ids(),
before_download=lambda _: self.update_artist_view(
@@ -364,13 +404,13 @@ class ArtistDetailPanel(Gtk.ScrolledWindow):
),
)
def on_play_all_clicked(self, btn: Any):
def on_play_all_clicked(self, _):
songs = self.get_artist_song_ids()
self.emit(
"song-clicked", 0, songs, {"force_shuffle_state": False},
)
def on_shuffle_all_button(self, btn: Any):
def on_shuffle_all_button(self, _):
songs = self.get_artist_song_ids()
self.emit(
"song-clicked",
@@ -379,6 +419,13 @@ class ArtistDetailPanel(Gtk.ScrolledWindow):
{"force_shuffle_state": True},
)
def on_expand_collapse_click(self, _):
self.emit(
"refresh-window",
{"artist_details_expanded": not self.artist_details_expanded},
False,
)
# Helper Methods
# =========================================================================
def set_all_loading(self, loading_state: bool):

View File

@@ -673,7 +673,6 @@ class PlaylistDetailPanel(Gtk.Overlay):
)
def on_expand_collapse_click(self, _):
# TODO
self.emit(
"refresh-window",
{"playlist_details_expanded": not self.playlist_details_expanded},