def plugin_songs(self, songs): # Check this is a launch, not a configure if self.chosen_site: url_pat = self.get_url_pattern(self.chosen_site) pat = Pattern(url_pat) urls = set() for song in songs: # Generate a sanitised AudioFile; allow through most tags subs = AudioFile() for k in (USER_TAGS + MACHINE_TAGS): vals = song.comma(k) if vals: try: encoded = unicode(vals).encode('utf-8') subs[k] = (encoded if k == 'website' else quote_plus(encoded)) # Dodgy unicode problems except KeyError: print_d("Problem with %s tag values: %r" % (k, vals)) url = str(pat.format(subs)) if not url: print_w("Couldn't build URL using \"%s\"." "Check your pattern?" % url_pat) return # Grr, set.add() should return boolean... if url not in urls: urls.add(url) website(url)
def plugin_songs(self, songs): # Check this is a launch, not a configure if self.chosen_site: url_pat = self.get_url_pattern(self.chosen_site) pat = Pattern(url_pat) urls = set() for song in songs: # Generate a sanitised AudioFile; allow through most tags subs = AudioFile() for k in (USER_TAGS + MACHINE_TAGS): vals = song.comma(k) if vals: try: encoded = text_type(vals).encode('utf-8') subs[k] = (encoded if k == 'website' else quote_plus(encoded)) # Dodgy unicode problems except KeyError: print_d("Problem with %s tag values: %r" % (k, vals)) url = str(pat.format(subs)) if not url: print_w("Couldn't build URL using \"%s\"." "Check your pattern?" % url_pat) return # Grr, set.add() should return boolean... if url not in urls: urls.add(url) website(url)
def plugin_songs(self, songs): # Check this is a launch, not a configure if self.chosen_site: url_pat = self.get_url_pattern(self.chosen_site) pat = Pattern(url_pat) urls = set() for song in songs: # Generate a sanitised AudioFile; allow through most tags subs = AudioFile() for k, v in song.items(): if k in (STANDARD_TAGS + MACHINE_TAGS): try: subs[k] = quote(unicode(v).encode('utf-8')) # Dodgy unicode problems except KeyError: print_d("Problem with %s tag value: %r" % (k, v)) url = str(pat.format(subs)) if not url: print_w("Couldn't build URL using \"%s\"." "Check your pattern?" % url_pat) return # Grr, set.add() should return boolean... if url not in urls: urls.add(url) website(url)
def __view_online(self, add, song): # TODO: make this modular and plugin-friendly (#54, #3642 etc) def sanitise(s: str) -> str: return quote( s.replace(" ", "-").replace(".", "").replace("'", "").replace( '"', "").replace(",", "-").lower().encode('utf-8')) artist = sanitise(song.list('artist')[0]) title = sanitise(song.comma('title')) util.website(f"https://genius.com/{artist}-{title}-lyrics")
def show_shortcuts(parent): """Either opens a window showing keyboard shortcuts or a website in the default browser, depending on the Gtk+ version """ if has_shortcut_window(): window = build_shortcut_window(SHORTCUTS) window.set_transient_for(parent) window.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) window.set_modal(True) window.show() else: util.website(const.SHORTCUTS_HELP)
def run_error_dialogs(exc_info, sentry_error): error_text = u"%s: %s" % (exc_info[0].__name__, (text_type(exc_info[1]).strip() or u"\n").splitlines()[0]) error_text += u"\n------\n" error_text += u"\n".join(format_exception(*exc_info)) # Don't reshow the error dialog in case the user wanted to quit the app # but due to the error state more errors pile up.. if app.is_quitting: return window = find_active_window() if window is None: return # XXX: This does blocking IO and uses nested event loops... but it's simple dialog = ErrorDialog(window, error_text, show_bug_report=(sentry_error is None)) while 1: response = dialog.run() if response == ErrorDialog.RESPONSE_QUIT: dialog.destroy() app.quit() elif response == ErrorDialog.RESPONSE_SUBMIT: dialog.hide() submit_dialog = SubmitErrorDialog(window, sentry_error.get_report()) submit_response = submit_dialog.run() if submit_response == SubmitErrorDialog.RESPONSE_SUBMIT: sentry_error.set_comment(submit_dialog.get_comment()) timeout_seconds = 5 try: sentry_error.send(timeout_seconds) except SentryError: print_exc() submit_dialog.destroy() dialog.destroy() else: submit_dialog.destroy() dialog.show() continue elif response == ErrorDialog.RESPONSE_BUGREPORT: url = get_github_issue_url(exc_info) website(url) dialog.destroy() else: dialog.destroy() break
def plugin_songs(self, songs): if not self.selected_tag: return l = dict.fromkeys([song(self.selected_tag) for song in songs]).keys() # If no tags values were found, show an error dialog if list(l) == ['']: ErrorMessage(app.window, _('Search failed'), _('Tag "%s" not found.') % self.selected_tag).run() return for a in l: # Only search for non-empty tags if a: a = quote(str(a).title().replace(' ', '_')) util.website(WIKI_URL % get_lang() + a)
def PluginPreferences(self, win): box = Gtk.VBox(spacing=12) # api key section def key_changed(entry, *args): config.set("plugins", "fingerprint_acoustid_api_key", entry.get_text()) button = Button(_("Request API key"), Gtk.STOCK_NETWORK) button.connect("clicked", lambda s: util.website("https://acoustid.org/api-key")) key_box = Gtk.HBox(spacing=6) entry = UndoEntry() entry.set_text(get_api_key()) entry.connect("changed", key_changed) label = Gtk.Label(label=_("API _key:")) label.set_use_underline(True) label.set_mnemonic_widget(entry) key_box.pack_start(label, False, True, 0) key_box.pack_start(entry, True, True, 0) key_box.pack_start(button, False, True, 0) box.pack_start(Frame(_("Acoustid Web Service"), child=key_box), True, True, 0) return box
def plugin_songs(self, songs, launch=True) -> bool: # Check this is a launch, not a configure if self.chosen_site: url_pat = self.get_url_pattern(self.chosen_site) pat = Pattern(url_pat) # Remove Nones, and de-duplicate collection urls = set(filter(None, (website_for(pat, s) for s in songs))) if not urls: print_w("Couldn't build URLs using \"%s\"." "Check your pattern?" % url_pat) return False print_d("Got %d websites from %d songs" % (len(urls), len(songs))) if launch: for url in urls: website(url) return True
def PluginPreferences(self, win): box = Gtk.VBox(spacing=12) # api key section def key_changed(entry, *args): config.set("plugins", "fingerprint_acoustid_api_key", entry.get_text()) button = Button(_("Request API key"), Icons.NETWORK_WORKGROUP) button.connect("clicked", lambda s: util.website("https://acoustid.org/api-key")) key_box = Gtk.HBox(spacing=6) entry = UndoEntry() entry.set_text(get_api_key()) entry.connect("changed", key_changed) label = Gtk.Label(label=_("API _key:")) label.set_use_underline(True) label.set_mnemonic_widget(entry) key_box.pack_start(label, False, True, 0) key_box.pack_start(entry, True, True, 0) key_box.pack_start(button, False, True, 0) box.pack_start(Frame(_("AcoustID Web Service"), child=key_box), True, True, 0) return box
def run_error_dialogs(exc_info, sentry_error): error_text = u"%s: %s" % ( exc_info[0].__name__, (text_type(exc_info[1]).strip() or u"\n").splitlines()[0]) error_text += u"\n------\n" error_text += u"\n".join(format_exception(*exc_info)) window = find_active_window() if window is None: return # XXX: This does blocking IO and uses nested event loops... but it's simple dialog = ErrorDialog( window, error_text, show_bug_report=(sentry_error is None)) while 1: response = dialog.run() if response == ErrorDialog.RESPONSE_QUIT: dialog.destroy() app.quit() elif response == ErrorDialog.RESPONSE_SUBMIT: dialog.hide() submit_dialog = SubmitErrorDialog( window, sentry_error.get_report()) submit_response = submit_dialog.run() if submit_response == SubmitErrorDialog.RESPONSE_SUBMIT: sentry_error.set_comment(submit_dialog.get_comment()) timeout_seconds = 5 try: sentry_error.send(timeout_seconds) except SentryError: print_exc() submit_dialog.destroy() dialog.destroy() else: submit_dialog.destroy() dialog.show() continue elif response == ErrorDialog.RESPONSE_BUGREPORT: url = get_github_issue_url(exc_info) website(url) dialog.destroy() else: dialog.destroy() break
def show_shortcuts(parent): """Either opens a window showing keyboard shortcuts or a website in the default browser, depending on the Gtk+ version """ if has_shortcut_window(): window = build_shortcut_window(SHORTCUTS) window.set_transient_for(parent) window.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) window.set_modal(True) window.show() # XXX: The windows does some weird size changes on start which confuses # window placement. This fixes the jumping around and wrong position # with some WMs and under Windows. window.hide() window.show() else: util.website(const.SHORTCUTS_HELP)
def _create_footer(self): hbox = Gtk.HBox() button = Gtk.Button(always_show_image=True, relief=Gtk.ReliefStyle.NONE) button.connect('clicked', lambda _: website(SITE_URL)) button.set_tooltip_text(_("Go to %s" % SITE_URL)) button.add(self._logo_image) hbox.pack_start(button, True, True, 6) hbox.show_all() return hbox
def PluginPreferences(cls, window): table = Gtk.Table(n_rows=len(engines), n_columns=2) table.props.expand = False table.set_col_spacings(6) table.set_row_spacings(6) frame = qltk.Frame(_("Sources"), child=table) for i, eng in enumerate(sorted(engines, key=lambda x: x["url"])): check = cls.ConfigCheckButton(eng["config_id"].title(), CONFIG_ENG_PREFIX + eng["config_id"], True) table.attach(check, 0, 1, i, i + 1) button = Gtk.Button(label=eng["url"]) button.connect("clicked", lambda s: util.website(s.get_label())) table.attach(button, 1, 2, i, i + 1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) return frame
def PluginPreferences(cls, window): table = Gtk.Table(len(engines), 2) table.set_col_spacings(6) table.set_row_spacings(6) frame = qltk.Frame(_("Sources"), child=table) for i, eng in enumerate(sorted(engines, key=lambda x: x["url"])): check = cls.ConfigCheckButton( eng['config_id'].title(), CONFIG_ENG_PREFIX + eng['config_id'], True) table.attach(check, 0, 1, i, i + 1) button = Gtk.Button(eng['url']) button.connect('clicked', lambda s: util.website(s.get_label())) table.attach(button, 1, 2, i, i + 1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK) return frame
def __view_online(self, add, song): artist = song.comma('artist').encode('utf-8') title = song.comma('title').encode('utf-8') util.website("http://lyrics.wikia.com/%s:%s" % (quote(artist), quote(title)))
def plugin_songs(self, songs): l = dict.fromkeys([song(self.k) for song in songs]).keys() for a in l: a = quote(str(a).title().replace(' ', '_')) website(WIKI_URL % get_lang() + a)
def __add(self, add, song): artist = song.comma("artist").encode("utf-8") util.website("http://lyricwiki.org/%s" % (urllib.quote(artist)))
def __add(self, add, song): artist = song.comma('artist').encode('utf-8') util.website("http://lyricwiki.org/%s" % (urllib.quote(artist)))
def search_help_handler(*args): util.website(const.SEARCH_HELP)
def website_handler(*args): util.website(const.ONLINE_HELP)
def authenticate_user(self): # create client object with app credentials if self.access_token: print_d("Ignoring saved Soundcloud token...") # redirect user to authorize URL website(self._authorize_url)
def __add(self, add, song): artist = song.comma('artist').encode('utf-8') util.website("http://lyricwiki.org/%s" % (quote(artist)))
def plugin_songs(self, songs): l = dict.fromkeys([song(self.k) for song in songs]).keys() for a in l: a = quote(str(a).title().replace(' ', '_')) website(WIKI_URL % config.get('plugins', __name__) + a)