コード例 #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 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')
コード例 #3
0
    def __init__(self, plugin, viewmgr):
        super(SortPopupController, 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"),
                (_("Sort by album artist"), "artist"),
                (_("Sort by year"), "year"),
                (_("Sort by rating"), "rating"),
            ]
        )

        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]

        self._spritesheet = None
        self.update_images(False)

        self.current_key = list(self.values.keys())[list(self.values.values()).index(value)]
コード例 #4
0
    def initialise(self, plugin, shell, callback):
        '''
        extend the default initialise function
        because we need to also resize the picture
        associated with the sort button as well as find the
        saved sort order
        '''
        if self.is_initialised:
            return

        self._spritesheet = ConfiguredSpriteSheet(plugin, 'sort')

        gs = GSetting()
        source_settings = gs.get_setting(gs.Path.PLUGIN)
        source_settings.bind(gs.PluginKey.SORT_BY,
            self, 'sort_by', Gio.SettingsBindFlags.DEFAULT)

        super(SortPopupButton, self).initialise(shell, callback,
            self.sorts[self.sort_by])

        # create the pop up menu
        for key, text in sorted(self.sorts.iteritems()):
            self.add_menuitem(text, self._sort_changed, key)

        self._sort_changed(None, self.sort_by)
コード例 #5
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)
コード例 #6
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)
コード例 #7
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)
コード例 #8
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')
コード例 #9
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)]
コード例 #10
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]
                
            self.window.remove(self._views[self._lastview].view)
            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.source.paned.expand(self._views[self.view_name].panedposition)
            
            self._lastview = self.view_name
            self.current_view.set_popup_menu(self.source.popup_menu)
            self.source.album_manager.current_view = self.current_view
            
            gs = GSetting()
            setting = gs.get_setting(gs.Path.PLUGIN)
            setting[gs.PluginKey.VIEW_NAME] = self.view_name

        self.emit('new-view')
コード例 #11
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)]
コード例 #12
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
コード例 #13
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
コード例 #14
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)
コード例 #15
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)
コード例 #16
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")
コード例 #17
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)
コード例 #18
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")
コード例 #19
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)
コード例 #20
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
コード例 #21
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)
コード例 #22
0
    def play_random_album_menu_item_callback(self, favourites=False):
        print('''CoverArtBrowser DEBUG - play_random_album_menu_item_callback''')
        query_model = RB.RhythmDBQueryModel.new_empty(self.shell.props.db)

        num_albums = len(self.album_manager.model.store)

        #random_list = []
        selected_albums = []

        gs = GSetting()
        settings = gs.get_setting(gs.Path.PLUGIN)        
        to_queue = settings[gs.PluginKey.RANDOM]

        if num_albums <= to_queue:
            dialog = Gtk.MessageDialog(None,
                    Gtk.DialogFlags.MODAL,
                    Gtk.MessageType.INFO,
                    Gtk.ButtonsType.OK,
                    _("The number of albums to randomly play is less than that displayed."))

            dialog.run()
            dialog.destroy()
            return
            
        album_col = self.album_manager.model.columns['album']

        chosen = {}

        # now loop through finding unique random albums
        # i.e. ensure we dont queue the same album twice
        
        for loop in range(0, to_queue):
            while True:
                pos = random.randint(0, num_albums - 1)
                if pos not in chosen:
                    chosen[pos] = None
                    selected_albums.append(self.album_manager.model.store[pos][album_col])
                    break

        threshold = self.rating_threshold if favourites else 0

        for album in selected_albums:
            # Retrieve and sort the entries of the album
            tracks = album.get_tracks(threshold)

            # Add the songs to the play queue
            for track in tracks:
                query_model.add_entry(track.entry, -1)

        self.props.query_model = query_model

        # Start the music
        player = self.shell.props.shell_player

        player.play_entry(query_model[0][0], self)

        print("CoverArtBrowser DEBUG - end play_selected_album")
コード例 #23
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)
コード例 #24
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)
コード例 #25
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()
コード例 #26
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)
コード例 #27
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)
コード例 #28
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)
コード例 #29
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()
コード例 #30
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)
コード例 #31
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)
コード例 #32
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']
コード例 #33
0
    def album_art_requested(self, store, key, last_time):
        searches = []
        
        gs = GSetting()
        setting = gs.get_setting(gs.Path.PLUGIN)
        
        if setting[gs.PluginKey.EMBEDDED_SEARCH]:
            searches.append(CoverAlbumSearch())
        if setting[gs.PluginKey.DISCOGS_SEARCH]:
            searches.append(DiscogsSearch())

        print "about to search"
        s = CoverSearch(store, key, last_time, searches)
        print "finished about to return"
        return s.next_search()
コード例 #34
0
    def _sort_changed(self, menu, sort):
        '''
        called when sort popup menu item chosen
        '''
        if not menu or menu.get_active():
            self.set_popup_value(self.sorts[sort])
            #self.sort_by = sort
            print sort
            gs = GSetting()
            settings = gs.get_setting(gs.Path.PLUGIN)
            settings[gs.PluginKey.SORT_BY] = sort

            self.resize_button_image(self._spritesheet[sort])

            self.callback(sort)
コード例 #35
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)
コード例 #36
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)
コード例 #37
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
コード例 #38
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)
コード例 #39
0
    def __init__(self, **kargs):
        '''
        Initializes the button.
        '''
        super(SortOrderButton, self).__init__(
            **kargs)

        self.gs = GSetting()
コード例 #40
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)
コード例 #41
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()
コード例 #42
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)
コード例 #43
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
コード例 #44
0
class SortOrderButton(ImageToggleButton):
    __gtype_name__ = 'SortOrderButton'

    def __init__(self, **kargs):
        '''
        Initializes the button.
        '''
        super(SortOrderButton, self).__init__(
            **kargs)

        self.gs = GSetting()

    def initialise(self, plugin, callback, sort_order):
        '''
        set up the images we will use for this widget
        '''
        self.image_display = sort_order
        self.set_tooltip(self.image_display)

        if not self.is_initialised:
            image1 = Gtk.Image.new_from_file(rb.find_plugin_file(plugin,
            'img/arrow_up.png'))
            image2 = Gtk.Image.new_from_file(rb.find_plugin_file(plugin,
            'img/arrow_down.png'))

            super(SortOrderButton, self).initialise(callback,
               image1, image2)

    def do_clicked(self):

        val = not self.image_display
        self.gs.set_value(self.gs.Path.PLUGIN,
                    self.gs.PluginKey.SORT_ORDER, val)
        self.set_tooltip(val)
        self.on_clicked()

    def set_tooltip(self, val):
        cl = CoverLocale()
        cl.switch_locale(cl.Locale.LOCALE_DOMAIN)
        if not val:
            self.set_tooltip_text(_('Sort in descending order'))
        else:
            self.set_tooltip_text(_('Sort in ascending order'))
コード例 #45
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
コード例 #46
0
 def __init__(self, *args, **kwargs):
     super(CoverIconView, self).__init__(*args, **kwargs)
     
     self.ext_menu_pos = 0
     self._external_plugins = None
     self.gs = GSetting()
     # custom text renderer
     self._text_renderer = None
     self.show_policy = AlbumShowingPolicy(self)
     self.view = self
     self._has_initialised = False
コード例 #47
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)
コード例 #48
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)
コード例 #49
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)
コード例 #50
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()
コード例 #51
0
    class _impl(GObject.Object):
        """ Implementation of the singleton interface """
        # properties
        theme = GObject.property(type=str, default="standard")

        # signals
        '''
        changed = signal emitted when a theme has changed
        '''
        __gsignals__ = {
            'theme_changed': (GObject.SIGNAL_RUN_LAST, None, ())
        }
        # below public variables and methods that can be called for Theme
        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()

        @property
        def current(self):
            return self.setting[self.gs.PluginKey.THEME]

        def _connect_properties(self):
            self.setting.bind(self.gs.PluginKey.THEME, self,
                              'theme', Gio.SettingsBindFlags.GET)

        def _connect_signals(self):
            self.connect('notify::theme', self._on_theme_changed,
                         None)

        def _on_theme_changed(self, *args):
            self.emit('theme_changed')
コード例 #52
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
コード例 #53
0
class SortOrderToggleController(OptionsController):

    toolbar_type = "album"

    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)

    def get_key(self):
        return self.gs.PluginKey.SORT_ORDER

    def update_images(self, *args):
        # initialize images
        if len(self._images) > 0:
            del self._images[:]

        self._images.append(
            self.create_button_image(self.plugin, None, 'arrow_down.png'))
        self._images.append(
            self.create_button_image(self.plugin, None, 'arrow_up.png'))

        if args[-1]:
            self.update_image = True

    def do_action(self):
        sort_order = self.values[self.current_key]
        self.settings[self.key] = sort_order
        self._viewmgr.current_view.get_default_manager().emit(
            'sort', self.toolbar_type)

    def get_current_image(self):
        return self._images[self.get_current_key_index()]
コード例 #54
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()
コード例 #55
0
    class _impl(GObject.Object):
        """ Implementation of the singleton interface """
        # properties
        theme = GObject.property(type=str, default="standard")

        # signals
        '''
        changed = signal emitted when a theme has changed
        '''
        __gsignals__ = {'theme_changed': (GObject.SIGNAL_RUN_LAST, None, ())}

        # below public variables and methods that can be called for Theme
        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()

        @property
        def current(self):
            return self.setting[self.gs.PluginKey.THEME]

        def _connect_properties(self):
            self.setting.bind(self.gs.PluginKey.THEME, self, 'theme',
                              Gio.SettingsBindFlags.GET)

        def _connect_signals(self):
            self.connect('notify::theme', self._on_theme_changed, None)

        def _on_theme_changed(self, *args):
            self.emit('theme_changed')
コード例 #56
0
class SortOrderToggleController(OptionsController):
    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)

    def update_images(self, *args):
        # initialize images
        if len(self._images) > 0:
            del self._images[:]

        self._images.append(
            self.create_button_image(self.plugin, None, 'arrow_down.png'))
        self._images.append(
            self.create_button_image(self.plugin, None, 'arrow_up.png'))

        if args[-1]:
            self.update_image = True

    def do_action(self):
        sort_order = self.values[self.current_key]

        if not sort_order or\
            sort_order != self.settings[self.gs.PluginKey.SORT_ORDER]:
            self._album_model.sort(reverse=True)

        self.settings[self.gs.PluginKey.SORT_ORDER] = sort_order

    def get_current_image(self):
        return self._images[self.get_current_key_index()]
コード例 #57
0
class CoverIconView(EnhancedIconView, AbstractView):
    __gtype_name__ = "CoverIconView"

    icon_spacing = GObject.property(type=int, default=0)
    icon_padding = GObject.property(type=int, default=0)
    icon_automatic = GObject.property(type=bool, default=True)

    display_text_enabled = GObject.property(type=bool, default=False)
    display_text_pos = GObject.property(type=bool, default=False)
    name = 'coverview'
    panedposition = PanedCollapsible.Paned.COLLAPSE
    text_alignment = GObject.property(type=int, default=1)

    __gsignals__ = {
        'update-toolbar': (GObject.SIGNAL_RUN_LAST, None, ())
    }

    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']

    def initialise(self, source):
        if self._has_initialised:
            return

        self._has_initialised = True

        self.view_name = "covers_view"
        super(CoverIconView, self).initialise(source)

        self.shell = source.shell
        self.album_manager = source.album_manager

        # setup iconview drag&drop support
        # first drag and drop on the coverart view to receive coverart
        self.enable_model_drag_dest([], Gdk.DragAction.COPY)
        self.drag_dest_add_image_targets()
        self.drag_dest_add_text_targets()
        self.connect('drag-drop', self.on_drag_drop)
        self.connect('drag-data-received',
                     self.on_drag_data_received)
        self.source.paned.connect("expanded", self.bottom_expander_expanded_callback)

        # lastly support drag-drop from coverart to devices/nautilus etc
        self.connect('drag-begin', self.on_drag_begin)
        self.enable_model_drag_source(Gdk.ModifierType.BUTTON1_MASK,
            [], Gdk.DragAction.COPY)
        # targets = Gtk.TargetList.new([Gtk.TargetEntry.new("application/x-rhythmbox-entry", 0, 0),
        # Gtk.TargetEntry.new("text/uri-list", 0, 1) ])
        targets = Gtk.TargetList.new([Gtk.TargetEntry.new("text/uri-list", 0, 0)])
        # N.B. values taken from rhythmbox v2.97 widgets/rb_entry_view.c
        targets.add_uri_targets(1)

        self.drag_source_set_target_list(targets)
        self.connect("drag-data-get", self.on_drag_data_get)

        # set the model to the view
        # self.set_pixbuf_column(AlbumsModel.columns['pixbuf'])
        self.set_model(self.album_manager.model.store)

        # setup view to monitor mouse movements
        self.add_events(Gdk.EventMask.POINTER_MOTION_MASK)

        self.hover_pixbufs = {
            'button_play': None,
            'button_play_hover': None,
            'button_playpause': None,
            'button_playpause_hover': None,
            'button_queue': None,
            'button_queue_hover': None,
        }

        for pixbuf_type in self.hover_pixbufs:
            filename = 'img/' + pixbuf_type + '.png'
            filename = rb.find_plugin_file(self.plugin, filename)
            self.hover_pixbufs[pixbuf_type] = GdkPixbuf.Pixbuf.new_from_file_at_size(filename,
                                                                                     PLAY_SIZE_X,
                                                                                     PLAY_SIZE_Y)

        self._connect_properties()
        self._connect_signals()

        self._activate_markup()
        self.on_notify_icon_padding()
        self.on_notify_icon_spacing()

    def _connect_properties(self):
        setting = self.gs.get_setting(self.gs.Path.PLUGIN)
        setting.bind(
            self.gs.PluginKey.ICON_SPACING,
            self,
            'icon_spacing',
            Gio.SettingsBindFlags.GET)
        setting.bind(
            self.gs.PluginKey.ICON_PADDING,
            self,
            'icon_padding',
            Gio.SettingsBindFlags.GET)

        setting.bind(self.gs.PluginKey.DISPLAY_TEXT, self,
                     'display_text_enabled', Gio.SettingsBindFlags.GET)

        setting.bind(self.gs.PluginKey.ICON_AUTOMATIC, self,
                     'icon_automatic', Gio.SettingsBindFlags.GET)

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

        setting.bind(self.gs.PluginKey.TEXT_ALIGNMENT, self,
                     'text-alignment', Gio.SettingsBindFlags.GET)

    def _connect_signals(self):
        self.connect("item-clicked", self.item_clicked_callback)
        self.connect("selection-changed", self.selectionchanged_callback)
        self.connect("item-activated", self.item_activated_callback)
        self.connect('notify::icon-spacing',
                     self.on_notify_icon_spacing)
        self.connect('notify::icon-padding',
                     self.on_notify_icon_padding)
        self.connect('notify::display-text-enabled',
                     self._activate_markup)
        self.connect('notify::display-text-pos',
                     self._activate_markup)
        self.connect('notify::text-alignment',
                     self._create_and_configure_renderer)
        self.connect("motion-notify-event", self.on_pointer_motion)

    def get_view_icon_name(self):
        return "iconview.png"

    def resize_icon(self, cover_size):
        '''
        Callback called when to resize the icon
        [common to all views]
        '''
        self.set_item_width(cover_size)

    def on_drag_drop(self, widget, context, x, y, time):
        '''
        Callback called when a drag operation finishes over the cover view
        of the source. It decides if the dropped item can be processed as
        an image to use as a cover.
        '''

        # stop the propagation of the signal (deactivates superclass callback)
        widget.stop_emission_by_name('drag-drop')

        # obtain the path of the icon over which the drag operation finished
        path, pos = widget.get_dest_item_at_pos(x, y)
        result = path is not None

        if result:
            target = self.drag_dest_find_target(context, None)
            widget.drag_get_data(context, target, time)

        return result

    def on_drag_data_received(self, widget, drag_context, x, y, data, info,
                              time):
        '''
        Callback called when the drag source has prepared the data (pixbuf)
        for us to use.
        '''

        # stop the propagation of the signal (deactivates superclass callback)
        widget.stop_emission_by_name('drag-data-received')

        # get the album and the info and ask the loader to update the cover
        path, pos = widget.get_dest_item_at_pos(x, y)
        album = widget.get_model()[path][2]

        pixbuf = data.get_pixbuf()

        if pixbuf:
            self.album_manager.cover_man.update_cover(album, pixbuf)
        else:
            uri = data.get_text()
            self.album_manager.cover_man.update_cover(album, uri=uri)

        # call the context drag_finished to inform the source about it
        drag_context.finish(True, False, time)


    def on_drag_data_get(self, widget, drag_context, data, info, time):
        '''
        Callback called when the drag destination (playlist) has
        requested what album (icon) has been dragged
        '''

        uris = []
        for album in widget.get_selected_objects():
            for track in album.get_tracks():
                uris.append(track.location)

        sel = data.set_uris(uris)
        # stop the propagation of the signal (deactivates superclass callback)
        widget.stop_emission_by_name('drag-data-get')

    def on_drag_begin(self, widget, context):
        '''
        Callback called when the drag-drop from coverview has started
        Changes the drag icon as appropriate
        '''
        album_number = len(widget.get_selected_objects())

        if album_number == 1:
            item = Gtk.STOCK_DND
        else:
            item = Gtk.STOCK_DND_MULTIPLE

        widget.drag_source_set_icon_stock(item)
        widget.stop_emission_by_name('drag-begin')

    def _cover_play_hotspot(self, path, in_vacinity=False):
        if path:
            valid, rect = self.get_cell_rect(path, None)  # rect of widget coords

            cursor_x, cursor_y = self.get_pointer()  # returns widget coords
            c_x = cursor_x - rect.x - (self.icon_padding / 2) - (self.icon_spacing / 2)
            c_y = cursor_y - rect.y - (self.icon_padding / 2) - (self.icon_spacing / 2)

            sizing = (rect.width / 3) if in_vacinity else 0

            full, x_offset, y_offset = self.props.cell_area.calc_play_icon_offset(0, 0)
            if full and c_y > y_offset:
                return False

            y_offset = y_offset - PLAY_SIZE_Y

            if (y_offset - PLAY_SIZE_Y) < 0:
                return False

            if c_x < (PLAY_SIZE_X + sizing + x_offset) and \
                            c_y < (PLAY_SIZE_Y + sizing + y_offset) and \
                            c_x > x_offset and \
                            c_y > (y_offset - sizing):
                return True

                # c_y 0 value at top - largest at bottom of the cover
        return False

    def on_pointer_motion(self, widget, event):
        self._current_mouse_x = event.x
        self._current_mouse_y = event.y

        if self._calc_motion_step == 0:
            self._calc_motion_step = 1
            Gdk.threads_add_timeout(GLib.PRIORITY_DEFAULT_IDLE, 100,
                                    self._calculate_hotspot)
        else:
            path = self.get_path_at_pos(self._current_mouse_x,
                                        self._current_mouse_y)

            if not self._last_path or self._last_path != path:
                self._display_icon(None, self._last_path)

    def _display_icon(self, icon, path):
        self.props.cell_area.hover_pixbuf = icon
        if path and self.props.window:
            valid, rect = self.get_cell_rect(path, None)
            self.props.window.invalidate_rect(rect, True)

        self.queue_draw()

    def _calculate_hotspot(self, *args):

        path = self.get_path_at_pos(self._current_mouse_x,
                                    self._current_mouse_y)

        # if the current path was not the same as the last path then
        # reset the counter
        if not self._last_path or self._last_path != path:
            self._display_icon(None, self._last_path)
            self._last_path = path
            self._calc_motion_step = 0
            return False

        self._calc_motion_step = self._calc_motion_step + 1

        # if havent yet reached the requisite number of steps then
        # let the thread roll to the next increment
        if self._calc_motion_step < 8:
            return True

        if not self._cover_play_hotspot(path, in_vacinity=True):
            # we are not near the hot-spot so decrement the counter
            # hoping next time around we are near
            self._calc_motion_step = self._calc_motion_step - 1
            self._display_icon(None, self._last_path)
            return True

        # from  here on in, we are going to display a hotspot icon
        # so lets decide which one

        (_, playing) = self.shell.props.shell_player.get_playing()

        calc_path = -1
        if playing:
            entry = self.shell.props.shell_player.get_playing_entry()
            album = self.album_manager.model.get_from_dbentry(entry)
            calc_path = self.album_manager.model.get_path(album)

        if playing and calc_path == path:
            icon = 'button_playpause'
        elif playing:
            icon = 'button_queue'
        else:
            icon = 'button_play'

        # now we've got the icon - lets double check that we are
        # actually hovering exactly on the hotspot because the icon will visually change

        exact_hotspot = self._cover_play_hotspot(path)
        if exact_hotspot:
            icon = icon + '_hover'

        hover = self.hover_pixbufs[icon]

        self._display_icon(hover, path)
        self._calc_motion_step = self._calc_motion_step - 1

        return True

    def item_clicked_callback(self, iconview, event, path):
        '''
        Callback called when the user clicks somewhere on the cover_view.
        Along with source "show_hide_pane", takes care of showing/hiding the bottom
        pane after a second click on a selected album.
        '''

        # first test if we've clicked on the cover-play icon
        if self._cover_play_hotspot(path):
            (_, playing) = self.shell.props.shell_player.get_playing()

            # first see if anything is playing...
            if playing:
                entry = self.shell.props.shell_player.get_playing_entry()
                album = self.album_manager.model.get_from_dbentry(entry)

                # if the current playing entry corresponds to the album
                # we are hovering over then we are requesting to pause
                if self.album_manager.model.get_from_path(path) == album:
                    self._last_path = path
                    self.shell.props.shell_player.pause()
                    self.on_pointer_motion(self, event)
                    return

            # this must be a new album so we are asking just
            # to play this new album ... just need a short interval
            # for the selection event to kick in first
            def delay(*args):
                if playing:  # if we are playing then queue up the next album
                    self.source.queue_selected_album(None, self.source.favourites)
                    album = self.get_selected_objects()[0]
                    cl = CoverLocale()
                    cl.switch_locale(cl.Locale.LOCALE_DOMAIN)
                    message = gettext.gettext('Album has added to list of playing albums')
                    self.display_notification(album.name,
                                              message,
                                              album.cover.original)
                else:  # otherwise just play it
                    self._last_path = path
                    self.source.play_selected_album(self.source.favourites)

                icon = 'button_play_hover'
                self.props.cell_area.hover_pixbuf = \
                    self.hover_pixbufs[icon]

            Gdk.threads_add_timeout(GLib.PRIORITY_DEFAULT_IDLE, 250,
                                    delay, None)

            return

        # to expand the entry view
        ctrl = event.state & Gdk.ModifierType.CONTROL_MASK
        shift = event.state & Gdk.ModifierType.SHIFT_MASK

        if self.icon_automatic:
            self.source.click_count += 1 if not ctrl and not shift else 0

        if self.source.click_count == 1:
            album = self.album_manager.model.get_from_path(path) \
                if path else None
            Gdk.threads_add_timeout(GLib.PRIORITY_DEFAULT_IDLE, 250,
                                    self.source.show_hide_pane, album)

    def item_activated_callback(self, iconview, path):
        '''
        Callback called when the cover view is double clicked or space-bar
        is pressed. It plays the selected album
        '''
        self.source.play_selected_album(self.source.favourites)

        return True

    def on_notify_icon_padding(self, *args):
        '''
        Callback called when the icon-padding gsetting value is changed
        '''
        self.set_item_padding(self.icon_padding)

    def on_notify_icon_spacing(self, *args):
        '''
        Callback called when the icon-spacing gsetting value is changed
        '''
        self.set_row_spacing(self.icon_spacing)
        self.set_column_spacing(self.icon_spacing)

    def _create_and_configure_renderer(self, *args):
        if not self._text_renderer:
            # Add own cellrenderer
            self._text_renderer = Gtk.CellRendererText()

        self._text_renderer.props.alignment = self.text_alignment
        self._text_renderer.props.wrap_mode = Pango.WrapMode.WORD
        if self.text_alignment == 1:
            self._text_renderer.props.xalign = 0.5
        elif self.text_alignment == 0:
            self._text_renderer.props.xalign = 0
        else:
            self._text_renderer.props.xalign = 1

        self._text_renderer.props.yalign = 0
        self._text_renderer.props.width = \
            self.album_manager.cover_man.cover_size
        self._text_renderer.props.wrap_width = \
            self.album_manager.cover_man.cover_size

    def _activate_markup(self, *args):
        '''
        Utility method to activate/deactivate the markup text on the
        cover view.
        '''
        if self.display_text_enabled and self.display_text_pos:
            if not self._text_renderer:
                # create and configure the custom cell renderer
                self._create_and_configure_renderer()

            # set the renderer
            self.pack_end(self._text_renderer, False)
            self.add_attribute(self._text_renderer,
                               'markup', AlbumsModel.columns['markup'])
        elif self._text_renderer:
            # remove the cell renderer
            self.props.cell_area.remove(self._text_renderer)

        if self.display_text_enabled:
            self.set_tooltip_column(-1)  # turnoff tooltips
        else:
            self.set_tooltip_column(AlbumsModel.columns['tooltip'])

    def bottom_expander_expanded_callback(self, paned, expand):
        '''
        Callback connected to expanded signal of the paned GtkExpander
        '''
        if expand:
            # accommodate the viewport if there's an album selected
            if self.source.last_selected_album:
                def scroll_to_album(*args):
                    # accommodate the viewport if there's an album selected
                    path = self.album_manager.model.get_path(
                        self.source.last_selected_album)

                    self.scroll_to_path(path, False, 0, 0)

                    return False

                Gdk.threads_add_idle(GObject.PRIORITY_DEFAULT_IDLE,
                                     scroll_to_album, None)


    def switch_to_view(self, source, album):
        self.initialise(source)
        self.show_policy.initialise(source.album_manager)

        self.scroll_to_album(album)

    def grab_focus(self):
        super(EnhancedIconView, self).grab_focus()