def __init__(self, player, parent_view): """Initialize the AlbumWidget. :param player: The player object :param parent_view: The view this widget is part of """ Gtk.EventBox.__init__(self) self._tracks = [] scale = self.get_scale_factor() self._cache = AlbumArtCache(scale) self._loading_icon_surface = DefaultIcon(scale).get( DefaultIcon.Type.loading, ArtSize.large) self._player = player self._iter_to_clean = None self._selection_mode = False self._builder = Gtk.Builder() self._builder.add_from_resource('/org/gnome/Music/AlbumWidget.ui') self._create_model() self._album = None self._header_bar = None self._selection_mode_allowed = True self._composer_label = self._builder.get_object('composer_label') self._composer_info = self._builder.get_object('composer_info') view_box = self._builder.get_object('view') self._disc_listbox = DiscListBox() self._disc_listbox.set_selection_mode_allowed(True) # 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. self._disc_listbox.set_margin_top(64 - 16) self._disc_listbox.set_margin_bottom(64) self._disc_listbox.set_margin_end(32) self._disc_listbox.connect('selection-changed', self._on_selection_changed) view_box.add(self._disc_listbox) # FIXME: Assigned to appease searchview # get_selected_tracks self.view = self._disc_listbox self.add(self._builder.get_object('AlbumWidget')) self.get_style_context().add_class('view') self.get_style_context().add_class('content-view') self.show_all()
def __init__(self, media, player, model, header_bar, selection_mode_allowed, size_group=None, cover_size_group=None): super().__init__(self, orientation=Gtk.Orientation.HORIZONTAL) self._size_group = size_group self._cover_size_group = cover_size_group scale = self.get_scale_factor() self._cache = AlbumArtCache(scale) self._loading_icon_surface = DefaultIcon(scale).get( DefaultIcon.Type.loading, ArtSize.medium) self._media = media self._player = player self._artist = utils.get_artist_name(self._media) self._album_title = utils.get_album_title(self._media) self._model = model self._header_bar = header_bar self._selection_mode = False self._selection_mode_allowed = selection_mode_allowed self._songs = [] self._header_bar._select_button.connect( 'toggled', self._on_header_select_button_toggled) ui = Gtk.Builder() ui.add_from_resource('/org/gnome/Music/ArtistAlbumWidget.ui') self.cover = ui.get_object('cover') self.cover.set_from_surface(self._loading_icon_surface) self._disc_listbox = ui.get_object('disclistbox') self._disc_listbox.set_selection_mode_allowed( self._selection_mode_allowed) ui.get_object('title').set_label(self._album_title) creation_date = self._media.get_creation_date() if creation_date: year = creation_date.get_year() ui.get_object('year').set_markup( '<span color=\'grey\'>{}</span>'.format(year)) if self._size_group: self._size_group.add_widget(ui.get_object('box1')) if self._cover_size_group: self._cover_size_group.add_widget(self.cover) self.pack_start(ui.get_object('ArtistAlbumWidget'), True, True, 0) GLib.idle_add(self._update_album_art) grilo.populate_album_songs(self._media, self._add_item)
def __init__(self, window, player): BaseView.__init__(self, 'search', None, window, Gd.MainViewType.LIST) self._items = {} self.isStarred = None self.iter_to_clean = None scale = self.get_scale_factor() loading_icon_surface = DefaultIcon(scale).get(DefaultIcon.Type.loading, ArtSize.small) self._loading_icon = Gdk.pixbuf_get_from_surface( loading_icon_surface, 0, 0, loading_icon_surface.get_width(), loading_icon_surface.get_height()) self._add_list_renderers() self.player = player self.head_iters = [None, None, None, None] self.songs_model = self.model self.previous_view = None self.connect('no-music-found', self._no_music_found_callback) self.albums_selected = [] self._albums = {} self._albumWidget = AlbumWidget(player, self) self.add(self._albumWidget) self.artists_albums_selected = [] self._artists = {} self._artistAlbumsWidget = None self.view.get_generic_view().set_show_expanders(False) self.items_selected = [] self.items_selected_callback = None self.found_items_number = None
def __init__(self, parent_window): GObject.GObject.__init__(self) self._parent_window = parent_window self.playlist = None self.playlistType = None self.playlistId = None self.playlistField = None self.currentTrack = None self.currentTrackUri = None self._lastState = Gst.State.PAUSED scale = parent_window.get_scale_factor() self.cache = AlbumArtCache(scale) self._loading_icon_surface = DefaultIcon(scale).get( DefaultIcon.Type.loading, ArtSize.xsmall) self._missingPluginMessages = [] Gst.init(None) GstPbutils.pb_utils_init() self.discoverer = GstPbutils.Discoverer() self.discoverer.connect('discovered', self._on_discovered) self.discoverer.start() self._discovering_urls = {} self.player = Gst.ElementFactory.make('playbin', 'player') self.bus = self.player.get_bus() self.bus.add_signal_watch() self.setup_replaygain() self._settings = Gio.Settings.new('org.gnome.Music') self._settings.connect('changed::repeat', self._on_repeat_setting_changed) self._settings.connect('changed::replaygain', self._on_replaygain_setting_changed) self.repeat = self._settings.get_enum('repeat') self.replaygain = self._settings.get_value('replaygain') is not None self.toggle_replaygain(self.replaygain) self.bus.connect('message::state-changed', self._on_bus_state_changed) self.bus.connect('message::error', self._onBusError) self.bus.connect('message::element', self._on_bus_element) self.bus.connect('message::eos', self._on_bus_eos) self._setup_view() self.playlist_insert_handler = 0 self.playlist_delete_handler = 0 self._check_last_fm()
def __init__(self, player, parent_view): """Initialize the AlbumWidget. :param player: The player object :param parent_view: The view this widget is part of """ Gtk.EventBox.__init__(self) scale = self.get_scale_factor() self._cache = AlbumArtCache(scale) self._loading_icon_surface = DefaultIcon(scale).get( DefaultIcon.Type.loading, ArtSize.large) self._player = player self._iter_to_clean = None self._ui = Gtk.Builder() self._ui.add_from_resource('/org/gnome/Music/AlbumWidget.ui') self._create_model() self.view = Gd.MainView(shadow_type=Gtk.ShadowType.NONE) self.view.set_view_type(Gd.MainViewType.LIST) self._album = None self._header_bar = None self.view.connect('item-activated', self._on_item_activated) view_box = self._ui.get_object('view') self._ui.get_object('scrolledWindow').set_placement( Gtk.CornerType.TOP_LEFT) self.view.connect('selection-mode-request', self._on_selection_mode_request) child_view = self.view.get_children()[0] child_view.set_margin_top(64) child_view.set_margin_bottom(64) child_view.set_margin_end(32) self.view.remove(child_view) view_box.add(child_view) self.add(self._ui.get_object('AlbumWidget')) self._star_handler = StarHandlerWidget(self, 9) self._add_list_renderers() self.get_style_context().add_class('view') self.get_style_context().add_class('content-view') self.view.get_generic_view().get_style_context().remove_class('view') self.show_all()
def __init__(self, name, title, window, view_type, use_sidebar=False, sidebar=None): Gtk.Stack.__init__(self, transition_type=Gtk.StackTransitionType.CROSSFADE) self._grid = Gtk.Grid(orientation=Gtk.Orientation.HORIZONTAL) self._offset = 0 self._adjustmentValueId = 0 self._adjustmentChangedId = 0 self._scrollbarVisibleId = 0 self.old_vsbl_range = None self.model = Gtk.ListStore( GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_STRING, GdkPixbuf.Pixbuf, GObject.TYPE_OBJECT, GObject.TYPE_BOOLEAN, GObject.TYPE_INT, GObject.TYPE_STRING, GObject.TYPE_INT, GObject.TYPE_BOOLEAN, GObject.TYPE_INT ) self._box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) # Setup the main view self._setup_view(view_type) if use_sidebar: self.stack = Gtk.Stack( transition_type=Gtk.StackTransitionType.SLIDE_RIGHT, ) dummy = Gtk.Frame(visible=False) self.stack.add_named(dummy, 'dummy') if sidebar: self.stack.add_named(sidebar, 'sidebar') else: self.stack.add_named(self._box, 'sidebar') self.stack.set_visible_child_name('dummy') self._grid.add(self.stack) if not use_sidebar or sidebar: self._grid.add(self._box) self.star_handler = StarHandlerWidget(self, 9) self._cursor = None self.window = window self.header_bar = window.toolbar self.selection_toolbar = window.selection_toolbar self.header_bar._select_button.connect( 'toggled', self._on_header_bar_toggled) self.header_bar._cancel_button.connect( 'clicked', self._on_cancel_button_clicked) self.name = name self.title = title self.add(self._grid) self.show_all() self.view.hide() self._items = [] scale = self.get_scale_factor() self.cache = AlbumArtCache(scale) self._loading_icon_surface = DefaultIcon(scale).get( DefaultIcon.Type.loading, ArtSize.medium) self._init = False grilo.connect('ready', self._on_grilo_ready) self.selection_socket = None self.header_bar.connect('selection-mode-changed', self._on_selection_mode_changed) self._discovering_urls = {} grilo.connect('changes-pending', self._on_changes_pending)
class BaseView(Gtk.Stack): nowPlayingIconName = 'media-playback-start-symbolic' errorIconName = 'dialog-error-symbolic' selection_mode = GObject.Property(type=bool, default=False) def __repr__(self): return '<BaseView>' @log def __init__(self, name, title, window, view_type, use_sidebar=False, sidebar=None): Gtk.Stack.__init__(self, transition_type=Gtk.StackTransitionType.CROSSFADE) self._grid = Gtk.Grid(orientation=Gtk.Orientation.HORIZONTAL) self._offset = 0 self._adjustmentValueId = 0 self._adjustmentChangedId = 0 self._scrollbarVisibleId = 0 self.old_vsbl_range = None self.model = Gtk.ListStore( GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_STRING, GdkPixbuf.Pixbuf, GObject.TYPE_OBJECT, GObject.TYPE_BOOLEAN, GObject.TYPE_INT, GObject.TYPE_STRING, GObject.TYPE_INT, GObject.TYPE_BOOLEAN, GObject.TYPE_INT ) self._box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) # Setup the main view self._setup_view(view_type) if use_sidebar: self.stack = Gtk.Stack( transition_type=Gtk.StackTransitionType.SLIDE_RIGHT, ) dummy = Gtk.Frame(visible=False) self.stack.add_named(dummy, 'dummy') if sidebar: self.stack.add_named(sidebar, 'sidebar') else: self.stack.add_named(self._box, 'sidebar') self.stack.set_visible_child_name('dummy') self._grid.add(self.stack) if not use_sidebar or sidebar: self._grid.add(self._box) self.star_handler = StarHandlerWidget(self, 9) self._cursor = None self.window = window self.header_bar = window.toolbar self.selection_toolbar = window.selection_toolbar self.header_bar._select_button.connect( 'toggled', self._on_header_bar_toggled) self.header_bar._cancel_button.connect( 'clicked', self._on_cancel_button_clicked) self.name = name self.title = title self.add(self._grid) self.show_all() self.view.hide() self._items = [] scale = self.get_scale_factor() self.cache = AlbumArtCache(scale) self._loading_icon_surface = DefaultIcon(scale).get( DefaultIcon.Type.loading, ArtSize.medium) self._init = False grilo.connect('ready', self._on_grilo_ready) self.selection_socket = None self.header_bar.connect('selection-mode-changed', self._on_selection_mode_changed) self._discovering_urls = {} grilo.connect('changes-pending', self._on_changes_pending) @log def _on_changes_pending(self, data=None): pass @log def _setup_view(self, view_type): self.view = Gd.MainView(shadow_type=Gtk.ShadowType.NONE) self.view.set_view_type(view_type) self.view.click_handler = self.view.connect('item-activated', self._on_item_activated) self.view.connect('selection-mode-request', self._on_selection_mode_request) self.view.bind_property('selection-mode', self, 'selection_mode', GObject.BindingFlags.BIDIRECTIONAL) self.view.connect('view-selection-changed', self._on_view_selection_changed) self._box.pack_start(self.view, True, True, 0) @log def _on_header_bar_toggled(self, button): self.selection_mode = button.get_active() if self.selection_mode: self.header_bar.set_selection_mode(True) self.player.actionbar.set_visible(False) self.selection_toolbar.actionbar.set_visible(True) self.selection_toolbar._add_to_playlist_button.set_sensitive(False) self.selection_toolbar._remove_from_playlist_button.set_sensitive(False) else: self.header_bar.set_selection_mode(False) self.player.actionbar.set_visible(self.player.currentTrack is not None) self.selection_toolbar.actionbar.set_visible(False) self.unselect_all() @log def _on_cancel_button_clicked(self, button): self.view.set_selection_mode(False) self.header_bar.set_selection_mode(False) @log def _on_grilo_ready(self, data=None): # FIXME: with async changes in Window this seems never to be # called anymore. Fix it proper or remove. if (self.header_bar.get_stack().get_visible_child() == self and not self._init): self._populate() self.header_bar.get_stack().connect('notify::visible-child', self._on_headerbar_visible) @log def _on_headerbar_visible(self, widget, param): if self == widget.get_visible_child() and not self._init: self._populate() @log def _on_view_selection_changed(self, widget): if not self.selection_mode: return items = self.view.get_selection() self.update_header_from_selection(len(items)) @log def update_header_from_selection(self, n_items): self.selection_toolbar._add_to_playlist_button.\ set_sensitive(n_items > 0) self.selection_toolbar._remove_from_playlist_button.\ set_sensitive(n_items > 0) if n_items > 0: self.header_bar._selection_menu_label.set_text( ngettext("Selected %d item", "Selected %d items", n_items) % n_items) else: self.header_bar._selection_menu_label.set_text(_("Click on items to select them")) @log def _populate(self, data=None): self._init = True self.populate() @log def _on_selection_mode_changed(self, widget, data=None): pass @log def populate(self): pass @log def _add_item(self, source, param, item, remaining=0, data=None): if not item: if remaining == 0: self.view.set_model(self.model) self.window.pop_loading_notification() self.view.show() return self._offset += 1 artist = utils.get_artist_name(item) title = utils.get_media_title(item) _iter = self.model.append(None) loading_icon = Gdk.pixbuf_get_from_surface( self._loadin_icon_surface, 0, 0, self._loading_icon_surface.get_width(), self._loading_icon_surface.get_height()) self.model[_iter][0, 1, 2, 3, 4, 5, 7, 9] = [ str(item.get_id()), '', title, artist, loading_icon, item, 0, False ] self.cache.lookup(item, self._iconWidth, self._iconHeight, self._on_lookup_ready, _iter) @log def _on_lookup_ready(self, surface, _iter): if surface: pixbuf = Gdk.pixbuf_get_from_surface(surface, 0, 0, surface.get_width(), surface.get_height()) self.model[_iter][4] = pixbuf @log def _add_list_renderers(self): pass @log def _on_item_activated(self, widget, id, path): pass @log def _on_selection_mode_request(self, *args): self.header_bar._select_button.clicked() @log def get_selected_tracks(self, callback): callback([]) @log def _set_selection(self, value, parent=None): count = 0 _iter = self.model.iter_children(parent) while _iter is not None: if self.model.iter_has_child(_iter): count += self._set_selection(value, _iter) if self.model[_iter][5]: self.model[_iter][6] = value count += 1 _iter = self.model.iter_next(_iter) return count @log def select_all(self): """Select all the available tracks.""" count = self._set_selection(True) if count > 0: self.selection_toolbar._add_to_playlist_button.set_sensitive(True) self.selection_toolbar._remove_from_playlist_button.set_sensitive(True) self.update_header_from_selection(count) self.view.queue_draw() @log def unselect_all(self): """Unselects all the selected tracks.""" self._set_selection(False) self.selection_toolbar._add_to_playlist_button.set_sensitive(False) self.selection_toolbar._remove_from_playlist_button.set_sensitive(False) self.header_bar._selection_menu_label.set_text(_("Click on items to select them")) self.queue_draw()
def __init__(self, name, title, window, view_type, use_sidebar=False, sidebar=None): Gtk.Stack.__init__(self, transition_type=Gtk.StackTransitionType.CROSSFADE) self._grid = Gtk.Grid(orientation=Gtk.Orientation.HORIZONTAL) self._offset = 0 self._adjustmentValueId = 0 self._adjustmentChangedId = 0 self._scrollbarVisibleId = 0 self.old_vsbl_range = None self.model = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_STRING, GdkPixbuf.Pixbuf, GObject.TYPE_OBJECT, GObject.TYPE_BOOLEAN, GObject.TYPE_INT, GObject.TYPE_STRING, GObject.TYPE_INT, GObject.TYPE_BOOLEAN, GObject.TYPE_INT) self._box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) # Setup the main view self._setup_view(view_type) if use_sidebar: self.stack = Gtk.Stack( transition_type=Gtk.StackTransitionType.SLIDE_RIGHT, ) dummy = Gtk.Frame(visible=False) self.stack.add_named(dummy, 'dummy') if sidebar: self.stack.add_named(sidebar, 'sidebar') else: self.stack.add_named(self._box, 'sidebar') self.stack.set_visible_child_name('dummy') self._grid.add(self.stack) if not use_sidebar or sidebar: self._grid.add(self._box) self.star_handler = StarHandlerWidget(self, 9) self._cursor = None self.window = window self.header_bar = window.toolbar self.selection_toolbar = window.selection_toolbar self.header_bar._select_button.connect('toggled', self._on_header_bar_toggled) self.header_bar._cancel_button.connect('clicked', self._on_cancel_button_clicked) self.name = name self.title = title self.add(self._grid) self.show_all() self.view.hide() self._items = [] scale = self.get_scale_factor() self.cache = AlbumArtCache(scale) self._loading_icon_surface = DefaultIcon(scale).get( DefaultIcon.Type.loading, ArtSize.medium) self._init = False grilo.connect('ready', self._on_grilo_ready) self.selection_socket = None self.header_bar.connect('selection-mode-changed', self._on_selection_mode_changed) self._discovering_urls = {} grilo.connect('changes-pending', self._on_changes_pending)
class BaseView(Gtk.Stack): nowPlayingIconName = 'media-playback-start-symbolic' errorIconName = 'dialog-error-symbolic' selection_mode = GObject.Property(type=bool, default=False) def __repr__(self): return '<BaseView>' @log def __init__(self, name, title, window, view_type, use_sidebar=False, sidebar=None): Gtk.Stack.__init__(self, transition_type=Gtk.StackTransitionType.CROSSFADE) self._grid = Gtk.Grid(orientation=Gtk.Orientation.HORIZONTAL) self._offset = 0 self._adjustmentValueId = 0 self._adjustmentChangedId = 0 self._scrollbarVisibleId = 0 self.old_vsbl_range = None self.model = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_STRING, GdkPixbuf.Pixbuf, GObject.TYPE_OBJECT, GObject.TYPE_BOOLEAN, GObject.TYPE_INT, GObject.TYPE_STRING, GObject.TYPE_INT, GObject.TYPE_BOOLEAN, GObject.TYPE_INT) self._box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) # Setup the main view self._setup_view(view_type) if use_sidebar: self.stack = Gtk.Stack( transition_type=Gtk.StackTransitionType.SLIDE_RIGHT, ) dummy = Gtk.Frame(visible=False) self.stack.add_named(dummy, 'dummy') if sidebar: self.stack.add_named(sidebar, 'sidebar') else: self.stack.add_named(self._box, 'sidebar') self.stack.set_visible_child_name('dummy') self._grid.add(self.stack) if not use_sidebar or sidebar: self._grid.add(self._box) self.star_handler = StarHandlerWidget(self, 9) self._cursor = None self.window = window self.header_bar = window.toolbar self.selection_toolbar = window.selection_toolbar self.header_bar._select_button.connect('toggled', self._on_header_bar_toggled) self.header_bar._cancel_button.connect('clicked', self._on_cancel_button_clicked) self.name = name self.title = title self.add(self._grid) self.show_all() self.view.hide() self._items = [] scale = self.get_scale_factor() self.cache = AlbumArtCache(scale) self._loading_icon_surface = DefaultIcon(scale).get( DefaultIcon.Type.loading, ArtSize.medium) self._init = False grilo.connect('ready', self._on_grilo_ready) self.selection_socket = None self.header_bar.connect('selection-mode-changed', self._on_selection_mode_changed) self._discovering_urls = {} grilo.connect('changes-pending', self._on_changes_pending) @log def _on_changes_pending(self, data=None): pass @log def _setup_view(self, view_type): self.view = Gd.MainView(shadow_type=Gtk.ShadowType.NONE) self.view.set_view_type(view_type) self.view.click_handler = self.view.connect('item-activated', self._on_item_activated) self.view.connect('selection-mode-request', self._on_selection_mode_request) self.view.bind_property('selection-mode', self, 'selection_mode', GObject.BindingFlags.BIDIRECTIONAL) self.view.connect('view-selection-changed', self._on_view_selection_changed) self._box.pack_start(self.view, True, True, 0) @log def _on_header_bar_toggled(self, button): self.selection_mode = button.get_active() if self.selection_mode: self.header_bar.set_selection_mode(True) self.player.actionbar.set_visible(False) self.selection_toolbar.actionbar.set_visible(True) self.selection_toolbar._add_to_playlist_button.set_sensitive(False) self.selection_toolbar._remove_from_playlist_button.set_sensitive( False) else: self.header_bar.set_selection_mode(False) self.player.actionbar.set_visible( self.player.currentTrack is not None) self.selection_toolbar.actionbar.set_visible(False) self.unselect_all() @log def _on_cancel_button_clicked(self, button): self.view.set_selection_mode(False) self.header_bar.set_selection_mode(False) @log def _on_grilo_ready(self, data=None): if (self.header_bar.get_stack().get_visible_child() == self and not self._init): self._populate() self.header_bar.get_stack().connect('notify::visible-child', self._on_headerbar_visible) @log def _on_headerbar_visible(self, widget, param): if self == widget.get_visible_child() and not self._init: self._populate() @log def _on_view_selection_changed(self, widget): if not self.selection_mode: return items = self.view.get_selection() self.update_header_from_selection(len(items)) @log def update_header_from_selection(self, n_items): self.selection_toolbar._add_to_playlist_button.\ set_sensitive(n_items > 0) self.selection_toolbar._remove_from_playlist_button.\ set_sensitive(n_items > 0) if n_items > 0: self.header_bar._selection_menu_label.set_text( ngettext("Selected %d item", "Selected %d items", n_items) % n_items) else: self.header_bar._selection_menu_label.set_text( _("Click on items to select them")) @log def _populate(self, data=None): self._init = True self.populate() @log def _on_selection_mode_changed(self, widget, data=None): pass @log def populate(self): print('populate') @log def _add_item(self, source, param, item, remaining=0, data=None): self.window.notification.set_timeout(0) if not item: if remaining == 0: self.view.set_model(self.model) self.window.notification.dismiss() self.view.show() return self._offset += 1 artist = utils.get_artist_name(item) title = utils.get_media_title(item) _iter = self.model.append(None) loading_icon = Gdk.pixbuf_get_from_surface( self._loadin_icon_surface, 0, 0, self._loading_icon_surface.get_width(), self._loading_icon_surface.get_height()) self.model[_iter][0, 1, 2, 3, 4, 5, 7, 9] = [ str(item.get_id()), '', title, artist, loading_icon, item, 0, False ] self.cache.lookup(item, self._iconWidth, self._iconHeight, self._on_lookup_ready, _iter) @log def _on_lookup_ready(self, surface, _iter): if surface: pixbuf = Gdk.pixbuf_get_from_surface(surface, 0, 0, surface.get_width(), surface.get_height()) self.model[_iter][4] = pixbuf @log def _add_list_renderers(self): pass @log def _on_item_activated(self, widget, id, path): pass @log def _on_selection_mode_request(self, *args): self.header_bar._select_button.clicked() @log def get_selected_tracks(self, callback): callback([]) def _on_list_widget_star_render(self, col, cell, model, _iter, data): pass @log def _set_selection(self, value, parent=None): count = 0 _iter = self.model.iter_children(parent) while _iter is not None: if self.model.iter_has_child(_iter): count += self._set_selection(value, _iter) if self.model[_iter][5]: self.model[_iter][6] = value count += 1 _iter = self.model.iter_next(_iter) return count @log def select_all(self): """Select all the available tracks.""" count = self._set_selection(True) if count > 0: self.selection_toolbar._add_to_playlist_button.set_sensitive(True) self.selection_toolbar._remove_from_playlist_button.set_sensitive( True) self.update_header_from_selection(count) self.view.queue_draw() @log def unselect_all(self): """Unselects all the selected tracks.""" self._set_selection(False) self.selection_toolbar._add_to_playlist_button.set_sensitive(False) self.selection_toolbar._remove_from_playlist_button.set_sensitive( False) self.header_bar._selection_menu_label.set_text( _("Click on items to select them")) self.queue_draw()
class CoverStack(GObject.GObject): """Provides a smooth transition between image states Uses a Gtk.Stack to provide an in-situ transition between an image state. Either between the 'loading' state versus the 'loaded' state or in between songs. """ __gsignals__ = {'updated': (GObject.SignalFlags.RUN_FIRST, None, ())} _default_icon = DefaultIcon() @log def __init__(self, stack, size): super().__init__() self._size = size self._stack = stack self._stack.set_transition_type(Gtk.StackTransitionType.CROSSFADE) self._scale = self._stack.get_scale_factor() self._handler_id = None self._loading_icon = self._default_icon.get(DefaultIcon.Type.LOADING, self._size, self._scale) self._loading_cover = Gtk.Image.new_from_surface(self._loading_icon) self._cover_a = Gtk.Image() self._cover_b = Gtk.Image() self._stack.add_named(self._loading_cover, "loading") self._stack.add_named(self._cover_a, "A") self._stack.add_named(self._cover_b, "B") self._stack.set_visible_child_name("loading") self._stack.show_all() @log def update(self, media): """Update the stack with the given media Update the stack with the art retrieved from the given media. :param Grl.Media media: The media object """ self._active_child = self._stack.get_visible_child_name() art = Art(self._size, media, self._scale) self._handler_id = art.connect('finished', self._art_retrieved) art.lookup() @log def _art_retrieved(self, klass): klass.disconnect(self._handler_id) if self._active_child == "B": self._cover_a.set_from_surface(klass.surface) self._stack.set_visible_child_name("A") else: self._cover_b.set_from_surface(klass.surface) self._stack.set_visible_child_name("B") self.emit('updated')
class CoverStack(Gtk.Stack): """Provides a smooth transition between image states Uses a Gtk.Stack to provide an in-situ transition between an image state. Either between the 'loading' state versus the 'loaded' state or in between songs. """ __gtype_name__ = 'CoverStack' __gsignals__ = { 'updated': (GObject.SignalFlags.RUN_FIRST, None, ()) } _default_icon = DefaultIcon() def __repr__(self): return '<CoverStack>' @log def __init__(self, size=Art.Size.MEDIUM): """Initialize the CoverStack :param Art.Size size: The size of the art used for the cover """ super().__init__() self._size = None self._handler_id = None self._loading_cover = Gtk.Image() self._cover_a = Gtk.Image() self._cover_b = Gtk.Image() self.add_named(self._loading_cover, "loading") self.add_named(self._cover_a, "A") self.add_named(self._cover_b, "B") self.props.size = size self.props.transition_type = Gtk.StackTransitionType.CROSSFADE self.props.visible_child_name = "loading" self.show_all() @GObject.Property(type=object, flags=GObject.ParamFlags.READWRITE) def size(self): """Size of the cover :returns: The size used :rtype: Art.Size """ return self._size @size.setter def size(self, value): """Set the cover size :param Art.Size value: The size to use for the cover """ self._size = value icon = self._default_icon.get( DefaultIcon.Type.LOADING, self.props.size, self.props.scale_factor) self._loading_cover.props.surface = icon @log def update(self, media): """Update the stack with the given media Update the stack with the art retrieved from the given media. :param Grl.Media media: The media object """ self._active_child = self.props.visible_child_name art = Art(self.props.size, media, self.props.scale_factor) self._handler_id = art.connect('finished', self._art_retrieved) art.lookup() @log def _art_retrieved(self, klass): klass.disconnect(self._handler_id) if self._active_child == "B": self._cover_a.props.surface = klass.surface self.props.visible_child_name = "A" else: self._cover_b.props.surface = klass.surface self.props.visible_child_name = "B" self.emit('updated')
class CoverStack(Gtk.Stack): """Provides a smooth transition between image states Uses a Gtk.Stack to provide an in-situ transition between an image state. Either between the 'loading' state versus the 'loaded' state or in between songs. """ __gtype_name__ = 'CoverStack' __gsignals__ = {'updated': (GObject.SignalFlags.RUN_FIRST, None, ())} _default_icon = DefaultIcon() def __repr__(self): return '<CoverStack>' @log def __init__(self, size=Art.Size.MEDIUM): """Initialize the CoverStack :param Art.Size size: The size of the art used for the cover """ super().__init__() self._art = None self._handler_id = None self._size = None self._timeout = None self._loading_cover = Gtk.Image() self._cover_a = Gtk.Image() self._cover_b = Gtk.Image() self.add_named(self._loading_cover, "loading") self.add_named(self._cover_a, "A") self.add_named(self._cover_b, "B") self.props.size = size self.props.transition_type = Gtk.StackTransitionType.CROSSFADE self.props.visible_child_name = "loading" self.show_all() @GObject.Property(type=object, flags=GObject.ParamFlags.READWRITE) def size(self): """Size of the cover :returns: The size used :rtype: Art.Size """ return self._size @size.setter def size(self, value): """Set the cover size :param Art.Size value: The size to use for the cover """ self._size = value icon = self._default_icon.get(DefaultIcon.Type.LOADING, self.props.size, self.props.scale_factor) self._loading_cover.props.surface = icon @log def update(self, coresong): """Update the stack with the given CoreSong Update the stack with the art retrieved from the given Coresong. :param CoreSong coresong: The CoreSong object """ if self._handler_id and self._art: # Remove a possible dangling 'finished' callback if update # is called again, but it is still looking for the previous # art. self._art.disconnect(self._handler_id) # Set the loading state only after a delay to make between # song transitions smooth if loading time is negligible. self._timeout = GLib.timeout_add(100, self._set_loading_child) self._active_child = self.props.visible_child_name self._art = Art(self.props.size, coresong, self.props.scale_factor) self._handler_id = self._art.connect('finished', self._art_retrieved) self._art.lookup() @log def _set_loading_child(self): self.props.visible_child_name = "loading" self._active_child = self.props.visible_child_name self._timeout = None return GLib.SOURCE_REMOVE @log def _art_retrieved(self, klass): if self._timeout: GLib.source_remove(self._timeout) self._timeout = None if self._active_child == "B": self._cover_a.props.surface = klass.surface self.props.visible_child_name = "A" else: self._cover_b.props.surface = klass.surface self.props.visible_child_name = "B" self._active_child = self.props.visible_child_name self._art = None self.emit('updated')
def __init__(self, name, title, window, view_type, use_sidebar=False, sidebar=None): """Initialize :param name: The view name :param title: The view title :param GtkWidget window: The main window :param view_type: The Gtk view type :param use_sidebar: Whether to use sidebar :param sidebar: The sidebar object (Default: Gtk.Box) """ Gtk.Stack.__init__(self, transition_type=Gtk.StackTransitionType.CROSSFADE) self._grid = Gtk.Grid(orientation=Gtk.Orientation.HORIZONTAL) self._offset = 0 self.model = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_STRING, GdkPixbuf.Pixbuf, GObject.TYPE_OBJECT, GObject.TYPE_BOOLEAN, GObject.TYPE_INT, GObject.TYPE_STRING, GObject.TYPE_INT, GObject.TYPE_BOOLEAN, GObject.TYPE_INT) self._box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) # Setup the main view self._setup_view(view_type) if use_sidebar: self.stack = Gtk.Stack( transition_type=Gtk.StackTransitionType.SLIDE_RIGHT, ) dummy = Gtk.Frame(visible=False) self.stack.add_named(dummy, 'dummy') if sidebar: self.stack.add_named(sidebar, 'sidebar') else: self.stack.add_named(self._box, 'sidebar') self.stack.set_visible_child_name('dummy') self._grid.add(self.stack) if not use_sidebar or sidebar: self._grid.add(self._box) self._star_handler = StarHandlerWidget(self, 9) self._window = window self._header_bar = window.toolbar self._selection_toolbar = window.selection_toolbar self._header_bar._select_button.connect('toggled', self._on_header_bar_toggled) self._header_bar._cancel_button.connect('clicked', self._on_cancel_button_clicked) self.name = name self.title = title self.add(self._grid) self.show_all() self._view.hide() scale = self.get_scale_factor() self._cache = AlbumArtCache(scale) self._loading_icon_surface = DefaultIcon(scale).get( DefaultIcon.Type.loading, ArtSize.medium) self._init = False grilo.connect('ready', self._on_grilo_ready) self._header_bar.connect('selection-mode-changed', self._on_selection_mode_changed) grilo.connect('changes-pending', self._on_changes_pending)
class BaseView(Gtk.Stack): """Base Class for all view classes""" _now_playing_icon_name = 'media-playback-start-symbolic' _error_icon_name = 'dialog-error-symbolic' selection_mode = GObject.Property(type=bool, default=False) def __repr__(self): return '<BaseView>' @log def __init__(self, name, title, window, view_type, use_sidebar=False, sidebar=None): """Initialize :param name: The view name :param title: The view title :param GtkWidget window: The main window :param view_type: The Gtk view type :param use_sidebar: Whether to use sidebar :param sidebar: The sidebar object (Default: Gtk.Box) """ Gtk.Stack.__init__(self, transition_type=Gtk.StackTransitionType.CROSSFADE) self._grid = Gtk.Grid(orientation=Gtk.Orientation.HORIZONTAL) self._offset = 0 self.model = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_STRING, GdkPixbuf.Pixbuf, GObject.TYPE_OBJECT, GObject.TYPE_BOOLEAN, GObject.TYPE_INT, GObject.TYPE_STRING, GObject.TYPE_INT, GObject.TYPE_BOOLEAN, GObject.TYPE_INT) self._box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) # Setup the main view self._setup_view(view_type) if use_sidebar: self.stack = Gtk.Stack( transition_type=Gtk.StackTransitionType.SLIDE_RIGHT, ) dummy = Gtk.Frame(visible=False) self.stack.add_named(dummy, 'dummy') if sidebar: self.stack.add_named(sidebar, 'sidebar') else: self.stack.add_named(self._box, 'sidebar') self.stack.set_visible_child_name('dummy') self._grid.add(self.stack) if not use_sidebar or sidebar: self._grid.add(self._box) self._star_handler = StarHandlerWidget(self, 9) self._window = window self._header_bar = window.toolbar self._selection_toolbar = window.selection_toolbar self._header_bar._select_button.connect('toggled', self._on_header_bar_toggled) self._header_bar._cancel_button.connect('clicked', self._on_cancel_button_clicked) self.name = name self.title = title self.add(self._grid) self.show_all() self._view.hide() scale = self.get_scale_factor() self._cache = AlbumArtCache(scale) self._loading_icon_surface = DefaultIcon(scale).get( DefaultIcon.Type.loading, ArtSize.medium) self._init = False grilo.connect('ready', self._on_grilo_ready) self._header_bar.connect('selection-mode-changed', self._on_selection_mode_changed) grilo.connect('changes-pending', self._on_changes_pending) @log def _on_changes_pending(self, data=None): pass @log def _setup_view(self, view_type): """Instantiate and set up the view object""" self._view = Gd.MainView(shadow_type=Gtk.ShadowType.NONE) self._view.set_view_type(view_type) self._view.click_handler = self._view.connect('item-activated', self._on_item_activated) self._view.connect('selection-mode-request', self._on_selection_mode_request) self._view.bind_property('selection-mode', self, 'selection_mode', GObject.BindingFlags.BIDIRECTIONAL) self._view.connect('view-selection-changed', self._on_view_selection_changed) self._box.pack_start(self._view, True, True, 0) @log def _on_header_bar_toggled(self, button): self.selection_mode = button.get_active() if self.selection_mode: self._header_bar.set_selection_mode(True) self.player.actionbar.set_visible(False) select_toolbar = self._selection_toolbar select_toolbar.actionbar.set_visible(True) select_toolbar._add_to_playlist_button.set_sensitive(False) select_toolbar._remove_from_playlist_button.set_sensitive(False) else: self._header_bar.set_selection_mode(False) track_playing = self.player.currentTrack is not None self.player.actionbar.set_visible(track_playing) self._selection_toolbar.actionbar.set_visible(False) self.unselect_all() @log def _on_cancel_button_clicked(self, button): self._view.set_selection_mode(False) self._header_bar.set_selection_mode(False) @log def _on_grilo_ready(self, data=None): if (self._header_bar.get_stack().get_visible_child() == self and not self._init): self._populate() self._header_bar.get_stack().connect('notify::visible-child', self._on_headerbar_visible) @log def _on_headerbar_visible(self, widget, param): if (self == widget.get_visible_child() and not self._init): self._populate() @log def _on_view_selection_changed(self, widget): if not self.selection_mode: return items = self._view.get_selection() self.update_header_from_selection(len(items)) @log def update_header_from_selection(self, n_items): """Updates header during item selection.""" select_toolbar = self._selection_toolbar select_toolbar._add_to_playlist_button.set_sensitive(n_items > 0) select_toolbar._remove_from_playlist_button.set_sensitive(n_items > 0) if n_items > 0: self._header_bar._selection_menu_label.set_text( ngettext("Selected {} item", "Selected {} items", n_items).format(n_items)) else: self._header_bar._selection_menu_label.set_text( _("Click on items to select them")) @log def _populate(self, data=None): self._init = True self.populate() @log def _on_selection_mode_changed(self, widget, data=None): pass @log def populate(self): pass @log def _add_item(self, source, param, item, remaining=0, data=None): if not item: if remaining == 0: self._view.set_model(self.model) self._window.pop_loading_notification() self._view.show() return self._offset += 1 artist = utils.get_artist_name(item) title = utils.get_media_title(item) itr = self.model.append(None) loading_icon = Gdk.pixbuf_get_from_surface( self._loadin_icon_surface, 0, 0, self._loading_icon_surface.get_width(), self._loading_icon_surface.get_height()) self.model[itr][0, 1, 2, 3, 4, 5, 7, 9] = [ str(item.get_id()), '', title, artist, loading_icon, item, 0, False ] @log def _on_lookup_ready(self, surface, itr): if surface: pixbuf = Gdk.pixbuf_get_from_surface(surface, 0, 0, surface.get_width(), surface.get_height()) self.model[itr][4] = pixbuf @log def _add_list_renderers(self): pass @log def _on_item_activated(self, widget, id, path): pass @log def _on_selection_mode_request(self, *args): self._header_bar._select_button.clicked() @log def get_selected_songs(self, callback): callback([]) @log def _set_selection(self, value, parent=None): count = 0 itr = self.model.iter_children(parent) while itr != None: if self.model.iter_has_child(itr): count += self._set_selection(value, itr) if self.model[itr][5] != None: self.model[itr][6] = value count += 1 itr = self.model.iter_next(itr) return count @log def select_all(self): """Select all the available songs.""" count = self._set_selection(True) if count > 0: select_toolbar = self._selection_toolbar select_toolbar._add_to_playlist_button.set_sensitive(True) select_toolbar._remove_from_playlist_button.set_sensitive(True) self.update_header_from_selection(count) self._view.queue_draw() @log def unselect_all(self): """Unselects all the selected songs.""" self._set_selection(False) select_toolbar = self._selection_toolbar select_toolbar._add_to_playlist_button.set_sensitive(False) select_toolbar._remove_from_playlist_button.set_sensitive(False) self._header_bar._selection_menu_label.set_text( _("Click on items to select them")) self.queue_draw()