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 __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 __init__(self, header_bar, player): Stack.__init__(self, transition_type=StackTransitionType.CROSSFADE) builder = Gtk.Builder() builder.add_from_resource('/org/gnome/Music/NoMusic.ui') widget = builder.get_object('container') self.add(widget) self.show_all()
def __init__(self, header_bar, player): Stack.__init__(self, transition_type=StackTransitionType.CROSSFADE) builder = Gtk.Builder() builder.add_from_resource('/org/gnome/Music/NoMusic.ui') music_folder_path = GLib.get_user_special_dir(GLib.USER_DIRECTORY_MUSIC) widget = builder.get_object('container') label = builder.get_object('label1') label.set_label(_("No Music found!\n Put some files into the folder %s" %music_folder_path)) self.add(widget) self.show_all()
def _setup_view(self): self._box = Gtk.VBox() self.player = Player() self.selection_toolbar = SelectionToolbar() self.toolbar = Toolbar() self.views = [] self._stack = Stack( transition_type=StackTransitionType.CROSSFADE, transition_duration=100, visible=True) if Gtk.get_minor_version() > 8: self.set_titlebar(self.toolbar.header_bar) else: self._box.pack_start(self.toolbar.header_bar, False, False, 0) self.set_hide_titlebar_when_maximized(True) self._box.pack_start(self.toolbar.searchbar, False, False, 0) self._box.pack_start(self._stack, True, True, 0) self._box.pack_start(self.player.eventBox, False, False, 0) self._box.pack_start(self.selection_toolbar.eventbox, False, False, 0) self.add(self._box) count = 1 cursor = tracker.query(Query.SONGS_COUNT, None) if cursor is not None and cursor.next(None): count = cursor.get_integer(0) if count > 0: self.views.append(Views.Albums(self.toolbar, self.selection_toolbar, self.player)) self.views.append(Views.Artists(self.toolbar, self.selection_toolbar, self.player)) self.views.append(Views.Songs(self.toolbar, self.selection_toolbar, self.player)) #self.views.append(Views.Playlist(self.toolbar, self.selection_toolbar, self.player)) for i in self.views: self._stack.add_titled(i, i.title, i.title) self.toolbar.set_stack(self._stack) self.toolbar.searchbar.show() self._on_notify_model_id = self._stack.connect('notify::visible-child', self._on_notify_mode) self.connect('destroy', self._notify_mode_disconnect) self.connect('key_press_event', self._on_key_press) self.views[0].populate() #To revert to the No Music View when no songs are found else: self.views.append(Views.Empty(self.toolbar, self.player)) self._stack.add_titled(self.views[0], _("Empty"), _("Empty")) self.toolbar._search_button.connect('toggled', self._on_search_toggled) self.toolbar.set_state(ToolbarState.ALBUMS) self.toolbar.header_bar.show() self.player.eventBox.show_all() self._box.show() self.show()
def __init__(self, header_bar, player): Stack.__init__(self, transition_type=StackTransitionType.CROSSFADE) builder = Gtk.Builder() builder.add_from_resource('/org/gnome/Music/NoMusic.ui') music_folder_path = GLib.get_user_special_dir( GLib.USER_DIRECTORY_MUSIC) widget = builder.get_object('container') label = builder.get_object('label1') label.set_label( _("No Music found!\n Put some files into the folder %s" % music_folder_path)) self.add(widget) self.show_all()
def init_configs_stack(self): self._stack = Stack(transition_type=StackTransitionType.CROSSFADE, transition_duration=300, visible=True) self._stack.set_transition_type( Gtk.StackTransitionType.SLIDE_LEFT_RIGHT) for config in snapper.ListConfigs(): name = str(config[0]) self.configView[name] = snapshotsView(name) self._stack.add_titled(self.configView[name].scrolledwindow, name, name) self.configView[name].selection.connect( "changed", self.on_snapshots_selection_changed)
def on_stack_img_source_visible_child_notify(self, stack: Gtk.Stack, param: GObject.ParamSpec): self.reset_result() self.btn_img_chooser.unselect_all() child = stack.get_visible_child() child_name = child.get_name() logger.debug('Visible child: {} ({})', child, child_name) toolbar = self.btn_play.get_parent() if not child_name.endswith('webcam'): logger.info('To disable webcam') if self.gst_pipeline: self.gst_pipeline.set_state(Gst.State.NULL) toolbar.hide() self.webcam_combobox.hide() self.btn_img_chooser.show() self.grab_focus_on_event_box() elif self.gst_pipeline: logger.info('To enable webcam') ppl_source = self.gst_pipeline.get_by_name(self.GST_SOURCE_NAME) if ppl_source.get_property('device'): self.btn_pause.set_active(False) self.gst_pipeline.set_state(Gst.State.PLAYING) self.btn_img_chooser.hide() self.webcam_combobox.show() self.reset_image_placeholder() toolbar.show()
def _setup_view(self): self._box = Gtk.VBox() self.player = Player() self.selection_toolbar = SelectionToolbar() self.toolbar = Toolbar() self.views = [] self._stack = Stack( transition_type=StackTransitionType.CROSSFADE, transition_duration=100, visible=True) if Gtk.get_minor_version() > 8: self.set_titlebar(self.toolbar.header_bar) else: self._box.pack_start(self.toolbar.header_bar, False, False, 0) self.set_hide_titlebar_when_maximized(True) self._box.pack_start(self.toolbar.searchbar, False, False, 0) self._box.pack_start(self._stack, True, True, 0) self._box.pack_start(self.player.eventBox, False, False, 0) self._box.pack_start(self.selection_toolbar.eventbox, False, False, 0) self.add(self._box) count = 1 cursor = tracker.query(Query.SONGS_COUNT, None) if cursor is not None and cursor.next(None): count = cursor.get_integer(0) if count > 0: self.views.append(Views.Albums(self.toolbar, self.selection_toolbar, self.player)) self.views.append(Views.Artists(self.toolbar, self.selection_toolbar, self.player)) self.views.append(Views.Songs(self.toolbar, self.selection_toolbar, self.player)) self.views.append(Views.Playlist(self.toolbar, self.selection_toolbar, self.player)) for i in self.views: self._stack.add_titled(i, i.title, i.title) self.toolbar.set_stack(self._stack) self.toolbar.searchbar.show() self._on_notify_model_id = self._stack.connect('notify::visible-child', self._on_notify_mode) self.connect('destroy', self._notify_mode_disconnect) self.connect('key_press_event', self._on_key_press) self.views[0].populate() #To revert to the No Music View when no songs are found else: self.views.append(Views.Empty(self.toolbar, self.player)) self._stack.add_titled(self.views[0], _("Empty"), _("Empty")) self.toolbar._search_button.set_sensitive(False) self.toolbar._select_button.set_sensitive(False) self.toolbar._search_button.connect('toggled', self._on_search_toggled) self.toolbar.connect('selection-mode-changed', self._on_selection_mode_changed) self.selection_toolbar._add_to_playlist_button.connect( 'clicked', self._on_add_to_playlist_button_clicked) self.selection_toolbar._remove_from_playlist_button.connect( 'clicked', self._on_remove_from_playlist_button_clicked) self.toolbar.set_state(ToolbarState.ALBUMS) self.toolbar.header_bar.show() self.player.eventBox.show_all() self._box.show() self.show()
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 on_main_view_change(self, main_view: Gtk.Stack, somearg): from cloneentry import CloneToImageEntry from restoreentry import RestoreFromImageEntry current_view = main_view.get_visible_child() if not self.is_mounted(): self.clone_button.set_sensitive(type(current_view) is not CloneToImageEntry) self.restore_button.set_sensitive(type(current_view) is not RestoreFromImageEntry)
def __init__(self, snak=None, new=False, qualifier=False, css=None, **kwargs): Stack.__init__(self, **kwargs) context = self.entry.get_style_context() provider = CssProvider() provider.load_from_resource('/ml/prevete/Daty/gtk/entity.css') context.add_provider(provider, STYLE_PROVIDER_PRIORITY_APPLICATION) if qualifier: self.label.props.valign = 1 self.unit.props.valign = 1 self.new = new if self.new: print("new entity") item_new = lambda Q: { 'snaktype': 'value', 'datavalue': { 'type': 'wikibase-entityid', 'value': { 'entity-type': 'item', 'numeric-id': Q } }, 'datatype': 'wikibase-item' } snak = item_new(352346) try: self.read(snak) except Exception as err: raise err self.entry_focus_out_connection = self.entry.connect( "focus-out-event", self.entry_focus_out_event_cb) self.entry_focus_in_connection = self.entry.connect( "focus-in-event", self.entry_focus_in_event_cb)
def __init__(self, title, header_bar): Stack.__init__(self, transition_type=StackTransitionType.CROSSFADE) self.grid = Gtk.Grid(orientation=Gtk.Orientation.VERTICAL) self.view = Gd.MainView( shadow_type=Gtk.ShadowType.NONE ) self.title = title self.header_bar = header_bar self.view.set_model(self.model) self.filter = self.model.filter_new(None) self.view.set_model(self.filter) box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) box.pack_start(self.view, True, True, 0) self.grid.add(box) self.add(self.grid) self.view.connect('item-activated', self.on_item_activated) self.show_all()
def init_configs_stack(self): self._stack = Stack( transition_type=StackTransitionType.CROSSFADE, transition_duration=300, visible=True) self._stack.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT_RIGHT) for config in snapper.ListConfigs(): name = str(config[0]) self.configView[name] = snapshotsView(name) self._stack.add_titled(self.configView[name].scrolledwindow, name, name) self.configView[name].selection.connect("changed", self.on_snapshots_selection_changed)
def __init__(self, title, header_bar): Stack.__init__(self, transition_type=StackTransitionType.CROSSFADE) self.grid = Gtk.Grid(orientation=Gtk.Orientation.VERTICAL) self.view = Gd.MainView(shadow_type=Gtk.ShadowType.NONE) self.title = title self.header_bar = header_bar if hasattr(self, "model"): self.view.set_model(self.model) self.filter = self.model.filter_new(None) self.view.set_model(self.filter) box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) box.pack_start(self.view, True, True, 0) button = Gtk.Button(label=title) #self.add(button) self.grid.add(box) self.add(self.grid) if hasattr(self, "on_item_activated"): self.view.connect('item-activated', self.on_item_activated) self.show_all()
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()
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
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 = {}
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 Window(Gtk.ApplicationWindow): def __init__(self, app): Gtk.ApplicationWindow.__init__(self, application=app, title=_("Music")) self.connect('focus-in-event', self._windows_focus_cb) self.settings = Gio.Settings.new('org.gnome.Music') self.add_action(self.settings.create_action('repeat')) selectAll = Gio.SimpleAction.new('selectAll', None) selectAll.connect('activate', self._on_select_all) self.add_action(selectAll) selectNone = Gio.SimpleAction.new('selectNone', None) selectNone.connect('activate', self._on_select_none) self.add_action(selectNone) self.set_size_request(200, 100) size_setting = self.settings.get_value('window-size') if isinstance(size_setting[0], int) and isinstance(size_setting[1], int): self.resize(size_setting[0], size_setting[1]) position_setting = self.settings.get_value('window-position') if len(position_setting) == 2 \ and isinstance(position_setting[0], int) \ and isinstance(position_setting[1], int): self.move(position_setting[0], position_setting[1]) if self.settings.get_value('window-maximized'): self.maximize() self.connect("window-state-event", self._on_window_state_event) self.connect("configure-event", self._on_configure_event) self._setup_view() self.proxy = Gio.DBusProxy.new_sync(Gio.bus_get_sync(Gio.BusType.SESSION, None), Gio.DBusProxyFlags.NONE, None, 'org.gnome.SettingsDaemon', '/org/gnome/SettingsDaemon/MediaKeys', 'org.gnome.SettingsDaemon.MediaKeys', None) self._grab_media_player_keys() try: self.proxy.connect('g-signal', self._handle_media_keys) except GLib.GError: # We cannot grab media keys if no settings daemon is running pass def _on_configure_event(self, widget, event): size = widget.get_size() self.settings.set_value('window-size', GLib.Variant('ai', [size[0], size[1]])) position = widget.get_position() self.settings.set_value('window-position', GLib.Variant('ai', [position[0], position[1]])) def _on_window_state_event(self, widget, event): self.settings.set_boolean('window-maximized', 'GDK_WINDOW_STATE_MAXIMIZED' in event.new_window_state.value_names) def _grab_media_player_keys(self): try: self.proxy.call_sync('GrabMediaPlayerKeys', GLib.Variant('(su)', ('Music', 0)), Gio.DBusCallFlags.NONE, -1, None) except GLib.GError: # We cannot grab media keys if no settings daemon is running pass def _windows_focus_cb(self, window, event): self._grab_media_player_keys() def _handle_media_keys(self, proxy, sender, signal, parameters): if signal != 'MediaPlayerKeyPressed': print('Received an unexpected signal \'%s\' from media player'.format(signal)) return response = parameters.get_child_value(1).get_string() if 'Play' in response: self.player.play_pause() elif 'Stop' in response: self.player.Stop() elif 'Next' in response: self.player.play_next() elif 'Previous' in response: self.player.play_previous() def _setup_view(self): self._box = Gtk.VBox() self.player = Player() self.selection_toolbar = SelectionToolbar() self.toolbar = Toolbar() self.views = [] self._stack = Stack( transition_type=StackTransitionType.CROSSFADE, transition_duration=100, visible=True) if Gtk.get_minor_version() > 8: self.set_titlebar(self.toolbar.header_bar) else: self._box.pack_start(self.toolbar.header_bar, False, False, 0) self.set_hide_titlebar_when_maximized(True) self._box.pack_start(self.toolbar.searchbar, False, False, 0) self._box.pack_start(self._stack, True, True, 0) self._box.pack_start(self.player.eventBox, False, False, 0) self._box.pack_start(self.selection_toolbar.eventbox, False, False, 0) self.add(self._box) count = 1 cursor = tracker.query(Query.SONGS_COUNT, None) if cursor is not None and cursor.next(None): count = cursor.get_integer(0) if count > 0: self.views.append(Views.Albums(self.toolbar, self.selection_toolbar, self.player)) self.views.append(Views.Artists(self.toolbar, self.selection_toolbar, self.player)) self.views.append(Views.Songs(self.toolbar, self.selection_toolbar, self.player)) self.views.append(Views.Playlist(self.toolbar, self.selection_toolbar, self.player)) for i in self.views: self._stack.add_titled(i, i.title, i.title) self.toolbar.set_stack(self._stack) self.toolbar.searchbar.show() self._on_notify_model_id = self._stack.connect('notify::visible-child', self._on_notify_mode) self.connect('destroy', self._notify_mode_disconnect) self.connect('key_press_event', self._on_key_press) self.views[0].populate() #To revert to the No Music View when no songs are found else: self.views.append(Views.Empty(self.toolbar, self.player)) self._stack.add_titled(self.views[0], _("Empty"), _("Empty")) self.toolbar._search_button.set_sensitive(False) self.toolbar._select_button.set_sensitive(False) self.toolbar._search_button.connect('toggled', self._on_search_toggled) self.toolbar.connect('selection-mode-changed', self._on_selection_mode_changed) self.selection_toolbar._add_to_playlist_button.connect( 'clicked', self._on_add_to_playlist_button_clicked) self.selection_toolbar._remove_from_playlist_button.connect( 'clicked', self._on_remove_from_playlist_button_clicked) self.toolbar.set_state(ToolbarState.ALBUMS) self.toolbar.header_bar.show() self.player.eventBox.show_all() self._box.show() self.show() def _on_select_all(self, action, param): if self.toolbar._state != ToolbarState.SINGLE: model = self._stack.get_visible_child()._model else: model = self._stack.get_visible_child()._albumWidget.model _iter = model.get_iter_first() count = 0 while _iter is not None: model.set(_iter, [6], [True]) _iter = model.iter_next(_iter) count = count + 1 if count > 0: self.toolbar._selection_menu_label.set_text( ngettext(_("Selected %d item"), _("Selected %d items"), count) % count) self.selection_toolbar._add_to_playlist_button.set_sensitive(True) self.selection_toolbar._remove_from_playlist_button.set_sensitive(True) elif count == 0: self.toolbar._selection_menu_label.set_text(_("Click on items to select them")) def _on_select_none(self, action, param): if self.toolbar._state != ToolbarState.SINGLE: model = self._stack.get_visible_child()._model else: model = self._stack.get_visible_child()._albumWidget.model _iter = model.get_iter_first() self.selection_toolbar._add_to_playlist_button.set_sensitive(False) self.selection_toolbar._remove_from_playlist_button.set_sensitive(False) while _iter is not None: model.set(_iter, [6], [False]) _iter = model.iter_next(_iter) self.toolbar._selection_menu_label.set_text(_("Click on items to select them")) def _on_key_press(self, widget, event): modifiers = Gtk.accelerator_get_default_mod_mask() if (event.keyval == Gdk.KEY_f and (event.state & modifiers) == Gdk.ModifierType.CONTROL_MASK): self.toolbar.searchbar.toggle_bar() elif (event.keyval == Gdk.KEY_Escape and (event.state & modifiers) == 0): self.toolbar.searchbar.show_bar(False) if self.toolbar._selectionMode: self.toolbar.set_selection_mode(False) elif (event.state & modifiers) == 0 and \ event.keyval in range(33, 126) and \ not self.toolbar.searchbar.get_reveal_child(): self.toolbar.searchbar.show_bar(True) def _notify_mode_disconnect(self, data=None): self._stack.disconnect(self._on_notify_model_id) def _on_notify_mode(self, stack, param): #Slide out artist list on switching to artists view if stack.get_visible_child() == self.views[1] or \ stack.get_visible_child() == self.views[3]: stack.get_visible_child().stack.set_visible_child_name('dummy') stack.get_visible_child().stack.set_visible_child_name('sidebar') self.toolbar.searchbar.show_bar(False) def _toggle_view(self, btn, i): self._stack.set_visible_child(self.views[i]) def _on_search_toggled(self, button, data=None): self.toolbar.searchbar.show_bar(button.get_active()) def _on_selection_mode_changed(self, widget, data=None): if self.toolbar._selectionMode: in_playlist = self._stack.get_visible_child() == self.views[3] self.selection_toolbar._add_to_playlist_button.set_visible(not in_playlist) self.selection_toolbar._remove_from_playlist_button.set_visible(in_playlist) def _on_add_to_playlist_button_clicked(self, widget): if self._stack.get_visible_child() == self.views[3]: return def callback(selected_uris): if len(selected_uris) < 1: return add_to_playlist = Widgets.PlaylistDialog(self) if add_to_playlist.dialog_box.run() == Gtk.ResponseType.ACCEPT: playlist.add_to_playlist( add_to_playlist.get_selected(), selected_uris) self.toolbar.set_selection_mode(False) add_to_playlist.dialog_box.destroy() self._stack.get_visible_child().get_selected_track_uris(callback) def _on_remove_from_playlist_button_clicked(self, widget): if self._stack.get_visible_child() != self.views[3]: return def callback(selected_uris): if len(selected_uris) < 1: return playlist.remove_from_playlist( self.views[3].current_playlist, selected_uris) self.toolbar.set_selection_mode(False) self._stack.get_visible_child().get_selected_track_uris(callback)
class Window(Gtk.ApplicationWindow): def __init__(self, app): Gtk.ApplicationWindow.__init__(self, application=app, title=_("Music")) self.connect('focus-in-event', self._windows_focus_cb) self.settings = Gio.Settings('org.gnome.Music') self.add_action(self.settings.create_action('repeat')) self.set_size_request(887, 640) size_setting = self.settings.get_value('window-size') if isinstance(size_setting[0], int) and isinstance(size_setting[1], int): self.resize(size_setting[0], size_setting[1]) position_setting = self.settings.get_value('window-position') if len(position_setting) == 2 \ and isinstance(position_setting[0], int) \ and isinstance(position_setting[1], int): self.move(position_setting[0], position_setting[1]) if self.settings.get_value('window-maximized'): self.maximize() self.connect("window-state-event", self.on_window_state_event) self.connect("configure-event", self.on_configure_event) self._setup_view() self.proxy = Gio.DBusProxy.new_sync(Gio.bus_get_sync(Gio.BusType.SESSION, None), Gio.DBusProxyFlags.NONE, None, 'org.gnome.SettingsDaemon', '/org/gnome/SettingsDaemon/MediaKeys', 'org.gnome.SettingsDaemon.MediaKeys', None) self._grab_media_player_keys() self.proxy.connect('g-signal', self._handle_media_keys) def on_configure_event(self, widget, event): size = widget.get_size() self.settings.set_value('window-size', GLib.Variant('ai', [size[0], size[1]])) position = widget.get_position() self.settings.set_value('window-position', GLib.Variant('ai', [position[0], position[1]])) def on_window_state_event(self, widget, event): self.settings.set_boolean('window-maximized', 'GDK_WINDOW_STATE_MAXIMIZED' in event.new_window_state.value_names) def _grab_media_player_keys(self): self.proxy.call_sync('GrabMediaPlayerKeys', GLib.Variant('(su)', ('Music', 0)), Gio.DBusCallFlags.NONE, -1, None) def _windows_focus_cb(self, window, event): self._grab_media_player_keys() def _handle_media_keys(self, proxy, sender, signal, parameters): if signal != 'MediaPlayerKeyPressed': print('Received an unexpected signal \'%s\' from media player'.format(signal)) return response = parameters.get_child_value(1).get_string() if 'Play' in response: self.player.play_pause() elif 'Stop' in response: self.player.Stop() elif 'Next' in response: self.player.play_next() elif 'Previous' in response: self.player.play_previous() def _setup_view(self): self._box = Gtk.VBox() self.player = Player() self.selection_toolbar = SelectionToolbar() self.toolbar = Toolbar() self.views = [] self._stack = Stack( transition_type=StackTransitionType.CROSSFADE, transition_duration=100, visible=True) if Gtk.get_minor_version() > 8: self.set_titlebar(self.toolbar.header_bar) else: self._box.pack_start(self.toolbar.header_bar, False, False, 0) self.set_hide_titlebar_when_maximized(True) self._box.pack_start(self.toolbar.searchbar, False, False, 0) self._box.pack_start(self._stack, True, True, 0) self._box.pack_start(self.player.eventBox, False, False, 0) self._box.pack_start(self.selection_toolbar.eventbox, False, False, 0) self.add(self._box) count = 1 cursor = tracker.query(Query.SONGS_COUNT, None) if cursor is not None and cursor.next(None): count = cursor.get_integer(0) if count > 0: self.views.append(Views.Albums(self.toolbar, self.selection_toolbar, self.player)) self.views.append(Views.Artists(self.toolbar, self.selection_toolbar, self.player)) self.views.append(Views.Songs(self.toolbar, self.selection_toolbar, self.player)) #self.views.append(Views.Playlist(self.toolbar, self.selection_toolbar, self.player)) for i in self.views: self._stack.add_titled(i, i.title, i.title) self.toolbar.set_stack(self._stack) self.toolbar.searchbar.show() self._on_notify_model_id = self._stack.connect('notify::visible-child', self._on_notify_mode) self.connect('destroy', self._notify_mode_disconnect) self.connect('key_press_event', self._on_key_press) self.views[0].populate() #To revert to the No Music View when no songs are found else: self.views.append(Views.Empty(self.toolbar, self.player)) self._stack.add_titled(self.views[0], _("Empty"), _("Empty")) self.toolbar._search_button.connect('toggled', self._on_search_toggled) self.toolbar.set_state(ToolbarState.ALBUMS) self.toolbar.header_bar.show() self.player.eventBox.show_all() self._box.show() self.show() def _on_key_press(self, widget, event): modifiers = Gtk.accelerator_get_default_mod_mask() if (event.keyval == Gdk.KEY_f and (event.state & modifiers) == Gdk.ModifierType.CONTROL_MASK): self._show_searchbar(not self.toolbar.searchbar.get_child_revealed()) elif (event.keyval == Gdk.KEY_Escape and (event.state & modifiers) == 0): self._show_searchbar(False) if self.toolbar._selectionMode: self.toolbar.set_selection_mode(False) def _notify_mode_disconnect(self, data=None): self._stack.disconnect(self._on_notify_model_id) def _on_notify_mode(self, stack, param): #Slide out artist list on switching to artists view if stack.get_visible_child() == self.views[1]: stack.get_visible_child().stack.set_visible_child_name('dummy') stack.get_visible_child().stack.set_visible_child_name('artists') self._show_searchbar(False) def _toggle_view(self, btn, i): self._stack.set_visible_child(self.views[i]) def _on_search_toggled(self, button, data=None): self._show_searchbar(button.get_active()) def _show_searchbar(self, show): self.toolbar.searchbar.set_reveal_child(show) self.toolbar._search_button.set_active(show) if show: self.toolbar.searchbar._search_entry.grab_focus() else: self.toolbar.searchbar._search_entry.set_text('')
class SnapperGUI(Gtk.ApplicationWindow): """docstring for SnapperGUI""" def __init__(self, app): Gtk.ApplicationWindow.__init__(self, application=app, title="SnapperGUI") self.app = app self.builder = Gtk.Builder() self.builder.add_from_file( pkg_resources.resource_filename("snappergui", "glade/mainWindow.glade")) self.snapshotsBox = self.builder.get_object("snapshotsBox") self.statusbar = self.builder.get_object("statusbar") self.snapshotsTreeView = self.builder.get_object("snapstreeview") self.configsGroup = self.builder.get_object("configsGroup") self.builder.connect_signals(self) self.set_default_size(700, 600) self.configView = {} self.init_configs_stack() self._stack.set_visible_child_name("root") # Switch configurations from the header bar with a StackSwitcher switcher = Gtk.StackSwitcher(margin_top=2, margin_bottom=2, visible=True) switcher.set_stack(self._stack) self.header_bar = Gtk.HeaderBar(title="SnapperGUI", visible=True) self.header_bar.pack_start(switcher) self.header_bar.set_show_close_button(True) if Gtk.get_minor_version() > 8: self.set_titlebar(self.header_bar) else: self._box.pack_start(self.header_bar, False, False, 0) self.set_hide_titlebar_when_maximized(True) self.builder.get_object("snapshotsviewport").add(self._stack) self.add(self.snapshotsBox) # TODO do not hardcode to root configuration self.statusbar.push(5, "%d snapshots" % self.configView["root"].count) self.init_dbus_signal_handlers() self.show() def init_configs_stack(self): self._stack = Stack(transition_type=StackTransitionType.CROSSFADE, transition_duration=300, visible=True) self._stack.set_transition_type( Gtk.StackTransitionType.SLIDE_LEFT_RIGHT) for config in snapper.ListConfigs(): name = str(config[0]) self.configView[name] = snapshotsView(name) self._stack.add_titled(self.configView[name].scrolledwindow, name, name) self.configView[name].selection.connect( "changed", self.on_snapshots_selection_changed) def snapshot_columns(self, snapshot): if (snapshot[3] == -1): date = "Now" else: date = strftime("%a %R %e/%m/%Y", localtime(snapshot[3])) return [ snapshot[0], snapshot[1], snapshot[2], date, getpwuid(snapshot[4])[0], snapshot[5], snapshot[6] ] def get_current_config(self): return self._stack.get_visible_child_name() def on_snapshots_selection_changed(self, selection): config = self.get_current_config() userdatatreeview = self.builder.get_object("userdatatreeview") (model, paths) = selection.get_selected_rows() if (len(paths) == 0): self.builder.get_object("snapshotActions").set_sensitive(False) userdatatreeview.set_model(None) else: self.builder.get_object("snapshotActions").set_sensitive(True) try: snapshot_data = snapper.GetSnapshot( config, model[model.get_iter(paths[0])][0]) userdata_liststore = Gtk.ListStore(str, str) for key, value in snapshot_data[7].items(): userdata_liststore.append([key, value]) userdatatreeview.set_model(userdata_liststore) except dbus.exceptions.DBusException: pass def on_create_snapshot(self, widget): dialog = createSnapshot(self) response = dialog.run() dialog.destroy() if response == Gtk.ResponseType.OK: newSnapshot = snapper.CreateSingleSnapshot(dialog.config, dialog.description, dialog.cleanup, dialog.userdata) elif response == Gtk.ResponseType.CANCEL: pass def on_create_config(self, widget): dialog = createConfig(self) response = dialog.run() dialog.destroy() if response == Gtk.ResponseType.OK: snapper.CreateConfig(dialog.name, dialog.subvolume, dialog.fstype, dialog.template) elif response == Gtk.ResponseType.CANCEL: pass def on_delete_snapshot(self, widget): config = self.get_current_config() selection = self.configView[config].selection (model, paths) = selection.get_selected_rows() snapshots = [] for path in paths: treeiter = model.get_iter(path) # avoid duplicates because post snapshots are always added if model[treeiter][0] not in snapshots: snapshots.append(model[treeiter][0]) # if snapshot has post add that to delete if model.iter_has_child(treeiter): child_treeiter = model.iter_children(treeiter) snapshots.append(model[child_treeiter][0]) dialog = deleteDialog(self, config, snapshots) response = dialog.run() if response == Gtk.ResponseType.YES and len(dialog.to_delete) > 0: snapper.DeleteSnapshots(config, dialog.to_delete) def on_open_snapshot_folder(self, widget): config = self.get_current_config() selection = self.configView[config].selection model, paths = selection.get_selected_rows() for path in paths: treeiter = model.get_iter(path) mountpoint = snapper.GetMountPoint(config, model[treeiter][0]) subprocess.Popen(['xdg-open', mountpoint]) self.statusbar.push( True, "The mount point for the snapshot %s from %s is %s" % (model[treeiter][0], config, mountpoint)) def on_viewchanges_clicked(self, widget): config = self.get_current_config() selection = self.configView[config].selection model, paths = selection.get_selected_rows() if len(paths) > 1: # open a changes window with the first and the last snapshot selected begin = model[paths[0]][0] end = model[paths[-1]][0] window = changesWindow(config, begin, end) elif len(paths) == 1 and model.iter_has_child(model.get_iter( paths[0])): # open a changes window with the selected pre snapshot and is's post child_iter = model.iter_children(model.get_iter(paths[0])) begin = model[paths[0]][0] end = model.get_value(child_iter, 0) window = changesWindow(config, begin, end) def on_configs_properties_clicked(self, notebook): dialog = propertiesDialog(self) dialog.dialog.run() dialog.dialog.hide() def on_about_clicked(self, widget): about = self.builder.get_object("aboutdialog1") about.run() about.hide() def delete_event(self, widget): self.app._window.destroy() def init_dbus_signal_handlers(self): signals = { "SnapshotCreated": self.on_dbus_snapshot_created, "SnapshotModified": self.on_dbus_snapshot_modified, "SnapshotsDeleted": self.on_dbus_snapshots_deleted, "ConfigCreated": self.on_dbus_config_created, "ConfigModified": self.on_dbus_config_modified, "ConfigDeleted": self.on_dbus_config_deleted } for signal, handler in signals.items(): snapper.connect_to_signal(signal, handler) def on_dbus_snapshot_created(self, config, snapshot): self.statusbar.push( True, "Snapshot %s created for %s" % (str(snapshot), config)) self.configView[config].add_snapshot_to_tree(str(snapshot)) def on_dbus_snapshot_modified(self, config, snapshot): print("Snapshot SnapshotModified") def on_dbus_snapshots_deleted(self, config, snapshots): snaps_str = "" for snapshot in snapshots: snaps_str += str(snapshot) + " " self.statusbar.push( True, "Snapshots deleted from %s: %s" % (config, snaps_str)) for deleted in snapshots: self.configView[config].remove_snapshot_from_tree(deleted) def on_dbus_config_created(self, config): self.configView[config] = snapshotsView(config) self.configView[config].update_view() self._stack.add_titled(self.configView[config]._TreeView, config, config) self.statusbar.push(5, "Created new configuration %s" % config) def on_dbus_config_modified(self, args): print("Config Modified") def on_dbus_config_deleted(self, args): print("Config Deleted")
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)
def stackup_section(self, stack: Gtk.Stack) -> None: name = self.get_name() title = name.capitalize() stack.add_titled(self, name, title)
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])
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)
class Window(Gtk.ApplicationWindow): def __init__(self, app): Gtk.ApplicationWindow.__init__(self, application=app, title="Earthquake") self.setup_view() """ self.button = Gtk.Button(label="Play") self.button.connect("clicked", self.on_button_clicked) """ def setup_view(self): self._box = Gtk.VBox() self.toolbar = Toolbar() self.toolbar2 = Toolbar() self.views = [] self._stack = Stack( transition_type=StackTransitionType.CROSSFADE, transition_duration=100, visible=True) self.set_titlebar(self.toolbar.header_bar) self._box.pack_start(self.toolbar.searchbar, False, False, 0) self._box.pack_start(self._stack, True, True, 0) self.add(self._box) count = 1 plugins = Plugins() #self.views.append(Views.ElementView(self.toolbar, _("All"), all_plugins)) """" for cat in cats: self.views.append(Views.ElementView(self.toolbar, _(cat), plugins.get_by_cat(cat))) """ input_plugins = {} suffixes = [("Bins", "bin"), ("Decoders", "dec"), ("Demuxers", "demux"), ("Parsers", "parse"), ("Sources", "src")] for suffix in suffixes: input_plugins[suffix[0]] = plugins.get_by_suffix(suffix[1]) self.views.append(Views.ElementStackView(self.toolbar, "Input", input_plugins)) output_plugins = {} suffixes2 = [("Encoders", "enc"), ("Muxers", "mux"), ("Sinks", "sink")] for suffix in suffixes2: output_plugins[suffix[0]] = plugins.get_by_suffix(suffix[1]) self.views.append(Views.ElementStackView(self.toolbar, "Output", output_plugins)) lib_plugins = {} submodules = ["frei0r", "libav", "opengl", "effectv", "gnonlin", "rtp", "libvisual", "audiofx", "videofilter", "gaudieffects", "coreelements", "rtpmanager", "geometrictransform"] for submodule in submodules: lib_plugins[submodule] = plugins.get_by_cat(submodule) self.views.append(Views.ElementStackView(self.toolbar, "Libs", lib_plugins)) self.views.append(Views.ElementView(self.toolbar, _("Misc"), plugins.get_rest())) for i in self.views: self._stack.add_titled(i, i.title, i.title) self.toolbar.set_stack(self._stack) self.toolbar.searchbar.show() self.toolbar._search_button.connect('toggled', self._on_search_toggled) self.toolbar.set_state(ToolbarState.ALBUMS) self.toolbar.header_bar.show() self._box.show() self.show() def init_gst(self): Gst.init(None) self.pipeline = Gst.Pipeline.new("pipeline") videotestsrc = Gst.ElementFactory.make("videotestsrc", "src") glimagesink = Gst.ElementFactory.make("autovideosink", "sink") self.pipeline.add(videotestsrc) self.pipeline.add(glimagesink) Gst.Element.link(videotestsrc, glimagesink) def on_button_clicked(self, widget): if self.playing: self.pipeline.set_state(Gst.State.PAUSED) self.playing = False self.button.set_label("Play") else: self.pipeline.set_state(Gst.State.PLAYING) self.playing = True self.button.set_label("Pause") def _toggle_view(self, btn, i): self._stack.set_visible_child(self.views[i]) def _on_search_toggled(self, button, data=None): self._show_searchbar(button.get_active()) def _show_searchbar(self, show): self.toolbar.searchbar.set_reveal_child(show) self.toolbar._search_button.set_active(show) if show: self.toolbar.searchbar._search_entry.grab_focus() else: self.toolbar.searchbar._search_entry.set_text('')
def setup_view(self): self._box = Gtk.VBox() self.toolbar = Toolbar() self.toolbar2 = Toolbar() self.views = [] self._stack = Stack( transition_type=StackTransitionType.CROSSFADE, transition_duration=100, visible=True) self.set_titlebar(self.toolbar.header_bar) self._box.pack_start(self.toolbar.searchbar, False, False, 0) self._box.pack_start(self._stack, True, True, 0) self.add(self._box) count = 1 plugins = Plugins() #self.views.append(Views.ElementView(self.toolbar, _("All"), all_plugins)) """" for cat in cats: self.views.append(Views.ElementView(self.toolbar, _(cat), plugins.get_by_cat(cat))) """ input_plugins = {} suffixes = [("Bins", "bin"), ("Decoders", "dec"), ("Demuxers", "demux"), ("Parsers", "parse"), ("Sources", "src")] for suffix in suffixes: input_plugins[suffix[0]] = plugins.get_by_suffix(suffix[1]) self.views.append(Views.ElementStackView(self.toolbar, "Input", input_plugins)) output_plugins = {} suffixes2 = [("Encoders", "enc"), ("Muxers", "mux"), ("Sinks", "sink")] for suffix in suffixes2: output_plugins[suffix[0]] = plugins.get_by_suffix(suffix[1]) self.views.append(Views.ElementStackView(self.toolbar, "Output", output_plugins)) lib_plugins = {} submodules = ["frei0r", "libav", "opengl", "effectv", "gnonlin", "rtp", "libvisual", "audiofx", "videofilter", "gaudieffects", "coreelements", "rtpmanager", "geometrictransform"] for submodule in submodules: lib_plugins[submodule] = plugins.get_by_cat(submodule) self.views.append(Views.ElementStackView(self.toolbar, "Libs", lib_plugins)) self.views.append(Views.ElementView(self.toolbar, _("Misc"), plugins.get_rest())) for i in self.views: self._stack.add_titled(i, i.title, i.title) self.toolbar.set_stack(self._stack) self.toolbar.searchbar.show() self.toolbar._search_button.connect('toggled', self._on_search_toggled) self.toolbar.set_state(ToolbarState.ALBUMS) self.toolbar.header_bar.show() self._box.show() self.show()
class Window(Gtk.ApplicationWindow): def __init__(self, app): Gtk.ApplicationWindow.__init__(self, application=app, title=_("Music")) self.connect('focus-in-event', self._windows_focus_cb) settings = Gio.Settings('org.gnome.Music') self.add_action(settings.create_action('repeat')) self.set_size_request(887, 640) self._setup_view() self.proxy = Gio.DBusProxy.new_sync(Gio.bus_get_sync(Gio.BusType.SESSION, None), Gio.DBusProxyFlags.NONE, None, 'org.gnome.SettingsDaemon', '/org/gnome/SettingsDaemon/MediaKeys', 'org.gnome.SettingsDaemon.MediaKeys', None) self._grab_media_player_keys() self.proxy.connect('g-signal', self._handle_media_keys) def _grab_media_player_keys(self): self.proxy.call_sync('GrabMediaPlayerKeys', GLib.Variant('(su)', ('Music', 0)), Gio.DBusCallFlags.NONE, -1, None) def _windows_focus_cb(self, window, event): self._grab_media_player_keys() def _handle_media_keys(self, proxy, sender, signal, parameters): if signal != 'MediaPlayerKeyPressed': print('Received an unexpected signal \'%s\' from media player'.format(signal)) return response = parameters.get_child_value(1).get_string() if 'Play' in response: self.player.play_pause() elif 'Stop' in response: self.player.Stop() elif 'Next' in response: self.player.play_next() elif 'Previous' in response: self.player.play_previous() def _setup_view(self): self._box = Gtk.VBox() self.player = Player() self.selection_toolbar = SelectionToolbar() self.toolbar = Toolbar() self.views = [] self._stack = Stack( transition_type=StackTransitionType.CROSSFADE, transition_duration=100, visible=True) if Gtk.get_minor_version() > 8: self.set_titlebar(self.toolbar.header_bar) else: self._box.pack_start(self.toolbar.header_bar, False, False, 0) self.set_hide_titlebar_when_maximized(True) self._box.pack_start(self.toolbar.searchbar, False, False, 0) self._box.pack_start(self._stack, True, True, 0) self._box.pack_start(self.player.eventBox, False, False, 0) self._box.pack_start(self.selection_toolbar.eventbox, False, False, 0) self.add(self._box) count = 1 cursor = tracker.query(Query.SONGS_COUNT, None) if cursor is not None and cursor.next(None): count = cursor.get_integer(0) if count > 0: self.views.append(Views.Albums(self.toolbar, self.selection_toolbar, self.player)) self.views.append(Views.Artists(self.toolbar, self.selection_toolbar, self.player)) self.views.append(Views.Songs(self.toolbar, self.selection_toolbar, self.player)) #self.views.append(Views.Playlist(self.toolbar, self.selection_toolbar, self.player)) for i in self.views: self._stack.add_titled(i, i.title, i.title) self.toolbar.set_stack(self._stack) self.toolbar.searchbar.show() self._on_notify_model_id = self._stack.connect('notify::visible-child', self._on_notify_mode) self.connect('destroy', self._notify_mode_disconnect) self.connect('key_press_event', self._on_key_press) self.views[0].populate() #To revert to the No Music View when no songs are found else: self.views.append(Views.Empty(self.toolbar, self.player)) self._stack.add_titled(self.views[0], _("Empty"), _("Empty")) self.toolbar._search_button.connect('toggled', self._on_search_toggled) self.toolbar.set_state(ToolbarState.ALBUMS) self.toolbar.header_bar.show() self.player.eventBox.show_all() self._box.show() self.show() def _on_key_press(self, widget, event): modifiers = Gtk.accelerator_get_default_mod_mask() if (event.keyval == Gdk.KEY_f and (event.state & modifiers) == Gdk.ModifierType.CONTROL_MASK): self._show_searchbar(not self.toolbar.searchbar.get_child_revealed()) elif (event.keyval == Gdk.KEY_Escape and (event.state & modifiers) == 0): self._show_searchbar(False) def _notify_mode_disconnect(self, data=None): self._stack.disconnect(self._on_notify_model_id) def _on_notify_mode(self, stack, param): #Slide out artist list on switching to artists view if stack.get_visible_child() == self.views[1]: stack.get_visible_child().stack.set_visible_child_name('dummy') stack.get_visible_child().stack.set_visible_child_name('artists') self._show_searchbar(False) def _toggle_view(self, btn, i): self._stack.set_visible_child(self.views[i]) def _on_search_toggled(self, button, data=None): self._show_searchbar(button.get_active()) def _show_searchbar(self, show): self.toolbar.searchbar.set_reveal_child(show) self.toolbar._search_button.set_active(show) if show: self.toolbar.searchbar._search_entry.grab_focus() else: self.toolbar.searchbar._search_entry.set_text('')
class SnapperGUI(Gtk.ApplicationWindow): """docstring for SnapperGUI""" def __init__(self, app): Gtk.ApplicationWindow.__init__(self, application=app, title="SnapperGUI") self.app = app self.builder = Gtk.Builder() self.builder.add_from_file(pkg_resources.resource_filename("snappergui", "glade/mainWindow.glade")) self.snapshotsBox = self.builder.get_object("snapshotsBox") self.statusbar = self.builder.get_object("statusbar") self.snapshotsTreeView = self.builder.get_object("snapstreeview") self.configsGroup = self.builder.get_object("configsGroup") self.builder.connect_signals(self) self.set_default_size(700,600) self.configView = {} self.init_configs_stack() self._stack.set_visible_child_name("root") # Switch configurations from the header bar with a StackSwitcher switcher = Gtk.StackSwitcher(margin_top=2, margin_bottom=2, visible=True) switcher.set_stack(self._stack) self.header_bar = Gtk.HeaderBar(title="SnapperGUI",visible=True) self.header_bar.pack_start(switcher) self.header_bar.set_show_close_button(True) if Gtk.get_minor_version() > 8: self.set_titlebar(self.header_bar) else: self._box.pack_start(self.header_bar, False, False, 0) self.set_hide_titlebar_when_maximized(True) self.builder.get_object("snapshotsviewport").add(self._stack) self.add(self.snapshotsBox) # TODO do not hardcode to root configuration self.statusbar.push(5,"%d snapshots"% self.configView["root"].count) self.init_dbus_signal_handlers() self.show() def init_configs_stack(self): self._stack = Stack( transition_type=StackTransitionType.CROSSFADE, transition_duration=300, visible=True) self._stack.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT_RIGHT) for config in snapper.ListConfigs(): name = str(config[0]) self.configView[name] = snapshotsView(name) self._stack.add_titled(self.configView[name].scrolledwindow, name, name) self.configView[name].selection.connect("changed", self.on_snapshots_selection_changed) def snapshot_columns(self,snapshot): if(snapshot[3] == -1): date = "Now" else: date = strftime("%a %R %e/%m/%Y", localtime(snapshot[3])) return [snapshot[0], snapshot[1], snapshot[2], date, getpwuid(snapshot[4])[0], snapshot[5], snapshot[6]] def get_current_config(self): return self._stack.get_visible_child_name() def on_snapshots_selection_changed(self,selection): config = self.get_current_config() userdatatreeview = self.builder.get_object("userdatatreeview") (model, paths) = selection.get_selected_rows() if(len(paths) == 0): self.builder.get_object("snapshotActions").set_sensitive(False) userdatatreeview.set_model(None) else: self.builder.get_object("snapshotActions").set_sensitive(True) try: snapshot_data = snapper.GetSnapshot(config,model[model.get_iter(paths[0])][0]) userdata_liststore = Gtk.ListStore(str, str) for key, value in snapshot_data[7].items(): userdata_liststore.append([key, value]) userdatatreeview.set_model(userdata_liststore) except dbus.exceptions.DBusException: pass def on_create_snapshot(self, widget): dialog = createSnapshot(self) response = dialog.run() dialog.destroy() if response == Gtk.ResponseType.OK: newSnapshot = snapper.CreateSingleSnapshot(dialog.config, dialog.description, dialog.cleanup, dialog.userdata) elif response == Gtk.ResponseType.CANCEL: pass def on_create_config(self, widget): dialog = createConfig(self) response = dialog.run() dialog.destroy() if response == Gtk.ResponseType.OK: snapper.CreateConfig(dialog.name, dialog.subvolume, dialog.fstype, dialog.template) elif response == Gtk.ResponseType.CANCEL: pass def on_delete_snapshot(self, widget): config = self.get_current_config() selection = self.configView[config].selection (model, paths) = selection.get_selected_rows() snapshots = [] for path in paths: treeiter = model.get_iter(path) # avoid duplicates because post snapshots are always added if model[treeiter][0] not in snapshots: snapshots.append(model[treeiter][0]) # if snapshot has post add that to delete if model.iter_has_child(treeiter): child_treeiter = model.iter_children(treeiter) snapshots.append(model[child_treeiter][0]) dialog = deleteDialog(self, config,snapshots) response = dialog.run() if response == Gtk.ResponseType.YES and len(dialog.to_delete) > 0: snapper.DeleteSnapshots(config, dialog.to_delete) def on_open_snapshot_folder(self, widget): config = self.get_current_config() selection = self.configView[config].selection model, paths = selection.get_selected_rows() for path in paths: treeiter = model.get_iter(path) mountpoint = snapper.GetMountPoint(config, model[treeiter][0]) subprocess.Popen(['xdg-open', mountpoint]) self.statusbar.push(True, "The mount point for the snapshot %s from %s is %s"% (model[treeiter][0], config, mountpoint)) def on_viewchanges_clicked(self, widget): config = self.get_current_config() selection = self.configView[config].selection model, paths = selection.get_selected_rows() if len(paths) > 1: # open a changes window with the first and the last snapshot selected begin = model[paths[0]][0] end = model[paths[-1]][0] window = changesWindow(config, begin, end) elif len(paths) == 1 and model.iter_has_child(model.get_iter(paths[0])): # open a changes window with the selected pre snapshot and is's post child_iter = model.iter_children(model.get_iter(paths[0])) begin = model[paths[0]][0] end = model.get_value(child_iter,0) window = changesWindow(config, begin, end) def on_configs_properties_clicked(self, notebook): dialog = propertiesDialog(self) dialog.dialog.run() dialog.dialog.hide() def on_about_clicked(self,widget): about = self.builder.get_object("aboutdialog1") about.run() about.hide() def delete_event(self,widget): self.app._window.destroy() def init_dbus_signal_handlers(self): signals = { "SnapshotCreated" : self.on_dbus_snapshot_created, "SnapshotModified" : self.on_dbus_snapshot_modified, "SnapshotsDeleted" : self.on_dbus_snapshots_deleted, "ConfigCreated" : self.on_dbus_config_created, "ConfigModified" : self.on_dbus_config_modified, "ConfigDeleted" : self.on_dbus_config_deleted } for signal, handler in signals.items(): snapper.connect_to_signal(signal,handler) def on_dbus_snapshot_created(self,config,snapshot): self.statusbar.push(True, "Snapshot %s created for %s"% (str(snapshot), config)) self.configView[config].add_snapshot_to_tree(str(snapshot)) def on_dbus_snapshot_modified(self,config,snapshot): print("Snapshot SnapshotModified") def on_dbus_snapshots_deleted(self,config,snapshots): snaps_str = "" for snapshot in snapshots: snaps_str += str(snapshot) + " " self.statusbar.push(True, "Snapshots deleted from %s: %s"% (config, snaps_str)) for deleted in snapshots: self.configView[config].remove_snapshot_from_tree(deleted) def on_dbus_config_created(self, config): self.configView[config] = snapshotsView(config) self.configView[config].update_view() self._stack.add_titled(self.configView[config]._TreeView, config, config) self.statusbar.push(5,"Created new configuration %s"% config) def on_dbus_config_modified(self,args): print("Config Modified") def on_dbus_config_deleted(self,args): print("Config Deleted")
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])