def _on_tracks_populated(self, disc_number): """ Emit populated signal @param disc_number as int """ if TracksView.get_populated(self): from lollypop.view_albums_box import AlbumsBoxView for artist_id in self.__artist_ids: if artist_id == Type.COMPILATIONS: album_ids = App().albums.get_compilation_ids( self.__genre_ids) else: album_ids = App().albums.get_ids([artist_id], []) if self._album.id in album_ids: album_ids.remove(self._album.id) if not album_ids: continue artist = GLib.markup_escape_text( App().artists.get_name(artist_id)) label = Gtk.Label.new() label.set_markup('''<span size="large" alpha="40000" weight="bold">%s %s</span>''' % (_("Others albums from"), artist)) label.set_property("halign", Gtk.Align.START) label.set_margin_top(40) label.show() self.__grid.add(label) self.__others_box = AlbumsBoxView([], [artist_id], ViewType.SMALL) self.__others_box.show() self.__grid.add(self.__others_box) self.__others_box.populate([Album(id) for id in album_ids]) else: TracksView.populate(self)
def __init__(self, storage_type, view_type): """ Init view @param view_type as ViewType @param storage_type as StorageType """ AlbumsBoxView.__init__(self, [], [], storage_type, view_type) self.set_property("valign", Gtk.Align.START) self._label = Gtk.Label.new() self._label.set_ellipsize(Pango.EllipsizeMode.END) self._label.set_hexpand(True) self._label.set_property("halign", Gtk.Align.START) self._label.get_style_context().add_class("dim-label") self.__update_label(App().window.folded) self._backward_button = Gtk.Button.new_from_icon_name( "go-previous-symbolic", Gtk.IconSize.BUTTON) self._forward_button = Gtk.Button.new_from_icon_name( "go-next-symbolic", Gtk.IconSize.BUTTON) self._backward_button.get_style_context().add_class("menu-button") self._forward_button.get_style_context().add_class("menu-button") header = Gtk.Grid() header.set_column_spacing(10) header.add(self._label) header.add(self._backward_button) header.add(self._forward_button) header.set_margin_end(MARGIN) header.show_all() HorizontalScrollingHelper.__init__(self) self.add(header) self.add_widget(self._box)
def _on_populated(self, widget): """ Update buttons @param widget as Gtk.Widget """ self.update_buttons() AlbumsBoxView._on_populated(self, widget)
def __init__(self, artist_ids, genre_ids): """ Init ArtistView @param artist_id as int (Current if None) @param genre_id as int """ View.__init__(self) self._genre_ids = genre_ids self._artist_ids = artist_ids ArtistViewCommon.__init__(self) self._jump_button.hide() self.__overlay = Gtk.Overlay() self.__overlay.show() self.__overlay.add_overlay(self._banner) album_ids = App().albums.get_ids(artist_ids, genre_ids) self.__album_box = AlbumsBoxView( genre_ids, artist_ids, ViewType.MEDIUM | ViewType.SCROLLED | ViewType.NOT_ADAPTIVE) height = self._banner.default_height // 3 self._banner.set_height(height) self.__album_box.set_margin_top(height) self.__album_box.populate([Album(id) for id in album_ids]) self.__album_box.show() self.__overlay.add_overlay(self.__album_box) self.add(self.__overlay)
def _on_map(self, widget): """ Set initial view state @param widget as GtK.Widget """ AlbumsBoxView._on_map(self, widget) if self.view_type & ViewType.SCROLLED: self.scrolled.grab_focus()
def _on_adaptive_changed(self, window, status): """ Update label @param window as Window @param status as bool """ AlbumsBoxView._on_adaptive_changed(self, window, status) self.__update_label(status)
def add_value(self, album): """ Add a new album @param album as Album """ AlbumsBoxView.add_value_unsorted(self, album) self._box.set_min_children_per_line(len(self._box.get_children())) self.update_buttons()
def populate(self, albums): """ Configure widget based on albums @param items as [Album] """ if albums: self.show() self._box.set_min_children_per_line(len(albums)) AlbumsBoxView.populate(self, albums)
def _get_view_device_albums(self, index): """ Show albums for device at index @param index as int """ def load(): album_ids = App().albums.get_synced_ids(0) album_ids += App().albums.get_synced_ids(index) return [Album(album_id) for album_id in album_ids] from lollypop.view_albums_box import AlbumsBoxView view_type = ViewType.SCROLLED if App().window.is_adaptive: view_type |= ViewType.MEDIUM view = AlbumsBoxView([], [], view_type | self._view_type) loader = Loader(target=load, view=view) loader.start() view.show() return view
def _get_view_albums_years(self, years): """ Get album view for years @param years as [int] """ def load(): items = [] for year in years: items += App().albums.get_compilations_for_year(year) items += App().albums.get_albums_for_year(year) return [Album(album_id, [Type.YEARS], []) for album_id in items] from lollypop.view_albums_box import AlbumsBoxView view_type = ViewType.SCROLLED if App().window.is_adaptive: view_type |= ViewType.MEDIUM view = AlbumsBoxView([Type.YEARS], years, view_type | self._view_type) loader = Loader(target=load, view=view) loader.start() view.show() return view
def _get_view_albums(self, genre_ids, artist_ids): """ Get albums view for genres/artists @param genre ids as [int] @param is compilation as bool """ def load(): items = [] is_compilation = artist_ids and artist_ids[0] == Type.COMPILATIONS if genre_ids and genre_ids[0] == Type.ALL: if is_compilation or\ App().settings.get_value( "show-compilations-in-album-view"): items = App().albums.get_compilation_ids([]) if not is_compilation: items += App().albums.get_ids([], []) elif genre_ids and genre_ids[0] == Type.POPULARS: items = App().albums.get_rated() count = 100 - len(items) for album in App().albums.get_populars(count): if album not in items: items.append(album) elif genre_ids and genre_ids[0] == Type.LOVED: items = App().albums.get_loved_albums() elif genre_ids and genre_ids[0] == Type.RECENTS: items = App().albums.get_recents() elif genre_ids and genre_ids[0] == Type.NEVER: items = App().albums.get_never_listened_to() elif genre_ids and genre_ids[0] == Type.RANDOMS: items = App().albums.get_randoms() else: if is_compilation or\ App().settings.get_value( "show-compilations-in-album-view"): items = App().albums.get_compilation_ids(genre_ids) if not is_compilation: items += App().albums.get_ids([], genre_ids) return [ Album(album_id, genre_ids, artist_ids) for album_id in items ] if App().window.is_adaptive: from lollypop.view_albums_list import AlbumsListView view = AlbumsListView(RowListType.DEFAULT, genre_ids, artist_ids) else: from lollypop.view_albums_box import AlbumsBoxView view = AlbumsBoxView(genre_ids, artist_ids) loader = Loader(target=load, view=view) loader.start() view.show() return view
def _get_view_albums(self, genre_ids, artist_ids): """ Get albums view for genres/artists @param genre_ids as [int] @param is compilation as bool """ def load(): album_ids = self.get_view_album_ids(genre_ids, artist_ids) return [ Album(album_id, genre_ids, artist_ids) for album_id in album_ids ] from lollypop.view_albums_box import AlbumsBoxView view_type = ViewType.SCROLLED if App().window.is_adaptive: view_type |= ViewType.MEDIUM view = AlbumsBoxView(genre_ids, artist_ids, view_type | self._view_type) loader = Loader(target=load, view=view) loader.start() view.show() return view
def __init__(self, genre_ids, artist_ids, storage_type, view_type): """ Init ArtistView @param genre_ids as [int] @param artist_ids as [int] @param storage_type as StorageType @param view_type as ViewType """ AlbumsBoxView.__init__(self, genre_ids, artist_ids, storage_type, view_type | ViewType.OVERLAY | ViewType.ARTIST) self.__others_boxes = [] self.__banner = ArtistBannerWidget(genre_ids, artist_ids, self._storage_type, view_type) self.__banner.show() self._box.get_style_context().add_class("padding") self.connect("populated", self.__on_populated) self.__grid = Gtk.Grid() self.__grid.show() self.__grid.set_property("valign", Gtk.Align.START) self.__grid.set_row_spacing(10) self.__grid.set_orientation(Gtk.Orientation.VERTICAL) self.__grid.add(self._box) self.add_widget(self.__grid, self.__banner)
class ArtistViewSmall(View, ArtistViewCommon): """ Show artist albums and tracks """ def __init__(self, artist_ids, genre_ids): """ Init ArtistView @param artist_id as int (Current if None) @param genre_id as int """ View.__init__(self) self._genre_ids = genre_ids self._artist_ids = artist_ids ArtistViewCommon.__init__(self) self._jump_button.hide() self.__overlay = Gtk.Overlay() self.__overlay.show() self.__overlay.add_overlay(self._banner) album_ids = App().albums.get_ids(artist_ids, genre_ids) self.__album_box = AlbumsBoxView( genre_ids, artist_ids, ViewType.MEDIUM | ViewType.SCROLLED | ViewType.NOT_ADAPTIVE) height = self._banner.default_height // 3 self._banner.set_height(height) self.__album_box.set_margin_top(height) self.__album_box.populate([Album(id) for id in album_ids]) self.__album_box.show() self.__overlay.add_overlay(self.__album_box) self.add(self.__overlay) ####################### # PROTECTED # ####################### def _on_map(self, widget): """ Connect signals and set active ids @param widget as Gtk.Widget """ View._on_map(self, widget) App().settings.set_value("state-one-ids", GLib.Variant("ai", self._genre_ids)) App().settings.set_value("state-two-ids", GLib.Variant("ai", self._artist_ids)) App().settings.set_value("state-three-ids", GLib.Variant("ai", [])) def _on_adaptive_changed(self, window, status): """ Update banner style @param window as Window @param status as bool """ if not status: App().window.container.show_view(self._genre_ids, self._artist_ids, True) # Destroy after any animation GLib.idle_add(self.destroy, priority=GLib.PRIORITY_LOW)
def _get_view_albums_years(self, years): """ Get album view for years @param years as [int] """ def load(): items = [] for year in years: items += App().albums.get_compilations_for_year(year) items += App().albums.get_albums_for_year(year) return [Album(album_id, [Type.YEARS], []) for album_id in items] if App().window.is_adaptive: from lollypop.view_albums_list import AlbumsListView view = AlbumsListView(RowListType.DEFAULT, years, [Type.YEARS]) else: from lollypop.view_albums_box import AlbumsBoxView view = AlbumsBoxView([Type.YEARS], years) loader = Loader(target=load, view=view) loader.start() view.show() return view
class AlbumView(LazyLoadingView, TracksView, ViewController): """ Show artist albums and tracks """ def __init__(self, album, artist_ids, genre_ids, view_type): """ Init ArtistView @param album as Album @param artist_ids as [int] @param genre_ids as [int] @param view_type as ViewType """ LazyLoadingView.__init__(self, view_type) TracksView.__init__(self, view_type) ViewController.__init__(self, ViewControllerType.ALBUM) self._album = album self.__genre_ids = genre_ids self.__artist_ids = artist_ids self.__grid = Gtk.Grid() self.__grid.set_property("vexpand", True) self.__grid.set_row_spacing(10) self.__grid.set_margin_start(MARGIN) self.__grid.set_margin_end(MARGIN) self.__grid.set_orientation(Gtk.Orientation.VERTICAL) self.__grid.show() def populate(self): """ Populate the view with album """ TracksView.populate(self) self.__grid.add(self._responsive_widget) self._viewport.add(self.__grid) self._overlay = Gtk.Overlay.new() self._overlay.add(self._scrolled) self._overlay.show() self.__banner = AlbumBannerWidget(self._album, self._view_type | ViewType.ALBUM) self.__banner.show() self._overlay.add_overlay(self.__banner) self.add(self._overlay) self._responsive_widget.show() self._scrolled.get_vscrollbar().set_margin_top(self.__banner.height) ####################### # PROTECTED # ####################### def _on_value_changed(self, adj): """ Update scroll value and check for lazy queue @param adj as Gtk.Adjustment """ LazyLoadingView._on_value_changed(self, adj) if adj.get_value() == adj.get_lower(): height = self.__banner.default_height else: height = self.__banner.default_height // 3 self.__banner.set_height(height) self._scrolled.get_vscrollbar().set_margin_top(height) def _on_current_changed(self, player): """ Update children state @param player as Player """ self.set_playing_indicator() def _on_duration_changed(self, player, track_id): """ Update track duration @param player as Player @param track_id as int """ self.update_duration(track_id) def _on_album_updated(self, scanner, album_id, added): """ Handles changes in collection @param scanner as CollectionScanner @param album_id as int @param added as bool """ # Check we are not destroyed if album_id == self._album.id and not added: App().window.go_back() return def _on_map(self, widget): """ Set initial state and connect signals @param widget as Gtk.Widget """ LazyLoadingView._on_map(self, widget) self._responsive_widget.set_margin_top(self.__banner.default_height + 15) App().window.emit("show-can-go-back", True) App().window.emit("can-go-back-changed", True) App().settings.set_value("state-one-ids", GLib.Variant("ai", self.__genre_ids)) App().settings.set_value("state-two-ids", GLib.Variant("ai", self.__artist_ids)) App().settings.set_value("state-three-ids", GLib.Variant("ai", [self._album.id])) def _on_unmap(self, widget): """ Disconnect signals @param widget as Gtk.Widget """ LazyLoadingView._on_unmap(self, widget) def _on_tracks_populated(self, disc_number): """ Emit populated signal @param disc_number as int """ if TracksView.get_populated(self): from lollypop.view_albums_box import AlbumsBoxView for artist_id in self.__artist_ids: if artist_id == Type.COMPILATIONS: album_ids = App().albums.get_compilation_ids( self.__genre_ids) else: album_ids = App().albums.get_ids([artist_id], []) if self._album.id in album_ids: album_ids.remove(self._album.id) if not album_ids: continue artist = GLib.markup_escape_text( App().artists.get_name(artist_id)) label = Gtk.Label.new() label.set_markup('''<span size="large" alpha="40000" weight="bold">%s %s</span>''' % (_("Others albums from"), artist)) label.set_property("halign", Gtk.Align.START) label.set_margin_top(40) label.show() self.__grid.add(label) self.__others_box = AlbumsBoxView([], [artist_id], ViewType.SMALL) self.__others_box.show() self.__grid.add(self.__others_box) self.__others_box.populate([Album(id) for id in album_ids]) else: TracksView.populate(self) def _on_adaptive_changed(self, window, status): """ Update banner style @param window as Window @param status as bool """ if status: view_type = self._view_type | ViewType.SMALL else: view_type = self._view_type & ~ViewType.SMALL self.__banner.set_view_type(view_type)