def get_similar_info(self): """ Returns the dictionary { 'images', 'bio' } """ cl = CoverLocale() lang = cl.get_locale()[:2] try: if not self.artist['similar_' + lang]['parsed']: json_artists_data = self.artist['similar_' + lang]['data']['similarartists'] results = [] print(json_artists_data) for json_artist in json_artists_data["artist"]: print(json_artist) name = json_artist["name"] image_url = json_artist["image"][1]["#text"] similarity = int(100 * float(json_artist["match"])) results.append({ 'name': name, 'image_url': image_url, 'similarity': similarity }) self.artist['similar_' + lang]['data'] = results self.artist['similar_' + lang]['parsed'] = True return self.artist['similar_' + lang]['data'] except Exception as e: print("Error parsing similar_infot: %s" % e) return ""
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)]
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)]
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)
def _create_menu(self): app = Gio.Application.get_default() self.app_id = 'coverart-browser' self.locations = ['library-toolbar', 'queue-toolbar'] action_name = 'coverart-browser-views' self.action = Gio.SimpleAction.new_stateful( action_name, GLib.VariantType.new('s'), self._views.get_action_name(ListView.name) ) self.action.connect("activate", self.view_change_cb) app.add_action(self.action) menu_item = Gio.MenuItem() section = Gio.Menu() menu = Gio.Menu() toolbar_item = Gio.MenuItem() for view_name in self._views.get_view_names(): menu_item.set_label(self._views.get_menu_name(view_name)) menu_item.set_action_and_target_value( 'app.' + action_name, self._views.get_action_name(view_name) ) section.append_item(menu_item) menu.append_section(None, section) cl = CoverLocale() cl.switch_locale(cl.Locale.LOCALE_DOMAIN) toolbar_item.set_label(_('Views')) cl.switch_locale(cl.Locale.RB) toolbar_item.set_submenu(menu) for location in self.locations: app.add_plugin_menu_item(location, self.app_id, toolbar_item)
def artist_info_ready(self, ds): # Can only be called after the artist-info-ready signal has fired. # If called any other time, the behavior is undefined # try: info = ds.get_artist_info() small, med, big = info["images"] or (None, None, None) summary, full_bio = info["bio"] or (None, None) link_album = self.link_ds.get_album() if not link_album: link_album = "" links = self.link_ds.get_album_links() if not links: links = {} cl = CoverLocale() cl.switch_locale(cl.Locale.LOCALE_DOMAIN) self.file = self.template.render( artist=ds.get_current_artist(), error=ds.get_error(), image=med, fullbio=full_bio, shortbio=summary, datasource=lastfm_datasource_link(self.basepath), stylesheet=self.styles, album=link_album, art_links=self.link_ds.get_artist_links(), alb_links=links, link_images=self.link_images, similar=ds.get_similar_info(), ) self.load_view()
def artist_info_ready(self, ds): # Can only be called after the artist-info-ready signal has fired. # If called any other time, the behavior is undefined # try: info = ds.get_artist_info() small, med, big = info['images'] or (None, None, None) summary, full_bio = info['bio'] or (None, None) link_album = self.link_ds.get_album() if not link_album: link_album = "" links = self.link_ds.get_album_links() if not links: links = {} cl = CoverLocale() cl.switch_locale(cl.Locale.LOCALE_DOMAIN) self.file = self.template.render( artist=ds.get_current_artist(), error=ds.get_error(), image=med, fullbio=full_bio, shortbio=summary, datasource=lastfm_datasource_link(self.basepath), stylesheet=self.styles, album=link_album, art_links=self.link_ds.get_artist_links(), alb_links=links, link_images=self.link_images, similar=ds.get_similar_info()) self.load_view()
def __init__(self, plugin, source): super(PropertiesMenuController, self).__init__() self._source = source self.plugin = plugin self._connect_properties() # sorts dictionary cl = CoverLocale() cl.switch_locale(cl.Locale.LOCALE_DOMAIN) # options self.values = OrderedDict() self.values[MenuNode(_('Download all covers'))] = 'download' self.values[MenuNode(_('Play random album'))] = 'random' self.values[MenuNode(_('Follow playing song'), 'check', (True if self.follow else False))] = 'follow' self.values[MenuNode('separator1', 'separator')] = '' self.values[MenuNode(_('Use favourites only'), 'check', (True if self.favourites else False))] = 'favourite' self.values[MenuNode('separator2', 'separator')] = '' self.values[MenuNode(_('Browser Preferences'))] = 'browser prefs' self.values[MenuNode(_('Search Preferences'))] = 'search prefs' self.options = list(self.values.keys()) self.update_images(False) if self.favourites: self._source.propertiesbutton_callback('favourite') if self.follow: self._source.propertiesbutton_callback('follow') self.current_key = None
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)
def __init__(self, plugin, source): super(PropertiesMenuController, self).__init__() self._source = source self.plugin = plugin self._connect_properties() # sorts dictionary cl = CoverLocale() cl.switch_locale(cl.Locale.LOCALE_DOMAIN) # options self.values = OrderedDict() self.values[MenuNode(_('Download all covers'))] = 'download' self.values[MenuNode(_('Play random album'))] = 'random' self.values[MenuNode('separator1', 'separator')] = '' self.values[MenuNode(_('Use favourites only'), 'check', (True if self.favourites else False))] = 'favourite' self.values[MenuNode('separator2', 'separator')] = '' self.values[MenuNode(_('Browser Preferences'))] = 'browser prefs' self.values[MenuNode(_('Search Preferences'))] = 'search prefs' self.options = list(self.values.keys()) self.update_images(False) if self.favourites: self._source.propertiesbutton_callback('favourite') self.current_key = None
def get_current_description(self): cl = CoverLocale() cl.switch_locale(cl.Locale.LOCALE_DOMAIN) if self.current_key == self._initial_genre: return _('All Genres') else: return self.current_key
def get_similar_info(self): """ Returns the dictionary { 'images', 'bio' } """ cl = CoverLocale() lang = cl.get_locale()[:2] try: if not self.artist["similar_" + lang]["parsed"]: json_artists_data = self.artist["similar_" + lang]["data"]["similarartists"] results = [] print(json_artists_data) for json_artist in json_artists_data["artist"]: print(json_artist) name = json_artist["name"] image_url = json_artist["image"][1]["#text"] similarity = int(100 * float(json_artist["match"])) results.append({"name": name, "image_url": image_url, "similarity": similarity}) self.artist["similar_" + lang]["data"] = results self.artist["similar_" + lang]["parsed"] = True return self.artist["similar_" + lang]["data"] except Exception as e: print("Error parsing similar_infot: %s" % e) return ""
def __init__(self, plugin, album_model): super(GenrePopupController, self).__init__() cl = CoverLocale() cl.switch_locale(cl.Locale.LOCALE_DOMAIN) self._album_model = album_model shell = plugin.shell self.plugin = plugin # create a new property model for the genres genres_model = RB.RhythmDBPropertyModel.new(shell.props.db, RB.RhythmDBPropType.GENRE) query = shell.props.library_source.props.base_query_model genres_model.props.query_model = query # initial genre self._initial_genre = _('All Genres') self._spritesheet = None self._default_image = None self._unrecognised_image = None self._connect_properties() self._connect_signals(query, genres_model) # generate initial popup self._update_options(genres_model)
def __init__(self, plugin, source): super(PropertiesMenuController, self).__init__() self._source = source self.plugin = plugin self._connect_properties() # sorts dictionary cl = CoverLocale() cl.switch_locale(cl.Locale.LOCALE_DOMAIN) # options self.values = OrderedDict() self.values[MenuNode(_("Download all covers"))] = "download" self.values[MenuNode(_("Play random album"))] = "random" self.values[MenuNode(_("Follow playing song"), "check", (True if self.follow else False))] = "follow" self.values[MenuNode("separator1", "separator")] = "" self.values[MenuNode(_("Use favourites only"), "check", (True if self.favourites else False))] = "favourite" self.values[MenuNode("separator2", "separator")] = "" self.values[MenuNode(_("Browser Preferences"))] = "browser prefs" self.values[MenuNode(_("Search Preferences"))] = "search prefs" self.options = list(self.values.keys()) self.update_images(False) if self.favourites: self._source.propertiesbutton_callback("favourite") if self.follow: self._source.propertiesbutton_callback("follow") self.current_key = None
def get_artist_bio(self): """ Returns tuple of summary and full bio """ cl = CoverLocale() lang = cl.get_locale()[:2] def get_bio(lang): data = self.artist['info_' + lang]['data'] if data is None: return None if not self.artist['info_' + lang]['parsed']: content = data['artist']['bio']['content'] summary = data['artist']['bio']['summary'] return summary, content if lang != 'en': return None else: return self.artist['info_' + lang]['data']['bio'] arg = get_bio(lang) if not arg or arg[0] == '': arg = get_bio('en') return arg
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'))
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)]
def fetch_album_info(self, artist, album, index): print("start fetch_album_info") cl = CoverLocale() lang = cl.get_locale()[:2] qartist = urllib.parse.quote_plus(artist) qalbum = urllib.parse.quote_plus(album) self.fetched = 2 def fetch_information(lang): cachekey = "lastfm:album:getinfojson:%s:%s:%s" % (qartist, qalbum, lang) url = "%s?method=album.getinfo&artist=%s&album=%s&api_key=%s&format=json&lang=%s" % ( LastFM.API_URL, qartist, qalbum, LastFM.API_KEY, lang, ) print(url) self.info_cache.fetch(cachekey, url, self.parse_album_info, album, index, lang) self.album_data = {} fetch_information("en") fetch_information(lang) print("end fetch_album_info")
def _update_options(self, *args): genres_model = args[-1] self.update_images(False) still_exists = False # retrieve the options options = [] row_num = 0 for row in genres_model: if row_num == 0: cl = CoverLocale() cl.switch_locale(cl.Locale.LOCALE_DOMAIN) genre = _('All Genres') row_num = row_num + 1 else: genre = row[0] options.append(genre) still_exists = still_exists or genre == self.current_key self.options = options self.current_key = self.current_key if still_exists else \ self._initial_genre
def get_artist_bio(self): """ Returns tuple of summary and full bio """ cl = CoverLocale() lang = cl.get_locale()[:2] def get_bio(lang): data = self.artist["info_" + lang]["data"] if data is None: return None if not self.artist["info_" + lang]["parsed"]: content = data["artist"]["bio"]["content"] summary = data["artist"]["bio"]["summary"] return summary, content if lang != "en": return None else: return self.artist["info_" + lang]["data"]["bio"] arg = get_bio(lang) if not arg or arg[0] == "": arg = get_bio("en") return arg
def __init__(self, shell): ''' Initializes the singleton interface, assigning all the constants used to access the plugin's settings. ''' super(Views._impl, self).__init__() from coverart_covericonview import CoverIconView from coverart_coverflowview import CoverFlowView from coverart_artistview import ArtistView from coverart_listview import ListView from coverart_browser_prefs import webkit_support library_name = shell.props.library_source.props.name self._values = OrderedDict() cl = CoverLocale() cl.switch_locale(cl.Locale.LOCALE_DOMAIN) self._values[CoverIconView.name] = [_('Tiles'), GLib.Variant.new_string('coverart-browser-tile')] if webkit_support(): self._values[CoverFlowView.name] = [_('Flow'), GLib.Variant.new_string('coverart-browser-coverflow')] self._values[ArtistView.name] = [_('Artist'), GLib.Variant.new_string('coverart-browser-artist')] self._values[ListView.name] = [library_name, GLib.Variant.new_string('coverart-browser-list')] cl.switch_locale(cl.Locale.RB) print (self._values)
def do_activate(self): ''' Called by Rhythmbox when the plugin is activated. It creates the plugin's source and connects signals to manage the plugin's preferences. ''' print("CoverArtBrowser DEBUG - do_activate") self.shell = self.object self.db = self.shell.props.db try: entry_type = CoverArtBrowserEntryType() self.db.register_entry_type(entry_type) except NotImplementedError: entry_type = self.db.entry_register_type( 'CoverArtBrowserEntryType') cl = CoverLocale() cl.switch_locale(cl.Locale.LOCALE_DOMAIN) entry_type.category = RB.RhythmDBEntryCategory.NORMAL group = RB.DisplayPageGroup.get_by_id('library') # load plugin icon theme = Gtk.IconTheme.get_default() rb.append_plugin_source_path(theme, '/icons') # lets assume that python3 versions of RB only has the new icon attribute in the source if rb3compat.PYVER >=3: iconfile = Gio.File.new_for_path( rb.find_plugin_file(self, 'img/' + Theme(self).current\ + '/covermgr.png')) self.source = CoverArtBrowserSource( shell=self.shell, name=_("CoverArt"), entry_type=entry_type, plugin=self, icon=Gio.FileIcon.new(iconfile), query_model=self.shell.props.library_source.props.base_query_model) else: what, width, height = Gtk.icon_size_lookup(Gtk.IconSize.LARGE_TOOLBAR) pxbf = GdkPixbuf.Pixbuf.new_from_file_at_size( rb.find_plugin_file(self, 'img/' + Theme(self).current\ + '/covermgr.png'), width, height) self.source = CoverArtBrowserSource( shell=self.shell, name=_("CoverArt"), entry_type=entry_type, plugin=self, pixbuf=pxbf, query_model=self.shell.props.library_source.props.base_query_model) self.shell.register_entry_type_for_source(self.source, entry_type) self.shell.append_display_page(self.source, group) self.source.props.query_model.connect('complete', self.load_complete) print("CoverArtBrowser DEBUG - end do_activate")
def _toolbar(self, ui): ''' setup toolbar ui - called for sidebar and main-view ''' print "CoverArtBrowser DEBUG - _toolbar" # dialog has not been created so lets do so. cl = CoverLocale() # get widgets for main icon-view # the first part is to first remove the current search-entry # before recreating it again - we have to do this to ensure # the locale is set correctly i.e. the overall ui is coverart # locale but the search-entry uses rhythmbox translation align = ui.get_object('entry_search_alignment') align.remove(align.get_child()) cl.switch_locale(cl.Locale.RB) self.search_entry = RB.SearchEntry(has_popup=True) align.add(self.search_entry) align.show_all() cl.switch_locale(cl.Locale.LOCALE_DOMAIN) self.search_entry.connect('search', self.searchchanged_callback) self.search_entry.connect('show-popup', self.search_show_popup_callback) self.sort_by = ui.get_object('sort_by') self.sort_by.initialise(self.plugin, self.shell, self.sorting_criteria_changed) self.sort_order_button = ui.get_object('sort_order') self.sort_order_button.initialise(self.plugin, self.sorting_direction_changed, self.sort_order) # get widget for search and apply some workarounds search_entry = ui.get_object('search_entry') search_entry.set_placeholder(_('Search album')) search_entry.show_all() self.search_entry.set_placeholder(ui.get_object( 'filter_all_menu_item').get_label()) # genre genre_button = ui.get_object('genre_button') genre_button.initialise(self.plugin, self.shell, self.genre_filter_callback) # get playlist popup playlist_button = ui.get_object('playlist_button') playlist_button.initialise(self.plugin, self.shell, self.filter_by_model) # decade decade_button = ui.get_object('decade_button') decade_button.initialise(self.plugin, self.shell, self.decade_filter_callback) print "CoverArtBrowser DEBUG - end _toolbar"
def load_tmpl(self): cl = CoverLocale() cl.switch_locale(cl.Locale.LOCALE_DOMAIN) path = rb.find_plugin_file(self.plugin, "tmpl/artist-tmpl.html") empty_path = rb.find_plugin_file(self.plugin, "tmpl/artist_empty-tmpl.html") loading_path = rb.find_plugin_file(self.plugin, "tmpl/loading.html") self.template = Template(filename=path) self.loading_template = Template(filename=loading_path) self.empty_template = Template(filename=empty_path) self.styles = self.basepath + "/tmpl/artistmain.css"
def load_tmpl(self): cl = CoverLocale() cl.switch_locale(cl.Locale.LOCALE_DOMAIN) path = rb.find_plugin_file(self.plugin, 'tmpl/artist-tmpl.html') empty_path = rb.find_plugin_file(self.plugin, 'tmpl/artist_empty-tmpl.html') loading_path = rb.find_plugin_file(self.plugin, 'tmpl/loading.html') self.template = Template(filename=path) self.loading_template = Template(filename=loading_path) self.empty_template = Template(filename=empty_path) self.styles = self.basepath + '/tmpl/artistmain.css'
def do_activate(self): ''' Called by Rhythmbox when the plugin is activated. It creates the plugin's source and connects signals to manage the plugin's preferences. ''' # define .plugin text strings used for translation plugin = _('CoverArt Browser') desc = _('Browse and play your albums through their covers') print "CoverArtBrowser DEBUG - do_activate" self.shell = self.object self.db = self.shell.props.db try: entry_type = CoverArtBrowserEntryType() self.db.register_entry_type(entry_type) except NotImplementedError: entry_type = self.db.entry_register_type( 'CoverArtBrowserEntryType') cl = CoverLocale() cl.switch_locale(cl.Locale.LOCALE_DOMAIN) entry_type.category = RB.RhythmDBEntryCategory.NORMAL # load plugin icon theme = Gtk.IconTheme.get_default() rb.append_plugin_source_path(theme, '/icons') what, width, height = Gtk.icon_size_lookup(Gtk.IconSize.LARGE_TOOLBAR) pxbf = GdkPixbuf.Pixbuf.new_from_file_at_size( rb.find_plugin_file(self, 'img/' + Theme(self).current\ + '/covermgr.png'), width, height) group = RB.DisplayPageGroup.get_by_id('library') self.source = CoverArtBrowserSource( shell=self.shell, name=_("CoverArt"), entry_type=entry_type, plugin=self, pixbuf=pxbf, query_model=self.shell.props.library_source.props.base_query_model) self.shell.register_entry_type_for_source(self.source, entry_type) self.shell.append_display_page(self.source, group) self.source.props.query_model.connect('complete', self.load_complete) print "CoverArtBrowser DEBUG - end do_activate"
def __init__(self, plugin, parent, savedir=None): """Initializes and shows the cover :param plugin: source :type plugin: RBSource :param parent: Parent window to attach to :type parent: Gtk.Window :param savedir: Initial directory for the Save As functionality :type savedir: basestring """ super(CoverWindow, self).__init__() cl = CoverLocale() cl.switch_locale(cl.Locale.LOCALE_DOMAIN) self.builder = Gtk.Builder() self.builder.add_from_file( rb.find_plugin_file(plugin, 'ui/coverart_window.ui')) self.builder.connect_signals(self) self.cover_window = self.builder.get_object('CoverWindow') self.cover_window.connect('destroy', self.send_destroy_signal) self.layout = self.builder.get_object('layout') self.toolbar = self.builder.get_object('toolbar') self.save_as_button = self.builder.get_object('save_as_button') self.zoom_in_button = self.builder.get_object('zoom_in_button') self.zoom_out_button = self.builder.get_object('zoom_out_button') self.zoom_100_button = self.builder.get_object('zoom_100_button') self.zoom_fit_button = self.builder.get_object('zoom_fit_button') self.close_button = self.builder.get_object('close_button') self.image = self.builder.get_object('image') self.statusbar = self.builder.get_object('statusbar') self.scrolledwindow = self.builder.get_object('scrolledwindow') self.scrolledwindow.set_hadjustment(self.layout.get_hadjustment()) self.scrolledwindow.set_vadjustment(self.layout.get_vadjustment()) self.savedir = savedir if parent: self.cover_window.set_transient_for(parent) self.cover_window_width = 500 self.cover_window_height = 500 + self.toolbar.size_request().height + \ self.statusbar.size_request().height self.cover_window.set_default_size(self.cover_window_width, \ self.cover_window_height) self.min_percent = 1 self.max_percent = 500 self.ratio = 1.5 self.image_interp = GdkPixbuf.InterpType.BILINEAR self.image_fitted = True
def __init__(self, **kargs): ''' Initializes the button. ''' cl = CoverLocale() cl.switch_locale(cl.Locale.LOCALE_DOMAIN) self.sorts = {'name': _('Sort by album name'), 'artist': _('Sort by album artist'), 'year': _('Sort by year'), 'rating': _('Sort by rating')} super(SortPopupButton, self).__init__( **kargs)
def __init__(self, plugin, parent, savedir=None): """Initializes and shows the cover :param plugin: source :type plugin: RBSource :param parent: Parent window to attach to :type parent: Gtk.Window :param savedir: Initial directory for the Save As functionality :type savedir: basestring """ super(CoverWindow, self).__init__() cl = CoverLocale() cl.switch_locale(cl.Locale.LOCALE_DOMAIN) self.builder = Gtk.Builder() self.builder.add_from_file(rb.find_plugin_file(plugin, 'ui/coverart_window.ui')) self.builder.connect_signals(self) self.cover_window = self.builder.get_object('CoverWindow') self.cover_window.connect('destroy', self.send_destroy_signal) self.layout = self.builder.get_object('layout') self.toolbar = self.builder.get_object('toolbar') self.save_as_button = self.builder.get_object('save_as_button') self.zoom_in_button = self.builder.get_object('zoom_in_button') self.zoom_out_button = self.builder.get_object('zoom_out_button') self.zoom_100_button = self.builder.get_object('zoom_100_button') self.zoom_fit_button = self.builder.get_object('zoom_fit_button') self.close_button = self.builder.get_object('close_button') self.image = self.builder.get_object('image') self.statusbar = self.builder.get_object('statusbar') self.scrolledwindow = self.builder.get_object('scrolledwindow') self.scrolledwindow.set_hadjustment(self.layout.get_hadjustment()) self.scrolledwindow.set_vadjustment(self.layout.get_vadjustment()) self.savedir = savedir if parent: self.cover_window.set_transient_for(parent) self.cover_window_width = 500 self.cover_window_height = 500 + self.toolbar.size_request().height + \ self.statusbar.size_request().height self.cover_window.set_default_size(self.cover_window_width, \ self.cover_window_height) self.min_percent = 1 self.max_percent = 500 self.ratio = 1.5 self.image_interp = GdkPixbuf.InterpType.BILINEAR self.image_fitted = True
def __init__(self, plugin, sprite_name, size=None): popups = rb.find_plugin_file(plugin, 'img/popups.xml') root = ET.parse(open(popups)).getroot() base = 'theme/theme[@folder_name="' + Theme(plugin).current \ + '"]/spritesheet[@name="' + sprite_name + '"]/' image = rb.find_plugin_file(plugin, 'img/' + Theme(plugin).current \ + '/' + root.xpath(base + 'image')[0].text) icon_width = int(root.xpath(base + 'icon')[0].attrib['width']) icon_height = int(root.xpath(base + 'icon')[0].attrib['height']) x_spacing = int(root.xpath(base + 'spacing')[0].attrib['x']) y_spacing = int(root.xpath(base + 'spacing')[0].attrib['y']) x_start = int(root.xpath(base + 'start-position')[0].attrib['x']) y_start = int(root.xpath(base + 'start-position')[0].attrib['y']) across_dimension = int( root.xpath(base + 'dimension')[0].attrib['across']) down_dimension = int(root.xpath(base + 'dimension')[0].attrib['down']) try: alpha_color = list( map(int, root.xpath(base + 'alpha')[0].text.split(' '))) except: alpha_color = None self.names = [] self.locale_names = {} cl = CoverLocale() lang = cl.get_locale() base = sprite_name + '/' + sprite_name + \ '[@spritesheet="' + sprite_name + '"]' for elem in root.xpath(base + '[not(@xml:lang)]'): self.names.append(elem.text) for elem in root.xpath(base + '[@xml:lang="' + lang + '"]'): self.locale_names[elem.text] = elem.attrib['name'] if (not self.locale_names) and len(lang) > 2: for elem in root.xpath(base + '[@xml:lang="' + \ lang[0:2] + '"]'): self.locale_names[elem.text] = elem.attrib['name'] self._sheet = SpriteSheet(image, icon_width, icon_height, x_spacing, y_spacing, x_start, y_start, across_dimension, down_dimension, alpha_color, size) self._genre_db = RB.ExtDB(name='cb_genre')
def on_artist_treeview_selection_changed(self, view): model, artist_iter = view.get_selected() if artist_iter: artist = model[artist_iter][0] cl = CoverLocale() cl.switch_locale(cl.Locale.RB) #. TRANSLATORS - "All" is used in the context of "All artist names" if artist == _('All'): self.album_manager.model.remove_filter('quick_artist') else: self.album_manager.model.replace_filter('quick_artist', artist) cl.switch_locale(cl.Locale.LOCALE_DOMAIN)
def __init__(self, plugin, album_model): super(DecadePopupController, self).__init__() self._album_model = album_model self.plugin = plugin self._spritesheet = None # decade options cl = CoverLocale() cl.switch_locale(cl.Locale.LOCALE_DOMAIN) self.values = OrderedDict() self.values[_('All Decades')] = [-1, 'All Decades'] #'20s' as in the decade 2010 self.values[_('20s')] = [2020, '20s'] #'10s' as in the decade 2010 self.values[_('10s')] = [2010, '10s'] #'00s' as in the decade 2000 self.values[_('00s')] = [2000, '00s'] #'90s' as in the decade 1990 self.values[_('90s')] = [1990, '90s'] #'80s' as in the decade 1980 self.values[_('80s')] = [1980, '80s'] #'70s' as in the decade 1970 self.values[_('70s')] = [1970, '70s'] #'60s' as in the decade 1960 self.values[_('60s')] = [1960, '60s'] #'50s' as in the decade 1950 self.values[_('50s')] = [1950, '50s'] #'40s' as in the decade 1940 self.values[_('40s')] = [1940, '40s'] #'30s' as in the decade 1930 self.values[_('30s')] = [1930, '30s'] #'Older' as in 'older than the year 1930' self.values[_('Older')] = [-1, 'Older'] self.options = self.values.keys() # if we aren't on the 20s yet, remove it if date.today().year < 2020: self.options.remove(_('20s')) # define a initial decade an set the initial key self._initial_decade = self.options[0] self.update_images(False) self.current_key = self._initial_decade
def __init__(self, plugin, album_model): super(DecadePopupController, self).__init__() self._album_model = album_model self.plugin = plugin self._spritesheet = None # decade options cl = CoverLocale() cl.switch_locale(cl.Locale.LOCALE_DOMAIN) self.values = OrderedDict() self.values[_('All Decades')] = [-1, 'All Decades'] #'20s' as in the decade 2010 self.values[_('20s')] = [2020, '20s'] #'10s' as in the decade 2010 self.values[_('10s')] = [2010, '10s'] #'00s' as in the decade 2000 self.values[_('00s')] = [2000, '00s'] #'90s' as in the decade 1990 self.values[_('90s')] = [1990, '90s'] #'80s' as in the decade 1980 self.values[_('80s')] = [1980, '80s'] #'70s' as in the decade 1970 self.values[_('70s')] = [1970, '70s'] #'60s' as in the decade 1960 self.values[_('60s')] = [1960, '60s'] #'50s' as in the decade 1950 self.values[_('50s')] = [1950, '50s'] #'40s' as in the decade 1940 self.values[_('40s')] = [1940, '40s'] #'30s' as in the decade 1930 self.values[_('30s')] = [1930, '30s'] #'Older' as in 'older than the year 1930' self.values[_('Older')] = [-1, 'Older'] self.options = list(self.values.keys()) # if we aren't on the 20s yet, remove it if date.today().year < 2020: self.options.remove(_('20s')) # define a initial decade an set the initial key self._initial_decade = self.options[0] self.update_images(False) self.current_key = self._initial_decade
def do_activate(self): ''' Called by Rhythmbox when the plugin is activated. It creates the plugin's source and connects signals to manage the plugin's preferences. ''' # define .plugin text strings used for translation plugin = _('CoverArt Browser') desc = _('Browse and play your albums through their covers') print("CoverArtBrowser DEBUG - do_activate") self.shell = self.object self.db = self.shell.props.db try: entry_type = CoverArtBrowserEntryType() self.db.register_entry_type(entry_type) except NotImplementedError: entry_type = self.db.entry_register_type( 'CoverArtBrowserEntryType') cl = CoverLocale() cl.switch_locale(cl.Locale.LOCALE_DOMAIN) entry_type.category = RB.RhythmDBEntryCategory.NORMAL # load plugin icon theme = Gtk.IconTheme.get_default() rb.append_plugin_source_path(theme, '/icons') what, width, height = Gtk.icon_size_lookup(Gtk.IconSize.LARGE_TOOLBAR) pxbf = GdkPixbuf.Pixbuf.new_from_file_at_size( rb.find_plugin_file(self, 'img/' + Theme(self).current\ + '/covermgr.png'), width, height) group = RB.DisplayPageGroup.get_by_id('library') self.source = CoverArtBrowserSource(shell=self.shell, name=_("CoverArt"), entry_type=entry_type, plugin=self, pixbuf=pxbf, query_model=self.shell.props.library_source.props.base_query_model) self.shell.register_entry_type_for_source(self.source, entry_type) self.shell.append_display_page(self.source, group) self.source.props.query_model.connect('complete', self.load_complete) print("CoverArtBrowser DEBUG - end do_activate")
def parse_album_info(self, data, album, index, lang): print('parse_album_info %s' % lang) self.fetched = self.fetched - 1 self.album_data[lang] = data if self.fetched > 0: print('return %d' % self.fetched) return cl = CoverLocale() lang = cl.get_locale()[:2] rv = True try: print('decoding') parsed = json.loads(self.album_data[lang].decode('utf-8')) print('decoded') self.albums[index]['id'] = parsed['album']['id'] for k in ('releasedate', 'summary'): self.albums[index][k] = parsed['album'].get(k) tracklist = [] print(parsed['album']) tracks = parsed['album']['tracks'].get('track', []) for i, t in enumerate(tracks): title = t['name'] duration = int(t['duration']) tracklist.append((i, title, duration)) self.albums[index]['tracklist'] = tracklist self.albums[index]['duration'] = sum([t[2] for t in tracklist]) if 'wiki' in parsed['album']: self.albums[index]['wiki-summary'] = parsed['album']['wiki'][ 'summary'] self.albums[index]['wiki-content'] = parsed['album']['wiki'][ 'content'] elif lang != 'en': parsed = json.loads(self.album_data['en'].decode('utf-8')) if 'wiki' in parsed['album']: self.albums[index]['wiki-summary'] = parsed['album'][ 'wiki']['summary'] self.albums[index]['wiki-content'] = parsed['album'][ 'wiki']['content'] except Exception as e: print("Error parsing album tracklist: %s" % e) rv = False self.fetching -= 1 print("%s albums left to process" % self.fetching) if self.fetching == 0: self.emit('albums-ready') return rv
def do_impl_activate(self): ''' Called by do_selected the first time the source is activated. It creates all the source ui and connects the necessary signals for it correct behavior. ''' print('do_impl_activate') self.hasActivated = True self.entryview = CoverArtPlayEntryView(self.shell, self.source) self.entryview.props.hexpand = True self.entryview.props.vexpand = True grid = Gtk.Grid() grid.attach(self.entryview, 0, 1, 1, 1) self.entryview.set_model(self.source.source_query_model) # enable sorting on the entryview # entryview.set_columns_clickable(True) self.shell.props.library_source.get_entry_view().set_columns_clickable( True) cl = CoverLocale() cl.switch_locale(cl.Locale.LOCALE_DOMAIN) location = rb.find_plugin_file(self.plugin, 'ui/playsource-toolbar.ui') ui = Gtk.Builder() ui.set_translation_domain(cl.Locale.RB) ui.add_from_file(location) toolbar_menu = ui.get_object('playsource-toolbar') app = self.shell.props.application app.link_shared_menus(toolbar_menu) bar = RB.ButtonBar.new(toolbar_menu, toolbar_menu) grid.attach(bar, 0, 0, 1, 1) grid.show_all() self.pack_start(grid, True, True, 0) appshell = ApplicationShell(self.shell) action_group = ActionGroup(self.shell, 'PlaySourceActions') action_group.add_action(func=self.clear_playsource, action_name='playsource-clear', action_state=ActionGroup.STANDARD, action_type='app') action_group.add_action(func=self.shuffle_playsource, action_name='playsource-shuffle', action_state=ActionGroup.STANDARD, action_type='app') appshell.insert_action_group(action_group)
def __init__(self, **kargs): ''' Initializes the button. ''' super(DecadePopupButton, self).__init__(**kargs) self._decade=OrderedDict([('All',-1), ('20s',2020), \ ('10s',2010), ('00s',2000), ('90s',1990), ('80s',1980), \ ('70s',1970), ('60s',1960), ('50s',1950), ('40s',1940), \ ('30s',1930), ('Old',-1)]) cl = CoverLocale() cl.switch_locale(cl.Locale.LOCALE_DOMAIN) self._translation={'All':_('All'), 'Old':_('Old')} self._initial='All'
def load_from_file(self, rb2_ui_filename, rb3_ui_filename): ''' utility function to load the menu structure :param rb2_ui_filename: `str` RB2.98 and below UI file :param rb3_ui_filename: `str` RB2.99 and higher UI file ''' self.builder = Gtk.Builder() try: from coverart_browser_prefs import CoverLocale cl = CoverLocale() self.builder.set_translation_domain(cl.Locale.LOCALE_DOMAIN) except: pass if is_rb3(self.shell): ui_filename = rb3_ui_filename else: ui_filename = rb2_ui_filename self.ui_filename = ui_filename self.builder.add_from_file( rb.find_plugin_file(self.plugin, ui_filename))
def __init__(self, plugin, sprite_name, size=None): popups = rb.find_plugin_file(plugin, 'img/popups.xml') root = ET.parse(open(popups)).getroot() base = 'theme/theme[@folder_name="' + Theme(plugin).current \ + '"]/spritesheet[@name="' + sprite_name + '"]/' image = rb.find_plugin_file(plugin, 'img/' + Theme(plugin).current \ + '/' + root.xpath(base + 'image')[0].text) icon_width = int(root.xpath(base + 'icon')[0].attrib['width']) icon_height = int(root.xpath(base + 'icon')[0].attrib['height']) x_spacing = int(root.xpath(base + 'spacing')[0].attrib['x']) y_spacing = int(root.xpath(base + 'spacing')[0].attrib['y']) x_start = int(root.xpath(base + 'start-position')[0].attrib['x']) y_start = int(root.xpath(base + 'start-position')[0].attrib['y']) across_dimension = int(root.xpath(base + 'dimension')[0].attrib['across']) down_dimension = int(root.xpath(base + 'dimension')[0].attrib['down']) try: alpha_color = list(map(int, root.xpath(base + 'alpha')[0].text.split(' '))) except: alpha_color = None self.names = [] self.locale_names = {} cl = CoverLocale() lang = cl.get_locale() base = sprite_name + '/' + sprite_name + \ '[@spritesheet="' + sprite_name + '"]' for elem in root.xpath(base + '[not(@xml:lang)]'): self.names.append(elem.text) for elem in root.xpath(base + '[@xml:lang="' + lang + '"]'): self.locale_names[elem.text] = elem.attrib['name'] if (not self.locale_names) and len(lang) > 2: for elem in root.xpath(base + '[@xml:lang="' + \ lang[0:2] + '"]'): self.locale_names[elem.text] = elem.attrib['name'] self._sheet = SpriteSheet(image, icon_width, icon_height, x_spacing, y_spacing, x_start, y_start, across_dimension, down_dimension, alpha_color, size) self._genre_db = RB.ExtDB(name='cb_genre')
def fetch_album_list(self, artist): if LastFM.user_has_account() is False: self.error = LASTFM_NO_ACCOUNT_ERROR self.emit('albums-ready') return cl = CoverLocale() lang = cl.get_locale()[:2] self.artist = artist qartist = urllib.parse.quote_plus(artist) self.error = None url = "%s?method=artist.gettopalbums&artist=%s&api_key=%s&format=json&lang=%s" % ( LastFM.API_URL, qartist, LastFM.API_KEY, lang) print(url) cachekey = 'lastfm:artist:gettopalbumsjson:%s' % qartist self.ranking_cache.fetch(cachekey, url, self.parse_album_list, artist)
def __init__(self, plugin, mainbox, controllers): super(Toolbar, self).__init__() self.plugin = plugin self.mainbox = mainbox cl = CoverLocale() ui_file = rb.find_plugin_file(plugin, self.ui) # create the toolbar builder = Gtk.Builder() builder.set_translation_domain(cl.Locale.LOCALE_DOMAIN) builder.add_from_file(ui_file) # assign the controllers to the buttons for button, controller in controllers.items(): if button != 'search': builder.get_object(button).controller = controller if not webkit_support(): button = builder.get_object('iconview_button') button.set_visible(False) button = builder.get_object('flowview_button') button.set_visible(False) separator = builder.get_object('properties_separator') if separator: separator.set_visible(False) # workaround to translate the search entry tooltips cl.switch_locale(cl.Locale.RB) search_entry = SearchEntry(has_popup=True) search_entry.show_all() cl.switch_locale(cl.Locale.LOCALE_DOMAIN) # add it to the ui align = builder.get_object('entry_search_alignment') align.add(search_entry) # assign the controller search_entry.controller = controllers['search'] Theme(self.plugin).connect('theme_changed', self._theme_changed, controllers) self.builder = builder.get_object('main_box')
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]
def _parse_popups(self, plugin, root, genre_type): icon_names = {} cl = CoverLocale() lang = cl.get_locale() base = self._sprite_name + '/alt' for elem in root.xpath(base + '[not(@xml:lang)]/alt'): self.genre_alternate[GenreType(name=elem.text, genre_type=genre_type)] = elem.attrib['genre'] for elem in root.xpath(base + '[@xml:lang="' + lang + '"]/alt'): self.genre_alternate[GenreType(name=elem.text, genre_type=self.GENRE_LOCALE)] = elem.attrib['genre'] # if (not self.locale_alternate) and len(lang) > 2: if len(lang) > 2: for elem in root.xpath(base + '[@xml:lang="' + \ lang[0:2] + '"]/alt'): self.genre_alternate[GenreType(name=elem.text, genre_type=self.GENRE_LOCALE)] = elem.attrib['genre']
def __init__(self, info_cache, ranking_cache): GObject.GObject.__init__(self) self.current_artist = None self.error = None cl = CoverLocale() lang = cl.get_locale()[:2] self.artist = { 'info_en': { 'data': None, 'function': 'getinfo', 'cache': info_cache, 'signal': 'artist-info-ready', 'parsed': False, 'lang': 'en' }, 'similar_en': { 'data': None, 'function': 'getsimilar', 'cache': info_cache, 'signal': 'artist-info-ready', 'parsed': False, 'lang': 'en' } } if lang != 'en': self.artist['info_' + lang] = { 'data': None, 'function': 'getinfo', 'cache': info_cache, 'signal': 'artist-info-ready', 'parsed': False, 'lang': lang } self.artist['similar_' + lang] = { 'data': None, 'function': 'getsimilar', 'cache': info_cache, 'signal': 'artist-info-ready', 'parsed': False, 'lang': lang }
def album_list_ready(self, ds): print("album_list_ready") cl = CoverLocale() # cl.switch_locale(cl.Locale.LOCALE_DOMAIN) self.file = self.album_template.render( error=ds.get_error(), albums=ds.get_top_albums(), artist=ds.get_artist(), datasource=lastfm_datasource_link(self.basepath), stylesheet=self.styles) self.load_view()
def loading(self, current_artist, current_album_title): cl = CoverLocale() # cl.switch_locale(cl.Locale.LOCALE_DOMAIN) self.loading_file = self.loading_template.render( artist=current_artist, # Translators: 'top' here means 'most popular'. %s is replaced by the artist name. info=_("Loading top albums for %s") % current_artist, song="", basepath=self.basepath) self.webview.load_string(self.loading_file, 'text/html', 'utf-8', self.basepath)
def _create_menu(self): # for the standard menu control button add the button # to all supported view types app = Gio.Application.get_default() self.app_id = 'coverart-browser' action_name = 'coverart-browser-views' self.action = Gio.SimpleAction.new_stateful( action_name, GLib.VariantType.new('s'), self._views.get_action_name(ListView.name)) self.action.connect("activate", self.view_change_cb) app.add_action(self.action) menu_item = Gio.MenuItem() section = Gio.Menu() menu = Gio.Menu() toolbar_item = Gio.MenuItem() for view_name in self._views.get_view_names(): menu_item.set_label(self._views.get_menu_name(view_name)) menu_item.set_action_and_target_value( 'app.' + action_name, self._views.get_action_name(view_name)) section.append_item(menu_item) menu.append_section(None, section) cl = CoverLocale() cl.switch_locale(cl.Locale.LOCALE_DOMAIN) toolbar_item.set_label('…') cl.switch_locale(cl.Locale.RB) toolbar_item.set_submenu(menu) for location in self.locations: app.add_plugin_menu_item(location, self.app_id, toolbar_item)
def get_artist_info(self): """ Returns the dictionary { 'images', 'bio' } """ cl = CoverLocale() lang = cl.get_locale()[:2] images = self.get_artist_images() def fill_info(lang): if not self.artist['info_' + lang]['parsed']: bio = self.get_artist_bio() self.artist['info_' + lang]['data'] = { 'images': images, 'bio': bio } self.artist['info_' + lang]['parsed'] = True return self.artist['info_' + lang]['data'] fill_info('en') return fill_info(lang)
def _parse_popups(self, plugin, root, genre_type): icon_names = {} cl = CoverLocale() lang = cl.get_locale() base = self._sprite_name + '/alt' for elem in root.xpath(base + '[not(@xml:lang)]/alt'): self.genre_alternate[GenreType( name=elem.text, genre_type=genre_type)] = elem.attrib['genre'] for elem in root.xpath(base + '[@xml:lang="' + lang + '"]/alt'): self.genre_alternate[GenreType( name=elem.text, genre_type=self.GENRE_LOCALE)] = elem.attrib['genre'] # if (not self.locale_alternate) and len(lang) > 2: if len(lang) > 2: for elem in root.xpath(base + '[@xml:lang="' + \ lang[0:2] + '"]/alt'): self.genre_alternate[GenreType( name=elem.text, genre_type=self.GENRE_LOCALE)] = elem.attrib['genre']
def fetch_album_info(self, artist, album, index): print('start fetch_album_info') cl = CoverLocale() lang = cl.get_locale()[:2] qartist = urllib.parse.quote_plus(artist) qalbum = urllib.parse.quote_plus(album) self.fetched = 2 def fetch_information(lang): cachekey = "lastfm:album:getinfojson:%s:%s:%s" % (qartist, qalbum, lang) url = "%s?method=album.getinfo&artist=%s&album=%s&api_key=%s&format=json&lang=%s" % ( LastFM.API_URL, qartist, qalbum, LastFM.API_KEY, lang) print(url) self.info_cache.fetch(cachekey, url, self.parse_album_info, album, index, lang) self.album_data = {} fetch_information('en') fetch_information(lang) print('end fetch_album_info')
def loading(self, current_artist, current_album_title): cl = CoverLocale() # cl.switch_locale(cl.Locale.LOCALE_DOMAIN) self.link_ds.set_artist(current_artist) self.link_ds.set_album(current_album_title) self.loading_file = self.loading_template.render( artist=current_artist, info=_("Loading biography for %s") % current_artist, song="", basepath=self.basepath) self.webview.load_string(self.loading_file, 'text/html', 'utf-8', self.basepath)
def __init__(self, plugin, mainbox, controllers): super(Toolbar, self).__init__() self.plugin = plugin self.mainbox = mainbox cl = CoverLocale() ui_file = rb.find_plugin_file(plugin, self.ui) # create the toolbar builder = Gtk.Builder() builder.set_translation_domain(cl.Locale.LOCALE_DOMAIN) print (ui_file) builder.add_from_file(ui_file) # assign the controllers to the buttons for button, controller in controllers.items(): if button != 'search': builder.get_object(button).controller = controller if not webkit_support(): # button = builder.get_object('flowview_button') #button.set_visible(False) separator = builder.get_object('properties_separator') if separator: separator.set_visible(False) # workaround to translate the search entry tooltips cl.switch_locale(cl.Locale.RB) search_entry = SearchEntry(has_popup=True) search_entry.show_all() cl.switch_locale(cl.Locale.LOCALE_DOMAIN) # add it to the ui align = builder.get_object('entry_search_alignment') align.add(search_entry) # assign the controller search_entry.controller = controllers['search'] Theme(self.plugin).connect('theme_changed', self._theme_changed, controllers) self.builder = builder.get_object('toolbar') # now theme the toolbar including child objects such as the button popups style_context = self.builder.get_style_context() style_context.add_class(Gtk.STYLE_CLASS_TOOLBAR) view_button = builder.get_object(ToolbarObject.VIEW) view_button.set_visible(not self.plugin.using_headerbar)
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.display_columns() cl.switch_locale(cl.Locale.LOCALE_DOMAIN) self.define_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.actiongroup = ActionGroup(self.shell, 'coverentryplaylist_submenu') self.external_plugins = None self.source_query_model = self.source.source_query_model # RB.RhythmDBQueryModel.new_empty(self.shell.props.db) self.qm = RB.RhythmDBQueryModel.new_empty(self.shell.props.db) self.set_model(self.qm) self.connect_library_signals() self.echonest_similar_playlist = None self.echonest_similar_genre_playlist = None self.lastfm_similar_playlist = None self.connect('selection-changed', self.selection_changed) self.artists = "" print("end constructor")