Example #1
0
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)
Example #2
0
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