class Artists (ViewContainer): def __init__(self, header_bar, selection_toolbar, player): ViewContainer.__init__(self, _("Artists"), header_bar, selection_toolbar, True) self.artists_counter = 0 self.player = player self._artists = {} self.countQuery = Query.ARTISTS_COUNT self.artistAlbumsStack = Stack( transition_type=StackTransitionType.CROSSFADE, ) self._artistAlbumsWidget = Gtk.Frame( shadow_type=Gtk.ShadowType.NONE, hexpand=True ) self.artistAlbumsStack.add_named(self._artistAlbumsWidget, "artists") self.artistAlbumsStack.set_visible_child_name("artists") self.view.set_view_type(Gd.MainViewType.LIST) self.view.set_hexpand(False) self.view.get_style_context().add_class('artist-panel') self.view.get_generic_view().get_selection().set_mode( Gtk.SelectionMode.SINGLE) self._grid.attach(Gtk.Separator(orientation=Gtk.Orientation.VERTICAL), 1, 0, 1, 1) self._grid.attach(self.artistAlbumsStack, 2, 0, 2, 2) self._add_list_renderers() if (Gtk.Settings.get_default().get_property( 'gtk_application_prefer_dark_theme')): self.view.get_generic_view().get_style_context().\ add_class('artist-panel-dark') else: self.view.get_generic_view().get_style_context().\ add_class('artist-panel-white') self.show_all() def _populate(self, data=None): selection = self.view.get_generic_view().get_selection() if not selection.get_selected()[1]: self._allIter = self._model.append() self._last_selection = self._allIter self._artists[_("All Artists").lower()] =\ {'iter': self._allIter, 'albums': []} self._model.set(self._allIter, 2, _("All Artists")) selection.select_path(self._model.get_path(self._allIter)) self.view.emit('item-activated', '0', self._model.get_path(self._allIter)) self._init = True self.populate() def _add_list_renderers(self): list_widget = self.view.get_generic_view() cols = list_widget.get_columns() cells = cols[0].get_cells() cells[1].set_visible(False) cells[2].set_visible(False) type_renderer = Gd.StyledTextRenderer( xpad=16, ypad=16, ellipsize=Pango.EllipsizeMode.END, xalign=0.0, width=220 ) list_widget.add_renderer(type_renderer, lambda *args: None, None) cols[0].clear_attributes(type_renderer) cols[0].add_attribute(type_renderer, 'text', 2) def _on_item_activated(self, widget, item_id, path): # Prepare a new artistAlbumsWidget here self.new_artistAlbumsWidget = Gtk.Frame( shadow_type=Gtk.ShadowType.NONE, hexpand=True ) child_name = "artists_%i" % self.artists_counter self.artistAlbumsStack.add_named(self.new_artistAlbumsWidget, child_name) _iter = self._model.get_iter(path) self._last_selection = _iter artist = self._model.get_value(_iter, 2) albums = self._artists[artist.lower()]['albums'] self.artistAlbums = None if (self._model.get_string_from_iter(_iter) == self._model.get_string_from_iter(self._allIter)): self.artistAlbums = Widgets.AllArtistsAlbums(self.player) else: self.artistAlbums = Widgets.ArtistAlbums(artist, albums, self.player) self.new_artistAlbumsWidget.add(self.artistAlbums) self.new_artistAlbumsWidget.show() # Switch visible child child_name = "artists_%i" % self.artists_counter self.artists_counter += 1 # Replace previous widget self._artistAlbumsWidget = self.new_artistAlbumsWidget GLib.idle_add(self.artistAlbumsStack.set_visible_child_name, child_name) def _add_item(self, source, param, item): if item is None: return self._offset += 1 artist = item.get_string(Grl.METADATA_KEY_ARTIST) if not artist: artist = item.get_author() if not artist: artist = _("Unknown Artist") if not artist.lower() in self._artists: _iter = self._model.append() self._artists[artist.lower()] = {'iter': _iter, 'albums': []} self._model.set(_iter, [2], [artist]) self._artists[artist.lower()]['albums'].append(item) def populate(self): if grilo.tracker: GLib.idle_add(grilo.populate_artists, self._offset, self._add_item) def _on_header_bar_toggled(self, button): ViewContainer._on_header_bar_toggled(self, button) if button.get_active(): self._last_selection =\ self.view.get_generic_view().get_selection().get_selected()[1] self.view.get_generic_view().get_selection().set_mode( Gtk.SelectionMode.NONE) else: self.view.get_generic_view().get_selection().set_mode( Gtk.SelectionMode.SINGLE) if self._last_selection is not None: self.view.get_generic_view().get_selection().select_iter( self._last_selection)
class ViewContainer(Stack): if Gtk.Widget.get_default_direction() is not Gtk.TextDirection.RTL: nowPlayingIconName = 'media-playback-start-symbolic' else: nowPlayingIconName = 'media-playback-start-rtl-symbolic' errorIconName = 'dialog-error-symbolic' starIconName = 'starred-symbolic' countQuery = None def __init__(self, title, header_bar, selection_toolbar, useStack=False): Stack.__init__(self, transition_type=StackTransitionType.CROSSFADE) self._grid = Gtk.Grid(orientation=Gtk.Orientation.VERTICAL) self._iconWidth = -1 self._iconHeight = 128 self._offset = 0 self._adjustmentValueId = 0 self._adjustmentChangedId = 0 self._scrollbarVisibleId = 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_BOOLEAN, GObject.TYPE_BOOLEAN ) self.view = Gd.MainView( shadow_type=Gtk.ShadowType.NONE ) self.view.set_view_type(Gd.MainViewType.ICON) self.view.set_model(self._model) self.selection_toolbar = selection_toolbar box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) box.pack_start(self.view, True, True, 0) if useStack: self.stack = Stack( transition_type=StackTransitionType.SLIDE_RIGHT, ) dummy = Gtk.Frame(visible=False) self.stack.add_named(dummy, 'dummy') self.stack.add_named(box, 'artists') self.stack.set_visible_child_name('dummy') self._grid.add(self.stack) else: self._grid.add(box) self._loadMore = Widgets.LoadMoreButton(self._get_remaining_item_count) box.pack_end(self._loadMore.widget, False, False, 0) self._loadMore.widget.connect('clicked', self._populate) self.view.connect('item-activated', self._on_item_activated) self._cursor = None self.header_bar = header_bar 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.title = title self.add(self._grid) self.show_all() self._items = [] self._loadMore.widget.hide() self._connect_view() self.cache = albumArtCache.get_default() self._symbolicIcon = self.cache.make_default_icon(self._iconHeight, self._iconWidth) self._init = False grilo.connect('ready', self._on_grilo_ready) self.header_bar.header_bar.connect('state-changed', self._on_state_changed) self.view.connect('view-selection-changed', self._on_view_selection_changed) def _on_header_bar_toggled(self, button): if button.get_active(): self.view.set_selection_mode(True) self.header_bar.set_selection_mode(True) self.selection_toolbar.eventbox.set_visible(True) self.selection_toolbar._add_to_playlist_button.sensitive = False else: self.view.set_selection_mode(False) self.header_bar.set_selection_mode(False) self.selection_toolbar.eventbox.set_visible(False) def _on_cancel_button_clicked(self, button): self.view.set_selection_mode(False) self.header_bar.set_selection_mode(False) 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) def _on_headerbar_visible(self, widget, param): if self == widget.get_visible_child() and not self._init: self._populate() def _on_view_selection_changed(self, widget): items = self.view.get_selection() self.selection_toolbar\ ._add_to_playlist_button.set_sensitive(len(items) > 0) def _populate(self, data=None): self._init = True self.populate() def _on_state_changed(self, widget, data=None): pass def _connect_view(self): vadjustment = self.view.get_vadjustment() self._adjustmentValueId = vadjustment.connect( 'value-changed', self._on_scrolled_win_change) def _on_scrolled_win_change(self, data=None): vScrollbar = self.view.get_vscrollbar() adjustment = self.view.get_vadjustment() revealAreaHeight = 32 #if there's no vscrollbar, or if it's not visible, hide the button if not vScrollbar or not vScrollbar.get_visible(): self._loadMore.set_block(True) return value = adjustment.get_value() upper = adjustment.get_upper() page_size = adjustment.get_page_size() end = False #special case self values which happen at construction if (value == 0) and (upper == 1) and (page_size == 1): end = False else: end = not (value < (upper - page_size - revealAreaHeight)) if self._get_remaining_item_count() <= 0: end = False self._loadMore.set_block(not end) def populate(self): print('populate') def _add_item(self, source, param, item): if not item: return self._offset += 1 artist = item.get_string(Grl.METADATA_KEY_ARTIST)\ or item.get_author()\ or _("Unknown Artist") title = albumArtCache.get_media_title(item) item.set_title(title) def add_new_item(): _iter = self._model.append() icon_name = self.nowPlayingIconName if item.get_url(): try: self.player.discoverer.discover_uri(item.get_url()) except: print('failed to discover url ' + item.get_url()) icon_name = self.errorIconName self._model.set(_iter, [0, 1, 2, 3, 4, 5, 7, 8, 9, 10], [str(item.get_id()), '', title, artist, self._symbolicIcon, item, -1, icon_name, False, icon_name == self.errorIconName]) GLib.idle_add(self._update_album_art, item, _iter) GLib.idle_add(add_new_item) def _get_remaining_item_count(self): count = -1 if self.countQuery: cursor = tracker.query(self.countQuery, None) if cursor and cursor.next(None): count = cursor.get_integer(0) return count - self._offset def _insert_album_art(self, item, cb_item, itr, x=False): if item and cb_item and not item.get_thumbnail(): if cb_item.get_thumbnail(): item.set_thumbnail(cb_item.get_thumbnail()) albumArtCache.get_default().lookup( item, self._iconWidth, self._iconHeight, self._on_lookup_ready, itr) def _update_album_art(self, item, itr): grilo.get_album_art_for_album_id( item.get_id(), lambda source, count, cb_item, x, y, z: self._insert_album_art(item, cb_item, itr, True) ) def _on_lookup_ready(self, icon, path, _iter): if icon: self._model.set_value( _iter, 4, albumArtCache.get_default()._make_icon_frame(icon)) def _add_list_renderers(self): pass def _on_item_activated(self, widget, id, path): pass
class ViewContainer(Stack): if Gtk.Widget.get_default_direction() is not Gtk.TextDirection.RTL: nowPlayingIconName = 'media-playback-start-symbolic' else: nowPlayingIconName = 'media-playback-start-rtl-symbolic' errorIconName = 'dialog-error-symbolic' starIconName = 'starred-symbolic' countQuery = None filter = None def __init__(self, title, header_bar, selection_toolbar, useStack=False): Stack.__init__(self, transition_type=StackTransitionType.CROSSFADE) self._grid = Gtk.Grid(orientation=Gtk.Orientation.VERTICAL) self._iconWidth = -1 self._iconHeight = 128 self._offset = 0 self._adjustmentValueId = 0 self._adjustmentChangedId = 0 self._scrollbarVisibleId = 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_BOOLEAN, GObject.TYPE_BOOLEAN) self.view = Gd.MainView(shadow_type=Gtk.ShadowType.NONE) self.view.set_view_type(Gd.MainViewType.ICON) self.view.set_model(self._model) self.filter = self._model.filter_new(None) self.view.set_model(self.filter) self.vadjustment = self.view.get_vadjustment() self.selection_toolbar = selection_toolbar box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) box.pack_start(self.view, True, True, 0) if useStack: self.stack = Stack( transition_type=StackTransitionType.SLIDE_RIGHT, ) dummy = Gtk.Frame(visible=False) self.stack.add_named(dummy, 'dummy') self.stack.add_named(box, 'artists') self.stack.set_visible_child_name('dummy') self._grid.add(self.stack) else: self._grid.add(box) self._cached_count = -1 self._loadMore = Widgets.LoadMoreButton(self._get_remaining_item_count) box.pack_end(self._loadMore.widget, False, False, 0) self._loadMore.widget.connect('clicked', self._populate) self.view.connect('item-activated', self._on_item_activated) self.view.connect('selection-mode-request', self._on_selection_mode_request) self._cursor = None self.header_bar = header_bar 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.title = title self.add(self._grid) self.show_all() self._items = [] self._loadMore.widget.hide() self._connect_view() self.cache = albumArtCache.get_default() self._symbolicIcon = self.cache.make_default_icon( self._iconHeight, self._iconWidth) self._init = False grilo.connect('ready', self._on_grilo_ready) self.header_bar.header_bar.connect('state-changed', self._on_state_changed) self.view.connect('view-selection-changed', self._on_view_selection_changed) self._discovering_urls = {} def _get_remaining_item_count(self): if self._cached_count < 0: self._cached_count = Widgets.get_count(self.countQuery) return self._cached_count - self._offset def _on_header_bar_toggled(self, button): if button.get_active(): self.view.set_selection_mode(True) self.header_bar.set_selection_mode(True) self.selection_toolbar.eventbox.set_visible(True) self.selection_toolbar._add_to_playlist_button.sensitive = False else: self.view.set_selection_mode(False) self.header_bar.set_selection_mode(False) self.selection_toolbar.eventbox.set_visible(False) def _on_cancel_button_clicked(self, button): self.view.set_selection_mode(False) self.header_bar.set_selection_mode(False) 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) def _on_headerbar_visible(self, widget, param): if self == widget.get_visible_child() and not self._init: self._populate() def _on_view_selection_changed(self, widget): items = self.view.get_selection() self.selection_toolbar\ ._add_to_playlist_button.set_sensitive(len(items) > 0) def _populate(self, data=None): self._init = True self.populate() def _on_state_changed(self, widget, data=None): pass def _connect_view(self): self._adjustmentValueId = self.vadjustment.connect( 'value-changed', self._on_scrolled_win_change) def _on_scrolled_win_change(self, data=None): vScrollbar = self.view.get_vscrollbar() revealAreaHeight = 32 #if there's no vscrollbar, or if it's not visible, hide the button if not vScrollbar or not vScrollbar.get_visible(): self._loadMore.set_block(True) return value = self.vadjustment.get_value() upper = self.vadjustment.get_upper() page_size = self.vadjustment.get_page_size() end = False #special case self values which happen at construction if (value == 0) and (upper == 1) and (page_size == 1): end = False else: end = not (value < (upper - page_size - revealAreaHeight)) if self._get_remaining_item_count() <= 0: end = False self._loadMore.set_block(not end) def populate(self): print('populate') def _on_discovered(self, info, error, _iter): if error: self._model.set(_iter, [8, 10], [self.errorIconName, True]) def _add_item(self, source, param, item): if not item: return self._offset += 1 artist = item.get_string(Grl.METADATA_KEY_ARTIST)\ or item.get_author()\ or _("Unknown Artist") title = albumArtCache.get_media_title(item) item.set_title(title) def add_new_item(): _iter = self._model.append(None) icon_name = self.nowPlayingIconName if item.get_url(): try: self.player.discoverer.discover_uri(item.get_url()) except: print('failed to discover url ' + item.get_url()) icon_name = self.errorIconName self._model.set(_iter, [0, 1, 2, 3, 4, 5, 7, 8, 9, 10], [ str(item.get_id()), '', title, artist, self._symbolicIcon, item, -1, icon_name, False, icon_name == self.errorIconName ]) GLib.idle_add(self._update_album_art, item, _iter) GLib.idle_add(add_new_item) def _insert_album_art(self, item, cb_item, itr, x=False): if item and cb_item and not item.get_thumbnail(): if cb_item.get_thumbnail(): item.set_thumbnail(cb_item.get_thumbnail()) albumArtCache.get_default().lookup(item, self._iconWidth, self._iconHeight, self._on_lookup_ready, itr) def _update_album_art(self, item, itr): grilo.get_album_art_for_album_id( item.get_id(), lambda source, count, cb_item, x, y, z: self._insert_album_art( item, cb_item, itr, True)) def _on_lookup_ready(self, icon, path, _iter): if icon: self._model.set_value( _iter, 4, albumArtCache.get_default()._make_icon_frame(icon)) def _add_list_renderers(self): pass def _on_item_activated(self, widget, id, path): pass def _on_selection_mode_request(self, *args): self.header_bar._select_button.clicked()
class Artists(ViewContainer): def __init__(self, header_bar, selection_toolbar, player): ViewContainer.__init__(self, _("Artists"), header_bar, selection_toolbar, True) self.artists_counter = 0 self.player = player self._artists = {} self.countQuery = Query.ARTISTS_COUNT self.artistAlbumsStack = Stack( transition_type=StackTransitionType.CROSSFADE, ) self._artistAlbumsWidget = Gtk.Frame(shadow_type=Gtk.ShadowType.NONE, hexpand=True) self.artistAlbumsStack.add_named(self._artistAlbumsWidget, "artists") self.artistAlbumsStack.set_visible_child_name("artists") self.view.set_view_type(Gd.MainViewType.LIST) self.view.set_hexpand(False) self.view.get_style_context().add_class('artist-panel') self.view.get_generic_view().get_selection().set_mode( Gtk.SelectionMode.SINGLE) self._grid.attach(Gtk.Separator(orientation=Gtk.Orientation.VERTICAL), 1, 0, 1, 1) self._grid.attach(self.artistAlbumsStack, 2, 0, 2, 2) self._add_list_renderers() if (Gtk.Settings.get_default().get_property( 'gtk_application_prefer_dark_theme')): self.view.get_generic_view().get_style_context().\ add_class('artist-panel-dark') else: self.view.get_generic_view().get_style_context().\ add_class('artist-panel-white') self.show_all() def _populate(self, data=None): selection = self.view.get_generic_view().get_selection() if not selection.get_selected()[1]: self._allIter = self._model.insert_with_valuesv( -1, [2], [_("All Artists")]) self._last_selection = self._allIter self._artists[_("All Artists").lower()] =\ {'iter': self._allIter, 'albums': []} selection.select_path(self._model.get_path(self._allIter)) self.view.emit('item-activated', '0', self._model.get_path(self._allIter)) self._init = True self.populate() def _add_list_renderers(self): list_widget = self.view.get_generic_view() cols = list_widget.get_columns() cells = cols[0].get_cells() cells[1].set_visible(False) cells[2].set_visible(False) type_renderer = Gd.StyledTextRenderer( xpad=16, ypad=16, ellipsize=Pango.EllipsizeMode.END, xalign=0.0, width=220) list_widget.add_renderer(type_renderer, lambda *args: None, None) cols[0].clear_attributes(type_renderer) cols[0].add_attribute(type_renderer, 'text', 2) def _on_item_activated(self, widget, item_id, path): # Prepare a new artistAlbumsWidget here self.new_artistAlbumsWidget = Gtk.Frame( shadow_type=Gtk.ShadowType.NONE, hexpand=True) child_name = "artists_%i" % self.artists_counter self.artistAlbumsStack.add_named(self.new_artistAlbumsWidget, child_name) child_path = self.filter.convert_path_to_child_path(path) _iter = self._model.get_iter(child_path) self._last_selection = _iter artist = self._model.get_value(_iter, 2) albums = self._artists[artist.lower()]['albums'] self.artistAlbums = None if (self._model.get_string_from_iter(_iter) == self._model.get_string_from_iter(self._allIter)): self.artistAlbums = Widgets.AllArtistsAlbums(self.player) else: self.artistAlbums = Widgets.ArtistAlbums(artist, albums, self.player) self.new_artistAlbumsWidget.add(self.artistAlbums) self.new_artistAlbumsWidget.show() # Switch visible child child_name = "artists_%i" % self.artists_counter self.artists_counter += 1 # Replace previous widget self._artistAlbumsWidget = self.new_artistAlbumsWidget GLib.idle_add(self.artistAlbumsStack.set_visible_child_name, child_name) def _add_item(self, source, param, item): if item is None: return self._offset += 1 artist = item.get_string(Grl.METADATA_KEY_ARTIST)\ or item.get_author()\ or _("Unknown Artist") if not artist.lower() in self._artists: _iter = self._model.insert_with_valuesv(-1, [2], [artist]) self._artists[artist.lower()] = {'iter': _iter, 'albums': []} self._artists[artist.lower()]['albums'].append(item) def populate(self): if grilo.tracker: GLib.idle_add(grilo.populate_artists, self._offset, self._add_item) def _on_header_bar_toggled(self, button): ViewContainer._on_header_bar_toggled(self, button) if button.get_active(): self._last_selection =\ self.view.get_generic_view().get_selection().get_selected()[1] self.view.get_generic_view().get_selection().set_mode( Gtk.SelectionMode.NONE) else: self.view.get_generic_view().get_selection().set_mode( Gtk.SelectionMode.SINGLE) if self._last_selection is not None: self.view.get_generic_view().get_selection().select_iter( self._last_selection)
class ElementStackView (ViewContainer): def __init__(self, header_bar, title, plugins): 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_BOOLEAN, GObject.TYPE_BOOLEAN ) ViewContainer.__init__(self, title, header_bar) self.elementStack = Stack( transition_type=StackTransitionType.CROSSFADE, ) self.plugins = plugins self.subcats = {} self.populate() self.create_and_show(Gtk.TreePath.new_from_string ("0")) self.view.set_view_type(Gd.MainViewType.LIST) self.view.set_hexpand(False) #self.view.get_style_context().add_class('artist-panel') self.view.get_generic_view().get_selection().set_mode( Gtk.SelectionMode.SINGLE) self.grid.attach(Gtk.Separator(orientation=Gtk.Orientation.VERTICAL), 1, 0, 1, 1) self.grid.attach(self.elementStack, 2, 0, 2, 2) self.view.get_generic_view().get_style_context().\ add_class('artist-panel-dark') self.show_all() def populate(self): for cat in self.plugins: self.add_item(cat) def create_and_show(self, path): new_elementWidget = Gtk.Frame( shadow_type=Gtk.ShadowType.NONE, hexpand=True ) child_path = self.filter.convert_path_to_child_path(path) subcatname = "subcat%s" % child_path if not subcatname in self.subcats: self.elementStack.add_named(new_elementWidget, subcatname) _iter = self.model.get_iter(child_path) self._last_selection = _iter category = self.model.get_value(_iter, 2) print("Adding %s: %s" % (subcatname, category)) elementView = ElementView(None, None, self.plugins[category]) new_elementWidget.add(elementView) self.subcats[subcatname] = new_elementWidget self.subcats[subcatname].show() self.elementStack.set_visible_child_name(subcatname) def on_item_activated(self, widget, item_id, path): self.create_and_show(path) def add_item(self, name): _iter = self.model.insert_with_valuesv(-1, [2], [name])
class ElementStackView(ViewContainer): def __init__(self, header_bar, title, plugins): 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_BOOLEAN, GObject.TYPE_BOOLEAN) ViewContainer.__init__(self, title, header_bar) self.elementStack = Stack( transition_type=StackTransitionType.CROSSFADE, ) self.plugins = plugins self.subcats = {} self.populate() self.create_and_show(Gtk.TreePath.new_from_string("0")) self.view.set_view_type(Gd.MainViewType.LIST) self.view.set_hexpand(True) #self.view.get_style_context().add_class('artist-panel') self.view.get_generic_view().get_selection().set_mode( Gtk.SelectionMode.SINGLE) #self.grid.attach(Gtk.Separator(orientation=Gtk.Orientation.VERTICAL), # 1, 0, 1, 1) self.grid.attach(self.elementStack, 2, 0, 2, 2) self.view.get_generic_view().get_style_context().\ add_class('artist-panel-dark') self.show_all() def populate(self): for cat in self.plugins: self.add_item(cat) def create_and_show(self, path): frame = Gtk.Frame() child_path = self.filter.convert_path_to_child_path(path) subcatname = "subcat%s" % child_path if not subcatname in self.subcats: self.elementStack.add_named(frame, subcatname) _iter = self.model.get_iter(child_path) self._last_selection = _iter category = self.model.get_value(_iter, 2) print("Adding %s: %s" % (subcatname, category)) elementView = ElementView(self.plugins[category]) #elementView = Gtk.Button(label=category) frame.add(elementView) #new_elementWidget.add(button) self.subcats[subcatname] = frame self.subcats[subcatname].show() self.elementStack.set_visible_child_name(subcatname) def on_item_activated(self, widget, item_id, path): print("acitve", path) self.create_and_show(path) def add_item(self, name): self.model.insert_with_valuesv(-1, [2], [name])