class Toolbar(GObject.GObject): __gsignals__ = { 'selection-mode-changed': (GObject.SignalFlags.RUN_FIRST, None, ()), } def __repr__(self): return '<Toolbar>' @log def __init__(self): super().__init__() self._selection_mode = False self._stack_switcher = Gtk.StackSwitcher(can_focus=False, halign="center") self._stack_switcher.show() self._ui = Gtk.Builder() self._ui.add_from_resource('/org/gnome/Music/headerbar.ui') self.header_bar = self._ui.get_object('header-bar') self._search_button = self._ui.get_object('search-button') self.dropdown = DropDown() self.searchbar = Searchbar( self._stack_switcher, self._search_button, self.dropdown) self.dropdown.initialize_filters(self.searchbar) self._select_button = self._ui.get_object('select-button') self._cancel_button = self._ui.get_object('done-button') self._back_button = self._ui.get_object('back-button') self._selection_menu = self._ui.get_object('selection-menu') self._selection_menu_button = self._ui.get_object( 'selection-menu-button') self._selection_menu_label = self._ui.get_object( 'selection-menu-button-label') self._back_button.connect('clicked', self.on_back_button_clicked) self._window = self.header_bar.get_parent() @GObject.Property def selection_mode(self): return self._selection_mode @selection_mode.setter def selection_mode(self, mode): self.set_selection_mode(mode) @log def reset_header_title(self): self.header_bar.set_title(_("Music")) self.header_bar.set_custom_title(self._stack_switcher) @log def set_stack(self, stack): self._stack_switcher.set_stack(stack) @log def get_stack(self): return self._stack_switcher.get_stack() @log def hide_stack(self): self._stack_switcher.hide() @log def show_stack(self): self._stack_switcher.show() @log def set_selection_mode(self, mode): self._selection_mode = mode if mode: self._select_button.hide() self._cancel_button.show() self.header_bar.get_style_context().add_class('selection-mode') self._cancel_button.get_style_context().remove_class( 'selection-mode') else: self.header_bar.get_style_context().remove_class('selection-mode') self._select_button.set_active(False) self._select_button.show() self._cancel_button.hide() self.emit('selection-mode-changed') self._update() @log def on_back_button_clicked(self, widget=None): self._window = self.header_bar.get_parent() visible_child = self._window.curr_view.get_visible_child() view = self._stack_switcher.get_stack().get_visible_child() view._back_button_clicked(view) current_view = self._window.curr_view if not ((current_view == self._window.views[View.SEARCH] or current_view == self._window.views[View.EMPTY_SEARCH]) and visible_child != current_view._grid): self.set_state(ToolbarState.MAIN) else: self._search_button.set_visible(True) self.searchbar.reveal(False) @log def set_state(self, state, btn=None): self._state = state self._update() @log def _update(self): if self._selection_mode: self.header_bar.set_custom_title(self._selection_menu_button) elif self._state != ToolbarState.MAIN: self.header_bar.set_custom_title(None) else: self.reset_header_title() self._search_button.set_visible( self._state != ToolbarState.SEARCH_VIEW) self._back_button.set_visible( not self._selection_mode and self._state != ToolbarState.MAIN) self.header_bar.set_show_close_button(not self._selection_mode)
class HeaderBar(Gtk.HeaderBar): """Headerbar of the application""" class State(IntEnum): """States the Headerbar can have""" MAIN = 0 CHILD = 1 SEARCH = 2 EMPTY = 3 __gtype_name__ = "HeaderBar" _search_button = Gtk.Template.Child() _select_button = Gtk.Template.Child() _cancel_button = Gtk.Template.Child() _back_button = Gtk.Template.Child() items_selected = GObject.Property(type=int, default=0, minimum=0) selection_mode_allowed = GObject.Property(type=bool, default=True) stack = GObject.Property(type=Gtk.Stack) def __repr__(self): return "<HeaderBar>" @log def __init__(self): super().__init__() self._selection_mode = False self._stack_switcher = Gtk.StackSwitcher(can_focus=False, halign="center") self._stack_switcher.show() self.dropdown = DropDown() self.searchbar = Searchbar(self._stack_switcher, self._search_button, self.dropdown) self.dropdown.initialize_filters(self.searchbar) self._selection_menu = SelectionBarMenuButton() self.bind_property( "selection-mode", self, "show-close-button", GObject.BindingFlags.INVERT_BOOLEAN | GObject.BindingFlags.SYNC_CREATE) self.bind_property("selection-mode", self._cancel_button, "visible") self.bind_property("selection-mode", self._select_button, "visible", GObject.BindingFlags.INVERT_BOOLEAN) self.bind_property("selection-mode", self._select_button, "active", GObject.BindingFlags.BIDIRECTIONAL) self.bind_property( "stack", self._stack_switcher, "stack", GObject.BindingFlags.BIDIRECTIONAL | GObject.BindingFlags.SYNC_CREATE) self.bind_property("items-selected", self._selection_menu, "items-selected") self.connect("notify::selection-mode-allowed", self._on_selection_mode_allowed_changed) @GObject.Property(type=bool, default=False) def selection_mode(self): """Selection mode :returns: Selection mode :rtype: bool """ return self._selection_mode @selection_mode.setter def selection_mode(self, mode): """Set the selection mode :param bool value: Selection mode """ self._selection_mode = mode if mode: self.get_style_context().add_class("selection-mode") else: self.get_style_context().remove_class("selection-mode") self._select_button.props.active = False self._update() @GObject.Property def state(self): """State of the widget :returns: Widget state :rtype: HeaderBar.State """ return self._state @state.setter def state(self, value): """Set state of the of widget This influences the look and functionality of the headerbar. :param HeaderBar.State value: Widget state """ self._state = value self._update() search_visible = self.props.state != HeaderBar.State.SEARCH self._search_button.props.visible = search_visible if value == HeaderBar.State.EMPTY: self._search_button.props.sensitive = False self._select_button.props.sensitive = False self._stack_switcher.hide() else: self._search_button.props.sensitive = True self._select_button.props.sensitive = True self._stack_switcher.show() @Gtk.Template.Callback() @log def _on_back_button_clicked(self, widget=None): window = self.get_toplevel() visible_child = window.curr_view.props.visible_child # FIXME: Stack switch logic should not be here. view = self._stack_switcher.props.stack.props.visible_child view._back_button_clicked(view) current_view = window.curr_view if not ((current_view == window.views[View.SEARCH] or current_view == window.views[View.EMPTY]) and visible_child != current_view._grid): self.props.state = HeaderBar.State.MAIN else: self._search_button.props.visible = True self.searchbar.reveal(False) @Gtk.Template.Callback() @log def _on_cancel_button_clicked(self, button): self.props.selection_mode = False @log def _update(self): if self.props.selection_mode: self.props.custom_title = self._selection_menu elif self.props.state != HeaderBar.State.MAIN: self.props.custom_title = None else: self.props.custom_title = self._stack_switcher self._back_button.props.visible = ( not self.props.selection_mode and self.props.state != HeaderBar.State.MAIN and self.props.state != HeaderBar.State.EMPTY) @log def _on_selection_mode_allowed_changed(self, widget, data): if self.props.selection_mode_allowed: self._select_button.props.sensitive = True else: self._select_button.props.sensitive = False