コード例 #1
0
    def __init__(self, shell, plugin, source, entry_view_grid, viewmgr):
        self.gs = GSetting()

        self.entry_view_grid = entry_view_grid
        self.shell = shell
        self.viewmgr = viewmgr
        self.plugin = plugin
        self.source = source

        # setup entry-view objects and widgets
        self.stack = Gtk.Stack()
        self.stack.set_transition_type(
            Gtk.StackTransitionType.SLIDE_LEFT_RIGHT)
        self.stack.set_transition_duration(750)

        # create entry views. Don't allow to reorder until the load is finished
        self.entry_view_compact = CoverArtCompactEntryView(
            self.shell, self.source)
        self.entry_view_full = CoverArtEntryView(self.shell, self.source)
        self.entry_view = self.entry_view_compact
        self.shell.props.library_source.get_entry_view().set_columns_clickable(
            False)

        self.entry_view_results = ResultsGrid()
        self.entry_view_results.initialise(self.entry_view_grid, source)

        self.stack.add_titled(self.entry_view_results, "notebook_tracks",
                              _("Tracks"))
        self.entry_view_grid.attach(self.stack, 0, 0, 3, 1)
コード例 #2
0
    def __init__(self, *args, **kwargs):
        '''
        Initializes the button.
        '''
        Gtk.RadioButton.__init__(self, *args, **kwargs)
        OptionsWidget.__init__(self, *args, **kwargs)

        gs = GSetting()
        setting = gs.get_setting(gs.Path.PLUGIN)
        setting.bind(gs.PluginKey.BUTTON_RELIEF, self,
                     'button_relief', Gio.SettingsBindFlags.GET)

        self.connect('notify::button-relief',
                     self.on_notify_button_relief)

        # initialise some variables
        self.image_display = False
        self.initialised = False

        # ensure button appearance rather than standard radio toggle
        self.set_mode(False)

        #label colours
        self._not_active_colour = None
        self._active_colour = None
コード例 #3
0
    def sort(self):

        albums = SortedCollection(key=lambda album: getattr(album, 'name'))

        gs = GSetting()
        source_settings = gs.get_setting(gs.Path.PLUGIN)
        key = source_settings[gs.PluginKey.SORT_BY_ARTIST]
        order = source_settings[gs.PluginKey.SORT_ORDER_ARTIST]

        sort_keys = {
            'name_artist': ('album_sort', 'album_sort'),
            'year_artist': ('real_year', 'calc_year_sort'),
            'rating_artist': ('rating', 'album_sort')
        }

        props = sort_keys[key]

        def key_function(album):
            keys = [getattr(album, prop) for prop in props]
            return keys

        # remember the current sort then remove the sort order
        # because sorting will only work in unsorted lists
        sortSettings = self.store.get_sort_column_id()

        self.store.set_sort_column_id(-1, Gtk.SortType.ASCENDING)

        for artist in self._iters:
            albums.clear()
            albums.key = key_function

            if 'album' in self._iters[artist] and len(
                    self._iters[artist]['album']) > 1:
                # we only need to sort an artists albums if there is more than one album

                # sort all the artists albums
                for album_iter in self._iters[artist]['album']:
                    albums.insert(self._tree_store[album_iter][
                        self.columns['artist_album']])

                if not order:
                    albums = reversed(albums)

                # now we iterate through the sorted artist albums.  Look and swap iters
                # according to where they are in the tree store

                artist_iter = self._iters[artist]['iter']
                next_iter = self._tree_store.iter_children(artist_iter)

                for album in albums:
                    if self._tree_store[next_iter][
                            self.columns['artist_album']] != album:
                        self._tree_store.swap(next_iter,
                                              self._albumiters[album]['iter'])
                        next_iter = self._albumiters[album]['iter']
                    next_iter = self._tree_store.iter_next(next_iter)

        # now we have finished sorting, reapply the sort
        if sortSettings[0]:
            self.store.set_sort_column_id(*sortSettings)
コード例 #4
0
    def __init__(self, plugin, viewmgr):
        super(ArtistSortPopupController, self).__init__()

        self._viewmgr = viewmgr
        self.plugin = plugin
        # sorts dictionary
        cl = CoverLocale()
        cl.switch_locale(cl.Locale.LOCALE_DOMAIN)

        self.values = OrderedDict([(_('Sort by album name'), 'name_artist'),
                                   (_('Sort by year'), 'year_artist'),
                                   (_('Sort by rating'), 'rating_artist')])

        self.options = list(self.values.keys())

        # get the current sort key and initialise the superclass
        gs = GSetting()
        source_settings = gs.get_setting(gs.Path.PLUGIN)
        value = source_settings[gs.PluginKey.SORT_BY_ARTIST]

        if value not in list(self.values.values()):
            print("here")
            value = 'name_artist'
            source_settings[gs.PluginKey.SORT_BY_ARTIST] = value

        self._spritesheet = None
        self.update_images(False)

        self.current_key = list(self.values.keys())[
            list(self.values.values()).index(value)]
        print(self.current_key)
コード例 #5
0
    def display_columns(self):

        self.col_map = OrderedDict([
            ('track-number', RB.EntryViewColumn.TRACK_NUMBER),
            ('title', RB.EntryViewColumn.TITLE),
            ('genre', RB.EntryViewColumn.GENRE),
            ('artist', RB.EntryViewColumn.ARTIST),
            ('album', RB.EntryViewColumn.ALBUM),
            ('composer', RB.EntryViewColumn.COMPOSER),
            ('date', RB.EntryViewColumn.YEAR),
            ('duration', RB.EntryViewColumn.DURATION),
            ('bitrate', RB.EntryViewColumn.QUALITY),
            ('play-count', RB.EntryViewColumn.PLAY_COUNT),
            ('beats-per-minute', RB.EntryViewColumn.BPM),
            ('comment', RB.EntryViewColumn.COMMENT),
            ('location', RB.EntryViewColumn.LOCATION),
            ('rating', RB.EntryViewColumn.RATING),
            ('last-played', RB.EntryViewColumn.LAST_PLAYED),
            ('first-seen', RB.EntryViewColumn.FIRST_SEEN)
        ])

        for entry in self.col_map:
            visible = True if entry == 'title' else False
            self.append_column(self.col_map[entry], visible)

        # connect the visible-columns global setting to update our entryview
        gs = GSetting()
        rhythm_settings = gs.get_setting(gs.Path.RBSOURCE)
        rhythm_settings.connect('changed::visible-columns',
                                self.on_visible_columns_changed)
        self.on_visible_columns_changed(rhythm_settings, 'visible-columns')
コード例 #6
0
    def __init__(self, plugin, album_model):
        super(SortPopupController, self).__init__()

        self._album_model = album_model
        self.plugin = plugin
        # sorts dictionary
        cl = CoverLocale()
        cl.switch_locale(cl.Locale.LOCALE_DOMAIN)

        self.values = OrderedDict([(_('Sort by album name'), 'name'),
                                   (_('Sort by album artist'), 'artist'),
                                   (_('Sort by year'), 'year'),
                                   (_('Sort by rating'), 'rating')])

        self.options = self.values.keys()

        # get the current sort key and initialise the superclass
        gs = GSetting()
        source_settings = gs.get_setting(gs.Path.PLUGIN)
        value = source_settings[gs.PluginKey.SORT_BY]

        self._spritesheet = None
        self.update_images(False)

        self.current_key = self.values.keys()[self.values.values().index(
            value)]
コード例 #7
0
    def do_action(self):
        sort = self.values[self.current_key]

        gs = GSetting()
        settings = gs.get_setting(gs.Path.PLUGIN)
        settings[gs.PluginKey.SORT_BY_ARTIST] = sort

        self._viewmgr.current_view.get_default_manager().emit('sort', "artist")
コード例 #8
0
    def do_action(self):
        sort = self.values[self.current_key]

        gs = GSetting()
        settings = gs.get_setting(gs.Path.PLUGIN)
        settings[gs.PluginKey.SORT_BY] = sort

        self._album_model.sort(sort)
コード例 #9
0
 def __init__(self, *args, **kwargs):
     super(ArtistView, self).__init__(*args, **kwargs)
     
     self._external_plugins = None
     self.gs = GSetting()
     self.show_policy = ArtistShowingPolicy(self)
     self.view = self
     self._has_initialised = False        
     self._last_row_was_artist = False
コード例 #10
0
    def __init__(self, *args, **kwargs):
        super(EnhancedButton, self).__init__(*args, **kwargs)

        gs = GSetting()
        setting = gs.get_setting(gs.Path.PLUGIN)
        setting.bind(gs.PluginKey.BUTTON_RELIEF, self, 'button_relief',
                     Gio.SettingsBindFlags.GET)

        self.connect('notify::button-relief', self.on_notify_button_relief)
コード例 #11
0
    def _connect_properties(self):
        gs = GSetting()
        setting = gs.get_setting(gs.Path.PLUGIN)

        setting.bind(gs.PluginKey.COVER_SIZE, self, 'cover-size',
                     Gio.SettingsBindFlags.GET)

        setting.bind(gs.PluginKey.DISPLAY_TEXT_POS, self, 'display-text-pos',
                     Gio.SettingsBindFlags.GET)

        setting.bind(gs.PluginKey.DISPLAY_TEXT, self, 'display-text',
                     Gio.SettingsBindFlags.GET)
コード例 #12
0
    def load_complete(self, *args, **kwargs):
        '''
        Called by Rhythmbox when it has completed loading all data
        Used to automatically switch to the browser if the user
        has set in the preferences
        '''

        gs = GSetting()
        setting = gs.get_setting(gs.Path.PLUGIN)

        if setting[gs.PluginKey.AUTOSTART]:
            self._externalmenu.autostart_source()
コード例 #13
0
    def load_complete(self, *args, **kwargs):
        '''
        Called by Rhythmbox when it has completed loading all data
        Used to automatically switch to the browser if the user
        has set in the preferences
        '''
        gs = GSetting()
        setting = gs.get_setting(gs.Path.PLUGIN)

        if setting[gs.PluginKey.AUTOSTART]:
            GLib.idle_add(self.shell.props.display_page_tree.select,
                self.source)
コード例 #14
0
 def _connect_properties(self):
     gs = GSetting()
     setting = gs.get_setting(gs.Path.PLUGIN)
     setting.bind(
         gs.PluginKey.USE_FAVOURITES,
         self,
         'favourites',
         Gio.SettingsBindFlags.DEFAULT)
     setting.bind(
         gs.PluginKey.FOLLOWING,
         self,
         'follow',
         Gio.SettingsBindFlags.DEFAULT)
コード例 #15
0
 def view_change_cb(self, action, current):
     '''
     Called when the view state on a page is changed. Sets the new 
     state.
     '''
     action.set_state(current)
     view_name = self._views.get_view_name_for_action(current)
     if view_name != ListView.name:
         gs = GSetting()
         setting = gs.get_setting(gs.Path.PLUGIN)
         setting[gs.PluginKey.VIEW_NAME] = view_name
         GLib.idle_add(self.shell.props.display_page_tree.select,
                 self.source)
コード例 #16
0
    def __init__(self, *args, **kwargs):
        super(CoverIconView, self).__init__(cell_area=AlbumArtCellArea(), *args, **kwargs)

        self.gs = GSetting()
        # custom text renderer
        self._text_renderer = None
        self.show_policy = AlbumShowingPolicy(self)
        self.view = self
        self._has_initialised = False
        self._last_path = None
        self._calc_motion_step = 0
        self.set_selection_mode(Gtk.SelectionMode.MULTIPLE)
        self.object_column = AlbumsModel.columns['album']
コード例 #17
0
    def on_notify_view_name(self, *args):
        if self._lastview and self.view_name != self._lastview:
            selected = self._views[self._lastview].get_selected_objects()
            current_album = None
            if len(selected) > 0:
                current_album = self._views[
                    self._lastview].get_selected_objects()[0]

            if self._views[self.view_name].use_plugin_window:
                child = self.window.get_child()

                if child:
                    self.window.remove(child)
                self.window.add(self._views[self.view_name].view)
                self.window.show_all()
                self.click_count = 0

                self._views[
                    self.
                    _lastview].panedposition = self.source.paned.get_expansion_status(
                    )

            self._views[self.view_name].switch_to_view(self.source,
                                                       current_album)
            self._views[self.view_name].emit('update-toolbar')
            self._views[self.view_name].get_default_manager().emit(
                'sort', None)

            if self._views[self.view_name].use_plugin_window:
                self.source.paned.expand(
                    self._views[self.view_name].panedposition)

            self.current_view.set_popup_menu(self.source.popup_menu)
            self.source.album_manager.current_view = self.current_view

            if self._views[self.view_name].use_plugin_window:
                # we only ever save plugin views not external views
                saved_view = self.view_name
            else:
                saved_view = self._lastview

            self._lastview = self.view_name

            gs = GSetting()
            setting = gs.get_setting(gs.Path.PLUGIN)
            setting[gs.PluginKey.VIEW_NAME] = saved_view

        self.emit('new-view', self.view_name)
コード例 #18
0
 def _connect_properties(self):
     gs = GSetting()
     settings = gs.get_setting(gs.Path.PLUGIN)
     settings.bind(gs.PluginKey.FLOW_APPEARANCE, self,
         'flow_appearance', Gio.SettingsBindFlags.GET)
     settings.bind(gs.PluginKey.FLOW_HIDE_CAPTION, self,
         'flow_hide', Gio.SettingsBindFlags.GET)
     settings.bind(gs.PluginKey.FLOW_SCALE, self,
         'flow_scale', Gio.SettingsBindFlags.GET)
     settings.bind(gs.PluginKey.FLOW_AUTOMATIC, self,
         'flow_automatic', Gio.SettingsBindFlags.GET)
     settings.bind(gs.PluginKey.FLOW_BACKGROUND_COLOUR, self,
         'flow_background', Gio.SettingsBindFlags.GET)
     settings.bind(gs.PluginKey.FLOW_WIDTH, self,
         'flow_width', Gio.SettingsBindFlags.GET)
     settings.bind(gs.PluginKey.FLOW_MAX, self,
         'flow_max', Gio.SettingsBindFlags.GET)
コード例 #19
0
    def __init__(self, **kargs):
        '''
        Initializes the source.
        '''
        super(CoverArtBrowserSource, self).__init__(**kargs)

        # create source_source_settings and connect the source's properties
        self.gs = GSetting()

        self._connect_properties()

        self.hasActivated = False
        self.last_width = 0
        self.last_selected_album = None
        self.click_count = 0
        self.favourites = False
        self.task_progress = None
コード例 #20
0
    def __init__(self, plugin):
        super(ExternalPluginMenu, self).__init__()

        self.plugin = plugin
        self.shell = plugin.shell
        self.source = plugin.source
        self.app_id = None
        self.locations = [
            'library-toolbar', 'queue-toolbar', 'playsource-toolbar'
        ]

        from coverart_browser_source import Views

        self._views = Views(self.shell)

        self._use_standard_control = True
        self.plugin.using_alternative_toolbar = hasattr(
            self.shell, 'alternative_toolbar')
        if self.plugin.using_alternative_toolbar:
            from alttoolbar_type import AltToolbarHeaderBar
            self.plugin.using_headerbar = isinstance(
                self.shell.alternative_toolbar.toolbar_type,
                AltToolbarHeaderBar)

        if self.plugin.using_headerbar:
            self._use_standard_control = False

            # register with headerbar to complete the setup for coverart-browser
            print("registering")
            self.shell.alternative_toolbar.toolbar_type.setup_completed_async(
                self._headerbar_toolbar_completed)

        if self._use_standard_control:
            # ... otherwise just use the standard menubutton approach
            self.source.props.visibility = True  # make the source visible
            gs = GSetting()
            setting = gs.get_setting(gs.Path.PLUGIN)
            setting.bind(gs.PluginKey.TOOLBAR_POS, self, 'toolbar_pos',
                         Gio.SettingsBindFlags.GET)

            self.connect('notify::toolbar-pos', self._on_notify_toolbar_pos)
            self.shell.props.display_page_tree.connect("selected",
                                                       self.on_page_change)

            self._create_menu()
コード例 #21
0
    def _connect_properties(self):
        gs = GSetting()
        setting = gs.get_setting(gs.Path.PLUGIN)

        setting.bind(gs.PluginKey.COVER_SIZE, self, 'cover-size',
                     Gio.SettingsBindFlags.GET)

        setting.bind(gs.PluginKey.DISPLAY_TEXT_POS, self, 'display-text-pos',
                     Gio.SettingsBindFlags.GET)

        setting.bind(gs.PluginKey.DISPLAY_TEXT, self, 'display-text',
                     Gio.SettingsBindFlags.GET)

        setting.bind(gs.PluginKey.ADD_SHADOW, self, 'add-shadow',
                     Gio.SettingsBindFlags.GET)

        setting.bind(gs.PluginKey.TEXT_ALIGNMENT, self, 'text-alignment',
                     Gio.SettingsBindFlags.GET)
コード例 #22
0
    def __init__(self, *args, **kwargs):
        if not rb3compat.compare_pygobject_version("3.9"):
            super(CoverIconView, self).__init__(cell_area=AlbumArtCellArea(),
                                                *args,
                                                **kwargs)
        else:
            # this works in trusty but not in earlier versions - define in the super above
            super(CoverIconView, self).__init__(*args, **kwargs)
            self.props.cell_area = AlbumArtCellArea()

        self.gs = GSetting()
        # custom text renderer
        self._text_renderer = None
        self.show_policy = AlbumShowingPolicy(self)
        self.view = self
        self._has_initialised = False
        self._last_play_path = None
        self._recheck_in_progress = False
        self._current_hover_path = None
コード例 #23
0
    def __init__(self, plugin, album_model):
        super(SortOrderToggleController, self).__init__()

        self._album_model = album_model
        self.plugin = plugin

        # options
        self.values = OrderedDict([(_('Sort in descending order'), False),
                                   (_('Sort in ascending order'), True)])
        self.options = self.values.keys()

        self._images = []

        # set the current key
        self.gs = GSetting()
        self.settings = self.gs.get_setting(self.gs.Path.PLUGIN)
        sort_order = self.settings[self.gs.PluginKey.SORT_ORDER]
        self.current_key = self.values.keys()[self.values.values().index(
            sort_order)]
        self.update_images(False)
コード例 #24
0
    def __init__(self, plugin, viewmgr):
        super(SortOrderToggleController, self).__init__()

        self._viewmgr = viewmgr
        self.plugin = plugin

        # options
        self.values = OrderedDict([(_('Sort in descending order'), False),
                                   (_('Sort in ascending order'), True)])
        self.options = list(self.values.keys())

        self._images = []

        # set the current key
        self.gs = GSetting()
        self.settings = self.gs.get_setting(self.gs.Path.PLUGIN)
        self.key = self.get_key()
        sort_order = self.settings[self.key]
        self.current_key = list(self.values.keys())[
            list(self.values.values()).index(sort_order)]
        self.update_images(False)
コード例 #25
0
    def _select_view(self, view_name):
        '''
          with the view_name decide which view to be displayed
          or if view_name is None then use the last remembered view_name
          
          return view_name
        '''

        if not self.shell.props.display_page_tree:
            return

        print("_select_view")
        print(view_name)
        if view_name != ListView.name and \
                        view_name != QueueView.name and \
                        view_name != PlaySourceView.name:
            gs = GSetting()
            setting = gs.get_setting(gs.Path.PLUGIN)
            if view_name:
                setting[gs.PluginKey.VIEW_NAME] = view_name
            else:
                view_name = setting[gs.PluginKey.VIEW_NAME]
            player = self.shell.props.shell_player
            player.set_selected_source(self.source)  #.playlist_source)

            GLib.idle_add(self.shell.props.display_page_tree.select,
                          self.source)
        elif view_name == ListView.name:
            GLib.idle_add(self.shell.props.display_page_tree.select,
                          self.shell.props.library_source)
        elif view_name == QueueView.name:
            GLib.idle_add(self.shell.props.display_page_tree.select,
                          self.shell.props.queue_source)
        elif view_name == PlaySourceView.name:
            GLib.idle_add(self.shell.props.display_page_tree.select,
                          self.plugin.playlist_source)

        return view_name
コード例 #26
0
        def __init__(self, plugin):
            '''
            Initializes the singleton interface, assigning all the constants
            used to access the plugin's settings.
            '''
            super(Theme._impl, self).__init__()

            self.plugin = plugin
            popups = rb.find_plugin_file(plugin, 'img/popups.xml')
            root = ET.parse(open(popups)).getroot()

            base = 'theme/theme'
            self.themes = []

            for elem in root.xpath(base):
                self.themes.append(elem.attrib['folder_name'])

            self.gs = GSetting()
            self.setting = self.gs.get_setting(self.gs.Path.PLUGIN)

            # connect properties and signals
            self._connect_properties()
            self._connect_signals()
コード例 #27
0
    def __init__(self, shell, source):
        '''
        Initializes the entryview.
        '''
        self.shell = shell
        self.source = source
        self.plugin = self.source.props.plugin

        super(RB.EntryView, self).__init__(db=shell.props.db,
            shell_player=shell.props.shell_player, is_drag_source=True,
            visible_columns=[])

        cl = CoverLocale()
        cl.switch_locale(cl.Locale.RB)

        self.append_column(RB.EntryViewColumn.TRACK_NUMBER, False)
        self.append_column(RB.EntryViewColumn.TITLE, True)  # always shown
        self.append_column(RB.EntryViewColumn.GENRE, False)
        self.append_column(RB.EntryViewColumn.ARTIST, False)
        self.append_column(RB.EntryViewColumn.ALBUM, False)
        self.append_column(RB.EntryViewColumn.DURATION, False)
        self.append_column(RB.EntryViewColumn.COMMENT, False)
        self.append_column(RB.EntryViewColumn.RATING, False)
        self.append_column(RB.EntryViewColumn.QUALITY, False)
        self.append_column(RB.EntryViewColumn.PLAY_COUNT, False)
        self.append_column(RB.EntryViewColumn.LAST_PLAYED, False)
        self.append_column(RB.EntryViewColumn.YEAR, False)
        self.append_column(RB.EntryViewColumn.FIRST_SEEN, False)
        self.append_column(RB.EntryViewColumn.LOCATION, False)
        self.append_column(RB.EntryViewColumn.BPM, False)

        cl.switch_locale(cl.Locale.LOCALE_DOMAIN)

        # UI elements need to be imported.
        ui = Gtk.Builder()
        ui.set_translation_domain(cl.Locale.LOCALE_DOMAIN)
        ui.add_from_file(rb.find_plugin_file(self.plugin,
            'ui/coverart_entryview.ui'))
        ui.connect_signals(self)

        self.popup_menu = ui.get_object('entryview_popup_menu')

        # connect signals to the shell to know when the playing state changes
        self.shell.props.shell_player.connect('playing-song-changed',
            self.playing_song_changed)
        self.shell.props.shell_player.connect('playing-changed',
            self.playing_changed)

        self.playlist_sub_menu_item = ui.get_object('playlist_sub_menu_item')
        self.actiongroup = Gtk.ActionGroup('coverentryplaylist_submenu')
        uim = self.shell.props.ui_manager
        uim.insert_action_group(self.actiongroup)

        self.external_plugins = \
            CreateExternalPluginMenu("ca_entryview", self.shell)

        # connect the visible-columns global setting to update our entryview
        gs = GSetting()
        rhythm_settings = gs.get_setting(gs.Path.RBSOURCE)
        rhythm_settings.connect('changed::visible-columns',
            self.on_visible_columns_changed)
        self.on_visible_columns_changed(rhythm_settings, 'visible-columns')

        self.qm = RB.RhythmDBQueryModel.new_empty(self.shell.props.db)
        self.set_model(self.qm)

        # connect the sort-order to the library source sort
        library_view = self.shell.props.library_source.get_entry_view()
        library_view.connect('notify::sort-order',
            self._on_library_sorting_changed)
        self._on_library_sorting_changed(library_view,
            library_view.props.sort_order)

         # connect to the sort-order property
        self.connect('notify::sort-order', self._notify_sort_order,
            library_view)
コード例 #28
0
    def _connect_properties(self):
        gs = GSetting()
        setting = gs.get_setting(gs.Path.PLUGIN)

        setting.bind(gs.PluginKey.NEW_GENRE_ICON, self, 'new_genre_icon',
                     Gio.SettingsBindFlags.GET)
コード例 #29
0
 def _connect_properties(self):
     gs = GSetting()
     setting = gs.get_setting(gs.Path.PLUGIN)
     setting.bind(gs.PluginKey.TOOLBAR_POS, self, 'toolbar_pos',
                  Gio.SettingsBindFlags.GET)
コード例 #30
0
    def __init__(self, button_box, stack, info_paned, source):
        GObject.GObject.__init__(self)

        self.ds = {}
        self.view = {}

        # self.buttons = button_box
        self.source = source
        self.plugin = source.plugin
        self.shell = source.shell
        self.info_paned = info_paned
        self.current_artist = None
        self.current_album_title = None
        self.current = 'artist'
        self._from_paned_handle = 0

        self.stack = stack
        self.stack.set_transition_type(
            Gtk.StackTransitionType.SLIDE_LEFT_RIGHT)
        stack_switcher = Gtk.StackSwitcher()
        stack_switcher.set_stack(self.stack)
        self.stack.connect('notify::visible-child-name', self.change_stack)
        button_box.pack_start(stack_switcher, False, False, 0)
        button_box.show_all()

        # cache for artist/album information: valid for a month, can be used indefinitely
        # if offline, discarded if unused for six months
        self.info_cache = rb.URLCache(name='info',
                                      path=os.path.join(
                                          'coverart_browser', 'info'),
                                      refresh=30,
                                      discard=180)
        # cache for rankings (artist top tracks and top albums): valid for a week,
        # can be used for a month if offline
        self.ranking_cache = rb.URLCache(name='ranking',
                                         path=os.path.join(
                                             'coverart_browser', 'ranking'),
                                         refresh=7,
                                         lifetime=30)

        self.info_cache.clean()
        self.ranking_cache.clean()

        self.ds['link'] = LinksDataSource()
        self.ds['artist'] = ArtistDataSource(self.info_cache,
                                             self.ranking_cache)

        self.view['artist'] = ArtistInfoView()
        self.view['artist'].initialise(self.source, self.shell, self.plugin,
                                       self.stack, self.ds['artist'],
                                       self.ds['link'])

        self.ds['album'] = AlbumDataSource(self.info_cache, self.ranking_cache)
        self.view['album'] = AlbumInfoView()
        self.view['album'].initialise(self.source, self.shell, self.plugin,
                                      self.stack, self.ds['album'])

        self.ds['echoartist'] = EchoArtistDataSource(self.info_cache,
                                                     self.ranking_cache)
        self.view['echoartist'] = EchoArtistInfoView()
        self.view['echoartist'].initialise(self.source, self.shell,
                                           self.plugin, self.stack,
                                           self.ds['echoartist'],
                                           self.ds['link'])

        self.gs = GSetting()
        self.connect_properties()
        self.connect_signals()
        Gdk.threads_add_timeout(GLib.PRIORITY_DEFAULT_IDLE, 50,
                                self._change_paned_pos,
                                self.source.viewmgr.view_name)
        self.view[self.current].activate()