def __init__(self):
        """
        Initialises the object.
        """
        super(AltToolbarBase, self).__init__()

        gs = GSetting()
        plugin_settings = gs.get_setting(gs.Path.PLUGIN)
        plugin_settings.bind(gs.PluginKey.SOURCE_TOOLBAR, self, 'source_toolbar_visible',
                                  Gio.SettingsBindFlags.DEFAULT)

        self._async_functions = []  # array of functions to callback once the toolbar has been setup
        self.connect('notify::setup-completed', self._on_setup_completed)
Esempio n. 2
0
    def __init__(self):
        """
        Initialises the object.
        """
        super(AltToolbarBase, self).__init__()

        gs = GSetting()
        plugin_settings = gs.get_setting(gs.Path.PLUGIN)
        plugin_settings.bind(gs.PluginKey.SOURCE_TOOLBAR, self,
                             'source_toolbar_visible',
                             Gio.SettingsBindFlags.DEFAULT)

        self._async_functions = [
        ]  # array of functions to callback once the toolbar has been setup
        self.connect('notify::setup-completed', self._on_setup_completed)
    def __init__(self, parent_container, parent_button, *args, **kwargs):
        super (RepeatPopContainer, self).__init__(*args, **kwargs)

        self.set_orientation(Gtk.Orientation.HORIZONTAL)
        self.set_layout(Gtk.ButtonBoxStyle.START)
        self.props.margin = 5
        context = self.get_style_context()
        context.add_class('linked')

        icon_size = 4

        toggle1 = Gtk.RadioButton.new(None)
        toggle1.set_mode(False)
        icon = Gio.ThemedIcon.new_with_default_fallbacks('media-playlist-repeat-symbolic')
        image = Gtk.Image()
        image.set_from_gicon(icon, icon_size)
        image.props.margin = 5
        toggle1.set_image(image)
        toggle1.connect('leave-notify-event', self._on_popover_mouse_over)
        toggle1.connect('enter-notify-event', self._on_popover_mouse_over)
        toggle1.connect('toggled', self._on_popover_button_toggled)

        # locale stuff
        cl = CoverLocale()
        cl.switch_locale(cl.Locale.LOCALE_DOMAIN)
        
        if parent_button.get_has_tooltip():
            toggle1.set_tooltip_text(_("Repeat all tracks"))

        self._repeat_button = toggle1
        self.add(toggle1)
        self.child_set_property(toggle1, "non-homogeneous", True)
        toggle1.show_all()

        self._repeat_image = Gtk.Image()
        self._repeat_image.set_from_gicon(icon, icon_size)
        self._repeat_image.props.margin = 5

        toggle2 = Gtk.RadioButton.new_from_widget(toggle1)
        toggle2.set_mode(False)
        icon2 = Gio.ThemedIcon.new_with_default_fallbacks('media-playlist-repeat-song-symbolic')
        image2 = Gtk.Image()
        image2.set_from_gicon(icon2, icon_size)
        image2.props.margin = 5
        toggle2.set_image(image2)

        if parent_button.get_has_tooltip():
            toggle2.set_tooltip_text(_("Repeat the current track"))

        self._repeat_song_image = Gtk.Image()
        self._repeat_song_image.set_from_gicon(icon2, icon_size)
        self._repeat_song_image.props.margin = 5

        toggle2.connect('leave-notify-event', self._on_popover_mouse_over)
        toggle2.connect('enter-notify-event', self._on_popover_mouse_over)
        toggle2.connect('toggled', self._on_popover_button_toggled)
        toggle2.show_all()
        self._repeat_song_button = toggle2
        self.add(toggle2)
        self.child_set_property(toggle2, "non-homogeneous", True)

        self._popover_inprogress = 0
        parent_container.connect('leave-notify-event', self._on_popover_mouse_over)
        parent_container.connect('enter-notify-event', self._on_popover_mouse_over)
        parent_button.connect('leave-notify-event', self._on_popover_mouse_over)
        parent_button.connect('enter-notify-event', self._on_popover_mouse_over)

        gicon_name = image.props.gicon
        parent_button.set_image(self._repeat_image)

        self._parent_container = parent_container
        self._parent_button = parent_button

        # now get the repeat-type saved in gsettings
        # get values from gsettings
        self.gs = GSetting()
        self.plugin_settings = self.gs.get_setting(self.gs.Path.PLUGIN)

        repeat_type = self.plugin_settings[self.gs.PluginKey.REPEAT_TYPE]

        if repeat_type == RepeatPopContainer.ONE_SONG:
            self._repeat_song_button.set_active(True)
class RepeatPopContainer(Gtk.ButtonBox):

    __gsignals__ = {
        "repeat-type-changed": (GObject.SIGNAL_RUN_LAST, None, (int,))
    }

    # repeat-type-changed is emitted with one of the following values
    ONE_SONG = 1
    ALL_SONGS = 2

    def __init__(self, parent_container, parent_button, *args, **kwargs):
        super (RepeatPopContainer, self).__init__(*args, **kwargs)

        self.set_orientation(Gtk.Orientation.HORIZONTAL)
        self.set_layout(Gtk.ButtonBoxStyle.START)
        self.props.margin = 5
        context = self.get_style_context()
        context.add_class('linked')

        icon_size = 4

        toggle1 = Gtk.RadioButton.new(None)
        toggle1.set_mode(False)
        icon = Gio.ThemedIcon.new_with_default_fallbacks('media-playlist-repeat-symbolic')
        image = Gtk.Image()
        image.set_from_gicon(icon, icon_size)
        image.props.margin = 5
        toggle1.set_image(image)
        toggle1.connect('leave-notify-event', self._on_popover_mouse_over)
        toggle1.connect('enter-notify-event', self._on_popover_mouse_over)
        toggle1.connect('toggled', self._on_popover_button_toggled)

        # locale stuff
        cl = CoverLocale()
        cl.switch_locale(cl.Locale.LOCALE_DOMAIN)
        
        if parent_button.get_has_tooltip():
            toggle1.set_tooltip_text(_("Repeat all tracks"))

        self._repeat_button = toggle1
        self.add(toggle1)
        self.child_set_property(toggle1, "non-homogeneous", True)
        toggle1.show_all()

        self._repeat_image = Gtk.Image()
        self._repeat_image.set_from_gicon(icon, icon_size)
        self._repeat_image.props.margin = 5

        toggle2 = Gtk.RadioButton.new_from_widget(toggle1)
        toggle2.set_mode(False)
        icon2 = Gio.ThemedIcon.new_with_default_fallbacks('media-playlist-repeat-song-symbolic')
        image2 = Gtk.Image()
        image2.set_from_gicon(icon2, icon_size)
        image2.props.margin = 5
        toggle2.set_image(image2)

        if parent_button.get_has_tooltip():
            toggle2.set_tooltip_text(_("Repeat the current track"))

        self._repeat_song_image = Gtk.Image()
        self._repeat_song_image.set_from_gicon(icon2, icon_size)
        self._repeat_song_image.props.margin = 5

        toggle2.connect('leave-notify-event', self._on_popover_mouse_over)
        toggle2.connect('enter-notify-event', self._on_popover_mouse_over)
        toggle2.connect('toggled', self._on_popover_button_toggled)
        toggle2.show_all()
        self._repeat_song_button = toggle2
        self.add(toggle2)
        self.child_set_property(toggle2, "non-homogeneous", True)

        self._popover_inprogress = 0
        parent_container.connect('leave-notify-event', self._on_popover_mouse_over)
        parent_container.connect('enter-notify-event', self._on_popover_mouse_over)
        parent_button.connect('leave-notify-event', self._on_popover_mouse_over)
        parent_button.connect('enter-notify-event', self._on_popover_mouse_over)

        gicon_name = image.props.gicon
        parent_button.set_image(self._repeat_image)

        self._parent_container = parent_container
        self._parent_button = parent_button

        # now get the repeat-type saved in gsettings
        # get values from gsettings
        self.gs = GSetting()
        self.plugin_settings = self.gs.get_setting(self.gs.Path.PLUGIN)

        repeat_type = self.plugin_settings[self.gs.PluginKey.REPEAT_TYPE]

        if repeat_type == RepeatPopContainer.ONE_SONG:
            self._repeat_song_button.set_active(True)

    def _on_popover_button_toggled(self, button, *args):
        print ("popover toggle")
        if button.get_active():
            if button == self._repeat_button:
                self._parent_button.set_image(self._repeat_image)
                self.emit('repeat-type-changed', RepeatPopContainer.ALL_SONGS)
                self.plugin_settings[self.gs.PluginKey.REPEAT_TYPE] = RepeatPopContainer.ALL_SONGS
            else:
                self._parent_button.set_image(self._repeat_song_image)
                self.emit('repeat-type-changed', RepeatPopContainer.ONE_SONG)
                self.plugin_settings[self.gs.PluginKey.REPEAT_TYPE] = RepeatPopContainer.ONE_SONG

    def get_repeat_type(self):
        repeat_type = RepeatPopContainer.ALL_SONGS
        if self._repeat_song_button.get_active():
            repeat_type = RepeatPopContainer.ONE_SONG

        return repeat_type


    def _on_popover_mouse_over(self, widget, eventcrossing):
        if eventcrossing.type == Gdk.EventType.ENTER_NOTIFY:
            if self._popover_inprogress == 0:
                self._popover_inprogress = 1
                print ("enter1")
            else:
                self._popover_inprogress = 2
                print ("enter2")
            self._popover_inprogress_count = 0

            if type(widget) is Gtk.ToggleButton:
                print ("here")
                if widget.get_active():
                    print (self._parent_container)
                    self._parent_container.show_all()
        else:
            print ("exit")
            self._popover_inprogress = 3

        def delayed(*args):
            if self._popover_inprogress == 3:
                self._popover_inprogress_count += 1

                if self._popover_inprogress_count < 5:
                    return True

                self._parent_container.hide()
                self._popover_inprogress = 0
                print ("exit timeout")
                return False
            else:
                return True

        if self._popover_inprogress == 1:
            print ("adding timeout")
            self._popover_inprogress = 2
            GLib.timeout_add(100, delayed)
Esempio n. 5
0
    def __init__(self, parent_container, parent_button, *args, **kwargs):
        super(RepeatPopContainer, self).__init__(*args, **kwargs)

        self.set_orientation(Gtk.Orientation.HORIZONTAL)
        self.set_layout(Gtk.ButtonBoxStyle.START)
        self.props.margin = 5
        context = self.get_style_context()
        context.add_class('linked')

        icon_size = 4

        toggle1 = Gtk.RadioButton.new(None)
        toggle1.set_mode(False)
        icon = Gio.ThemedIcon.new_with_default_fallbacks(
            'media-playlist-repeat-symbolic')
        image = Gtk.Image()
        image.set_from_gicon(icon, icon_size)
        image.props.margin = 5
        toggle1.set_image(image)
        toggle1.connect('leave-notify-event', self._on_popover_mouse_over)
        toggle1.connect('enter-notify-event', self._on_popover_mouse_over)
        toggle1.connect('toggled', self._on_popover_button_toggled)

        # locale stuff
        cl = CoverLocale()
        cl.switch_locale(cl.Locale.LOCALE_DOMAIN)

        if parent_button.get_has_tooltip():
            toggle1.set_tooltip_text(_("Repeat all tracks"))

        self._repeat_button = toggle1
        self.add(toggle1)
        self.child_set_property(toggle1, "non-homogeneous", True)
        toggle1.show_all()

        self._repeat_image = Gtk.Image()
        self._repeat_image.set_from_gicon(icon, icon_size)
        self._repeat_image.props.margin = 5

        toggle2 = Gtk.RadioButton.new_from_widget(toggle1)
        toggle2.set_mode(False)
        icon2 = Gio.ThemedIcon.new_with_default_fallbacks(
            'media-playlist-repeat-song-symbolic')
        image2 = Gtk.Image()
        image2.set_from_gicon(icon2, icon_size)
        image2.props.margin = 5
        toggle2.set_image(image2)

        if parent_button.get_has_tooltip():
            toggle2.set_tooltip_text(_("Repeat the current track"))

        self._repeat_song_image = Gtk.Image()
        self._repeat_song_image.set_from_gicon(icon2, icon_size)
        self._repeat_song_image.props.margin = 5

        toggle2.connect('leave-notify-event', self._on_popover_mouse_over)
        toggle2.connect('enter-notify-event', self._on_popover_mouse_over)
        toggle2.connect('toggled', self._on_popover_button_toggled)
        toggle2.show_all()
        self._repeat_song_button = toggle2
        self.add(toggle2)
        self.child_set_property(toggle2, "non-homogeneous", True)

        self._popover_inprogress = 0
        parent_container.connect('leave-notify-event',
                                 self._on_popover_mouse_over)
        parent_container.connect('enter-notify-event',
                                 self._on_popover_mouse_over)
        parent_button.connect('leave-notify-event',
                              self._on_popover_mouse_over)
        parent_button.connect('enter-notify-event',
                              self._on_popover_mouse_over)

        gicon_name = image.props.gicon
        parent_button.set_image(self._repeat_image)

        self._parent_container = parent_container
        self._parent_button = parent_button

        # now get the repeat-type saved in gsettings
        # get values from gsettings
        self.gs = GSetting()
        self.plugin_settings = self.gs.get_setting(self.gs.Path.PLUGIN)

        repeat_type = self.plugin_settings[self.gs.PluginKey.REPEAT_TYPE]

        if repeat_type == RepeatPopContainer.ONE_SONG:
            self._repeat_song_button.set_active(True)
Esempio n. 6
0
class RepeatPopContainer(Gtk.ButtonBox):

    __gsignals__ = {
        "repeat-type-changed": (GObject.SIGNAL_RUN_LAST, None, (int, ))
    }

    # repeat-type-changed is emitted with one of the following values
    ONE_SONG = 1
    ALL_SONGS = 2

    def __init__(self, parent_container, parent_button, *args, **kwargs):
        super(RepeatPopContainer, self).__init__(*args, **kwargs)

        self.set_orientation(Gtk.Orientation.HORIZONTAL)
        self.set_layout(Gtk.ButtonBoxStyle.START)
        self.props.margin = 5
        context = self.get_style_context()
        context.add_class('linked')

        icon_size = 4

        toggle1 = Gtk.RadioButton.new(None)
        toggle1.set_mode(False)
        icon = Gio.ThemedIcon.new_with_default_fallbacks(
            'media-playlist-repeat-symbolic')
        image = Gtk.Image()
        image.set_from_gicon(icon, icon_size)
        image.props.margin = 5
        toggle1.set_image(image)
        toggle1.connect('leave-notify-event', self._on_popover_mouse_over)
        toggle1.connect('enter-notify-event', self._on_popover_mouse_over)
        toggle1.connect('toggled', self._on_popover_button_toggled)

        # locale stuff
        cl = CoverLocale()
        cl.switch_locale(cl.Locale.LOCALE_DOMAIN)

        if parent_button.get_has_tooltip():
            toggle1.set_tooltip_text(_("Repeat all tracks"))

        self._repeat_button = toggle1
        self.add(toggle1)
        self.child_set_property(toggle1, "non-homogeneous", True)
        toggle1.show_all()

        self._repeat_image = Gtk.Image()
        self._repeat_image.set_from_gicon(icon, icon_size)
        self._repeat_image.props.margin = 5

        toggle2 = Gtk.RadioButton.new_from_widget(toggle1)
        toggle2.set_mode(False)
        icon2 = Gio.ThemedIcon.new_with_default_fallbacks(
            'media-playlist-repeat-song-symbolic')
        image2 = Gtk.Image()
        image2.set_from_gicon(icon2, icon_size)
        image2.props.margin = 5
        toggle2.set_image(image2)

        if parent_button.get_has_tooltip():
            toggle2.set_tooltip_text(_("Repeat the current track"))

        self._repeat_song_image = Gtk.Image()
        self._repeat_song_image.set_from_gicon(icon2, icon_size)
        self._repeat_song_image.props.margin = 5

        toggle2.connect('leave-notify-event', self._on_popover_mouse_over)
        toggle2.connect('enter-notify-event', self._on_popover_mouse_over)
        toggle2.connect('toggled', self._on_popover_button_toggled)
        toggle2.show_all()
        self._repeat_song_button = toggle2
        self.add(toggle2)
        self.child_set_property(toggle2, "non-homogeneous", True)

        self._popover_inprogress = 0
        parent_container.connect('leave-notify-event',
                                 self._on_popover_mouse_over)
        parent_container.connect('enter-notify-event',
                                 self._on_popover_mouse_over)
        parent_button.connect('leave-notify-event',
                              self._on_popover_mouse_over)
        parent_button.connect('enter-notify-event',
                              self._on_popover_mouse_over)

        gicon_name = image.props.gicon
        parent_button.set_image(self._repeat_image)

        self._parent_container = parent_container
        self._parent_button = parent_button

        # now get the repeat-type saved in gsettings
        # get values from gsettings
        self.gs = GSetting()
        self.plugin_settings = self.gs.get_setting(self.gs.Path.PLUGIN)

        repeat_type = self.plugin_settings[self.gs.PluginKey.REPEAT_TYPE]

        if repeat_type == RepeatPopContainer.ONE_SONG:
            self._repeat_song_button.set_active(True)

    def _on_popover_button_toggled(self, button, *args):
        print("popover toggle")
        if button.get_active():
            if button == self._repeat_button:
                self._parent_button.set_image(self._repeat_image)
                self.emit('repeat-type-changed', RepeatPopContainer.ALL_SONGS)
                self.plugin_settings[
                    self.gs.PluginKey.
                    REPEAT_TYPE] = RepeatPopContainer.ALL_SONGS
            else:
                self._parent_button.set_image(self._repeat_song_image)
                self.emit('repeat-type-changed', RepeatPopContainer.ONE_SONG)
                self.plugin_settings[self.gs.PluginKey.
                                     REPEAT_TYPE] = RepeatPopContainer.ONE_SONG

    def get_repeat_type(self):
        repeat_type = RepeatPopContainer.ALL_SONGS
        if self._repeat_song_button.get_active():
            repeat_type = RepeatPopContainer.ONE_SONG

        return repeat_type

    def _on_popover_mouse_over(self, widget, eventcrossing):
        if eventcrossing.type == Gdk.EventType.ENTER_NOTIFY:
            if self._popover_inprogress == 0:
                self._popover_inprogress = 1
                print("enter1")
            else:
                self._popover_inprogress = 2
                print("enter2")
            self._popover_inprogress_count = 0

            if type(widget) is Gtk.ToggleButton:
                print("here")
                if widget.get_active():
                    print(self._parent_container)
                    self._parent_container.show_all()
        else:
            print("exit")
            self._popover_inprogress = 3

        def delayed(*args):
            if self._popover_inprogress == 3:
                self._popover_inprogress_count += 1

                if self._popover_inprogress_count < 5:
                    return True

                self._parent_container.hide()
                self._popover_inprogress = 0
                print("exit timeout")
                return False
            else:
                return True

        if self._popover_inprogress == 1:
            print("adding timeout")
            self._popover_inprogress = 2
            GLib.timeout_add(100, delayed)
    def __init__(self, toolbar, rbtree):
        """
        Initialises the object.
        """
        super(AltToolbarSidebar, self).__init__()

        self.shell = toolbar.shell
        self.toolbar = toolbar
        self.plugin = toolbar.plugin
        self.rbtree = rbtree

        self._drag_dest_source = None
        self._drag_motion_counter = -1

        # locale stuff
        cl = CoverLocale()
        cl.switch_locale(cl.Locale.LOCALE_DOMAIN)

        self.set_name("AltToolbarSideBar")
        self._category = {}
        self._last_click_source = None

        self._user_clicked = False

        gs = GSetting()
        plugin_settings = gs.get_setting(gs.Path.PLUGIN)
        plugin_settings.bind(gs.PluginKey.EXPANDERS, self, 'expanders',
                             Gio.SettingsBindFlags.DEFAULT)

        # title, source, visible
        self.treestore = Gtk.TreeStore.new([str, GObject.Object, bool])
        self.treestore_filter = self.treestore.filter_new(root=None)
        self.treestore_filter.set_visible_column(2)

        self.set_model(self.treestore_filter)
        context = self.get_style_context()
        context.add_class(Gtk.STYLE_CLASS_SIDEBAR)
        self.set_headers_visible(False)

        # define the headers - not visible by default
        def define_category(text, category):
            local = self.treestore.append(None)
            self.treestore[local] = [text, None, False]
            self._category[category] = local

        define_category(_("Local collection"), AltControllerCategory.LOCAL)
        define_category(_("Online sources"), AltControllerCategory.ONLINE)
        define_category(_("Other sources"), AltControllerCategory.OTHER)
        define_category(_("Playlists"), AltControllerCategory.PLAYLIST)

        def delayed(*args):
            model = self.shell.props.display_page_model
            rootiter = model.get_iter_first()
            depth = 0
            self._traverse_rows(model, rootiter, None, depth)

            # switch on/off headers depending upon what's in the model
            self._refresh_headers()

            # tidy up syncing by connecting signals
            self._connect_signals()

            # now expand or collapse each expander that we have saved from a
            # previous session
            expanders = eval(self.expanders)

            print(expanders)
            print(self.expanders)
            for category in expanders:
                print(category)
                path = self.treestore.get_path(self._category[category])

                if path and expanders[category]:
                    # self._user_clicked = True
                    self.expand_row(path, False)  # expanders[category])

            return False

        GLib.timeout_add_seconds(1, delayed)

        column = Gtk.TreeViewColumn.new()
        column.set_fixed_width(5)
        column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
        self.append_column(column)

        column = Gtk.TreeViewColumn.new()

        pixbuf_renderer = Gtk.CellRendererPixbuf()
        column.pack_start(pixbuf_renderer, False)
        renderer = Gtk.CellRendererText()
        renderer.connect('edited', self.on_renderertext_edited)
        self.text_renderer = renderer
        column.pack_start(renderer, False)

        column.set_cell_data_func(pixbuf_renderer, self._set_pixbuf)
        column.set_cell_data_func(renderer, self._set_text)

        self.tree_column = column

        self.append_column(column)
        self.set_expander_column(column)
        self.show_all()
        self.set_can_focus(True)

        cl = CoverLocale()
        cl.switch_locale(cl.Locale.RB)
    def __init__(self, toolbar, rbtree):
        """
        Initialises the object.
        """
        super(AltToolbarSidebar, self).__init__()

        self.shell = toolbar.shell
        self.toolbar = toolbar
        self.plugin = toolbar.plugin
        self.rbtree = rbtree

        self._drag_dest_source = None
        self._drag_motion_counter = -1

        # locale stuff
        cl = CoverLocale()
        cl.switch_locale(cl.Locale.LOCALE_DOMAIN)

        self.set_name("AltToolbarSideBar")
        self._category = {}
        self._last_click_source = None

        self._user_clicked = False

        gs = GSetting()
        plugin_settings = gs.get_setting(gs.Path.PLUGIN)
        plugin_settings.bind(gs.PluginKey.EXPANDERS, self, 'expanders',
                             Gio.SettingsBindFlags.DEFAULT)

        # title, source, visible
        self.treestore = Gtk.TreeStore.new([str, GObject.Object, bool])
        self.treestore_filter = self.treestore.filter_new(root=None)
        self.treestore_filter.set_visible_column(2)

        self.set_model(self.treestore_filter)
        context = self.get_style_context()
        context.add_class(Gtk.STYLE_CLASS_SIDEBAR)
        self.set_headers_visible(False)

        # define the headers - not visible by default
        def define_category(text, category):
            local = self.treestore.append(None)
            self.treestore[local] = [text, None, False]
            self._category[category] = local

        define_category(_("Local collection"), AltControllerCategory.LOCAL)
        define_category(_("Online sources"), AltControllerCategory.ONLINE)
        define_category(_("Other sources"), AltControllerCategory.OTHER)
        define_category(_("Playlists"), AltControllerCategory.PLAYLIST)

        def delayed(*args):
            model = self.shell.props.display_page_model
            rootiter = model.get_iter_first()
            depth = 0
            self._traverse_rows(model, rootiter, None, depth)

            # switch on/off headers depending upon what's in the model
            self._refresh_headers()

            # tidy up syncing by connecting signals
            self._connect_signals()

            # now expand or collapse each expander that we have saved from a
            # previous session
            expanders = eval(self.expanders)

            print(expanders)
            print(self.expanders)
            for category in expanders:
                print(category)
                path = self.treestore.get_path(self._category[category])

                if path and expanders[category]:
                    # self._user_clicked = True
                    self.expand_row(path, False)  # expanders[category])

            return False

        GLib.timeout_add_seconds(1, delayed)

        column = Gtk.TreeViewColumn.new()
        column.set_fixed_width(5)
        column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
        self.append_column(column)

        column = Gtk.TreeViewColumn.new()

        pixbuf_renderer = Gtk.CellRendererPixbuf()
        column.pack_start(pixbuf_renderer, False)
        renderer = Gtk.CellRendererText()
        renderer.connect('edited', self.on_renderertext_edited)
        self.text_renderer = renderer
        column.pack_start(renderer, False)

        column.set_cell_data_func(pixbuf_renderer, self._set_pixbuf)
        column.set_cell_data_func(renderer, self._set_text)

        self.tree_column = column

        self.append_column(column)
        self.set_expander_column(column)
        self.show_all()
        self.set_can_focus(True)

        cl = CoverLocale()
        cl.switch_locale(cl.Locale.RB)
    def do_activate(self):
        """
        Called by Rhythmbox when the plugin is activated. It creates the
        plugin's source and connects signals to manage the plugin's
        preferences.
        """

        self.shell = self.object
        self.db = self.shell.props.db
        self.shell_player = self.shell.props.shell_player

        # Prepare internal variables
        self.song_duration = 0
        self.entry = None
        self._plugin_dialog_width = 760
        self._plugin_dialog_height = 550

        # locale stuff
        cl = CoverLocale()
        cl.switch_locale(cl.Locale.LOCALE_DOMAIN)

        # for custom icons ensure we start looking in the plugin img folder
        # as a fallback
        theme = Gtk.IconTheme.get_default()
        theme.append_search_path(rb.find_plugin_file(self, 'img'))

        # Find the Rhythmbox Toolbar
        self.rb_toolbar = AltToolbarPlugin.find(self.shell.props.window,
                                                'main-toolbar', 'by_id')

        # get values from gsettings
        self.gs = GSetting()
        self.plugin_settings = self.gs.get_setting(self.gs.Path.PLUGIN)

        display_type = self.plugin_settings[self.gs.PluginKey.DISPLAY_TYPE]
        self.volume_control = self.plugin_settings[
            self.gs.PluginKey.VOLUME_CONTROL]
        self.show_compact_toolbar = self.plugin_settings[
            self.gs.PluginKey.SHOW_COMPACT]
        self.start_hidden = self.plugin_settings[
            self.gs.PluginKey.START_HIDDEN]
        self.inline_label = self.plugin_settings[
            self.gs.PluginKey.INLINE_LABEL]
        self.compact_progressbar = self.plugin_settings[
            self.gs.PluginKey.COMPACT_PROGRESSBAR]
        self.enhanced_sidebar = self.plugin_settings[
            self.gs.PluginKey.ENHANCED_SIDEBAR]
        self.show_tooltips = self.plugin_settings[
            self.gs.PluginKey.SHOW_TOOLTIPS]
        self.enhanced_plugins = self.plugin_settings[
            self.gs.PluginKey.ENHANCED_PLUGINS]

        # Add the various application view menus
        self.appshell = ApplicationShell(self.shell)
        self._add_menu_options()

        # Determine what type of toolbar is to be displayed
        default = Gtk.Settings.get_default()

        if display_type == 0:
            if (
                    not default.props.gtk_shell_shows_app_menu) or \
                    default.props.gtk_shell_shows_menubar:
                display_type = 2
            else:
                display_type = 1

        self.toolbar_type = None
        if display_type == 1:
            self.toolbar_type = AltToolbarHeaderBar()
        elif self.show_compact_toolbar:
            self.toolbar_type = AltToolbarCompact()
        else:
            self.toolbar_type = AltToolbarStandard()

        self.toolbar_type.initialise(self)
        self.toolbar_type.post_initialise()

        if self.enhanced_plugins:
            # redirect plugins action to our implementation

            action = Gio.SimpleAction.new('plugins', None)
            action.connect('activate', self._display_plugins)
            self.shell.props.application.add_action(action)

        self._connect_signals()
        self._connect_properties()

        # allow other plugins access to this toolbar
        self.shell.alternative_toolbar = self

        cl.switch_locale(cl.Locale.RB)
class AltToolbarPlugin(GObject.Object, Peas.Activatable):
    """
    Main class of the plugin. Manages the activation and deactivation of the
    plugin.
    """
    __gtype_name = 'AltToolbarPlugin'
    object = GObject.property(type=GObject.Object)
    display_page_tree_visible = GObject.property(type=bool, default=False)
    show_album_art = GObject.property(type=bool, default=False)
    show_song_position_slider = GObject.property(type=bool, default=False)
    playing_label = GObject.property(type=bool, default=False)

    # signals
    # toolbar-visibility - bool parameter True = visible, False = not visible
    __gsignals__ = {
        'toolbar-visibility': (GObject.SIGNAL_RUN_LAST, None, (bool,))
    }

    def __init__(self):
        """
        Initialises the plugin object.
        """
        GObject.Object.__init__(self)
        self.appshell = None
        self.sh_psc = self.sh_op = self.sh_pc = None

    def do_activate(self):
        """
        Called by Rhythmbox when the plugin is activated. It creates the
        plugin's source and connects signals to manage the plugin's
        preferences.
        """

        self.shell = self.object
        self.db = self.shell.props.db
        self.shell_player = self.shell.props.shell_player

        # Prepare internal variables
        self.song_duration = 0
        self.entry = None
        self._plugin_dialog_width = 760
        self._plugin_dialog_height = 550

        # locale stuff
        cl = CoverLocale()
        cl.switch_locale(cl.Locale.LOCALE_DOMAIN)

        # for custom icons ensure we start looking in the plugin img folder
        # as a fallback
        theme = Gtk.IconTheme.get_default()
        theme.append_search_path(rb.find_plugin_file(self, 'img'))

        # Find the Rhythmbox Toolbar
        self.rb_toolbar = AltToolbarPlugin.find(self.shell.props.window,
                                                'main-toolbar', 'by_id')

        # get values from gsettings
        self.gs = GSetting()
        self.plugin_settings = self.gs.get_setting(self.gs.Path.PLUGIN)

        display_type = self.plugin_settings[self.gs.PluginKey.DISPLAY_TYPE]
        self.volume_control = self.plugin_settings[
            self.gs.PluginKey.VOLUME_CONTROL]
        self.show_compact_toolbar = self.plugin_settings[
            self.gs.PluginKey.SHOW_COMPACT]
        self.start_hidden = self.plugin_settings[
            self.gs.PluginKey.START_HIDDEN]
        self.inline_label = self.plugin_settings[
            self.gs.PluginKey.INLINE_LABEL]
        self.compact_progressbar = self.plugin_settings[
            self.gs.PluginKey.COMPACT_PROGRESSBAR]
        self.enhanced_sidebar = self.plugin_settings[
            self.gs.PluginKey.ENHANCED_SIDEBAR]
        self.show_tooltips = self.plugin_settings[
            self.gs.PluginKey.SHOW_TOOLTIPS]
        self.enhanced_plugins = self.plugin_settings[
            self.gs.PluginKey.ENHANCED_PLUGINS]

        # Add the various application view menus
        self.appshell = ApplicationShell(self.shell)
        self._add_menu_options()

        # Determine what type of toolbar is to be displayed
        default = Gtk.Settings.get_default()

        if display_type == 0:
            if (
                    not default.props.gtk_shell_shows_app_menu) or \
                    default.props.gtk_shell_shows_menubar:
                display_type = 2
            else:
                display_type = 1

        self.toolbar_type = None
        if display_type == 1:
            self.toolbar_type = AltToolbarHeaderBar()
        elif self.show_compact_toolbar:
            self.toolbar_type = AltToolbarCompact()
        else:
            self.toolbar_type = AltToolbarStandard()

        self.toolbar_type.initialise(self)
        self.toolbar_type.post_initialise()

        if self.enhanced_plugins:
            # redirect plugins action to our implementation

            action = Gio.SimpleAction.new('plugins', None)
            action.connect('activate', self._display_plugins)
            self.shell.props.application.add_action(action)

        self._connect_signals()
        self._connect_properties()

        # allow other plugins access to this toolbar
        self.shell.alternative_toolbar = self

        cl.switch_locale(cl.Locale.RB)

    def _display_plugins(self, *args):
        """
          display our implementation of the LibPeas Plugin window
        """

        has_headerbar = isinstance(self.toolbar_type, AltToolbarHeaderBar)

        if gtk_version() < 3.12:
            has_headerbar = False

        dlg = PluginDialog(self.shell.props.window, has_headerbar)
        response = 0
        dlg.set_default_size(self._plugin_dialog_width,
                             self._plugin_dialog_height)

        while response >= 0:
            response = dlg.run()
            print(response)

        self._plugin_dialog_width, self._plugin_dialog_height = dlg.get_size()
        dlg.destroy()

    def _add_menu_options(self):
        """
          add the various menu options to the application
        """
        self.seek_action_group = ActionGroup(self.shell,
                                             'AltToolbarPluginSeekActions')
        self.seek_action_group.add_action(func=self.on_skip_backward,
                                          action_name='SeekBackward',
                                          label=_("Seek Backward"),
                                          action_type='app', accel="<Alt>Left",
                                          tooltip=_(
                                              "Seek backward, in current "
                                              "track, by 5 seconds."))
        self.seek_action_group.add_action(func=self.on_skip_forward,
                                          action_name='SeekForward',
                                          label=_("Seek Forward"),
                                          action_type='app',
                                          accel="<Alt>Right",
                                          tooltip=_(
                                              "Seek forward, in current "
                                              "track, by 10 seconds."))

        self.appshell.insert_action_group(self.seek_action_group)
        self.appshell.add_app_menuitems(view_seek_menu_ui,
                                        'AltToolbarPluginSeekActions', 'view')

        self.toggle_action_group = ActionGroup(self.shell,
                                               'AltToolbarPluginActions')
        self.toggle_action_group.add_action(func=self.toggle_visibility,
                                            action_name='ToggleToolbar',
                                            label=_(
                                                "Show Play-Controls Toolbar"),
                                            action_state=ActionGroup.TOGGLE,
                                            action_type='app',
                                            tooltip=_(
                                                "Show or hide the "
                                                "play-controls toolbar"))
        self.toggle_action_group.add_action(
            func=self.toggle_sourcemedia_visibility,
            action_name='ToggleSourceMediaToolbar',
            label=_("Show Source Toolbar"),
            action_state=ActionGroup.TOGGLE,
            action_type='app', accel="<Ctrl>t",
            tooltip=_("Show or hide the source toolbar"))

        self.appshell.insert_action_group(self.toggle_action_group)
        self.appshell.add_app_menuitems(view_menu_ui,
                                        'AltToolbarPluginActions', 'view')

    def _connect_properties(self):
        """
          bind plugin properties to various gsettings that we dynamically
          interact with
        """
        self.plugin_settings.bind(self.gs.PluginKey.PLAYING_LABEL, self,
                                  'playing_label',
                                  Gio.SettingsBindFlags.GET)

    def _connect_signals(self):
        """
          connect to various rhythmbox signals that the toolbars need
        """
        self.sh_display_page_tree = self.shell.props.display_page_tree.connect(
            "selected", self.on_page_change
        )

        self.sh_psc = self.shell_player.connect("playing-song-changed",
                                                self._sh_on_song_change)

        self.sh_op = self.shell_player.connect("elapsed-changed",
                                               self._sh_on_playing)

        self.sh_pc = self.shell_player.connect("playing-changed",
                                               self._sh_on_playing_change)

        self.sh_pspc = self.shell_player.connect(
            "playing-song-property-changed",
            self._sh_on_song_property_changed)

        self.rb_settings = Gio.Settings.new('org.gnome.rhythmbox')

        self.rb_settings.bind('show-album-art', self, 'show_album_art',
                              Gio.SettingsBindFlags.GET)
        self.connect('notify::show-album-art',
                     self.show_album_art_settings_changed)
        self.show_album_art_settings_changed(None)

        self.rb_settings.bind('show-song-position-slider', self,
                              'show_song_position_slider',
                              Gio.SettingsBindFlags.GET)
        self.connect('notify::show-song-position-slider',
                     self.show_song_position_slider_settings_changed)
        self.show_song_position_slider_settings_changed(None)

    def _sh_on_song_property_changed(self, sp, uri, property, old, new):
        """
           shell-player "playing-song-property-changed" signal handler
        """
        if sp.get_playing() and property in \
                ('artist',
                 'album',
                 'title',
                 RB.RHYTHMDB_PROP_STREAM_SONG_ARTIST,
                 RB.RHYTHMDB_PROP_STREAM_SONG_ALBUM,
                 RB.RHYTHMDB_PROP_STREAM_SONG_TITLE):
            entry = sp.get_playing_entry()
            self.toolbar_type.display_song(entry)

    def _sh_on_playing_change(self, player, playing):
        """
           shell-player "playing-change" signal handler
        """
        self.toolbar_type.play_control_change(player, playing)

    def _sh_on_song_change(self, player, entry):
        """
           shell-player "playing-song-changed" signal handler
        """
        if (entry is not None):
            self.song_duration = entry.get_ulong(RB.RhythmDBPropType.DURATION)
        else:
            self.song_duration = 0

        self.toolbar_type.display_song(entry)

    def _sh_on_playing(self, player, second):
        """
           shell-player "elapsed-changed" signal handler
        """
        if not hasattr(self.toolbar_type, 'song_progress'):
            return

        if (self.song_duration != 0):
            self.toolbar_type.song_progress.progress = float(
                second) / self.song_duration

            print(self.toolbar_type.song_progress.progress)

            try:
                valid, time = player.get_playing_time()
                if not valid or time == 0:
                    return
            except:
                return

            m, s = divmod(time, 60)
            h, m = divmod(m, 60)

            tm, ts = divmod(self.song_duration, 60)
            th, tm = divmod(tm, 60)

            if th == 0:
                label = "<small>{time} / {ttime}</small>".format(
                    time="%02d:%02d" % (m, s),
                    ttime="%02d:%02d" % (tm, ts))
            else:
                label = "<small>{time}</small>".format(
                    time="%d:%02d:%02d" % (h, m, s))

            self.toolbar_type.total_time_label.set_markup(label)

    def on_skip_backward(self, *args):
        """
           keyboard seek backwards signal handler
        """
        sp = self.object.props.shell_player
        if (sp.get_playing()[1]):
            seek_time = sp.get_playing_time()[1] - seek_backward_time
            print(seek_time)
            if (seek_time < 0):
                seek_time = 0

            print(seek_time)
            sp.set_playing_time(seek_time)

    def on_skip_forward(self, *args):
        """
           keyboard seek forwards signal handler
        """
        sp = self.object.props.shell_player
        if (sp.get_playing()[1]):
            seek_time = sp.get_playing_time()[1] + seek_forward_time
            song_duration = sp.get_playing_song_duration()
            if (song_duration > 0):  # sanity check
                if (seek_time > song_duration):
                    seek_time = song_duration

                sp.set_playing_time(seek_time)

    def show_song_position_slider_settings_changed(self, *args):
        """
           rhythmbox show-slider signal handler
        """
        self.toolbar_type.show_slider(self.show_song_position_slider)

    def show_album_art_settings_changed(self, *args):
        """
           rhythmbox show-album-art signal handler
        """
        self.toolbar_type.show_cover(self.show_album_art)

    def on_page_change(self, display_page_tree, page):
        """
           sources display-tree signal handler
        """
        print("page changed", page)
        self.toolbar_type.reset_toolbar(page)

    @staticmethod
    def find(node, search_id, search_type, button_label=None):
        """
        find various GTK Widgets
        :param node: node is the starting container to find from
        :param search_id: search_id is the GtkWidget type string or
        GtkWidget name
        :param search_type: search_type is the type of search
                            "by_name" to search by the type of GtkWidget
                            e.g. GtkButton
                            "by_id" to search by the GtkWidget (glade name)
                            e.g. box_1
        :param button_label: button_label to find specific buttons where we
        cannot use by_id
        :return:N/A
        """
        # Couldn't find better way to find widgets than loop through them
        # print("by_name %s by_id %s" % (node.get_name(),
        # Gtk.Buildable.get_name(node)))

        def extract_label(button):
            label = button.get_label()
            if label:
                return label

            child = button.get_child()
            if child and child.get_name() == "GtkLabel":
                return child.get_text()

            return None

        if isinstance(node, Gtk.Buildable):
            if search_type == 'by_id':
                if Gtk.Buildable.get_name(node) == search_id:
                    if button_label is None or \
                            ('Button' in node.get_name()
                             and extract_label(node) == button_label):
                        return node
            elif search_type == 'by_name':
                if node.get_name() == search_id:
                    if button_label is None or \
                            ('Button' in node.get_name()
                             and extract_label(node) == button_label):
                        return node

        if isinstance(node, Gtk.Container):
            for child in node.get_children():
                ret = AltToolbarPlugin.find(child, search_id, search_type,
                                            button_label)
                if ret:
                    return ret

        return None

    def do_deactivate(self):
        """
        Called by Rhythmbox when the plugin is deactivated. It makes sure to
        free all the resources used by the plugin.
        """
        del self.db

        if self.sh_op:
            self.shell_player.disconnect(self.sh_op)
            self.shell_player.disconnect(self.sh_psc)
            self.shell_player.disconnect(self.sh_pc)
            self.shell_player.disconnect(self.sh_pspc)
            # self.disconnect(self.sh_display_page)
            self.shell.props.display_page_tree.disconnect(
                self.sh_display_page_tree)
            del self.shell_player

        if self.appshell:
            self.appshell.cleanup()

        self.rb_toolbar.set_visible(True)

        self.toolbar_type.cleanup()

        del self.shell

    def toggle_visibility(self, action, param=None, data=None):
        """
        Display or Hide PlayControls signal handler
        :param action:
        :param param:
        :param data:
        :return:
        """
        action = self.toggle_action_group.get_action('ToggleToolbar')

        self.toolbar_type.set_visible(action.get_active())

    def toggle_sourcemedia_visibility(self, action, param=None, data=None):
        """
        Display or Hide the source toolbar
        :param action:
        :param param:
        :param data:
        :return:
        """
        action = self.toggle_action_group.get_action(
            'ToggleSourceMediaToolbar')

        self.toolbar_type.source_toolbar_visibility(action.get_active())

    def _translation_helper(self):
        """
        a method just to help out with translation strings
        it is not meant to be called by itself
        """

        # define .plugin text strings used for translation
        plugin = _('Alternative Toolbar')
        plugin += "dummy"
        desc = _(
            'Replace the Rhythmbox large toolbar with a Client-Side '
            'Decorated or Compact Toolbar which can be hidden')

        desc += "dummy"
        # stop PyCharm removing the Preference import on optimisation
        pref = Preferences()
        return pref
    def do_activate(self):
        """
        Called by Rhythmbox when the plugin is activated. It creates the
        plugin's source and connects signals to manage the plugin's
        preferences.
        """

        self.shell = self.object
        self.db = self.shell.props.db
        self.shell_player = self.shell.props.shell_player

        # Prepare internal variables
        self.song_duration = 0
        self.entry = None
        self._plugin_dialog_width = 760
        self._plugin_dialog_height = 550

        # locale stuff
        cl = CoverLocale()
        cl.switch_locale(cl.Locale.LOCALE_DOMAIN)

        # for custom icons ensure we start looking in the plugin img folder
        # as a fallback
        theme = Gtk.IconTheme.get_default()
        theme.append_search_path(rb.find_plugin_file(self, 'img'))

        # Find the Rhythmbox Toolbar
        self.rb_toolbar = AltToolbarPlugin.find(self.shell.props.window,
                                                'main-toolbar', 'by_id')

        # get values from gsettings
        self.gs = GSetting()
        self.plugin_settings = self.gs.get_setting(self.gs.Path.PLUGIN)

        display_type = self.plugin_settings[self.gs.PluginKey.DISPLAY_TYPE]
        self.volume_control = self.plugin_settings[
            self.gs.PluginKey.VOLUME_CONTROL]
        self.show_compact_toolbar = self.plugin_settings[
            self.gs.PluginKey.SHOW_COMPACT]
        self.start_hidden = self.plugin_settings[
            self.gs.PluginKey.START_HIDDEN]
        self.inline_label = self.plugin_settings[
            self.gs.PluginKey.INLINE_LABEL]
        self.enhanced_sidebar = self.plugin_settings[
            self.gs.PluginKey.ENHANCED_SIDEBAR]
        self.show_tooltips = self.plugin_settings[
            self.gs.PluginKey.SHOW_TOOLTIPS]
        self.enhanced_plugins = self.plugin_settings[
            self.gs.PluginKey.ENHANCED_PLUGINS]
        self.horiz_categories = self.plugin_settings[
            self.gs.PluginKey.HORIZ_CATEGORIES]
        self.app_menu = self.plugin_settings[self.gs.PluginKey.APP_MENU]
        self.prefer_dark_theme = \
            self.plugin_settings[self.gs.PluginKey.DARK_THEME]

        # Add the various application view menus
        self.appshell = ApplicationShell(self.shell)
        self._add_menu_options()

        # Determine what type of toolbar is to be displayed
        default = Gtk.Settings.get_default()

        if display_type == 0:
            if (
                    not default.props.gtk_shell_shows_app_menu) or \
                    default.props.gtk_shell_shows_menubar:
                display_type = 2
            else:
                display_type = 1

        self.toolbar_type = None
        if display_type == 1:
            self.toolbar_type = AltToolbarHeaderBar()
        elif self.show_compact_toolbar:
            self.toolbar_type = AltToolbarCompact()
        else:
            self.toolbar_type = AltToolbarStandard()

        self.toolbar_type.initialise(self)
        self.toolbar_type.post_initialise()

        if self.enhanced_plugins:
            # redirect plugins action to our implementation

            action = Gio.SimpleAction.new('plugins', None)
            action.connect('activate', self._display_plugins)
            self.shell.props.application.add_action(action)

        self._connect_signals()
        self._connect_properties()

        # allow other plugins access to this toolbar
        self.shell.alternative_toolbar = self

        cl.switch_locale(cl.Locale.RB)
class AltToolbarPlugin(GObject.Object, Peas.Activatable):
    """
    Main class of the plugin. Manages the activation and deactivation of the
    plugin.
    """
    __gtype_name = 'AltToolbarPlugin'
    object = GObject.property(type=GObject.Object)
    display_page_tree_visible = GObject.property(type=bool, default=False)
    show_album_art = GObject.property(type=bool, default=False)
    show_song_position_slider = GObject.property(type=bool, default=False)
    playing_label = GObject.property(type=bool, default=False)

    # signals
    # toolbar-visibility - bool parameter True = visible, False = not visible
    __gsignals__ = {
        'toolbar-visibility': (GObject.SIGNAL_RUN_LAST, None, (bool, ))
    }

    def __init__(self):
        """
        Initialises the plugin object.
        """
        GObject.Object.__init__(self)
        self.appshell = None
        self.sh_psc = self.sh_op = self.sh_pc = None

    def do_activate(self):
        """
        Called by Rhythmbox when the plugin is activated. It creates the
        plugin's source and connects signals to manage the plugin's
        preferences.
        """

        self.shell = self.object
        self.db = self.shell.props.db
        self.shell_player = self.shell.props.shell_player

        # Prepare internal variables
        self.song_duration = 0
        self.entry = None
        self._plugin_dialog_width = 760
        self._plugin_dialog_height = 550

        # locale stuff
        cl = CoverLocale()
        cl.switch_locale(cl.Locale.LOCALE_DOMAIN)

        # for custom icons ensure we start looking in the plugin img folder
        # as a fallback
        theme = Gtk.IconTheme.get_default()
        theme.append_search_path(rb.find_plugin_file(self, 'img'))

        # Find the Rhythmbox Toolbar
        self.rb_toolbar = AltToolbarPlugin.find(self.shell.props.window,
                                                'main-toolbar', 'by_id')

        # get values from gsettings
        self.gs = GSetting()
        self.plugin_settings = self.gs.get_setting(self.gs.Path.PLUGIN)

        display_type = self.plugin_settings[self.gs.PluginKey.DISPLAY_TYPE]
        self.volume_control = self.plugin_settings[
            self.gs.PluginKey.VOLUME_CONTROL]
        self.show_compact_toolbar = self.plugin_settings[
            self.gs.PluginKey.SHOW_COMPACT]
        self.start_hidden = self.plugin_settings[
            self.gs.PluginKey.START_HIDDEN]
        self.inline_label = self.plugin_settings[
            self.gs.PluginKey.INLINE_LABEL]
        self.enhanced_sidebar = self.plugin_settings[
            self.gs.PluginKey.ENHANCED_SIDEBAR]
        self.show_tooltips = self.plugin_settings[
            self.gs.PluginKey.SHOW_TOOLTIPS]
        self.enhanced_plugins = self.plugin_settings[
            self.gs.PluginKey.ENHANCED_PLUGINS]
        self.horiz_categories = self.plugin_settings[
            self.gs.PluginKey.HORIZ_CATEGORIES]
        self.app_menu = self.plugin_settings[self.gs.PluginKey.APP_MENU]
        self.prefer_dark_theme = \
            self.plugin_settings[self.gs.PluginKey.DARK_THEME]

        # Add the various application view menus
        self.appshell = ApplicationShell(self.shell)
        self._add_menu_options()

        # Determine what type of toolbar is to be displayed
        default = Gtk.Settings.get_default()

        if display_type == 0:
            if (
                    not default.props.gtk_shell_shows_app_menu) or \
                    default.props.gtk_shell_shows_menubar:
                display_type = 2
            else:
                display_type = 1

        self.toolbar_type = None
        if display_type == 1:
            self.toolbar_type = AltToolbarHeaderBar()
        elif self.show_compact_toolbar:
            self.toolbar_type = AltToolbarCompact()
        else:
            self.toolbar_type = AltToolbarStandard()

        self.toolbar_type.initialise(self)
        self.toolbar_type.post_initialise()

        if self.enhanced_plugins:
            # redirect plugins action to our implementation

            action = Gio.SimpleAction.new('plugins', None)
            action.connect('activate', self._display_plugins)
            self.shell.props.application.add_action(action)

        self._connect_signals()
        self._connect_properties()

        # allow other plugins access to this toolbar
        self.shell.alternative_toolbar = self

        cl.switch_locale(cl.Locale.RB)

    def _display_plugins(self, *args):
        """
          display our implementation of the LibPeas Plugin window
        """

        has_headerbar = isinstance(self.toolbar_type, AltToolbarHeaderBar)

        if gtk_version() < 3.12:
            has_headerbar = False

        dlg = PluginDialog(self.shell.props.window, has_headerbar)
        response = 0
        dlg.set_default_size(self._plugin_dialog_width,
                             self._plugin_dialog_height)

        while response >= 0:
            response = dlg.run()
            print(response)

        self._plugin_dialog_width, self._plugin_dialog_height = dlg.get_size()
        dlg.destroy()

    def _add_menu_options(self):
        """
          add the various menu options to the application
        """
        self.seek_action_group = ActionGroup(self.shell,
                                             'AltToolbarPluginSeekActions')
        self.seek_action_group.add_action(func=self.on_skip_backward,
                                          action_name='SeekBackward',
                                          label=_("Seek Backward"),
                                          action_type='app',
                                          accel="<Alt>Left",
                                          tooltip=_(
                                              "Seek backward, in current "
                                              "track, by 5 seconds."))
        self.seek_action_group.add_action(func=self.on_skip_forward,
                                          action_name='SeekForward',
                                          label=_("Seek Forward"),
                                          action_type='app',
                                          accel="<Alt>Right",
                                          tooltip=_("Seek forward, in current "
                                                    "track, by 10 seconds."))

        self.appshell.insert_action_group(self.seek_action_group)
        self.appshell.add_app_menuitems(view_seek_menu_ui,
                                        'AltToolbarPluginSeekActions', 'view')

        self.toggle_action_group = ActionGroup(self.shell,
                                               'AltToolbarPluginActions')
        self.toggle_action_group.add_action(
            func=self.toggle_visibility,
            action_name='ToggleToolbar',
            label=_("Show Play-Controls Toolbar"),
            action_state=ActionGroup.TOGGLE,
            action_type='app',
            tooltip=_("Show or hide the "
                      "play-controls toolbar"))
        self.toggle_action_group.add_action(
            func=self.toggle_sourcemedia_visibility,
            action_name='ToggleSourceMediaToolbar',
            label=_("Show Source Toolbar"),
            action_state=ActionGroup.TOGGLE,
            action_type='app',
            accel="<Ctrl>t",
            tooltip=_("Show or hide the source toolbar"))

        self.appshell.insert_action_group(self.toggle_action_group)
        self.appshell.add_app_menuitems(view_menu_ui,
                                        'AltToolbarPluginActions', 'view')

    def _connect_properties(self):
        """
          bind plugin properties to various gsettings that we dynamically
          interact with
        """
        self.plugin_settings.bind(self.gs.PluginKey.PLAYING_LABEL, self,
                                  'playing_label', Gio.SettingsBindFlags.GET)

    def _connect_signals(self):
        """
          connect to various rhythmbox signals that the toolbars need
        """
        self.sh_display_page_tree = self.shell.props.display_page_tree.connect(
            "selected", self.on_page_change)

        self.sh_psc = self.shell_player.connect("playing-song-changed",
                                                self._sh_on_song_change)

        self.sh_op = self.shell_player.connect("elapsed-changed",
                                               self._sh_on_playing)

        self.sh_pc = self.shell_player.connect("playing-changed",
                                               self._sh_on_playing_change)

        self.sh_pspc = self.shell_player.connect(
            "playing-song-property-changed", self._sh_on_song_property_changed)

        self.rb_settings = Gio.Settings.new('org.gnome.rhythmbox')

        self.rb_settings.bind('show-album-art', self, 'show_album_art',
                              Gio.SettingsBindFlags.GET)
        self.connect('notify::show-album-art',
                     self.show_album_art_settings_changed)
        self.show_album_art_settings_changed(None)

        self.rb_settings.bind('show-song-position-slider', self,
                              'show_song_position_slider',
                              Gio.SettingsBindFlags.GET)
        self.connect('notify::show-song-position-slider',
                     self.show_song_position_slider_settings_changed)
        self.show_song_position_slider_settings_changed(None)

    def _sh_on_song_property_changed(self, sp, uri, property, old, new):
        """
           shell-player "playing-song-property-changed" signal handler
        """
        if sp.get_playing() and property in \
                ('artist',
                 'album',
                 'title',
                 RB.RHYTHMDB_PROP_STREAM_SONG_ARTIST,
                 RB.RHYTHMDB_PROP_STREAM_SONG_ALBUM,
                 RB.RHYTHMDB_PROP_STREAM_SONG_TITLE):
            entry = sp.get_playing_entry()
            self.toolbar_type.display_song(entry)

    def _sh_on_playing_change(self, player, playing):
        """
        Shell-player 'playing-change' signal handler.
        """
        self.toolbar_type.play_control_change(player, playing)
        if (self.song_duration != 0):
            self.toolbar_type.enable_slider(True)
        else:
            self.toolbar_type.enable_slider(False)
            if (hasattr(self.toolbar_type, "total_time_label")):
                label = ""
                self.toolbar_type.total_time_label.set_markup(label)

    def _sh_on_song_change(self, player, entry):
        """
        Shell-player 'playing-song-changed' signal handler.
        """
        if (entry is not None):
            self.song_duration = entry.get_ulong(RB.RhythmDBPropType.DURATION)
        else:
            self.song_duration = 0

        if hasattr(self.toolbar_type, 'song_progress'):
            self.toolbar_type.song_progress.adjustment.set_upper(
                self.song_duration or 1)
        self.toolbar_type.display_song(entry)

    def _sh_on_playing(self, player, seconds):
        """
        Shell-player 'elapsed-changed' signal handler.
        """
        if self.song_duration == 0:
            return
        try:
            slider = self.toolbar_type.song_progress
        except AttributeError:
            return
        with slider.handler_block(slider.changed_callback_id):
            slider.adjustment.set_value(seconds)

        minutes, seconds = divmod(seconds, 60)
        hours, minutes = divmod(minutes, 60)
        total_minutes, total_seconds = divmod(self.song_duration, 60)
        total_hours, total_minutes = divmod(total_minutes, 60)

        if total_hours:
            label = "<small>{}:{:02}:{:02} / {}:{:02}:{:02}</small>".format(
                hours, minutes, seconds, total_hours, total_minutes,
                total_seconds)
        else:
            label = "<small>{:02}:{:02} / {:02}:{:02}</small>".format(
                minutes, seconds, total_minutes, total_seconds)
        self.toolbar_type.total_time_label.set_markup(label)

    def on_skip_backward(self, *args):
        """
           keyboard seek backwards signal handler
        """
        sp = self.object.props.shell_player
        if (sp.get_playing()[1]):
            seek_time = sp.get_playing_time()[1] - seek_backward_time
            print(seek_time)
            if (seek_time < 0):
                seek_time = 0

            print(seek_time)
            sp.set_playing_time(seek_time)

    def on_skip_forward(self, *args):
        """
           keyboard seek forwards signal handler
        """
        sp = self.object.props.shell_player
        if (sp.get_playing()[1]):
            seek_time = sp.get_playing_time()[1] + seek_forward_time
            song_duration = sp.get_playing_song_duration()
            if (song_duration > 0):  # sanity check
                if (seek_time > song_duration):
                    seek_time = song_duration

                sp.set_playing_time(seek_time)

    def show_song_position_slider_settings_changed(self, *args):
        """
           rhythmbox show-slider signal handler
        """
        self.toolbar_type.show_slider(self.show_song_position_slider)

    def show_album_art_settings_changed(self, *args):
        """
           rhythmbox show-album-art signal handler
        """
        self.toolbar_type.show_cover(self.show_album_art)

    def on_page_change(self, display_page_tree, page):
        """
           sources display-tree signal handler
        """
        print("page changed", page)
        self.toolbar_type.reset_categories_pos(page)
        self.toolbar_type.reset_toolbar(page)
        self.toolbar_type.reset_entryview(page)

    @staticmethod
    def find(node, search_id, search_type, button_label=None):
        """
        find various GTK Widgets
        :param node: node is the starting container to find from
        :param search_id: search_id is the GtkWidget type string or
        GtkWidget name
        :param search_type: search_type is the type of search
                            "by_name" to search by the type of GtkWidget
                            e.g. GtkButton
                            "by_id" to search by the GtkWidget (glade name)
                            e.g. box_1
        :param button_label: button_label to find specific buttons where we
        cannot use by_id
        :return:N/A
        """

        # Couldn't find better way to find widgets than loop through them
        # print("by_name %s by_id %s" % (node.get_name(),
        # Gtk.Buildable.get_name(node)))

        def extract_label(button):
            label = button.get_label()
            if label:
                return label

            child = button.get_child()
            if child and child.get_name() == "GtkLabel":
                return child.get_text()

            return None

        if isinstance(node, Gtk.Buildable):
            if search_type == 'by_id':
                if Gtk.Buildable.get_name(node) == search_id:
                    if button_label is None or ('Button' in node.get_name()
                                                and extract_label(node)
                                                == button_label):
                        return node
            elif search_type == 'by_name':
                if node.get_name() == search_id:
                    if button_label is None or ('Button' in node.get_name()
                                                and extract_label(node)
                                                == button_label):
                        return node

        if isinstance(node, Gtk.Container):
            for child in node.get_children():
                ret = AltToolbarPlugin.find(child, search_id, search_type,
                                            button_label)
                if ret:
                    return ret

        return None

    def do_deactivate(self):
        """
        Called by Rhythmbox when the plugin is deactivated. It makes sure to
        free all the resources used by the plugin.
        """
        del self.db

        if self.sh_op:
            self.shell_player.disconnect(self.sh_op)
            self.shell_player.disconnect(self.sh_psc)
            self.shell_player.disconnect(self.sh_pc)
            self.shell_player.disconnect(self.sh_pspc)
            # self.disconnect(self.sh_display_page)
            self.shell.props.display_page_tree.disconnect(
                self.sh_display_page_tree)
            del self.shell_player

        if self.appshell:
            self.appshell.cleanup()

        self.rb_toolbar.set_visible(True)

        self.toolbar_type.cleanup()

        del self.shell

    def toggle_visibility(self, action, param=None, data=None):
        """
        Display or Hide PlayControls signal handler
        :param action:
        :param param:
        :param data:
        :return:
        """
        action = self.toggle_action_group.get_action('ToggleToolbar')

        self.toolbar_type.set_visible(action.get_active())

    def toggle_sourcemedia_visibility(self, action, param=None, data=None):
        """
        Display or Hide the source toolbar
        :param action:
        :param param:
        :param data:
        :return:
        """
        action = self.toggle_action_group.get_action(
            'ToggleSourceMediaToolbar')

        self.toolbar_type.source_toolbar_visibility(action.get_active())

    def _translation_helper(self):
        """
        a method just to help out with translation strings
        it is not meant to be called by itself
        """

        # define .plugin text strings used for translation
        plugin = _('Alternative Toolbar')
        plugin += "dummy"
        desc = _('Replace the Rhythmbox large toolbar with a Client-Side '
                 'Decorated or Compact Toolbar which can be hidden')

        desc += "dummy"
        # stop PyCharm removing the Preference import on optimisation
        pref = Preferences()
        return pref

    def get_toolbar(self, callback):
        """
        a method to return the toolbar itself
        :param callback: function callback - func(AT.ToolbarCallback)
        passed
        :return:
        """

        self.toolbar_type.setup_completed_async(callback)
    def do_activate(self):
        """
        Called by Rhythmbox when the plugin is activated. It creates the
        plugin's source and connects signals to manage the plugin's
        preferences.
        """

        self.shell = self.object
        self.db = self.shell.props.db
        self.shell_player = self.shell.props.shell_player

        # Prepare internal variables
        self.song_duration = 0
        self.entry = None
        self._plugin_dialog_width = 760
        self._plugin_dialog_height = 550

        # locale stuff
        cl = CoverLocale()
        cl.switch_locale(cl.Locale.LOCALE_DOMAIN)

        # for custom icons ensure we start looking in the plugin img folder
        # as a fallback
        theme = Gtk.IconTheme.get_default()
        theme.append_search_path(rb.find_plugin_file(self, 'img'))

        # Find the Rhythmbox Toolbar
        self.rb_toolbar = AltToolbarPlugin.find(self.shell.props.window,
                                                'main-toolbar', 'by_id')

        # get values from gsettings
        self.gs = GSetting()
        self.plugin_settings = self.gs.get_setting(self.gs.Path.PLUGIN)

        display_type = self.plugin_settings[self.gs.PluginKey.DISPLAY_TYPE]
        self.volume_control = self.plugin_settings[
            self.gs.PluginKey.VOLUME_CONTROL]
        self.show_compact_toolbar = self.plugin_settings[
            self.gs.PluginKey.SHOW_COMPACT]
        self.start_hidden = self.plugin_settings[
            self.gs.PluginKey.START_HIDDEN]
        self.inline_label = self.plugin_settings[
            self.gs.PluginKey.INLINE_LABEL]
        self.enhanced_sidebar = self.plugin_settings[
            self.gs.PluginKey.ENHANCED_SIDEBAR]
        self.show_tooltips = self.plugin_settings[
            self.gs.PluginKey.SHOW_TOOLTIPS]
        self.enhanced_plugins = self.plugin_settings[
            self.gs.PluginKey.ENHANCED_PLUGINS]
        self.horiz_categories = self.plugin_settings[
            self.gs.PluginKey.HORIZ_CATEGORIES]
        self.app_menu = self.plugin_settings[
            self.gs.PluginKey.APP_MENU]
        self.prefer_dark_theme = \
            self.plugin_settings[self.gs.PluginKey.DARK_THEME]

        # Add the various application view menus
        self.appshell = ApplicationShell(self.shell)
        self._add_menu_options()

        # Determine what type of toolbar is to be displayed
        if display_type == 0:
            if 'gnome' in os.environ['XDG_CURRENT_DESKTOP'].lower():
                display_type = 1
            else:
                display_type = 2

            self.plugin_settings[self.gs.PluginKey.DISPLAY_TYPE] = display_type

        self.toolbar_type = None
        if display_type == 1:
            self.toolbar_type = AltToolbarHeaderBar()
        elif self.show_compact_toolbar:
            self.toolbar_type = AltToolbarCompact()
        else:
            self.toolbar_type = AltToolbarStandard()

        self.toolbar_type.initialise(self)
        self.toolbar_type.post_initialise()

        try:
            process = Gio.Subprocess.new(['rhythmbox', '--version'],
                Gio.SubprocessFlags.STDOUT_PIPE)
            passval, buf, err = process.communicate_utf8(None)

            if passval:
                buf = buf[:-1]
                ver = buf.split(' ')[1]
        except:
            ver = "999.99.99"

        if self.enhanced_plugins and ver <= "3.4.3":
            # redirect plugins action to our implementation
            # after v3.4.3 plugins has been moved into
            # preferences so no need to activate our own
            # implementation

            action = Gio.SimpleAction.new('plugins', None)
            action.connect('activate', self._display_plugins)
            self.shell.props.application.add_action(action)

        self._connect_signals()
        self._connect_properties()

        # allow other plugins access to this toolbar
        self.shell.alternative_toolbar = self

        cl.switch_locale(cl.Locale.RB)