[gnome-music/wip/mschraal/core: 15/70] Add nonfunctional albumwidget2
- From: Marinus Schraal <mschraal src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-music/wip/mschraal/core: 15/70] Add nonfunctional albumwidget2
- Date: Tue, 18 Jun 2019 15:55:34 +0000 (UTC)
commit a37b0966f041c9881db1dcad4b88870e2781ae07
Author: Marinus Schraal <mschraal gnome org>
Date: Wed May 8 20:35:46 2019 +0200
Add nonfunctional albumwidget2
data/org.gnome.Music.gresource.xml | 1 +
data/ui/AlbumWidget2.ui | 245 ++++++++++++++++++++++++++++++++++
gnomemusic/views/albumsview.py | 5 +-
gnomemusic/widgets/albumwidget2.py | 261 +++++++++++++++++++++++++++++++++++++
4 files changed, 509 insertions(+), 3 deletions(-)
---
diff --git a/data/org.gnome.Music.gresource.xml b/data/org.gnome.Music.gresource.xml
index 3992ffa4..953c5c03 100644
--- a/data/org.gnome.Music.gresource.xml
+++ b/data/org.gnome.Music.gresource.xml
@@ -7,6 +7,7 @@
<file preprocess="xml-stripblanks">ui/AboutDialog.ui</file>
<file preprocess="xml-stripblanks">ui/AlbumCover.ui</file>
<file preprocess="xml-stripblanks">ui/AlbumWidget.ui</file>
+ <file preprocess="xml-stripblanks">ui/AlbumWidget2.ui</file>
<file preprocess="xml-stripblanks">ui/AppMenu.ui</file>
<file preprocess="xml-stripblanks">ui/ArtistAlbumWidget.ui</file>
<file preprocess="xml-stripblanks">ui/ArtistAlbumsWidget.ui</file>
diff --git a/data/ui/AlbumWidget2.ui b/data/ui/AlbumWidget2.ui
new file mode 100644
index 00000000..743a1d44
--- /dev/null
+++ b/data/ui/AlbumWidget2.ui
@@ -0,0 +1,245 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.20.0 -->
+<interface>
+ <requires lib="gtk+" version="3.12"/>
+ <template class="AlbumWidget2" parent="GtkEventBox">
+ <property name="visible">True</property>
+ <style>
+ <class name="view"/>
+ <class name="content-view"/>
+ </style>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkBox" id="albumInfo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="margin_start">32</property>
+ <property name="margin_end">32</property>
+ <property name="margin_top">64</property>
+ <property name="margin_bottom">32</property>
+ <property name="vexpand">True</property>
+ <property name="hexpand">True</property>
+ <child>
+ <object class="GtkBox" id="albumDetails">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">center</property>
+ <property name="valign">start</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">18</property>
+ <child>
+ <object class="CoverStack" id="_cover_stack">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">center</property>
+ <property name="valign">start</property>
+ <property name="margin_start">1</property>
+ <property name="margin_end">1</property>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="artistBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">center</property>
+ <property name="valign">start</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">3</property>
+ <child>
+ <object class="GtkLabel" id="_title_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">center</property>
+ <property name="justify">center</property>
+ <property name="ellipsize">middle</property>
+ <style>
+ <class name="title-artist"/>
+ </style>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="_artist_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">center</property>
+ <property name="justify">center</property>
+ <property name="ellipsize">middle</property>
+ <style>
+ <class name="title-artist"/>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid" id="grid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">21</property>
+ <property name="column_spacing">32</property>
+ <property name="column_homogeneous">True</property>
+ <child>
+ <object class="GtkLabel" id="released_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="margin_top">2</property>
+ <property name="margin_bottom">2</property>
+ <property name="label" translatable="yes">Released</property>
+ <property name="use_markup">True</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="running_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="label" translatable="yes">Running Length</property>
+ <property name="use_markup">True</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="_released_info_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin_top">2</property>
+ <property name="margin_bottom">2</property>
+ <property name="label">----</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="_running_info_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label">--:--</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="_composer_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="halign">end</property>
+ <property name="margin_top">2</property>
+ <property name="margin_bottom">2</property>
+ <property name="label" translatable="yes">Composer</property>
+ <property name="use_markup">True</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="_composer_info_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="halign">start</property>
+ <property name="margin_top">2</property>
+ <property name="margin_bottom">2</property>
+ <property name="ellipsize">end</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="hscrollbar_policy">never</property>
+ <child>
+ <object class="GtkViewport" id="_viewport">
+ <property name="width_request">600</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="hexpand">True</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- TODO: The top of the coverart is the same vertical -->
+ <!-- position as the top of the album songs, however -->
+ <!-- since we set a top margins for the discbox -->
+ <!-- subtract that margin here. A cleaner solution is appreciated. -->
+ <object class="GtkListBox" id="_listbox">
+ <property name="can_focus">False</property>
+ <property name="margin_top">48</property>
+ <property name="margin_bottom">64</property>
+ <property name="margin_end">32</property>
+ <property name="visible">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/gnomemusic/views/albumsview.py b/gnomemusic/views/albumsview.py
index 76af3cfe..91472926 100644
--- a/gnomemusic/views/albumsview.py
+++ b/gnomemusic/views/albumsview.py
@@ -30,7 +30,7 @@ from gnomemusic.grilo import grilo
from gnomemusic.views.baseview import BaseView
from gnomemusic.widgets.headerbar import HeaderBar
from gnomemusic.widgets.albumcover import AlbumCover
-from gnomemusic.widgets.albumwidget import AlbumWidget
+from gnomemusic.widgets.albumwidget2 import AlbumWidget2
import gnomemusic.utils as utils
@@ -46,8 +46,7 @@ class AlbumsView(BaseView):
super().__init__('albums', _("Albums"), window)
self.player = player
-
- self._album_widget = AlbumWidget(player)
+ self._album_widget = AlbumWidget2(player, self)
self._album_widget.bind_property(
"selection-mode", self, "selection-mode",
GObject.BindingFlags.BIDIRECTIONAL)
diff --git a/gnomemusic/widgets/albumwidget2.py b/gnomemusic/widgets/albumwidget2.py
new file mode 100644
index 00000000..4d7762cc
--- /dev/null
+++ b/gnomemusic/widgets/albumwidget2.py
@@ -0,0 +1,261 @@
+from gettext import ngettext
+from gi.repository import GdkPixbuf, GObject, Grl, Gtk
+
+from gnomemusic import log
+from gnomemusic.albumartcache import Art
+from gnomemusic.grilo import grilo
+from gnomemusic.player import PlayerPlaylist
+from gnomemusic.widgets.disclistboxwidget import DiscBox
+from gnomemusic.widgets.disclistboxwidget import DiscListBox # noqa: F401
+from gnomemusic.widgets.songwidget import SongWidget
+import gnomemusic.utils as utils
+
+
+@Gtk.Template(resource_path='/org/gnome/Music/ui/AlbumWidget2.ui')
+class AlbumWidget2(Gtk.EventBox):
+ """Album widget.
+
+ The album widget consists of an image with the album art
+ on the left and a list of songs on the right.
+ """
+
+ __gtype_name__ = 'AlbumWidget2'
+
+ _artist_label = Gtk.Template.Child()
+ _composer_label = Gtk.Template.Child()
+ _composer_info_label = Gtk.Template.Child()
+ _cover_stack = Gtk.Template.Child()
+ _listbox = Gtk.Template.Child()
+ _released_info_label = Gtk.Template.Child()
+ _running_info_label = Gtk.Template.Child()
+ _title_label = Gtk.Template.Child()
+
+ selected_items_count = GObject.Property(type=int, default=0, minimum=0)
+ selection_mode = GObject.Property(type=bool, default=False)
+
+ _duration = 0
+
+ def __repr__(self):
+ return '<AlbumWidget>'
+
+ @log
+ def __init__(self, player, parent_view):
+ """Initialize the AlbumWidget.
+
+ :param player: The player object
+ :param parent_view: The view this widget is part of
+ """
+ super().__init__()
+
+ self._album = None
+ self._songs = []
+
+ self._cover_stack.props.size = Art.Size.LARGE
+ self._parent_view = parent_view
+ self._player = player
+ self._iter_to_clean = None
+
+ self._create_model()
+ self._album_name = None
+
+ self._listbox.connect("row-activated", self._on_row_activated)
+
+ @log
+ def _create_model(self):
+ """Create the ListStore model for this widget."""
+ self._model = Gtk.ListStore(
+ GObject.TYPE_STRING, # title
+ GObject.TYPE_STRING,
+ GObject.TYPE_STRING,
+ GObject.TYPE_STRING,
+ GdkPixbuf.Pixbuf, # icon
+ GObject.TYPE_OBJECT, # song object
+ GObject.TYPE_BOOLEAN, # item selected
+ GObject.TYPE_STRING,
+ GObject.TYPE_BOOLEAN,
+ GObject.TYPE_INT, # icon shown
+ GObject.TYPE_BOOLEAN,
+ GObject.TYPE_INT
+ )
+
+ @log
+ def update(self, album):
+ """Update the album widget.
+
+ :param Grl.Media album: The grilo media album
+ """
+ # reset view
+ self._songs = []
+ self._create_model()
+ # for widget in self._disc_listbox.get_children():
+ # self._disc_listbox.remove(widget)
+
+ self._cover_stack.update(album)
+
+ self._duration = 0
+
+ self._album_name = utils.get_album_title(album)
+ artist = utils.get_artist_name(album)
+
+ self._title_label.props.label = self._album_name
+ self._title_label.props.tooltip_text = self._album_name
+
+ self._artist_label.props.label = artist
+ self._artist_label.props.tooltip_text = artist
+
+ year = utils.get_media_year(album)
+ if not year:
+ year = '----'
+ self._released_info_label.props.label = year
+
+ self._set_composer_label(album)
+
+ self._album = album
+
+ # self._player.connect('song-changed', self._update_model)
+
+ # grilo.populate_album_songs(album, self.add_item)
+
+ @log
+ def _set_composer_label(self, album):
+ composer = album.get_composer()
+ show = False
+
+ if composer:
+ self._composer_info_label.props.label = composer
+ self._composer_info_label.props.max_width_chars = 10
+ self._composer_info_label.props.tooltip_text = composer
+ show = True
+
+ self._composer_label.props.visible = show
+ self._composer_info_label.props.visible = show
+
+ @log
+ def _set_duration_label(self):
+ mins = (self._duration // 60) + 1
+ self._running_info_label.props.label = ngettext(
+ "{} minute", "{} minutes", mins).format(mins)
+
+ # @Gtk.Template.Callback()
+ @log
+ def _on_selection_changed(self, widget):
+ n_items = len(self._disc_listbox.get_selected_items())
+ self.props.selected_items_count = n_items
+
+ @log
+ def _create_disc_box(self, disc_nr, disc_songs):
+ disc_box = DiscBox(self._model)
+ disc_box.set_songs(disc_songs)
+ disc_box.set_disc_number(disc_nr)
+ disc_box.props.columns = 1
+ disc_box.props.show_durations = True
+ disc_box.props.show_favorites = True
+ disc_box.props.show_song_numbers = False
+ disc_box.connect('song-activated', self._song_activated)
+
+ return disc_box
+
+ @log
+ def _song_activated(self, widget, song_widget):
+ if self.props.selection_mode:
+ song_widget.props.selected = not song_widget.props.selected
+ return
+
+ self._player.set_playlist(
+ PlayerPlaylist.Type.ALBUM, self._album_name, song_widget.model,
+ song_widget.itr)
+ self._player.play()
+ return True
+
+ @log
+ def add_item(self, source, prefs, song, remaining, data=None):
+ """Add a song to the item to album list.
+
+ If no song is remaining create DiscBox and display the widget.
+ :param GrlTrackerSource source: The grilo source
+ :param prefs: not used
+ :param GrlMedia song: The grilo media object
+ :param int remaining: Remaining number of items to add
+ :param data: User data
+ """
+ if song:
+ self._songs.append(song)
+ self._duration += song.get_duration()
+ return
+
+ if remaining == 0:
+ discs = {}
+ for song in self._songs:
+ disc_nr = song.get_album_disc_number()
+ if disc_nr not in discs.keys():
+ discs[disc_nr] = [song]
+ else:
+ discs[disc_nr].append(song)
+
+ for disc_nr in discs:
+ disc = self._create_disc_box(disc_nr, discs[disc_nr])
+ if len(discs) == 1:
+ disc.props.show_disc_label = False
+ self._disc_listbox.add(disc)
+
+ self._set_duration_label()
+ self._update_model(self._player)
+
+ @log
+ def _update_model(self, player, position=None):
+ """Updates model when the song changes
+
+ :param Player player: The main player object
+ :param int position: current song position
+ """
+ if not player.playing_playlist(
+ PlayerPlaylist.Type.ALBUM, self._album_name):
+ return True
+
+ current_song = player.props.current_song
+ self._duration = 0
+ song_passed = False
+
+ for song in self._songs:
+ song_widget = song.song_widget
+ self._duration += song.get_duration()
+
+ if (song.get_id() == current_song.get_id()):
+ song_widget.props.state = SongWidget.State.PLAYING
+ song_passed = True
+ elif (song_passed):
+ # Counter intuitive, but this is due to call order.
+ song_widget.props.state = SongWidget.State.UNPLAYED
+ else:
+ song_widget.props.state = SongWidget.State.PLAYED
+
+ self._set_duration_label()
+
+ return True
+
+ @log
+ def select_all(self):
+ self._disc_listbox.select_all()
+
+ @log
+ def select_none(self):
+ self._disc_listbox.select_none()
+
+ @log
+ def get_selected_songs(self):
+ """Return a list of selected songs.
+
+ :returns: selected songs
+ :rtype: list
+ """
+ return self._disc_listbox.get_selected_items()
+
+ @GObject.Property(
+ type=Grl.Media, default=False, flags=GObject.ParamFlags.READABLE)
+ def album(self):
+ """Get the current album.
+
+ :returns: the current album
+ :rtype: Grl.Media
+ """
+ return self._album
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]