diff --git a/picard/acoustid.py b/picard/acoustid.py index f38766fca..ecbc98471 100644 --- a/picard/acoustid.py +++ b/picard/acoustid.py @@ -19,6 +19,7 @@ from collections import deque from PyQt4 import QtCore +from picard import config, log from picard.const import ACOUSTID_KEY, FPCALC_NAMES from picard.util import partial, call_next, find_executable from picard.webservice import XmlNode @@ -32,10 +33,10 @@ class AcoustIDClient(QtCore.QObject): self._running = 0 self._max_processes = 2 - if not self.config.setting["acoustid_fpcalc"]: + if not config.setting["acoustid_fpcalc"]: fpcalc_path = find_executable(*FPCALC_NAMES) if fpcalc_path: - self.config.setting["acoustid_fpcalc"] = fpcalc_path + config.setting["acoustid_fpcalc"] = fpcalc_path def init(self): pass @@ -106,7 +107,7 @@ class AcoustIDClient(QtCore.QObject): parse_recording(recording) else: error_message = document.response[0].error[0].message[0].text - self.log.error("Fingerprint lookup failed: %r", error_message) + log.error("Fingerprint lookup failed: %r", error_message) next(doc, http, error) @@ -161,7 +162,7 @@ class AcoustIDClient(QtCore.QObject): if fingerprint and duration: result = 'fingerprint', fingerprint, duration else: - self.log.error("Fingerprint calculator failed exit code = %r, exit status = %r, error = %s", exit_code, exit_status, unicode(process.errorString())) + log.error("Fingerprint calculator failed exit code = %r, exit status = %r, error = %s", exit_code, exit_status, unicode(process.errorString())) finally: next(result) @@ -174,7 +175,7 @@ class AcoustIDClient(QtCore.QObject): try: self._running -= 1 self._run_next_task() - self.log.error("Fingerprint calculator failed error = %s (%r)", unicode(process.errorString()), error) + log.error("Fingerprint calculator failed error = %s (%r)", unicode(process.errorString()), error) finally: next(None) @@ -183,14 +184,14 @@ class AcoustIDClient(QtCore.QObject): file, next = self._queue.popleft() except IndexError: return - fpcalc = self.config.setting["acoustid_fpcalc"] or "fpcalc" + fpcalc = config.setting["acoustid_fpcalc"] or "fpcalc" self._running += 1 process = QtCore.QProcess(self) process.setProperty('picard_finished', QtCore.QVariant(False)) process.finished.connect(partial(self._on_fpcalc_finished, next, file)) process.error.connect(partial(self._on_fpcalc_error, next, file)) process.start(fpcalc, ["-length", "120", file.filename]) - self.log.debug("Starting fingerprint calculator %r %r", fpcalc, file.filename) + log.debug("Starting fingerprint calculator %r %r", fpcalc, file.filename) def analyze(self, file, next): fpcalc_next = partial(self._lookup_fingerprint, next, file.filename) diff --git a/picard/album.py b/picard/album.py index 7a744002f..3a338e54e 100644 --- a/picard/album.py +++ b/picard/album.py @@ -20,6 +20,7 @@ import traceback from PyQt4 import QtCore, QtNetwork +from picard import config, log from picard.coverart import coverart from picard.metadata import (Metadata, register_album_metadata_processor, @@ -74,7 +75,7 @@ class Album(DataObject, Item): yield file def _parse_release(self, document): - self.log.debug("Loading release %r", self.id) + log.debug("Loading release %r", self.id) self._tracks_loaded = False release_node = document.metadata[0].release[0] @@ -82,7 +83,7 @@ class Album(DataObject, Item): self.tagger.mbid_redirects[self.id] = release_node.id album = self.tagger.albums.get(release_node.id) if album: - self.log.debug("Release %r already loaded", release_node.id) + log.debug("Release %r already loaded", release_node.id) album.match_files(self.unmatched_files.files) album.update() self.tagger.remove_album(self) @@ -101,19 +102,19 @@ class Album(DataObject, Item): rg.loaded_albums.add(self.id) rg.refcount += 1 - release_group_to_metadata(rg_node, rg.metadata, self.config, rg) + release_group_to_metadata(rg_node, rg.metadata, rg) m.copy(rg.metadata) - release_to_metadata(release_node, m, config=self.config, album=self) + release_to_metadata(release_node, m, album=self) if self._discid: m['musicbrainz_discid'] = self._discid # Custom VA name if m['musicbrainz_albumartistid'] == VARIOUS_ARTISTS_ID: - m['albumartistsort'] = m['albumartist'] = self.config.setting['va_name'] + m['albumartistsort'] = m['albumartist'] = config.setting['va_name'] # Convert Unicode punctuation - if self.config.setting['convert_punctuation']: + if config.setting['convert_punctuation']: m.apply_func(asciipunct) m['totaldiscs'] = release_node.medium_list[0].count @@ -121,7 +122,7 @@ class Album(DataObject, Item): # Add album to collections if "collection_list" in release_node.children: for node in release_node.collection_list[0].collection: - if node.editor[0].text.lower() == self.config.setting["username"].lower(): + if node.editor[0].text.lower() == config.setting["username"].lower(): if node.id not in user_collections: user_collections[node.id] = \ Collection(node.id, node.name[0].text, node.release_list[0].count) @@ -131,7 +132,7 @@ class Album(DataObject, Item): try: run_album_metadata_processors(self, m, release_node) except: - self.log.error(traceback.format_exc()) + log.error(traceback.format_exc()) self._release_node = release_node return True @@ -143,11 +144,11 @@ class Album(DataObject, Item): parsed = False try: if error: - self.log.error("%r", unicode(http.errorString())) + log.error("%r", unicode(http.errorString())) # Fix for broken NAT releases if error == QtNetwork.QNetworkReply.ContentNotFoundError: nats = False - nat_name = self.config.setting["nat_name"] + nat_name = config.setting["nat_name"] files = list(self.unmatched_files.files) for file in files: trackid = file.metadata["musicbrainz_trackid"] @@ -163,7 +164,7 @@ class Album(DataObject, Item): parsed = self._parse_release(document) except: error = True - self.log.error(traceback.format_exc()) + log.error(traceback.format_exc()) finally: self._requests -= 1 if parsed or error: @@ -205,7 +206,7 @@ class Album(DataObject, Item): # Get track metadata tm = track.metadata tm.copy(mm) - track_to_metadata(track_node, track, self.config) + track_to_metadata(track_node, track) track._customize_metadata() self._new_metadata.length += tm.length @@ -215,7 +216,7 @@ class Album(DataObject, Item): try: run_track_metadata_processors(self, tm, self._release_node, track_node) except: - self.log.error(traceback.format_exc()) + log.error(traceback.format_exc()) totalalbumtracks = str(totalalbumtracks) @@ -229,8 +230,8 @@ class Album(DataObject, Item): if not self._requests: # Prepare parser for user's script - if self.config.setting["enable_tagger_script"]: - script = self.config.setting["tagger_script"] + if config.setting["enable_tagger_script"]: + script = config.setting["tagger_script"] if script: parser = ScriptParser() for track in self._new_tracks: @@ -238,14 +239,14 @@ class Album(DataObject, Item): try: parser.eval(script, track.metadata) except: - self.log.error(traceback.format_exc()) + log.error(traceback.format_exc()) # Strip leading/trailing whitespace track.metadata.strip_whitespace() # Run tagger script for the album itself try: parser.eval(script, self._new_metadata) except: - self.log.error(traceback.format_exc()) + log.error(traceback.format_exc()) self._new_metadata.strip_whitespace() for track in self.tracks: @@ -265,7 +266,7 @@ class Album(DataObject, Item): def load(self): if self._requests: - self.log.info("Not reloading, some requests are still active.") + log.info("Not reloading, some requests are still active.") return self.tagger.window.set_statusbar_message('Loading album %s...', self.id) self.loaded = False @@ -282,17 +283,17 @@ class Album(DataObject, Item): require_authentication = False inc = ['release-groups', 'media', 'recordings', 'artist-credits', 'artists', 'aliases', 'labels', 'isrcs', 'collections'] - if self.config.setting['release_ars'] or self.config.setting['track_ars']: + if config.setting['release_ars'] or config.setting['track_ars']: inc += ['artist-rels', 'release-rels', 'url-rels', 'recording-rels', 'work-rels'] - if self.config.setting['track_ars']: + if config.setting['track_ars']: inc += ['recording-level-rels', 'work-level-rels'] - if self.config.setting['folksonomy_tags']: - if self.config.setting['only_my_tags']: + if config.setting['folksonomy_tags']: + if config.setting['only_my_tags']: require_authentication = True inc += ['user-tags'] else: inc += ['tags'] - if self.config.setting['enable_ratings']: + if config.setting['enable_ratings']: require_authentication = True inc += ['user-ratings'] self.load_task = self.tagger.xmlws.get_release_by_id( @@ -334,7 +335,7 @@ class Album(DataObject, Item): if not matches: for track in self.tracks: sim = track.metadata.compare(file.orig_metadata) - if sim >= self.config.setting['track_matching_threshold']: + if sim >= config.setting['track_matching_threshold']: matches.append((sim, track)) if matches: matches.sort(reverse=True) @@ -478,7 +479,7 @@ class NatAlbum(Album): self.update() def update(self, update_tracks=True): - self.metadata["album"] = self.config.setting["nat_name"] + self.metadata["album"] = config.setting["nat_name"] for track in self.tracks: track.metadata["album"] = self.metadata["album"] for file in track.linked_files: diff --git a/picard/browser/browser.py b/picard/browser/browser.py index 0d84ff4d6..f2fce7837 100644 --- a/picard/browser/browser.py +++ b/picard/browser/browser.py @@ -18,6 +18,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. from PyQt4 import QtCore, QtNetwork +from picard import log class BrowserIntegration(QtNetwork.QTcpServer): @@ -30,14 +31,14 @@ class BrowserIntegration(QtNetwork.QTcpServer): def start(self): self.port = 8000 while self.port < 65535: - self.log.debug("Starting the browser integration (port %d)", self.port) + log.debug("Starting the browser integration (port %d)", self.port) if self.listen(QtNetwork.QHostAddress(QtNetwork.QHostAddress.Any), self.port): self.tagger.listen_port_changed.emit(self.port) break self.port += 1 def stop(self): - self.log.debug("Stopping the browser integration") + log.debug("Stopping the browser integration") self.close() def process_request(self): @@ -46,7 +47,7 @@ class BrowserIntegration(QtNetwork.QTcpServer): conn.write("HTTP/1.1 200 OK\r\nCache-Control: max-age=0\r\n\r\nNothing to see here.") conn.disconnectFromHost() line = line.split() - self.log.debug("Browser integration request: %r", line) + log.debug("Browser integration request: %r", line) if line[0] == "GET" and "?" in line[1]: action, args = line[1].split("?") args = [a.split("=", 1) for a in args.split("&")] @@ -56,7 +57,7 @@ class BrowserIntegration(QtNetwork.QTcpServer): elif action == "/opennat": self.tagger.load_nat(args["id"]) else: - self.log.error("Unknown browser integration request: %r", action) + log.error("Unknown browser integration request: %r", action) def accept_connection(self): conn = self.nextPendingConnection() diff --git a/picard/cluster.py b/picard/cluster.py index 4fcd18149..cc1901240 100644 --- a/picard/cluster.py +++ b/picard/cluster.py @@ -22,6 +22,7 @@ import re from operator import itemgetter from heapq import heappush, heappop from PyQt4 import QtCore +from picard import config from picard.metadata import Metadata from picard.similarity import similarity2, similarity from picard.ui.item import Item @@ -155,7 +156,7 @@ class Cluster(QtCore.QObject, Item): release, Cluster.comparison_weights) for release in releases), reverse=True, key=itemgetter(0))[0] - if match[0] < self.config.setting['cluster_lookup_threshold']: + if match[0] < config.setting['cluster_lookup_threshold']: self.tagger.window.set_statusbar_message(N_("No matching releases for cluster %s"), self.metadata['album'], timeout=3000) return self.tagger.window.set_statusbar_message(N_("Cluster %s identified!"), self.metadata['album'], timeout=3000) diff --git a/picard/collection.py b/picard/collection.py index c10ed5770..1f49cd559 100644 --- a/picard/collection.py +++ b/picard/collection.py @@ -18,6 +18,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. from PyQt4 import QtCore +from picard import config from picard.util import partial @@ -98,6 +99,5 @@ def load_user_collections(callback=None): if callback: callback() - setting = QtCore.QObject.config.setting - if setting["username"] and setting["password"]: + if config.setting["username"] and config.setting["password"]: tagger.xmlws.get_collection_list(partial(request_finished)) diff --git a/picard/config.py b/picard/config.py index 2b7f38338..d7ea9b127 100644 --- a/picard/config.py +++ b/picard/config.py @@ -21,10 +21,6 @@ from PyQt4 import QtCore from picard.util import LockableObject, rot13 -class ConfigError(Exception): - pass - - class ConfigSection(LockableObject): """Configuration section.""" @@ -64,6 +60,7 @@ class ConfigSection(LockableObject): if self.__config.contains(key): self.__config.remove(key) + class Config(QtCore.QSettings): """Configuration.""" @@ -81,7 +78,7 @@ class Config(QtCore.QSettings): if self.contains(key): self.profile.name = key else: - raise ConfigError, "Unknown profile '%s'" % (profilename,) + raise KeyError, "Unknown profile '%s'" % (profilename,) class Option(QtCore.QObject): @@ -147,3 +144,9 @@ class PasswordOption(Option): def convert(value): return rot13(unicode(value.toString())) Option.__init__(self, section, name, default, convert) + + +_config = Config() + +setting = _config.setting +persist = _config.persist diff --git a/picard/const.py b/picard/const.py index f43802478..c36edb276 100644 --- a/picard/const.py +++ b/picard/const.py @@ -17,10 +17,24 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +import os, sys + # Install gettext "noop" function in case const.py gets imported directly. import __builtin__ __builtin__.__dict__['N_'] = lambda a: a +# Config directory +if sys.platform == "win32": + USER_DIR = os.environ.get("APPDATA", "~\\Application Data") +else: + USER_DIR = os.environ.get("XDG_CONFIG_HOME", "~/.config") + +USER_DIR = os.path.join( + os.path.expanduser(USER_DIR), "MusicBrainz", "Picard" +) + +USER_PLUGIN_DIR = os.path.join(USER_DIR, "plugins") + # AcoustID client API key ACOUSTID_KEY = '0zClDiGo' ACOUSTID_HOST = 'api.acoustid.org' diff --git a/picard/coverart.py b/picard/coverart.py index 6ca896650..17f6b44f8 100644 --- a/picard/coverart.py +++ b/picard/coverart.py @@ -25,6 +25,7 @@ import re import traceback import picard.webservice +from picard import config, log from picard.util import partial, mimetype from PyQt4.QtCore import QUrl, QObject @@ -88,13 +89,13 @@ def _coverart_downloaded(album, metadata, release, try_list, imagedata, data, ht if error or len(data) < 1000: if error: - album.log.error(str(http.errorString())) + log.error(str(http.errorString())) else: QObject.tagger.window.set_statusbar_message(N_("Coverart %s downloaded"), http.url().toString()) mime = mimetype.get_from_data(data, default="image/jpeg") filename = None - if imagetype != 'front' and QObject.config.setting["caa_image_type_as_filename"]: + if imagetype != 'front' and config.setting["caa_image_type_as_filename"]: filename = imagetype metadata.add_image(mime, data, filename, imagedata["description"], imagetype) @@ -116,17 +117,17 @@ def _caa_json_downloaded(album, metadata, release, try_list, data, http, error): album._requests -= 1 caa_front_found = False if error: - album.log.error(str(http.errorString())) + log.error(str(http.errorString())) else: try: caa_data = json.loads(data) except ValueError: - QObject.log.debug("Invalid JSON: %s", http.url().toString()) + log.debug("Invalid JSON: %s", http.url().toString()) else: - caa_types = QObject.config.setting["caa_image_types"].split() + caa_types = config.setting["caa_image_types"].split() caa_types = map(unicode.lower, caa_types) for image in caa_data["images"]: - if QObject.config.setting["caa_approved_only"] and not image["approved"]: + if config.setting["caa_approved_only"] and not image["approved"]: continue if not image["types"] and 'unknown' in caa_types: _caa_append_image_to_trylist(try_list, image) @@ -150,7 +151,7 @@ _CAA_THUMBNAIL_SIZE_MAP = { def _caa_append_image_to_trylist(try_list, imagedata): """Adds URLs to `try_list` depending on the users CAA image size settings.""" - imagesize = QObject.config.setting["caa_image_size"] + imagesize = config.setting["caa_image_size"] thumbsize = _CAA_THUMBNAIL_SIZE_MAP.get(imagesize, None) if thumbsize is None: url = QUrl(imagedata["image"]) @@ -171,7 +172,7 @@ def coverart(album, metadata, release, try_list=None): # http://tickets.musicbrainz.org/browse/MBS-4536 has_caa_artwork = False caa_types = map(unicode.lower, - QObject.config.setting["caa_image_types"].split()) + config.setting["caa_image_types"].split()) if 'cover_art_archive' in release.children: caa_node = release.children['cover_art_archive'][0] @@ -196,9 +197,9 @@ def coverart(album, metadata, release, try_list=None): back_in_caa = caa_node.back[0].text == 'true' and 'back' in caa_types has_caa_artwork = has_caa_artwork and (front_in_caa or back_in_caa) - if QObject.config.setting['ca_provider_use_caa'] and has_caa_artwork\ + if config.setting['ca_provider_use_caa'] and has_caa_artwork\ and len(caa_types) > 0: - QObject.log.debug("There are suitable images in the cover art archive for %s" + log.debug("There are suitable images in the cover art archive for %s" % release.id) album._requests += 1 album.tagger.xmlws.download( @@ -207,7 +208,7 @@ def coverart(album, metadata, release, try_list=None): partial(_caa_json_downloaded, album, metadata, release, try_list), priority=True, important=True) else: - QObject.log.debug("There are no suitable images in the cover art archive for %s" + log.debug("There are no suitable images in the cover art archive for %s" % release.id) _fill_try_list(album, release, try_list) _walk_try_list(album, metadata, release, try_list) @@ -223,16 +224,16 @@ def _fill_try_list(album, release, try_list): _process_url_relation(try_list, relation) # Use the URL of a cover art link directly - if QObject.config.setting['ca_provider_use_whitelist']\ + if config.setting['ca_provider_use_whitelist']\ and (relation.type == 'cover art link' or relation.type == 'has_cover_art_at'): _try_list_append_image_url(try_list, QUrl(relation.target[0].text)) - elif QObject.config.setting['ca_provider_use_amazon']\ + elif config.setting['ca_provider_use_amazon']\ and (relation.type == 'amazon asin' or relation.type == 'has_Amazon_ASIN'): _process_asin_relation(try_list, relation) except AttributeError, e: - album.log.error(traceback.format_exc()) + log.error(traceback.format_exc()) def _walk_try_list(album, metadata, release, try_list): @@ -262,7 +263,7 @@ def _process_url_relation(try_list, relation): # musicbrainz server. # See mb_server/cgi-bin/MusicBrainz/Server/CoverArt.pm # hartzell --- Tue Apr 15 15:25:58 PDT 2008 - if not QObject.config.setting['ca_provider_use_%s' % site['name']]: + if not config.setting['ca_provider_use_%s' % site['name']]: continue match = re.match(site['regexp'], relation.target[0].text) if match is not None: @@ -290,7 +291,7 @@ def _process_asin_relation(try_list, relation): def _try_list_append_image_url(try_list, parsedUrl, imagetype="front", description=""): - QObject.log.debug("Adding %s image %s", imagetype, parsedUrl) + log.debug("Adding %s image %s", imagetype, parsedUrl) path = str(parsedUrl.encodedPath()) if parsedUrl.hasQuery(): path += '?' + parsedUrl.encodedQuery() diff --git a/picard/disc.py b/picard/disc.py index bc379e413..4008dc5a3 100644 --- a/picard/disc.py +++ b/picard/disc.py @@ -22,6 +22,7 @@ import ctypes import sys import traceback from PyQt4 import QtCore +from picard import log from picard.ui.cdlookup import CDLookupDialog @@ -62,12 +63,12 @@ class Disc(QtCore.QObject): self.tagger.restore_cursor() releases = [] if error: - self.log.error("%r", unicode(http.errorString())) + log.error("%r", unicode(http.errorString())) else: try: releases = document.metadata[0].disc[0].release_list[0].release except (AttributeError, IndexError): - self.log.error(traceback.format_exc()) + log.error(traceback.format_exc()) dialog = CDLookupDialog(releases, self, parent=self.tagger.window) dialog.exec_() diff --git a/picard/file.py b/picard/file.py index bb607cac8..0cbbc1036 100644 --- a/picard/file.py +++ b/picard/file.py @@ -27,6 +27,7 @@ import unicodedata from operator import itemgetter from collections import defaultdict from PyQt4 import QtCore +from picard import config, log from picard.track import Track from picard.metadata import Metadata from picard.ui.item import Item @@ -132,7 +133,7 @@ class File(QtCore.QObject, Item): def copy_metadata(self, metadata): acoustid = self.metadata["acoustid_id"] - preserve = self.config.setting["preserved_tags"].strip() + preserve = config.setting["preserved_tags"].strip() saved_metadata = {} for tag in re.split(r"\s+", preserve) + File._default_preserved_tags: @@ -152,35 +153,35 @@ class File(QtCore.QObject, Item): """Load metadata from the file.""" raise NotImplementedError - def save(self, next, settings): + def save(self, next): self.set_pending() metadata = Metadata() metadata.copy(self.metadata) self.tagger.save_queue.put(( - partial(self._save_and_rename, self.filename, metadata, settings), + partial(self._save_and_rename, self.filename, metadata), partial(self._saving_finished, next), QtCore.Qt.LowEventPriority + 2)) - def _save_and_rename(self, old_filename, metadata, settings): + def _save_and_rename(self, old_filename, metadata): """Save the metadata.""" new_filename = old_filename - if not settings["dont_write_tags"]: + if not config.setting["dont_write_tags"]: encoded_old_filename = encode_filename(old_filename) info = os.stat(encoded_old_filename) - self._save(old_filename, metadata, settings) - if settings["preserve_timestamps"]: + self._save(old_filename, metadata) + if config.setting["preserve_timestamps"]: try: os.utime(encoded_old_filename, (info.st_atime, info.st_mtime)) except OSError: - self.log.warning("Couldn't preserve timestamp for %r", old_filename) + log.warning("Couldn't preserve timestamp for %r", old_filename) # Rename files - if settings["rename_files"] or settings["move_files"]: - new_filename = self._rename(old_filename, metadata, settings) + if config.setting["rename_files"] or config.setting["move_files"]: + new_filename = self._rename(old_filename, metadata) # Move extra files (images, playlists, etc.) - if settings["move_files"] and settings["move_additional_files"]: - self._move_additional_files(old_filename, new_filename, settings) + if config.setting["move_files"] and config.setting["move_additional_files"]: + self._move_additional_files(old_filename, new_filename) # Delete empty directories - if settings["delete_empty_dirs"]: + if config.setting["delete_empty_dirs"]: dirname = encode_filename(os.path.dirname(old_filename)) try: self._rmdir(dirname) @@ -196,8 +197,8 @@ class File(QtCore.QObject, Item): except EnvironmentError: pass # Save cover art images - if settings["save_images_to_files"]: - self._save_images(os.path.dirname(new_filename), metadata, settings) + if config.setting["save_images_to_files"]: + self._save_images(os.path.dirname(new_filename), metadata) return new_filename @staticmethod @@ -222,7 +223,7 @@ class File(QtCore.QObject, Item): for info in ('~bitrate', '~sample_rate', '~channels', '~bits_per_sample', '~format'): temp_info[info] = self.orig_metadata[info] - if self.config.setting["clear_existing_tags"]: + if config.setting["clear_existing_tags"]: self.orig_metadata.copy(self.metadata) else: self.orig_metadata.update(self.metadata) @@ -235,13 +236,13 @@ class File(QtCore.QObject, Item): self._add_path_to_metadata(self.orig_metadata) return self, old_filename, new_filename - def _save(self, filename, metadata, settings): + def _save(self, filename, metadata): """Save the metadata.""" raise NotImplementedError - def _script_to_filename(self, format, file_metadata, settings): + def _script_to_filename(self, format, file_metadata): metadata = Metadata() - if self.config.setting["clear_existing_tags"]: + if config.setting["clear_existing_tags"]: metadata.copy(file_metadata) else: metadata.copy(self.orig_metadata) @@ -252,37 +253,37 @@ class File(QtCore.QObject, Item): metadata[name] = sanitize_filename(metadata[name]) format = format.replace("\t", "").replace("\n", "") filename = ScriptParser().eval(format, metadata, self) - if settings["ascii_filenames"]: + if config.setting["ascii_filenames"]: if isinstance(filename, unicode): filename = unaccent(filename) filename = replace_non_ascii(filename) # replace incompatible characters - if settings["windows_compatible_filenames"] or sys.platform == "win32": + if config.setting["windows_compatible_filenames"] or sys.platform == "win32": filename = replace_win32_incompat(filename) # remove null characters filename = filename.replace("\x00", "") return filename - def _make_filename(self, filename, metadata, settings): + def _make_filename(self, filename, metadata): """Constructs file name based on metadata and file naming formats.""" - if settings["move_files"]: - new_dirname = settings["move_files_to"] + if config.setting["move_files"]: + new_dirname = config.setting["move_files_to"] if not os.path.isabs(new_dirname): new_dirname = os.path.normpath(os.path.join(os.path.dirname(filename), new_dirname)) else: new_dirname = os.path.dirname(filename) new_filename, ext = os.path.splitext(os.path.basename(filename)) - if settings["rename_files"]: + if config.setting["rename_files"]: # expand the naming format - format = settings['file_naming_format'] + format = config.setting['file_naming_format'] if len(format) > 0: - new_filename = self._script_to_filename(format, metadata, settings) - if not settings['move_files']: + new_filename = self._script_to_filename(format, metadata) + if not config.setting['move_files']: new_filename = os.path.basename(new_filename) new_filename = make_short_filename(new_dirname, new_filename) # win32 compatibility fixes - if settings['windows_compatible_filenames'] or sys.platform == 'win32': + if config.setting['windows_compatible_filenames'] or sys.platform == 'win32': new_filename = new_filename.replace('./', '_/').replace('.\\', '_\\') # replace . at the beginning of file and directory names new_filename = new_filename.replace('/.', '/_').replace('\\.', '\\_') @@ -293,9 +294,9 @@ class File(QtCore.QObject, Item): new_filename = unicodedata.normalize("NFD", unicode(new_filename)) return os.path.realpath(os.path.join(new_dirname, new_filename + ext.lower())) - def _rename(self, old_filename, metadata, settings): + def _rename(self, old_filename, metadata): new_filename, ext = os.path.splitext( - self._make_filename(old_filename, metadata, settings)) + self._make_filename(old_filename, metadata)) if old_filename != new_filename + ext: new_dirname = os.path.dirname(new_filename) if not os.path.isdir(encode_filename(new_dirname)): @@ -307,31 +308,31 @@ class File(QtCore.QObject, Item): new_filename = "%s (%d)" % (tmp_filename, i) i += 1 new_filename = new_filename + ext - self.log.debug("Moving file %r => %r", old_filename, new_filename) + log.debug("Moving file %r => %r", old_filename, new_filename) shutil.move(encode_filename(old_filename), encode_filename(new_filename)) return new_filename else: return old_filename - def _make_image_filename(self, image_filename, dirname, metadata, settings): - image_filename = self._script_to_filename(image_filename, metadata, settings) + def _make_image_filename(self, image_filename, dirname, metadata): + image_filename = self._script_to_filename(image_filename, metadata) if not image_filename: image_filename = "cover" if os.path.isabs(image_filename): filename = image_filename else: filename = os.path.join(dirname, image_filename) - if settings['windows_compatible_filenames'] or sys.platform == 'win32': + if config.setting['windows_compatible_filenames'] or sys.platform == 'win32': filename = filename.replace('./', '_/').replace('.\\', '_\\') return encode_filename(filename) - def _save_images(self, dirname, metadata, settings): + def _save_images(self, dirname, metadata): """Save the cover images to disk.""" if not metadata.images: return default_filename = self._make_image_filename( - settings["cover_image_filename"], dirname, metadata, settings) - overwrite = settings["save_images_overwrite"] + config.setting["cover_image_filename"], dirname, metadata) + overwrite = config.setting["save_images_overwrite"] counters = defaultdict(lambda: 0) for image in metadata.images: filename = image["filename"] @@ -340,7 +341,7 @@ class File(QtCore.QObject, Item): if filename is None: filename = default_filename else: - filename = self._make_image_filename(filename, dirname, metadata, settings) + filename = self._make_image_filename(filename, dirname, metadata) image_filename = filename ext = mimetype.get_extension(mime, ".jpg") if counters[filename] > 0: @@ -348,7 +349,7 @@ class File(QtCore.QObject, Item): counters[filename] = counters[filename] + 1 while os.path.exists(image_filename + ext) and not overwrite: if os.path.getsize(image_filename + ext) == len(data): - self.log.debug("Identical file size, not saving %r", image_filename) + log.debug("Identical file size, not saving %r", image_filename) break image_filename = "%s (%d)" % (filename, counters[filename]) counters[filename] = counters[filename] + 1 @@ -358,9 +359,9 @@ class File(QtCore.QObject, Item): # image multiple times if (os.path.exists(new_filename) and os.path.getsize(new_filename) == len(data)): - self.log.debug("Identical file size, not saving %r", image_filename) + log.debug("Identical file size, not saving %r", image_filename) return - self.log.debug("Saving cover images to %r", image_filename) + log.debug("Saving cover images to %r", image_filename) new_dirname = os.path.dirname(image_filename) if not os.path.isdir(new_dirname): os.makedirs(new_dirname) @@ -368,11 +369,11 @@ class File(QtCore.QObject, Item): f.write(data) f.close() - def _move_additional_files(self, old_filename, new_filename, settings): + def _move_additional_files(self, old_filename, new_filename): """Move extra files, like playlists...""" old_path = encode_filename(os.path.dirname(old_filename)) new_path = encode_filename(os.path.dirname(new_filename)) - patterns = encode_filename(settings["move_additional_files_pattern"]) + patterns = encode_filename(config.setting["move_additional_files_pattern"]) patterns = filter(bool, [p.strip() for p in patterns.split()]) for pattern in patterns: # FIXME glob1 is not documented, maybe we need our own implemention? @@ -381,21 +382,21 @@ class File(QtCore.QObject, Item): old_file = os.path.join(old_path, old_file) # FIXME we shouldn't do this from a thread! if self.tagger.files.get(decode_filename(old_file)): - self.log.debug("File loaded in the tagger, not moving %r", old_file) + log.debug("File loaded in the tagger, not moving %r", old_file) continue - self.log.debug("Moving %r to %r", old_file, new_file) + log.debug("Moving %r to %r", old_file, new_file) shutil.move(old_file, new_file) def remove(self, from_parent=True): if from_parent and self.parent: - self.log.debug("Removing %r from %r", self, self.parent) + log.debug("Removing %r from %r", self, self.parent) self.parent.remove_file(self) self.tagger.acoustidmanager.remove(self) self.state = File.REMOVED def move(self, parent): if parent != self.parent: - self.log.debug("Moving %r from %r to %r", self, self.parent, parent) + log.debug("Moving %r from %r to %r", self, self.parent, parent) self.clear_lookup_task() self.tagger._acoustid.stop_analyze(file) if self.parent: @@ -407,7 +408,7 @@ class File(QtCore.QObject, Item): def _move(self, parent): if parent != self.parent: - self.log.debug("Moving %r from %r to %r", self, self.parent, parent) + log.debug("Moving %r from %r to %r", self, self.parent, parent) if self.parent: self.parent.remove_file(self) self.parent = parent @@ -423,7 +424,7 @@ class File(QtCore.QObject, Item): def update(self, signal=True): names = set(self.metadata.keys()) names.update(self.orig_metadata.keys()) - clear_existing_tags = self.config.setting["clear_existing_tags"] + clear_existing_tags = config.setting["clear_existing_tags"] for name in names: if not name.startswith('~') and self.supports_tag(name): new_values = self.metadata.getall(name) @@ -440,7 +441,7 @@ class File(QtCore.QObject, Item): if self.state in (File.CHANGED, File.NORMAL): self.state = File.NORMAL if signal: - self.log.debug("Updating file %r", self) + log.debug("Updating file %r", self) if self.item: self.item.update() @@ -542,7 +543,7 @@ class File(QtCore.QObject, Item): reverse=True, key=itemgetter(0))[0] if lookuptype != 'acoustid': - threshold = self.config.setting['file_lookup_threshold'] + threshold = config.setting['file_lookup_threshold'] if match[0] < threshold: self.tagger.window.set_statusbar_message(N_("No matching tracks above the threshold for file %s"), self.filename, timeout=3000) self.clear_pending() diff --git a/picard/formats/apev2.py b/picard/formats/apev2.py index 3eee578bd..1a41f8a56 100644 --- a/picard/formats/apev2.py +++ b/picard/formats/apev2.py @@ -23,11 +23,13 @@ import mutagen.musepack import mutagen.wavpack import mutagen.optimfrog import mutagenext.tak +from picard import log from picard.file import File from picard.metadata import Metadata from picard.util import encode_filename, sanitize_date, mimetype from os.path import isfile + class APEv2File(File): """Generic APEv2-based file.""" _File = None @@ -49,7 +51,7 @@ class APEv2File(File): __rtranslate = dict([(v, k) for k, v in __translate.iteritems()]) def _load(self, filename): - self.log.debug("Loading file %r", filename) + log.debug("Loading file %r", filename) file = self._File(encode_filename(filename)) metadata = Metadata() if file.tags: @@ -96,7 +98,7 @@ class APEv2File(File): def _save(self, filename, metadata, settings): """Save metadata to the file.""" - self.log.debug("Saving file %r", filename) + log.debug("Saving file %r", filename) try: tags = mutagen.apev2.APEv2(encode_filename(filename)) except mutagen.apev2.APENoHeaderError: diff --git a/picard/formats/asf.py b/picard/formats/asf.py index 58c0e4f2f..e42df123b 100644 --- a/picard/formats/asf.py +++ b/picard/formats/asf.py @@ -17,6 +17,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +from picard import config, log from picard.file import File from picard.formats.id3 import ID3_IMAGE_TYPE_MAP, ID3_REVERSE_IMAGE_TYPE_MAP from picard.util import encode_filename @@ -123,7 +124,7 @@ class ASFFile(File): __RTRANS = dict([(b, a) for a, b in __TRANS.items()]) def _load(self, filename): - self.log.debug("Loading file %r", filename) + log.debug("Loading file %r", filename) file = ASF(encode_filename(filename)) metadata = Metadata() for name, values in file.tags.items(): @@ -138,7 +139,7 @@ class ASFFile(File): continue elif name == 'WM/SharedUserRating': # Rating in WMA ranges from 0 to 99, normalize this to the range 0 to 5 - values[0] = int(round(int(unicode(values[0])) / 99.0 * (self.config.setting['rating_steps'] - 1))) + values[0] = int(round(int(unicode(values[0])) / 99.0 * (config.setting['rating_steps'] - 1))) name = self.__RTRANS[name] values = filter(bool, map(unicode, values)) if values: @@ -147,7 +148,7 @@ class ASFFile(File): return metadata def _save(self, filename, metadata, settings): - self.log.debug("Saving file %r", filename) + log.debug("Saving file %r", filename) file = ASF(encode_filename(filename)) if settings['clear_existing_tags']: @@ -155,7 +156,7 @@ class ASFFile(File): if settings['save_images_to_tags']: cover = [] for image in metadata.images: - if self.config.setting["save_only_front_images_to_tags"] and image["type"] != "front": + if config.setting["save_only_front_images_to_tags"] and image["type"] != "front": continue imagetype = ID3_IMAGE_TYPE_MAP.get(image["type"], 0) tag_data = pack_image(image["mime"], image["data"], imagetype, diff --git a/picard/formats/id3.py b/picard/formats/id3.py index 165b730e1..44f743d6e 100644 --- a/picard/formats/id3.py +++ b/picard/formats/id3.py @@ -22,6 +22,7 @@ import mutagen.mp3 import mutagen.trueaudio from collections import defaultdict from mutagen import id3 +from picard import config, log from picard.metadata import Metadata from picard.file import File from picard.formats.mutagenext import compatid3 @@ -156,7 +157,7 @@ class ID3File(File): "totaldiscs", "totaltracks") def _load(self, filename): - self.log.debug("Loading file %r", filename) + log.debug("Loading file %r", filename) file = self._File(encode_filename(filename), ID3=compatid3.CompatID3) tags = file.tags or {} # upgrade custom 2.3 frames to 2.4 @@ -228,8 +229,8 @@ class ID3File(File): description=frame.desc, type_=imagetype) elif frameid == 'POPM': # Rating in ID3 ranges from 0 to 255, normalize this to the range 0 to 5 - if frame.email == self.config.setting['rating_user_email']: - rating = unicode(int(round(frame.rating / 255.0 * (self.config.setting['rating_steps'] - 1)))) + if frame.email == config.setting['rating_user_email']: + rating = unicode(int(round(frame.rating / 255.0 * (config.setting['rating_steps'] - 1)))) metadata.add('~rating', rating) if 'date' in metadata: @@ -242,7 +243,7 @@ class ID3File(File): def _save(self, filename, metadata, settings): """Save metadata to the file.""" - self.log.debug("Saving file %r", filename) + log.debug("Saving file %r", filename) try: tags = compatid3.CompatID3(encode_filename(filename)) except mutagen.id3.ID3NoHeaderError: @@ -281,7 +282,7 @@ class ID3File(File): counters = defaultdict(lambda: 0) for image in metadata.images: desc = image["description"] - if self.config.setting["save_only_front_images_to_tags"] and image["type"] != "front": + if config.setting["save_only_front_images_to_tags"] and image["type"] != "front": continue type_ = ID3_IMAGE_TYPE_MAP.get(image["type"], 0) if counters[desc] > 0: diff --git a/picard/formats/mp4.py b/picard/formats/mp4.py index b0894fd64..f713d04e8 100644 --- a/picard/formats/mp4.py +++ b/picard/formats/mp4.py @@ -18,6 +18,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. from mutagen.mp4 import MP4, MP4Cover +from picard import config, log from picard.file import File from picard.metadata import Metadata from picard.util import encode_filename @@ -103,7 +104,7 @@ class MP4File(File): "totaldiscs", "totaltracks") def _load(self, filename): - self.log.debug("Loading file %r", filename) + log.debug("Loading file %r", filename) file = MP4(encode_filename(filename)) if file.tags is None: file.add_tags() @@ -144,7 +145,7 @@ class MP4File(File): return metadata def _save(self, filename, metadata, settings): - self.log.debug("Saving file %r", filename) + log.debug("Saving file %r", filename) file = MP4(encode_filename(self.filename)) if file.tags is None: file.add_tags() @@ -187,7 +188,7 @@ class MP4File(File): if settings['save_images_to_tags']: covr = [] for image in metadata.images: - if self.config.setting["save_only_front_images_to_tags"] and image["type"] != "front": + if config.setting["save_only_front_images_to_tags"] and image["type"] != "front": continue mime = image["mime"] if mime == "image/jpeg": diff --git a/picard/formats/vorbis.py b/picard/formats/vorbis.py index b2bdab318..7f5668123 100644 --- a/picard/formats/vorbis.py +++ b/picard/formats/vorbis.py @@ -30,6 +30,7 @@ try: except ImportError: OggOpus = None with_opus = False +from picard import config, log from picard.file import File from picard.formats.id3 import ID3_IMAGE_TYPE_MAP, ID3_REVERSE_IMAGE_TYPE_MAP from picard.metadata import Metadata @@ -40,7 +41,7 @@ class VCommentFile(File): _File = None def _load(self, filename): - self.log.debug("Loading file %r", filename) + log.debug("Loading file %r", filename) file = self._File(encode_filename(filename)) file.tags = file.tags or {} metadata = Metadata() @@ -68,10 +69,10 @@ class VCommentFile(File): elif name.startswith('rating'): try: name, email = name.split(':', 1) except ValueError: email = '' - if email != self.config.setting['rating_user_email']: + if email != config.setting['rating_user_email']: continue name = '~rating' - value = unicode(int(round((float(value) * (self.config.setting['rating_steps'] - 1))))) + value = unicode(int(round((float(value) * (config.setting['rating_steps'] - 1))))) elif name == "fingerprint" and value.startswith("MusicMagic Fingerprint"): name = "musicip_fingerprint" value = value[22:] @@ -108,7 +109,7 @@ class VCommentFile(File): def _save(self, filename, metadata, settings): """Save metadata to the file.""" - self.log.debug("Saving file %r", filename) + log.debug("Saving file %r", filename) file = self._File(encode_filename(filename)) if file.tags is None: file.add_tags() @@ -152,7 +153,7 @@ class VCommentFile(File): if settings['save_images_to_tags']: for image in metadata.images: - if self.config.setting["save_only_front_images_to_tags"] and image["type"] != "front": + if config.setting["save_only_front_images_to_tags"] and image["type"] != "front": continue picture = mutagen.flac.Picture() picture.data = image["data"] diff --git a/picard/formats/wav.py b/picard/formats/wav.py index 01f7ad544..8471fc756 100644 --- a/picard/formats/wav.py +++ b/picard/formats/wav.py @@ -18,16 +18,18 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. import wave +from picard import log from picard.file import File from picard.metadata import Metadata from picard.util import encode_filename + class WAVFile(File): EXTENSIONS = [".wav"] NAME = "Microsoft WAVE" def _load(self, filename): - self.log.debug("Loading file %r", filename) + log.debug("Loading file %r", filename) f = wave.open(encode_filename(filename), "rb") metadata = Metadata() metadata['~channels'] = f.getnchannels() @@ -39,5 +41,5 @@ class WAVFile(File): return metadata def _save(self, filename, metadata, settings): - self.log.debug("Saving file %r", filename) + log.debug("Saving file %r", filename) pass diff --git a/picard/log.py b/picard/log.py index d5269a19f..a547fcb7b 100644 --- a/picard/log.py +++ b/picard/log.py @@ -20,7 +20,6 @@ import sys import os from PyQt4 import QtCore -import picard from picard.util import thread @@ -28,54 +27,49 @@ def _stderr_receiver(prefix, time, msg): sys.stderr.write("%s %s %s %s%s" % (prefix, str(QtCore.QThread.currentThreadId()), time, msg, os.linesep)) -class Log(object): - - def __init__(self): - self.entries = [] - self.receivers = [_stderr_receiver] - picard.log.log = self - picard.log.debug = self.debug - picard.log.info = self.info - picard.log.warning = self.warning - picard.log.error = self.error - - def _message(self, prefix, message, args, kwargs): - if not (isinstance(message, str) or isinstance(message, unicode)): - message = repr(message) - if args: - message = message % args - prefix = "%s" % (prefix,) - time = str(QtCore.QTime.currentTime().toString()) - message = "%s" % (message,) - if isinstance(prefix, unicode): - prefix = prefix.encode("utf-8", "replace") - if isinstance(message, unicode): - message = message.encode("utf-8", "replace") - self.entries.append((prefix, time, message)) - for func in self.receivers: - try: - func(prefix, time, message) - except Exception, e: - import traceback - traceback.print_exc() - - def add_receiver(self, receiver): - self.receivers.append(receiver) - - def debug(self, message, *args, **kwargs): - pass - - def info(self, message, *args, **kwargs): - thread.proxy_to_main(self._message, "I:", message, args, kwargs) - - def warning(self, message, *args, **kwargs): - thread.proxy_to_main(self._message, "W:", message, args, kwargs) - - def error(self, message, *args, **kwargs): - thread.proxy_to_main(self._message, "E:", message, args, kwargs) +_entries = [] +_receivers = [_stderr_receiver] -class DebugLog(Log): +def _message(prefix, message, args, kwargs): + if not (isinstance(message, str) or isinstance(message, unicode)): + message = repr(message) + if args: + message = message % args + prefix = "%s" % (prefix,) + time = str(QtCore.QTime.currentTime().toString()) + message = "%s" % (message,) + if isinstance(prefix, unicode): + prefix = prefix.encode("utf-8", "replace") + if isinstance(message, unicode): + message = message.encode("utf-8", "replace") + _entries.append((prefix, time, message)) + for func in _receivers: + try: + func(prefix, time, message) + except Exception, e: + import traceback + traceback.print_exc() - def debug(self, message, *args, **kwargs): - thread.proxy_to_main(self._message, "D:", message, args, kwargs) + +def add_receiver(receiver): + _receivers.append(receiver) + + +_log_debug_messages = False + +def debug(message, *args, **kwargs): + if _log_debug_messages: + thread.proxy_to_main(_message, "D:", message, args, kwargs) + + +def info(message, *args, **kwargs): + thread.proxy_to_main(_message, "I:", message, args, kwargs) + + +def warning(message, *args, **kwargs): + thread.proxy_to_main(_message, "W:", message, args, kwargs) + + +def error(message, *args, **kwargs): + thread.proxy_to_main(_message, "E:", message, args, kwargs) diff --git a/picard/mbxml.py b/picard/mbxml.py index f248a0ae3..f607e384e 100644 --- a/picard/mbxml.py +++ b/picard/mbxml.py @@ -18,6 +18,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. import re +from picard import config from picard.util import format_time, translate_from_sortname from picard.const import RELEASE_FORMATS @@ -67,12 +68,12 @@ def _parse_attributes(attrs): return ' '.join([prefix, attrs]).strip().lower() -def _relations_to_metadata(relation_lists, m, config): +def _relations_to_metadata(relation_lists, m): for relation_list in relation_lists: if relation_list.target_type == 'artist': for relation in relation_list.relation: artist = relation.artist[0] - value = _translate_artist_node(artist, config)[0] or artist.name[0].text + value = _translate_artist_node(artist)[0] or artist.name[0].text reltype = relation.type attribs = [] if 'attribute_list' in relation.children: @@ -95,7 +96,7 @@ def _relations_to_metadata(relation_lists, m, config): elif relation_list.target_type == 'work': for relation in relation_list.relation: if relation.type == 'performance': - work_to_metadata(relation.work[0], m, config) + work_to_metadata(relation.work[0], m) elif relation_list.target_type == 'url': for relation in relation_list.relation: if relation.type == 'amazon asin': @@ -108,9 +109,9 @@ def _relations_to_metadata(relation_lists, m, config): m.add('license', url) -def _translate_artist_node(node, config=None): +def _translate_artist_node(node): transl, translsort = None, None - if config and config.setting['translate_artist_names']: + if config.setting['translate_artist_names']: locale = config.setting["artist_locale"] lang = locale.split("_")[0] if "alias_list" in node.children: @@ -131,16 +132,16 @@ def _translate_artist_node(node, config=None): return (transl, translsort) -def artist_credit_from_node(node, config=None): +def artist_credit_from_node(node): artist = "" artistsort = "" for credit in node.name_credit: a = credit.artist[0] - transl, translsort = _translate_artist_node(a, config) + transl, translsort = _translate_artist_node(a) if transl: artist += transl else: - if 'name' in credit.children and not (config and config.setting["standardize_artists"]): + if 'name' in credit.children and not config.setting["standardize_artists"]: artist += credit.name[0].text else: artist += a.name[0].text @@ -151,9 +152,9 @@ def artist_credit_from_node(node, config=None): return (artist, artistsort) -def artist_credit_to_metadata(node, m, config, release=False): +def artist_credit_to_metadata(node, m, release=False): ids = [n.artist[0].id for n in node.name_credit] - artist, artistsort = artist_credit_from_node(node, config) + artist, artistsort = artist_credit_from_node(node) if release: m["musicbrainz_albumartistid"] = ids m["albumartist"] = artist @@ -199,9 +200,9 @@ def media_formats_from_node(node): return " + ".join(formats) -def track_to_metadata(node, track, config): +def track_to_metadata(node, track): m = track.metadata - recording_to_metadata(node.recording[0], track, config) + recording_to_metadata(node.recording[0], track) # overwrite with data we have on the track for name, nodes in node.children.iteritems(): if not nodes: @@ -213,11 +214,11 @@ def track_to_metadata(node, track, config): elif name == 'length' and nodes[0].text: m.length = int(nodes[0].text) elif name == 'artist_credit': - artist_credit_to_metadata(nodes[0], m, config) + artist_credit_to_metadata(nodes[0], m) m['~length'] = format_time(m.length) -def recording_to_metadata(node, track, config): +def recording_to_metadata(node, track): m = track.metadata m.length = 0 m['musicbrainz_trackid'] = node.attribs['id'] @@ -231,9 +232,9 @@ def recording_to_metadata(node, track, config): elif name == 'disambiguation': m['~recordingcomment'] = nodes[0].text elif name == 'artist_credit': - artist_credit_to_metadata(nodes[0], m, config) + artist_credit_to_metadata(nodes[0], m) elif name == 'relation_list': - _relations_to_metadata(nodes, m, config) + _relations_to_metadata(nodes, m) elif name == 'tag_list': add_folksonomy_tags(nodes[0], track) elif name == 'user_tag_list': @@ -244,12 +245,12 @@ def recording_to_metadata(node, track, config): m['~rating'] = nodes[0].text m['~length'] = format_time(m.length) -def work_to_metadata(work, m, config): +def work_to_metadata(work, m): m.add("musicbrainz_workid", work.attribs['id']) if 'language' in work.children: m.add_unique("language", work.language[0].text) if 'relation_list' in work.children: - _relations_to_metadata(work.relation_list, m, config) + _relations_to_metadata(work.relation_list, m) def medium_to_metadata(node, m): for name, nodes in node.children.iteritems(): @@ -265,7 +266,7 @@ def medium_to_metadata(node, m): m['media'] = nodes[0].text -def release_to_metadata(node, m, config, album=None): +def release_to_metadata(node, m, album=None): """Make metadata dict from a XML 'release' node.""" m['musicbrainz_albumid'] = node.attribs['id'] for name, nodes in node.children.iteritems(): @@ -280,7 +281,7 @@ def release_to_metadata(node, m, config, album=None): elif name == 'asin': m['asin'] = nodes[0].text elif name == 'artist_credit': - artist_credit_to_metadata(nodes[0], m, config, release=True) + artist_credit_to_metadata(nodes[0], m, release=True) elif name == 'date': m['date'] = nodes[0].text elif name == 'country': @@ -288,7 +289,7 @@ def release_to_metadata(node, m, config, album=None): elif name == 'barcode': m['barcode'] = nodes[0].text elif name == 'relation_list': - _relations_to_metadata(nodes, m, config) + _relations_to_metadata(nodes, m) elif name == 'label_info_list' and nodes[0].count != '0': m['label'], m['catalognumber'] = label_info_from_node(nodes[0]) elif name == 'text_representation': @@ -302,7 +303,7 @@ def release_to_metadata(node, m, config, album=None): add_user_folksonomy_tags(nodes[0], album) -def release_group_to_metadata(node, m, config, release_group=None): +def release_group_to_metadata(node, m, release_group=None): """Make metadata dict from a XML 'release-group' node taken from inside a 'release' node.""" m['musicbrainz_releasegroupid'] = node.attribs['id'] for name, nodes in node.children.iteritems(): diff --git a/picard/metadata.py b/picard/metadata.py index 8a05b7a19..f8300c06c 100644 --- a/picard/metadata.py +++ b/picard/metadata.py @@ -18,6 +18,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. from PyQt4.QtCore import QObject +from picard import config from picard.plugin import ExtensionPoint from picard.similarity import similarity2 from picard.util import load_release_type_scores @@ -95,7 +96,6 @@ class Metadata(dict): Compare metadata to a MusicBrainz release. Produces a probability as a linear combination of weights that the metadata matches a certain album. """ - config = QObject.config total = 0.0 parts = [] @@ -106,7 +106,7 @@ class Metadata(dict): if "albumartist" in self and "albumartist" in weights: a = self["albumartist"] - b = artist_credit_from_node(release.artist_credit[0], config)[0] + b = artist_credit_from_node(release.artist_credit[0])[0] parts.append((similarity2(a, b), weights["albumartist"])) total += weights["albumartist"] @@ -168,7 +168,6 @@ class Metadata(dict): (reduce(lambda x, y: x + y[0] * y[1] / total, parts, 0.0), release) def compare_to_track(self, track, weights): - config = QObject.config total = 0.0 parts = [] @@ -180,7 +179,7 @@ class Metadata(dict): if 'artist' in self: a = self['artist'] - b = artist_credit_from_node(track.artist_credit[0], config)[0] + b = artist_credit_from_node(track.artist_credit[0])[0] parts.append((similarity2(a, b), weights["artist"])) total += weights["artist"] diff --git a/picard/plugin.py b/picard/plugin.py index 6e5901a4e..a5c551c4f 100644 --- a/picard/plugin.py +++ b/picard/plugin.py @@ -23,6 +23,9 @@ import os.path import shutil import picard.plugins import traceback +from picard import config, log +from picard.const import USER_PLUGIN_DIR + _suffixes = [s[0] for s in imp.get_suffixes()] _package_entries = ["__init__.py", "__init__.pyc", "__init__.pyo"] @@ -50,10 +53,9 @@ def _unregister_module_extensions(module): ep.unregister_module(module) -class ExtensionPoint(QtCore.QObject): +class ExtensionPoint(object): def __init__(self): - QtCore.QObject.__init__(self) self.__items = [] _extension_points.append(self) @@ -68,7 +70,7 @@ class ExtensionPoint(QtCore.QObject): self.__items = filter(lambda i: i[0] != name, self.__items) def __iter__(self): - enabled_plugins = self.config.setting["enabled_plugins"].split() + enabled_plugins = config.setting["enabled_plugins"].split() for module, item in self.__items: if module is None or module in enabled_plugins: yield item @@ -138,7 +140,7 @@ class PluginManager(QtCore.QObject): def load_plugindir(self, plugindir): if not os.path.isdir(plugindir): - self.log.debug("Plugin directory %r doesn't exist", plugindir) + log.debug("Plugin directory %r doesn't exist", plugindir) return names = set() for path in [os.path.join(plugindir, file) for file in os.listdir(plugindir)]: @@ -149,7 +151,7 @@ class PluginManager(QtCore.QObject): self.load_plugin(name, plugindir) def load_plugin(self, name, plugindir): - self.log.debug("Loading plugin %r", name) + log.debug("Loading plugin %r", name) info = imp.find_module(name, [plugindir]) plugin = None try: @@ -175,17 +177,16 @@ class PluginManager(QtCore.QObject): continue break else: - self.log.info("Plugin '%s' from '%s' is not compatible" + log.info("Plugin '%s' from '%s' is not compatible" " with this version of Picard." % (plugin.name, plugin.file)) except: - self.log.error(traceback.format_exc()) + log.error(traceback.format_exc()) if info[0] is not None: info[0].close() return plugin def install_plugin(self, path, dest): plugin_name = _plugin_name_from_path(path) - plugin_dir = self.tagger.user_plugin_dir if plugin_name: try: dest_exists = os.path.exists(dest) @@ -196,11 +197,11 @@ class PluginManager(QtCore.QObject): if dest_exists: shutil.rmtree(dest) shutil.copytree(path, dest) - plugin = self.load_plugin(plugin_name, plugin_dir) + plugin = self.load_plugin(plugin_name, USER_PLUGIN_DIR) if plugin is not None: self.plugin_installed.emit(plugin, False) except OSError, IOError: - self.tagger.log.debug("Unable to copy %s to plugin folder %s" % (path, plugin_dir)) + log.debug("Unable to copy %s to plugin folder %s" % (path, USER_PLUGIN_DIR)) def enabled(self, name): return True diff --git a/picard/releasegroup.py b/picard/releasegroup.py index 290c834f5..6f740a4ba 100644 --- a/picard/releasegroup.py +++ b/picard/releasegroup.py @@ -19,6 +19,7 @@ import traceback from PyQt4 import QtCore +from picard import config, log from picard.metadata import Metadata from picard.dataobj import DataObject from picard.mbxml import media_formats_from_node, label_info_from_node @@ -67,13 +68,13 @@ class ReleaseGroup(DataObject): def _request_finished(self, callback, document, http, error): try: if error: - self.log.error("%r", unicode(http.errorString())) + log.error("%r", unicode(http.errorString())) else: try: self._parse_versions(document) except: error = True - self.log.error(traceback.format_exc()) + log.error(traceback.format_exc()) finally: self.loaded = True callback() diff --git a/picard/tagger.py b/picard/tagger.py index 63484b3cd..1826c4578 100644 --- a/picard/tagger.py +++ b/picard/tagger.py @@ -52,12 +52,12 @@ shutil.copystat = _patched_shutil_copystat import picard.resources import picard.plugins -from picard import version_string, log, acoustid +from picard import version_string, log, acoustid, config from picard.album import Album, NatAlbum from picard.browser.browser import BrowserIntegration from picard.browser.filelookup import FileLookup from picard.cluster import Cluster, ClusterList, UnmatchedFiles -from picard.config import Config +from picard.const import USER_DIR, USER_PLUGIN_DIR from picard.disc import Disc from picard.file import File from picard.formats import open as open_file @@ -96,13 +96,6 @@ class Tagger(QtGui.QApplication): self._args = args self._autoupdate = autoupdate - self.config = Config() - - if sys.platform == "win32": - userdir = os.environ.get("APPDATA", "~\\Application Data") - else: - userdir = os.environ.get("XDG_CONFIG_HOME", "~/.config") - self.userdir = os.path.join(os.path.expanduser(userdir), "MusicBrainz", "Picard") # Initialize threading and allocate threads self.thread_pool = thread.ThreadPool(self) @@ -124,11 +117,8 @@ class Tagger(QtGui.QApplication): self.stopping = False # Setup logging - if debug or "PICARD_DEBUG" in os.environ: - self.log = log.DebugLog() - else: - self.log = log.Log() - self.log.debug("Starting Picard %s from %r", picard.__version__, os.path.abspath(__file__)) + log._log_debug_messages = debug or "PICARD_DEBUG" in os.environ + log.debug("Starting Picard %s from %r", picard.__version__, os.path.abspath(__file__)) # TODO remove this before the final release if sys.platform == "win32": @@ -137,15 +127,16 @@ class Tagger(QtGui.QApplication): olduserdir = "~/.picard" olduserdir = os.path.expanduser(olduserdir) if os.path.isdir(olduserdir): - self.log.info("Moving %s to %s", olduserdir, self.userdir) + log.info("Moving %s to %s", olduserdir, USER_DIR) try: - shutil.move(olduserdir, self.userdir) + shutil.move(olduserdir, USER_DIR) except: pass + # for compatibility with pre-1.3 plugins QtCore.QObject.tagger = self - QtCore.QObject.config = self.config - QtCore.QObject.log = self.log + QtCore.QObject.config = config + QtCore.QObject.log = log check_io_encoding() @@ -165,10 +156,10 @@ class Tagger(QtGui.QApplication): self.pluginmanager.load_plugindir(os.path.join(os.path.dirname(sys.argv[0]), "plugins")) else: self.pluginmanager.load_plugindir(os.path.join(os.path.dirname(__file__), "plugins")) - self.user_plugin_dir = os.path.join(self.userdir, "plugins") - if not os.path.exists(self.user_plugin_dir): - os.makedirs(self.user_plugin_dir) - self.pluginmanager.load_plugindir(self.user_plugin_dir) + + if not os.path.exists(USER_PLUGIN_DIR): + os.makedirs(USER_PLUGIN_DIR) + self.pluginmanager.load_plugindir(USER_PLUGIN_DIR) self.acoustidmanager = AcoustIDManager() self.browser_integration = BrowserIntegration() @@ -184,20 +175,20 @@ class Tagger(QtGui.QApplication): def remove_va_file_naming_format(merge=True): if merge: - self.config.setting["file_naming_format"] = \ + config.setting["file_naming_format"] = \ "$if($eq(%compilation%,1),\n$noop(Various Artist albums)\n"+\ "%s,\n$noop(Single Artist Albums)\n%s)" %\ - (self.config.setting["va_file_naming_format"].toString(), - self.config.setting["file_naming_format"]) - self.config.setting.remove("va_file_naming_format") - self.config.setting.remove("use_va_format") + (config.setting["va_file_naming_format"].toString(), + config.setting["file_naming_format"]) + config.setting.remove("va_file_naming_format") + config.setting.remove("use_va_format") - if "va_file_naming_format" in self.config.setting\ - and "use_va_format" in self.config.setting: - if self.config.setting["use_va_format"].toBool(): + if "va_file_naming_format" in config.setting\ + and "use_va_format" in config.setting: + if config.setting["use_va_format"].toBool(): remove_va_file_naming_format() self.window.show_va_removal_notice() - elif self.config.setting["va_file_naming_format"].toString() !=\ + elif config.setting["va_file_naming_format"].toString() !=\ r"$if2(%albumartist%,%artist%)/%album%/$if($gt(%totaldiscs%,1),%discnumber%-,)$num(%tracknumber%,2) %artist% - %title%": if self.window.confirm_va_removal(): remove_va_file_naming_format(merge=False) @@ -209,7 +200,7 @@ class Tagger(QtGui.QApplication): def setup_gettext(self, localedir): """Setup locales, load translations, install gettext functions.""" - ui_language = self.config.setting["ui_language"] + ui_language = config.setting["ui_language"] if ui_language: os.environ['LANGUAGE'] = '' os.environ['LANG'] = ui_language @@ -237,7 +228,7 @@ class Tagger(QtGui.QApplication): except: pass try: - self.log.debug("Loading gettext translation, localedir=%r", localedir) + log.debug("Loading gettext translation, localedir=%r", localedir) self.translation = gettext.translation("picard", localedir) self.translation.install(True) ungettext = self.translation.ungettext @@ -326,7 +317,7 @@ class Tagger(QtGui.QApplication): trackid = file.metadata['musicbrainz_trackid'] if target is not None: self.move_files([file], target) - elif not self.config.setting["ignore_file_mbids"]: + elif not config.setting["ignore_file_mbids"]: albumid = file.metadata['musicbrainz_albumid'] if mbid_validate(albumid): if mbid_validate(trackid): @@ -335,9 +326,9 @@ class Tagger(QtGui.QApplication): self.move_file_to_album(file, albumid) elif mbid_validate(trackid): self.move_file_to_nat(file, trackid) - elif self.config.setting['analyze_new_files'] and file.can_analyze(): + elif config.setting['analyze_new_files'] and file.can_analyze(): self.analyze([file]) - elif self.config.setting['analyze_new_files'] and file.can_analyze(): + elif config.setting['analyze_new_files'] and file.can_analyze(): self.analyze([file]) def move_files(self, files, target): @@ -354,7 +345,7 @@ class Tagger(QtGui.QApplication): def add_files(self, filenames, target=None): """Add files to the tagger.""" - self.log.debug("Adding files %r", filenames) + log.debug("Adding files %r", filenames) new_files = [] for filename in filenames: filename = os.path.normpath(os.path.realpath(filename)) @@ -392,8 +383,8 @@ class Tagger(QtGui.QApplication): def get_file_lookup(self): """Return a FileLookup object.""" - return FileLookup(self, self.config.setting["server_host"], - self.config.setting["server_port"], + return FileLookup(self, config.setting["server_host"], + config.setting["server_port"], self.browser_integration.port) def search(self, text, type, adv=False): @@ -438,7 +429,7 @@ class Tagger(QtGui.QApplication): """Save the specified objects.""" files = self.get_files_from_objects(objects, save=True) for file in files: - file.save(self._file_saved, self.tagger.config.setting) + file.save(self._file_saved) def load_album(self, id, discid=None): id = self.mbid_redirects.get(id, id) @@ -485,7 +476,7 @@ class Tagger(QtGui.QApplication): def remove_album(self, album): """Remove the specified album.""" - self.log.debug("Removing %r", album) + log.debug("Removing %r", album) album.stop_loading() self.remove_files(self.get_files_from_objects([album])) del self.albums[album.id] @@ -498,7 +489,7 @@ class Tagger(QtGui.QApplication): def remove_cluster(self, cluster): """Remove the specified cluster.""" if not cluster.special: - self.log.debug("Removing %r", cluster) + log.debug("Removing %r", cluster) files = list(cluster.files) cluster.files = [] cluster.clear_lookup_task() @@ -534,7 +525,7 @@ class Tagger(QtGui.QApplication): if isinstance(action, QtGui.QAction): device = unicode(action.text()) else: - device = self.config.setting["cd_lookup_device"].split(",", 1)[0] + device = config.setting["cd_lookup_device"].split(",", 1)[0] disc = Disc() self.set_wait_cursor() @@ -545,7 +536,7 @@ class Tagger(QtGui.QApplication): @property def use_acoustid(self): - return self.config.setting["fingerprinting_system"] == "acoustid" + return config.setting["fingerprinting_system"] == "acoustid" def analyze(self, objs): """Analyze the file(s).""" @@ -570,7 +561,7 @@ class Tagger(QtGui.QApplication): def cluster(self, objs): """Group files with similar metadata to 'clusters'.""" - self.log.debug("Clustering %r", objs) + log.debug("Clustering %r", objs) if len(objs) <= 1 or self.unmatched_files in objs: files = list(self.unmatched_files.files) else: diff --git a/picard/track.py b/picard/track.py index 116a8a816..c29c9c00a 100644 --- a/picard/track.py +++ b/picard/track.py @@ -18,6 +18,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +from picard import config, log from picard.metadata import Metadata, run_track_metadata_processors from picard.dataobj import DataObject from picard.util import asciipunct, partial @@ -116,13 +117,13 @@ class Track(DataObject, Item): # Custom VA name if tm['musicbrainz_artistid'] == VARIOUS_ARTISTS_ID: - tm['artistsort'] = tm['artist'] = self.config.setting['va_name'] + tm['artistsort'] = tm['artist'] = config.setting['va_name'] - if self.config.setting['folksonomy_tags']: + if config.setting['folksonomy_tags']: self._convert_folksonomy_tags_to_genre() # Convert Unicode punctuation - if self.config.setting['convert_punctuation']: + if config.setting['convert_punctuation']: tm.apply_func(asciipunct) def _convert_folksonomy_tags_to_genre(self): @@ -140,9 +141,9 @@ class Track(DataObject, Item): taglist.append((100 * count / maxcount, name)) taglist.sort(reverse=True) # And generate the genre metadata tag - maxtags = self.config.setting['max_tags'] - minusage = self.config.setting['min_tag_usage'] - ignore_tags = self.config.setting['ignore_tags'] + maxtags = config.setting['max_tags'] + minusage = config.setting['min_tag_usage'] + ignore_tags = config.setting['ignore_tags'] genre = [] for usage, name in taglist[:maxtags]: if name in ignore_tags: @@ -151,7 +152,7 @@ class Track(DataObject, Item): break name = _TRANSLATE_TAGS.get(name, name.title()) genre.append(name) - join_tags = self.config.setting['join_tags'] + join_tags = config.setting['join_tags'] if join_tags: genre = [join_tags.join(genre)] self.metadata['genre'] = genre @@ -179,16 +180,16 @@ class NonAlbumTrack(Track): self.tagger.nats.update(True) mblogin = False inc = ["artist-credits", "artists", "aliases"] - if self.config.setting["track_ars"]: + if config.setting["track_ars"]: inc += ["artist-rels", "url-rels", "recording-rels", "work-rels", "work-level-rels"] - if self.config.setting["folksonomy_tags"]: - if self.config.setting["only_my_tags"]: + if config.setting["folksonomy_tags"]: + if config.setting["only_my_tags"]: mblogin = True inc += ["user-tags"] else: inc += ["tags"] - if self.config.setting["enable_ratings"]: + if config.setting["enable_ratings"]: mblogin = True inc += ["user-ratings"] self.tagger.xmlws.get_track_by_id(self.id, @@ -196,7 +197,7 @@ class NonAlbumTrack(Track): def _recording_request_finished(self, document, http, error): if error: - self.log.error("%r", unicode(http.errorString())) + log.error("%r", unicode(http.errorString())) return try: recording = document.metadata[0].recording[0] @@ -204,21 +205,21 @@ class NonAlbumTrack(Track): for file in self.linked_files: self.update_file_metadata(file) except: - self.log.error(traceback.format_exc()) + log.error(traceback.format_exc()) def _parse_recording(self, recording): - recording_to_metadata(recording, self, self.config) + recording_to_metadata(recording, self) self._customize_metadata() m = self.metadata run_track_metadata_processors(self.album, m, None, recording) - if self.config.setting["enable_tagger_script"]: - script = self.config.setting["tagger_script"] + if config.setting["enable_tagger_script"]: + script = config.setting["tagger_script"] if script: parser = ScriptParser() try: parser.eval(script, m) except: - self.log.error(traceback.format_exc()) + log.error(traceback.format_exc()) m.strip_whitespace() self.loaded = True if self.callback: diff --git a/picard/ui/cdlookup.py b/picard/ui/cdlookup.py index cfe6070c2..41b0959bb 100644 --- a/picard/ui/cdlookup.py +++ b/picard/ui/cdlookup.py @@ -40,7 +40,7 @@ class CDLookupDialog(QtGui.QDialog): barcode = release.barcode[0].text if "barcode" in release.children else "" item = QtGui.QTreeWidgetItem(self.ui.release_list) item.setText(0, release.title[0].text) - item.setText(1, artist_credit_from_node(release.artist_credit[0], self.config)[0]) + item.setText(1, artist_credit_from_node(release.artist_credit[0])[0]) item.setText(2, date) item.setText(3, country) item.setText(4, ", ".join(labels)) diff --git a/picard/ui/coverartbox.py b/picard/ui/coverartbox.py index f3f5ac9d9..df6c45155 100644 --- a/picard/ui/coverartbox.py +++ b/picard/ui/coverartbox.py @@ -19,6 +19,7 @@ import os from PyQt4 import QtCore, QtGui, QtNetwork +from picard import config, log from picard.album import Album from picard.track import Track from picard.file import File @@ -137,8 +138,8 @@ class CoverArtBox(QtGui.QGroupBox): self.release = release def open_release_page(self): - host = self.config.setting["server_host"] - port = self.config.setting["server_port"] + host = config.setting["server_host"] + port = config.setting["server_port"] url = "http://%s:%s/release/%s" % (host, port, self.release) webbrowser2.open(url) @@ -164,14 +165,14 @@ class CoverArtBox(QtGui.QGroupBox): def on_remote_image_fetched(self, data, reply, error): mime = str(reply.header(QtNetwork.QNetworkRequest.ContentTypeHeader).toString()) if mime not in ('image/jpeg', 'image/png'): - self.log.warning("Can't load image with MIME-Type %s", mime) + log.warning("Can't load image with MIME-Type %s", mime) return return self.load_remote_image(mime, data) def load_remote_image(self, mime, data): pixmap = QtGui.QPixmap() if not pixmap.loadFromData(data): - self.log.warning("Can't load image") + log.warning("Can't load image") return self.__set_data([mime, data], pixmap=pixmap) if isinstance(self.item, Album): diff --git a/picard/ui/filebrowser.py b/picard/ui/filebrowser.py index 251d76cc3..202e8eab9 100644 --- a/picard/ui/filebrowser.py +++ b/picard/ui/filebrowser.py @@ -20,15 +20,16 @@ import os, sys from PyQt4 import QtCore, QtGui +from picard import config from picard.formats import supported_formats -from picard.config import TextOption, BoolOption from picard.util import find_existing_path + class FileBrowser(QtGui.QTreeView): options = [ - TextOption("persist", "current_browser_path", ""), - BoolOption("persist", "show_hidden_files", False), + config.TextOption("persist", "current_browser_path", ""), + config.BoolOption("persist", "show_hidden_files", False), ] def __init__(self, parent): @@ -40,7 +41,7 @@ class FileBrowser(QtGui.QTreeView): self.addAction(self.move_files_here_action) self.toggle_hidden_action = QtGui.QAction(_("Show &Hidden Files"), self) self.toggle_hidden_action.setCheckable(True) - self.toggle_hidden_action.setChecked(self.config.persist["show_hidden_files"]) + self.toggle_hidden_action.setChecked(config.persist["show_hidden_files"]) self.toggle_hidden_action.toggled.connect(self.show_hidden) self.addAction(self.toggle_hidden_action) self.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) @@ -71,7 +72,7 @@ class FileBrowser(QtGui.QTreeView): def _set_model_filter(self): filter = QtCore.QDir.AllDirs | QtCore.QDir.Files | QtCore.QDir.Drives | QtCore.QDir.NoDotAndDotDot - if self.config.persist["show_hidden_files"]: + if config.persist["show_hidden_files"]: filter |= QtCore.QDir.Hidden self.model.setFilter(filter) @@ -98,20 +99,20 @@ class FileBrowser(QtGui.QTreeView): QtGui.QTreeView.focusInEvent(self, event) def show_hidden(self, state): - self.config.persist["show_hidden_files"] = state + config.persist["show_hidden_files"] = state self._set_model_filter() def save_state(self): indexes = self.selectedIndexes() if indexes: path = self.model.filePath(indexes[0]) - self.config.persist["current_browser_path"] = path + config.persist["current_browser_path"] = path def restore_state(self): pass def _restore_state(self): - path = self.config.persist["current_browser_path"] + path = config.persist["current_browser_path"] if path: index = self.model.index(find_existing_path(unicode(path))) self.setCurrentIndex(index) @@ -122,4 +123,4 @@ class FileBrowser(QtGui.QTreeView): if not indexes: return path = self.model.filePath(indexes[0]) - self.config.setting["move_files_to"] = os.path.normpath(unicode(path)) + config.setting["move_files_to"] = os.path.normpath(unicode(path)) diff --git a/picard/ui/itemviews.py b/picard/ui/itemviews.py index 1820faa30..6657db840 100644 --- a/picard/ui/itemviews.py +++ b/picard/ui/itemviews.py @@ -20,12 +20,12 @@ import os import re from PyQt4 import QtCore, QtGui +from picard import config, log from picard.album import Album, NatAlbum from picard.cluster import Cluster, ClusterList, UnmatchedFiles from picard.file import File from picard.track import Track, NonAlbumTrack from picard.util import encode_filename, icontheme, partial -from picard.config import Option, TextOption from picard.plugin import ExtensionPoint from picard.ui.ratingwidget import RatingWidget from picard.ui.collectionmenu import CollectionMenu @@ -80,7 +80,7 @@ def get_match_color(similarity, basecolor): class MainPanel(QtGui.QSplitter): options = [ - Option("persist", "splitter_state", QtCore.QByteArray(), QtCore.QVariant.toByteArray), + config.Option("persist", "splitter_state", QtCore.QByteArray(), QtCore.QVariant.toByteArray), ] columns = [ @@ -103,25 +103,25 @@ class MainPanel(QtGui.QSplitter): TreeItem.base_color = self.palette().base().color() TreeItem.text_color = self.palette().text().color() TrackItem.track_colors = { - File.NORMAL: self.config.setting["color_saved"], + File.NORMAL: config.setting["color_saved"], File.CHANGED: TreeItem.text_color, - File.PENDING: self.config.setting["color_pending"], - File.ERROR: self.config.setting["color_error"], + File.PENDING: config.setting["color_pending"], + File.ERROR: config.setting["color_error"], } FileItem.file_colors = { File.NORMAL: TreeItem.text_color, - File.CHANGED: self.config.setting["color_modified"], - File.PENDING: self.config.setting["color_pending"], - File.ERROR: self.config.setting["color_error"], + File.CHANGED: config.setting["color_modified"], + File.PENDING: config.setting["color_pending"], + File.ERROR: config.setting["color_error"], } def save_state(self): - self.config.persist["splitter_state"] = self.saveState() + config.persist["splitter_state"] = self.saveState() for view in self.views: view.save_state() def restore_state(self): - self.restoreState(self.config.persist["splitter_state"]) + self.restoreState(config.persist["splitter_state"]) def create_icons(self): if hasattr(QtGui.QStyle, 'SP_DirIcon'): @@ -191,10 +191,10 @@ class MainPanel(QtGui.QSplitter): class BaseTreeView(QtGui.QTreeWidget): options = [ - Option("setting", "color_modified", QtGui.QColor(QtGui.QPalette.WindowText), QtGui.QColor), - Option("setting", "color_saved", QtGui.QColor(0, 128, 0), QtGui.QColor), - Option("setting", "color_error", QtGui.QColor(200, 0, 0), QtGui.QColor), - Option("setting", "color_pending", QtGui.QColor(128, 128, 128), QtGui.QColor), + config.Option("setting", "color_modified", QtGui.QColor(QtGui.QPalette.WindowText), QtGui.QColor), + config.Option("setting", "color_saved", QtGui.QColor(0, 128, 0), QtGui.QColor), + config.Option("setting", "color_error", QtGui.QColor(200, 0, 0), QtGui.QColor), + config.Option("setting", "color_pending", QtGui.QColor(128, 128, 128), QtGui.QColor), ] def __init__(self, window, parent=None): @@ -303,7 +303,7 @@ class BaseTreeView(QtGui.QTreeWidget): else: releases_menu.setEnabled(False) - if self.config.setting["enable_ratings"] and \ + if config.setting["enable_ratings"] and \ len(self.window.selected_objects) == 1 and isinstance(obj, Track): menu.addSeparator() action = QtGui.QWidgetAction(menu) @@ -343,7 +343,7 @@ class BaseTreeView(QtGui.QTreeWidget): event.accept() def restore_state(self): - sizes = self.config.persist[self.view_sizes.name] + sizes = config.persist[self.view_sizes.name] header = self.header() sizes = sizes.split(" ") try: @@ -355,7 +355,7 @@ class BaseTreeView(QtGui.QTreeWidget): def save_state(self): cols = range(self.numHeaderSections - 1) sizes = " ".join(str(self.header().sectionSize(i)) for i in cols) - self.config.persist[self.view_sizes.name] = sizes + config.persist[self.view_sizes.name] = sizes def supportedDropActions(self): return QtCore.Qt.CopyAction | QtCore.Qt.MoveAction @@ -444,7 +444,7 @@ class BaseTreeView(QtGui.QTreeWidget): item = parent.child(index) if item is not None: target = item.obj - self.log.debug("Drop target = %r", target) + log.debug("Drop target = %r", target) handled = False # text/uri-list urls = data.urls() @@ -490,7 +490,7 @@ class BaseTreeView(QtGui.QTreeWidget): class FileTreeView(BaseTreeView): - view_sizes = TextOption("persist", "file_view_sizes", "250 40 100") + view_sizes = config.TextOption("persist", "file_view_sizes", "250 40 100") def __init__(self, window, parent=None): BaseTreeView.__init__(self, window, parent) @@ -512,7 +512,7 @@ class FileTreeView(BaseTreeView): class AlbumTreeView(BaseTreeView): - view_sizes = TextOption("persist", "album_view_sizes", "250 40 100") + view_sizes = config.TextOption("persist", "album_view_sizes", "250 40 100") def __init__(self, window, parent=None): BaseTreeView.__init__(self, window, parent) diff --git a/picard/ui/logview.py b/picard/ui/logview.py index 78b7e192a..f8ee38f20 100644 --- a/picard/ui/logview.py +++ b/picard/ui/logview.py @@ -19,7 +19,7 @@ from PyQt4 import QtCore, QtGui -from picard.log import log +from picard import log class LogView(QtGui.QDialog): @@ -38,7 +38,7 @@ class LogView(QtGui.QDialog): self.browser.setDocument(self.doc) vbox = QtGui.QHBoxLayout(self) vbox.addWidget(self.browser) - for prefix, time, msg in log.entries: + for prefix, time, msg in log._entries: self.add_entry(prefix, time, msg) log.add_receiver(self.add_entry) diff --git a/picard/ui/mainwindow.py b/picard/ui/mainwindow.py index 2a020e031..e7b8cdfb6 100644 --- a/picard/ui/mainwindow.py +++ b/picard/ui/mainwindow.py @@ -22,10 +22,10 @@ from PyQt4 import QtCore, QtGui import sys import os.path +from picard import config, log from picard.file import File from picard.track import Track from picard.album import Album -from picard.config import Option, BoolOption, TextOption from picard.formats import supported_formats from picard.ui.coverartbox import CoverArtBox from picard.ui.itemviews import MainPanel @@ -46,18 +46,18 @@ def register_ui_init (function): class MainWindow(QtGui.QMainWindow): options = [ - Option("persist", "window_state", QtCore.QByteArray(), + config.Option("persist", "window_state", QtCore.QByteArray(), QtCore.QVariant.toByteArray), - Option("persist", "window_position", QtCore.QPoint(), + config.Option("persist", "window_position", QtCore.QPoint(), QtCore.QVariant.toPoint), - Option("persist", "window_size", QtCore.QSize(780, 560), + config.Option("persist", "window_size", QtCore.QSize(780, 560), QtCore.QVariant.toSize), - Option("persist", "bottom_splitter_state", QtCore.QByteArray(), + config.Option("persist", "bottom_splitter_state", QtCore.QByteArray(), QtCore.QVariant.toByteArray), - BoolOption("persist", "window_maximized", False), - BoolOption("persist", "view_cover_art", False), - BoolOption("persist", "view_file_browser", False), - TextOption("persist", "current_directory", ""), + config.BoolOption("persist", "window_maximized", False), + config.BoolOption("persist", "view_cover_art", False), + config.BoolOption("persist", "view_file_browser", False), + config.TextOption("persist", "current_directory", ""), ] def __init__(self, parent=None): @@ -134,7 +134,7 @@ class MainWindow(QtGui.QMainWindow): self.metadata_box.restore_state() def closeEvent(self, event): - if self.config.setting["quit_confirmation"] and not self.show_quit_confirmation(): + if config.setting["quit_confirmation"] and not self.show_quit_confirmation(): event.ignore() return self.saveWindowState() @@ -166,39 +166,39 @@ class MainWindow(QtGui.QMainWindow): return True def saveWindowState(self): - self.config.persist["window_state"] = self.saveState() + config.persist["window_state"] = self.saveState() isMaximized = int(self.windowState()) & QtCore.Qt.WindowMaximized != 0 if isMaximized: # FIXME: this doesn't include the window frame geom = self.normalGeometry() - self.config.persist["window_position"] = geom.topLeft() - self.config.persist["window_size"] = geom.size() + config.persist["window_position"] = geom.topLeft() + config.persist["window_size"] = geom.size() else: pos = self.pos() if not pos.isNull(): - self.config.persist["window_position"] = pos - self.config.persist["window_size"] = self.size() - self.config.persist["window_maximized"] = isMaximized - self.config.persist["view_cover_art"] = self.show_cover_art_action.isChecked() - self.config.persist["view_file_browser"] = self.show_file_browser_action.isChecked() - self.config.persist["bottom_splitter_state"] = self.centralWidget().saveState() + config.persist["window_position"] = pos + config.persist["window_size"] = self.size() + config.persist["window_maximized"] = isMaximized + config.persist["view_cover_art"] = self.show_cover_art_action.isChecked() + config.persist["view_file_browser"] = self.show_file_browser_action.isChecked() + config.persist["bottom_splitter_state"] = self.centralWidget().saveState() self.file_browser.save_state() self.panel.save_state() self.metadata_box.save_state() def restoreWindowState(self): - self.restoreState(self.config.persist["window_state"]) - pos = self.config.persist["window_position"] - size = self.config.persist["window_size"] + self.restoreState(config.persist["window_state"]) + pos = config.persist["window_position"] + size = config.persist["window_size"] self._desktopgeo = self.tagger.desktop().screenGeometry() if pos.x() > 0 and pos.y() > 0 and pos.x()+size.width() < self._desktopgeo.width() and pos.y()+size.height() < self._desktopgeo.height(): self.move(pos) if size.width() <= 0 or size.height() <= 0: size = QtCore.QSize(780, 560) self.resize(size) - if self.config.persist["window_maximized"]: + if config.persist["window_maximized"]: self.setWindowState(QtCore.Qt.WindowMaximized) - bottom_splitter_state = self.config.persist["bottom_splitter_state"] + bottom_splitter_state = config.persist["bottom_splitter_state"] if bottom_splitter_state.isEmpty(): self.centralWidget().setSizes([366, 194]) else: @@ -232,7 +232,7 @@ class MainWindow(QtGui.QMainWindow): """Set the status bar message.""" try: if message: - self.log.debug(repr(message.replace('%%s', '%%r')), *args) + log.debug(repr(message.replace('%%s', '%%r')), *args) except: pass self.tagger.thread_pool.call_from_thread( @@ -248,7 +248,7 @@ class MainWindow(QtGui.QMainWindow): def _on_submit(self): if self.tagger.use_acoustid: - if not self.config.setting["acoustid_apikey"]: + if not config.setting["acoustid_apikey"]: QtGui.QMessageBox.warning(self, _(u"Submission Error"), _(u"You need to configure your AcoustID API key before you can submit fingerprints.")) @@ -330,14 +330,14 @@ class MainWindow(QtGui.QMainWindow): self.show_file_browser_action = QtGui.QAction(_(u"File &Browser"), self) self.show_file_browser_action.setCheckable(True) - if self.config.persist["view_file_browser"]: + if config.persist["view_file_browser"]: self.show_file_browser_action.setChecked(True) self.show_file_browser_action.setShortcut(QtGui.QKeySequence(_(u"Ctrl+B"))) self.show_file_browser_action.triggered.connect(self.show_file_browser) self.show_cover_art_action = QtGui.QAction(_(u"&Cover Art"), self) self.show_cover_art_action.setCheckable(True) - if self.config.persist["view_cover_art"]: + if config.persist["view_cover_art"]: self.show_cover_art_action.setChecked(True) self.show_cover_art_action.triggered.connect(self.show_cover_art) @@ -383,17 +383,17 @@ class MainWindow(QtGui.QMainWindow): self.enable_renaming_action = QtGui.QAction(_(u"&Rename Files"), self) self.enable_renaming_action.setCheckable(True) - self.enable_renaming_action.setChecked(self.config.setting["rename_files"]) + self.enable_renaming_action.setChecked(config.setting["rename_files"]) self.enable_renaming_action.triggered.connect(self.toggle_rename_files) self.enable_moving_action = QtGui.QAction(_(u"&Move Files"), self) self.enable_moving_action.setCheckable(True) - self.enable_moving_action.setChecked(self.config.setting["move_files"]) + self.enable_moving_action.setChecked(config.setting["move_files"]) self.enable_moving_action.triggered.connect(self.toggle_move_files) self.enable_tag_saving_action = QtGui.QAction(_(u"Save &Tags"), self) self.enable_tag_saving_action.setCheckable(True) - self.enable_tag_saving_action.setChecked(not self.config.setting["dont_write_tags"]) + self.enable_tag_saving_action.setChecked(not config.setting["dont_write_tags"]) self.enable_tag_saving_action.triggered.connect(self.toggle_tag_saving) self.tags_from_filenames_action = QtGui.QAction(_(u"Tags From &File Names..."), self) @@ -415,13 +415,13 @@ class MainWindow(QtGui.QMainWindow): self.open_folder_action.triggered.connect(self.open_folder) def toggle_rename_files(self, checked): - self.config.setting["rename_files"] = checked + config.setting["rename_files"] = checked def toggle_move_files(self, checked): - self.config.setting["move_files"] = checked + config.setting["move_files"] = checked def toggle_tag_saving(self, checked): - self.config.setting["dont_write_tags"] = not checked + config.setting["dont_write_tags"] = not checked def open_tags_from_filenames(self): files = self.tagger.get_files_from_objects(self.selected_objects) @@ -480,7 +480,7 @@ class MainWindow(QtGui.QMainWindow): menu.addAction(self.about_action) def update_toolbar_style(self): - if self.config.setting["toolbar_show_labels"]: + if config.setting["toolbar_show_labels"]: self.toolbar.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon) else: self.toolbar.setToolButtonStyle(QtCore.Qt.ToolButtonIconOnly) @@ -578,11 +578,11 @@ class MainWindow(QtGui.QMainWindow): text = unicode(self.search_edit.text()) type = unicode(self.search_combo.itemData( self.search_combo.currentIndex()).toString()) - self.tagger.search(text, type, self.config.setting["use_adv_search_syntax"]) + self.tagger.search(text, type, config.setting["use_adv_search_syntax"]) def add_files(self): """Add files to the tagger.""" - current_directory = self.config.persist["current_directory"] or QtCore.QDir.homePath() + current_directory = config.persist["current_directory"] or QtCore.QDir.homePath() current_directory = find_existing_path(unicode(current_directory)) formats = [] extensions = [] @@ -596,16 +596,16 @@ class MainWindow(QtGui.QMainWindow): files = QtGui.QFileDialog.getOpenFileNames(self, "", current_directory, u";;".join(formats)) if files: files = map(unicode, files) - self.config.persist["current_directory"] = os.path.dirname(files[0]) + config.persist["current_directory"] = os.path.dirname(files[0]) self.tagger.add_files(files) def add_directory(self): """Add directory to the tagger.""" - current_directory = self.config.persist["current_directory"] or QtCore.QDir.homePath() + current_directory = config.persist["current_directory"] or QtCore.QDir.homePath() current_directory = find_existing_path(unicode(current_directory)) dir_list = [] - if not self.config.setting["toolbar_multiselect"]: + if not config.setting["toolbar_multiselect"]: directory = QtGui.QFileDialog.getExistingDirectory(self, "", current_directory) if directory: dir_list.append(directory) @@ -624,10 +624,10 @@ class MainWindow(QtGui.QMainWindow): dir_list = file_dialog.selectedFiles() if len(dir_list) == 1: - self.config.persist["current_directory"] = dir_list[0] + config.persist["current_directory"] = dir_list[0] elif len(dir_list) > 1: (parent, dir) = os.path.split(str(dir_list[0])) - self.config.persist["current_directory"] = parent + config.persist["current_directory"] = parent for directory in dir_list: directory = unicode(directory) @@ -684,10 +684,10 @@ been merged with that of single artist albums."""), self.panel.remove(self.selected_objects) def analyze(self): - if not self.config.setting['fingerprinting_system']: + if not config.setting['fingerprinting_system']: if self.show_analyze_settings_info(): self.show_options("fingerprinting") - if not self.config.setting['fingerprinting_system']: + if not config.setting['fingerprinting_system']: return return self.tagger.analyze(self.selected_objects) diff --git a/picard/ui/metadatabox.py b/picard/ui/metadatabox.py index d4694024c..5001396f7 100644 --- a/picard/ui/metadatabox.py +++ b/picard/ui/metadatabox.py @@ -20,11 +20,11 @@ from PyQt4 import QtCore, QtGui from collections import defaultdict +from picard import config from picard.album import Album from picard.cluster import Cluster from picard.track import Track from picard.file import File -from picard.config import TextOption, BoolOption from picard.util import partial, format_time from picard.util.tags import display_tag_name from picard.ui.edittagdialog import EditTagDialog @@ -141,8 +141,8 @@ class TagDiff: class MetadataBox(QtGui.QTableWidget): options = ( - TextOption("persist", "metadata_box_sizes", "150 300 300"), - BoolOption("persist", "show_changes_first", False) + config.TextOption("persist", "metadata_box_sizes", "150 300 300"), + config.BoolOption("persist", "show_changes_first", False) ) def __init__(self, parent): @@ -181,7 +181,7 @@ class MetadataBox(QtGui.QTableWidget): self.add_tag_action.triggered.connect(partial(self.edit_tag, "")) self.changes_first_action = QtGui.QAction(_(u"Show Changes First"), parent) self.changes_first_action.setCheckable(True) - self.changes_first_action.setChecked(self.config.persist["show_changes_first"]) + self.changes_first_action.setChecked(config.persist["show_changes_first"]) self.changes_first_action.toggled.connect(self.toggle_changes_first) def edit(self, index, trigger, event): @@ -267,7 +267,7 @@ class MetadataBox(QtGui.QTableWidget): EditTagDialog(self.parent, tag).exec_() def toggle_changes_first(self, checked): - self.config.persist["show_changes_first"] = checked + config.persist["show_changes_first"] = checked self.update() def set_tag_values(self, tag, values, objects=None): @@ -358,7 +358,7 @@ class MetadataBox(QtGui.QTableWidget): existing_tags = set() tag_diff.objects = len(self.files) - clear_existing_tags = self.config.setting["clear_existing_tags"] + clear_existing_tags = config.setting["clear_existing_tags"] for file in self.files: new_metadata = file.metadata @@ -393,7 +393,7 @@ class MetadataBox(QtGui.QTableWidget): all_tags = set(orig_tags.keys() + new_tags.keys()) tag_names = COMMON_TAGS + sorted(all_tags.difference(COMMON_TAGS)) - if self.config.persist["show_changes_first"]: + if config.persist["show_changes_first"]: self.tag_names = [] tags_by_status = {} @@ -467,7 +467,7 @@ class MetadataBox(QtGui.QTableWidget): self.set_tag_values(self.tag_names[item.row()], [unicode(item.text())]) def restore_state(self): - sizes = self.config.persist["metadata_box_sizes"].split(" ") + sizes = config.persist["metadata_box_sizes"].split(" ") header = self.horizontalHeader() try: for i in range(header.count()): @@ -482,7 +482,7 @@ class MetadataBox(QtGui.QTableWidget): header = self.horizontalHeader() for i in range(header.count()): sizes.append(str(header.sectionSize(i))) - self.config.persist["metadata_box_sizes"] = " ".join(sizes) + config.persist["metadata_box_sizes"] = " ".join(sizes) def shrink_columns(self): header = self.horizontalHeader() diff --git a/picard/ui/options/cdlookup.py b/picard/ui/options/cdlookup.py index 9e07dff51..cc05ca480 100644 --- a/picard/ui/options/cdlookup.py +++ b/picard/ui/options/cdlookup.py @@ -18,7 +18,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -from picard.config import TextOption +from picard import config from picard.ui.options import OptionsPage, register_options_page from picard.util.cdrom import get_cdrom_drives, AUTO_DETECT_DRIVES @@ -37,7 +37,7 @@ class CDLookupOptionsPage(OptionsPage): ACTIVE = True options = [ - TextOption("setting", "cd_lookup_device", ""), + config.TextOption("setting", "cd_lookup_device", ""), ] def __init__(self, parent=None): @@ -51,17 +51,17 @@ class CDLookupOptionsPage(OptionsPage): def load(self): if AUTO_DETECT_DRIVES: try: - self.ui.cd_lookup_device.setCurrentIndex(self.drives.index(self.config.setting["cd_lookup_device"])) + self.ui.cd_lookup_device.setCurrentIndex(self.drives.index(config.setting["cd_lookup_device"])) except ValueError: pass else: - self.ui.cd_lookup_device.setText(self.config.setting["cd_lookup_device"]) + self.ui.cd_lookup_device.setText(config.setting["cd_lookup_device"]) def save(self): if AUTO_DETECT_DRIVES: - self.config.setting["cd_lookup_device"] = unicode(self.ui.cd_lookup_device.currentText()) + config.setting["cd_lookup_device"] = unicode(self.ui.cd_lookup_device.currentText()) else: - self.config.setting["cd_lookup_device"] = unicode(self.ui.cd_lookup_device.text()) + config.setting["cd_lookup_device"] = unicode(self.ui.cd_lookup_device.text()) register_options_page(CDLookupOptionsPage) diff --git a/picard/ui/options/cover.py b/picard/ui/options/cover.py index bc4a07953..ea521ffda 100644 --- a/picard/ui/options/cover.py +++ b/picard/ui/options/cover.py @@ -18,7 +18,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. from PyQt4 import QtCore, QtGui -from picard.config import BoolOption, IntOption, TextOption +from picard import config from picard.ui.options import OptionsPage, register_options_page from picard.ui.ui_options_cover import Ui_CoverOptionsPage from picard.coverartarchive import CAA_TYPES, CAA_TYPES_SEPARATOR @@ -71,19 +71,19 @@ class CoverOptionsPage(OptionsPage): ACTIVE = True options = [ - BoolOption("setting", "save_images_to_tags", True), - BoolOption("setting", "save_only_front_images_to_tags", False), - BoolOption("setting", "save_images_to_files", False), - TextOption("setting", "cover_image_filename", "cover"), - BoolOption("setting", "save_images_overwrite", False), - BoolOption("setting", "ca_provider_use_amazon", False), - BoolOption("setting", "ca_provider_use_cdbaby", False), - BoolOption("setting", "ca_provider_use_caa", False), - BoolOption("setting", "ca_provider_use_whitelist", False), - BoolOption("setting", "caa_approved_only", False), - BoolOption("setting", "caa_image_type_as_filename", False), - IntOption("setting", "caa_image_size", 2), - TextOption("setting", "caa_image_types", "front"), + config.BoolOption("setting", "save_images_to_tags", True), + config.BoolOption("setting", "save_only_front_images_to_tags", False), + config.BoolOption("setting", "save_images_to_files", False), + config.TextOption("setting", "cover_image_filename", "cover"), + config.BoolOption("setting", "save_images_overwrite", False), + config.BoolOption("setting", "ca_provider_use_amazon", False), + config.BoolOption("setting", "ca_provider_use_cdbaby", False), + config.BoolOption("setting", "ca_provider_use_caa", False), + config.BoolOption("setting", "ca_provider_use_whitelist", False), + config.BoolOption("setting", "caa_approved_only", False), + config.BoolOption("setting", "caa_image_type_as_filename", False), + config.IntOption("setting", "caa_image_size", 2), + config.TextOption("setting", "caa_image_types", "front"), ] def __init__(self, parent=None): @@ -93,51 +93,51 @@ class CoverOptionsPage(OptionsPage): self.ui.save_images_to_files.clicked.connect(self.update_filename) def load(self): - self.ui.save_images_to_tags.setChecked(self.config.setting["save_images_to_tags"]) - self.ui.cb_embed_front_only.setChecked(self.config.setting["save_only_front_images_to_tags"]) - self.ui.save_images_to_files.setChecked(self.config.setting["save_images_to_files"]) - self.ui.cover_image_filename.setText(self.config.setting["cover_image_filename"]) - self.ui.save_images_overwrite.setChecked(self.config.setting["save_images_overwrite"]) + self.ui.save_images_to_tags.setChecked(config.setting["save_images_to_tags"]) + self.ui.cb_embed_front_only.setChecked(config.setting["save_only_front_images_to_tags"]) + self.ui.save_images_to_files.setChecked(config.setting["save_images_to_files"]) + self.ui.cover_image_filename.setText(config.setting["cover_image_filename"]) + self.ui.save_images_overwrite.setChecked(config.setting["save_images_overwrite"]) self.update_filename() - self.ui.caprovider_amazon.setChecked(self.config.setting["ca_provider_use_amazon"]) - self.ui.caprovider_cdbaby.setChecked(self.config.setting["ca_provider_use_cdbaby"]) - self.ui.caprovider_caa.setChecked(self.config.setting["ca_provider_use_caa"]) - self.ui.caprovider_whitelist.setChecked(self.config.setting["ca_provider_use_whitelist"]) - self.ui.gb_caa.setEnabled(self.config.setting["ca_provider_use_caa"]) + self.ui.caprovider_amazon.setChecked(config.setting["ca_provider_use_amazon"]) + self.ui.caprovider_cdbaby.setChecked(config.setting["ca_provider_use_cdbaby"]) + self.ui.caprovider_caa.setChecked(config.setting["ca_provider_use_caa"]) + self.ui.caprovider_whitelist.setChecked(config.setting["ca_provider_use_whitelist"]) + self.ui.gb_caa.setEnabled(config.setting["ca_provider_use_caa"]) - self.ui.cb_image_size.setCurrentIndex(self.config.setting["caa_image_size"]) + self.ui.cb_image_size.setCurrentIndex(config.setting["caa_image_size"]) widget = self.ui.caa_types_selector_1 - self._selector = CAATypesSelector(widget, self.config.setting["caa_image_types"]) - self.config.setting["caa_image_types"] = \ + self._selector = CAATypesSelector(widget, config.setting["caa_image_types"]) + config.setting["caa_image_types"] = \ self._selector.get_selected_types_as_string() - self.ui.cb_approved_only.setChecked(self.config.setting["caa_approved_only"]) - self.ui.cb_type_as_filename.setChecked(self.config.setting["caa_image_type_as_filename"]) + self.ui.cb_approved_only.setChecked(config.setting["caa_approved_only"]) + self.ui.cb_type_as_filename.setChecked(config.setting["caa_image_type_as_filename"]) self.connect(self.ui.caprovider_caa, QtCore.SIGNAL("toggled(bool)"), self.ui.gb_caa.setEnabled) def save(self): - self.config.setting["save_images_to_tags"] = self.ui.save_images_to_tags.isChecked() - self.config.setting["save_only_front_images_to_tags"] = self.ui.cb_embed_front_only.isChecked() - self.config.setting["save_images_to_files"] = self.ui.save_images_to_files.isChecked() - self.config.setting["cover_image_filename"] = unicode(self.ui.cover_image_filename.text()) - self.config.setting["ca_provider_use_amazon"] =\ + config.setting["save_images_to_tags"] = self.ui.save_images_to_tags.isChecked() + config.setting["save_only_front_images_to_tags"] = self.ui.cb_embed_front_only.isChecked() + config.setting["save_images_to_files"] = self.ui.save_images_to_files.isChecked() + config.setting["cover_image_filename"] = unicode(self.ui.cover_image_filename.text()) + config.setting["ca_provider_use_amazon"] =\ self.ui.caprovider_amazon.isChecked() - self.config.setting["ca_provider_use_cdbaby"] =\ + config.setting["ca_provider_use_cdbaby"] =\ self.ui.caprovider_cdbaby.isChecked() - self.config.setting["ca_provider_use_caa"] =\ + config.setting["ca_provider_use_caa"] =\ self.ui.caprovider_caa.isChecked() - self.config.setting["ca_provider_use_whitelist"] =\ + config.setting["ca_provider_use_whitelist"] =\ self.ui.caprovider_whitelist.isChecked() - self.config.setting["caa_image_size"] =\ + config.setting["caa_image_size"] =\ self.ui.cb_image_size.currentIndex() - self.config.setting["caa_image_types"] = \ + config.setting["caa_image_types"] = \ self._selector.get_selected_types_as_string() - self.config.setting["caa_approved_only"] =\ + config.setting["caa_approved_only"] =\ self.ui.cb_approved_only.isChecked() - self.config.setting["caa_image_type_as_filename"] = \ + config.setting["caa_image_type_as_filename"] = \ self.ui.cb_type_as_filename.isChecked() - self.config.setting["save_images_overwrite"] = self.ui.save_images_overwrite.isChecked() + config.setting["save_images_overwrite"] = self.ui.save_images_overwrite.isChecked() def update_filename(self): enabled = self.ui.save_images_to_files.isChecked() diff --git a/picard/ui/options/dialog.py b/picard/ui/options/dialog.py index d9ff4fe21..25a1ca9c9 100644 --- a/picard/ui/options/dialog.py +++ b/picard/ui/options/dialog.py @@ -18,7 +18,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. from PyQt4 import QtCore, QtGui -from picard.config import Option +from picard import config from picard.plugin import ExtensionPoint from picard.util import webbrowser2 from picard.ui.util import StandardButton @@ -48,9 +48,9 @@ from picard.ui.options import ( class OptionsDialog(QtGui.QDialog): options = [ - Option("persist", "options_position", QtCore.QPoint(), QtCore.QVariant.toPoint), - Option("persist", "options_size", QtCore.QSize(560, 400), QtCore.QVariant.toSize), - Option("persist", "options_splitter", QtCore.QByteArray(), QtCore.QVariant.toByteArray), + config.Option("persist", "options_position", QtCore.QPoint(), QtCore.QVariant.toPoint), + config.Option("persist", "options_size", QtCore.QSize(560, 400), QtCore.QVariant.toSize), + config.Option("persist", "options_splitter", QtCore.QByteArray(), QtCore.QVariant.toByteArray), ] def add_pages(self, parent, default_page, parent_item): @@ -134,13 +134,13 @@ class OptionsDialog(QtGui.QDialog): def saveWindowState(self): pos = self.pos() if not pos.isNull(): - self.config.persist["options_position"] = pos - self.config.persist["options_size"] = self.size() - self.config.persist["options_splitter"] = self.ui.splitter.saveState() + config.persist["options_position"] = pos + config.persist["options_size"] = self.size() + config.persist["options_splitter"] = self.ui.splitter.saveState() def restoreWindowState(self): - pos = self.config.persist["options_position"] + pos = config.persist["options_position"] if pos.x() > 0 and pos.y() > 0: self.move(pos) - self.resize(self.config.persist["options_size"]) - self.ui.splitter.restoreState(self.config.persist["options_splitter"]) + self.resize(config.persist["options_size"]) + self.ui.splitter.restoreState(config.persist["options_splitter"]) diff --git a/picard/ui/options/fingerprinting.py b/picard/ui/options/fingerprinting.py index 367e033c0..0e7efd6e3 100644 --- a/picard/ui/options/fingerprinting.py +++ b/picard/ui/options/fingerprinting.py @@ -19,9 +19,9 @@ import os from PyQt4 import QtCore, QtGui +from picard import config from picard.util import webbrowser2, find_executable from picard.const import FPCALC_NAMES -from picard.config import BoolOption, TextOption from picard.ui.options import OptionsPage, register_options_page from picard.ui.ui_options_fingerprinting import Ui_FingerprintingOptionsPage @@ -35,9 +35,9 @@ class FingerprintingOptionsPage(OptionsPage): ACTIVE = True options = [ - TextOption("setting", "fingerprinting_system", "acoustid"), - TextOption("setting", "acoustid_fpcalc", ""), - TextOption("setting", "acoustid_apikey", ""), + config.TextOption("setting", "fingerprinting_system", "acoustid"), + config.TextOption("setting", "acoustid_fpcalc", ""), + config.TextOption("setting", "acoustid_apikey", ""), ] def __init__(self, parent=None): @@ -51,21 +51,21 @@ class FingerprintingOptionsPage(OptionsPage): self.ui.acoustid_apikey_get.clicked.connect(self.acoustid_apikey_get) def load(self): - if self.config.setting["fingerprinting_system"] == "acoustid": + if config.setting["fingerprinting_system"] == "acoustid": self.ui.use_acoustid.setChecked(True) else: self.ui.disable_fingerprinting.setChecked(True) - self.ui.acoustid_fpcalc.setText(self.config.setting["acoustid_fpcalc"]) - self.ui.acoustid_apikey.setText(self.config.setting["acoustid_apikey"]) + self.ui.acoustid_fpcalc.setText(config.setting["acoustid_fpcalc"]) + self.ui.acoustid_apikey.setText(config.setting["acoustid_apikey"]) self.update_groupboxes() def save(self): if self.ui.use_acoustid.isChecked(): - self.config.setting["fingerprinting_system"] = "acoustid" + config.setting["fingerprinting_system"] = "acoustid" else: - self.config.setting["fingerprinting_system"] = "" - self.config.setting["acoustid_fpcalc"] = unicode(self.ui.acoustid_fpcalc.text()) - self.config.setting["acoustid_apikey"] = unicode(self.ui.acoustid_apikey.text()) + config.setting["fingerprinting_system"] = "" + config.setting["acoustid_fpcalc"] = unicode(self.ui.acoustid_fpcalc.text()) + config.setting["acoustid_apikey"] = unicode(self.ui.acoustid_apikey.text()) def update_groupboxes(self): if self.ui.use_acoustid.isChecked(): diff --git a/picard/ui/options/folksonomy.py b/picard/ui/options/folksonomy.py index e75a1692f..11e9b92cd 100644 --- a/picard/ui/options/folksonomy.py +++ b/picard/ui/options/folksonomy.py @@ -17,7 +17,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -from picard.config import BoolOption, TextOption, IntOption +from picard import config from picard.ui.options import OptionsPage, register_options_page from picard.ui.ui_options_folksonomy import Ui_FolksonomyOptionsPage @@ -31,11 +31,11 @@ class FolksonomyOptionsPage(OptionsPage): ACTIVE = True options = [ - IntOption("setting", "max_tags", 5), - IntOption("setting", "min_tag_usage", 90), - TextOption("setting", "ignore_tags", "seen live,favorites,fixme,owned"), - TextOption("setting", "join_tags", ""), - BoolOption("setting", "only_my_tags", False), + config.IntOption("setting", "max_tags", 5), + config.IntOption("setting", "min_tag_usage", 90), + config.TextOption("setting", "ignore_tags", "seen live,favorites,fixme,owned"), + config.TextOption("setting", "join_tags", ""), + config.BoolOption("setting", "only_my_tags", False), ] def __init__(self, parent=None): @@ -44,18 +44,18 @@ class FolksonomyOptionsPage(OptionsPage): self.ui.setupUi(self) def load(self): - self.ui.max_tags.setValue(self.config.setting["max_tags"]) - self.ui.min_tag_usage.setValue(self.config.setting["min_tag_usage"]) - self.ui.join_tags.setEditText(self.config.setting["join_tags"]) - self.ui.ignore_tags.setText(self.config.setting["ignore_tags"]) - self.ui.only_my_tags.setChecked(self.config.setting["only_my_tags"]) + self.ui.max_tags.setValue(config.setting["max_tags"]) + self.ui.min_tag_usage.setValue(config.setting["min_tag_usage"]) + self.ui.join_tags.setEditText(config.setting["join_tags"]) + self.ui.ignore_tags.setText(config.setting["ignore_tags"]) + self.ui.only_my_tags.setChecked(config.setting["only_my_tags"]) def save(self): - self.config.setting["max_tags"] = self.ui.max_tags.value() - self.config.setting["min_tag_usage"] = self.ui.min_tag_usage.value() - self.config.setting["join_tags"] = self.ui.join_tags.currentText() - self.config.setting["ignore_tags"] = self.ui.ignore_tags.text() - self.config.setting["only_my_tags"] = self.ui.only_my_tags.isChecked() + config.setting["max_tags"] = self.ui.max_tags.value() + config.setting["min_tag_usage"] = self.ui.min_tag_usage.value() + config.setting["join_tags"] = self.ui.join_tags.currentText() + config.setting["ignore_tags"] = self.ui.ignore_tags.text() + config.setting["only_my_tags"] = self.ui.only_my_tags.isChecked() register_options_page(FolksonomyOptionsPage) diff --git a/picard/ui/options/general.py b/picard/ui/options/general.py index 0ebc131e0..82abd3f37 100644 --- a/picard/ui/options/general.py +++ b/picard/ui/options/general.py @@ -17,7 +17,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -from picard.config import IntOption, TextOption, BoolOption, PasswordOption +from picard import config from picard.ui.options import OptionsPage, register_options_page from picard.ui.ui_options_general import Ui_GeneralOptionsPage from picard.util import rot13 @@ -32,12 +32,12 @@ class GeneralOptionsPage(OptionsPage): ACTIVE = True options = [ - TextOption("setting", "server_host", "musicbrainz.org"), - IntOption("setting", "server_port", 80), - TextOption("setting", "username", ""), - PasswordOption("setting", "password", ""), - BoolOption("setting", "analyze_new_files", False), - BoolOption("setting", "ignore_file_mbids", False), + config.TextOption("setting", "server_host", "musicbrainz.org"), + config.IntOption("setting", "server_port", 80), + config.TextOption("setting", "username", ""), + config.PasswordOption("setting", "password", ""), + config.BoolOption("setting", "analyze_new_files", False), + config.BoolOption("setting", "ignore_file_mbids", False), ] def __init__(self, parent=None): @@ -50,21 +50,21 @@ class GeneralOptionsPage(OptionsPage): self.ui.server_host.addItems(sorted(mirror_servers)) def load(self): - self.ui.server_host.setEditText(self.config.setting["server_host"]) - self.ui.server_port.setValue(self.config.setting["server_port"]) - self.ui.username.setText(self.config.setting["username"]) - self.ui.password.setText(self.config.setting["password"]) - self.ui.analyze_new_files.setChecked(self.config.setting["analyze_new_files"]) - self.ui.ignore_file_mbids.setChecked(self.config.setting["ignore_file_mbids"]) + self.ui.server_host.setEditText(config.setting["server_host"]) + self.ui.server_port.setValue(config.setting["server_port"]) + self.ui.username.setText(config.setting["username"]) + self.ui.password.setText(config.setting["password"]) + self.ui.analyze_new_files.setChecked(config.setting["analyze_new_files"]) + self.ui.ignore_file_mbids.setChecked(config.setting["ignore_file_mbids"]) def save(self): - self.config.setting["server_host"] = unicode(self.ui.server_host.currentText()).strip() - self.config.setting["server_port"] = self.ui.server_port.value() - self.config.setting["username"] = unicode(self.ui.username.text()) + config.setting["server_host"] = unicode(self.ui.server_host.currentText()).strip() + config.setting["server_port"] = self.ui.server_port.value() + config.setting["username"] = unicode(self.ui.username.text()) # trivially encode the password, just to not make it so apparent - self.config.setting["password"] = rot13(unicode(self.ui.password.text())) - self.config.setting["analyze_new_files"] = self.ui.analyze_new_files.isChecked() - self.config.setting["ignore_file_mbids"] = self.ui.ignore_file_mbids.isChecked() + config.setting["password"] = rot13(unicode(self.ui.password.text())) + config.setting["analyze_new_files"] = self.ui.analyze_new_files.isChecked() + config.setting["ignore_file_mbids"] = self.ui.ignore_file_mbids.isChecked() register_options_page(GeneralOptionsPage) diff --git a/picard/ui/options/interface.py b/picard/ui/options/interface.py index 1871752cd..807dfd4c2 100644 --- a/picard/ui/options/interface.py +++ b/picard/ui/options/interface.py @@ -18,7 +18,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. from PyQt4 import QtCore, QtGui -from picard.config import BoolOption, TextOption +from picard import config from picard.ui.options import OptionsPage, register_options_page from picard.ui.ui_options_interface import Ui_InterfaceOptionsPage from picard.const import UI_LANGUAGES @@ -35,11 +35,11 @@ class InterfaceOptionsPage(OptionsPage): ACTIVE = True options = [ - BoolOption("setting", "toolbar_show_labels", True), - BoolOption("setting", "toolbar_multiselect", False), - BoolOption("setting", "use_adv_search_syntax", False), - BoolOption("setting", "quit_confirmation", True), - TextOption("setting", "ui_language", u""), + config.BoolOption("setting", "toolbar_show_labels", True), + config.BoolOption("setting", "toolbar_multiselect", False), + config.BoolOption("setting", "use_adv_search_syntax", False), + config.BoolOption("setting", "quit_confirmation", True), + config.TextOption("setting", "ui_language", u""), ] def __init__(self, parent=None): @@ -57,22 +57,22 @@ class InterfaceOptionsPage(OptionsPage): self.ui.ui_language.addItem(name, QtCore.QVariant(lang_code)) def load(self): - self.ui.toolbar_show_labels.setChecked(self.config.setting["toolbar_show_labels"]) - self.ui.toolbar_multiselect.setChecked(self.config.setting["toolbar_multiselect"]) - self.ui.use_adv_search_syntax.setChecked(self.config.setting["use_adv_search_syntax"]) - self.ui.quit_confirmation.setChecked(self.config.setting["quit_confirmation"]) - current_ui_language = QtCore.QVariant(self.config.setting["ui_language"]) + self.ui.toolbar_show_labels.setChecked(config.setting["toolbar_show_labels"]) + self.ui.toolbar_multiselect.setChecked(config.setting["toolbar_multiselect"]) + self.ui.use_adv_search_syntax.setChecked(config.setting["use_adv_search_syntax"]) + self.ui.quit_confirmation.setChecked(config.setting["quit_confirmation"]) + current_ui_language = QtCore.QVariant(config.setting["ui_language"]) self.ui.ui_language.setCurrentIndex(self.ui.ui_language.findData(current_ui_language)) def save(self): - self.config.setting["toolbar_show_labels"] = self.ui.toolbar_show_labels.isChecked() - self.config.setting["toolbar_multiselect"] = self.ui.toolbar_multiselect.isChecked() - self.config.setting["use_adv_search_syntax"] = self.ui.use_adv_search_syntax.isChecked() - self.config.setting["quit_confirmation"] = self.ui.quit_confirmation.isChecked() + config.setting["toolbar_show_labels"] = self.ui.toolbar_show_labels.isChecked() + config.setting["toolbar_multiselect"] = self.ui.toolbar_multiselect.isChecked() + config.setting["use_adv_search_syntax"] = self.ui.use_adv_search_syntax.isChecked() + config.setting["quit_confirmation"] = self.ui.quit_confirmation.isChecked() self.tagger.window.update_toolbar_style() new_language = self.ui.ui_language.itemData(self.ui.ui_language.currentIndex()).toString() - if new_language != self.config.setting["ui_language"]: - self.config.setting["ui_language"] = self.ui.ui_language.itemData(self.ui.ui_language.currentIndex()).toString() + if new_language != config.setting["ui_language"]: + config.setting["ui_language"] = self.ui.ui_language.itemData(self.ui.ui_language.currentIndex()).toString() dialog = QtGui.QMessageBox(QtGui.QMessageBox.Information, _('Language changed'), _('You have changed the interface language. You have to restart Picard in order for the change to take effect.'), QtGui.QMessageBox.Ok, self) dialog.exec_() diff --git a/picard/ui/options/matching.py b/picard/ui/options/matching.py index e259abfc1..b39630243 100644 --- a/picard/ui/options/matching.py +++ b/picard/ui/options/matching.py @@ -17,7 +17,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -from picard.config import FloatOption +from picard import config from picard.ui.options import OptionsPage, register_options_page from picard.ui.ui_options_matching import Ui_MatchingOptionsPage @@ -31,9 +31,9 @@ class MatchingOptionsPage(OptionsPage): ACTIVE = True options = [ - FloatOption("setting", "file_lookup_threshold", 0.7), - FloatOption("setting", "cluster_lookup_threshold", 0.8), - FloatOption("setting", "track_matching_threshold", 0.4), + config.FloatOption("setting", "file_lookup_threshold", 0.7), + config.FloatOption("setting", "cluster_lookup_threshold", 0.8), + config.FloatOption("setting", "track_matching_threshold", 0.4), ] _release_type_sliders = {} @@ -44,14 +44,14 @@ class MatchingOptionsPage(OptionsPage): self.ui.setupUi(self) def load(self): - self.ui.file_lookup_threshold.setValue(int(self.config.setting["file_lookup_threshold"] * 100)) - self.ui.cluster_lookup_threshold.setValue(int(self.config.setting["cluster_lookup_threshold"] * 100)) - self.ui.track_matching_threshold.setValue(int(self.config.setting["track_matching_threshold"] * 100)) + self.ui.file_lookup_threshold.setValue(int(config.setting["file_lookup_threshold"] * 100)) + self.ui.cluster_lookup_threshold.setValue(int(config.setting["cluster_lookup_threshold"] * 100)) + self.ui.track_matching_threshold.setValue(int(config.setting["track_matching_threshold"] * 100)) def save(self): - self.config.setting["file_lookup_threshold"] = float(self.ui.file_lookup_threshold.value()) / 100.0 - self.config.setting["cluster_lookup_threshold"] = float(self.ui.cluster_lookup_threshold.value()) / 100.0 - self.config.setting["track_matching_threshold"] = float(self.ui.track_matching_threshold.value()) / 100.0 + config.setting["file_lookup_threshold"] = float(self.ui.file_lookup_threshold.value()) / 100.0 + config.setting["cluster_lookup_threshold"] = float(self.ui.cluster_lookup_threshold.value()) / 100.0 + config.setting["track_matching_threshold"] = float(self.ui.track_matching_threshold.value()) / 100.0 register_options_page(MatchingOptionsPage) diff --git a/picard/ui/options/metadata.py b/picard/ui/options/metadata.py index 9eeb16794..bca58544a 100644 --- a/picard/ui/options/metadata.py +++ b/picard/ui/options/metadata.py @@ -18,7 +18,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. from PyQt4 import QtCore -from picard.config import BoolOption, TextOption +from picard import config from picard.ui.options import OptionsPage, register_options_page from picard.ui.ui_options_metadata import Ui_MetadataOptionsPage from picard.const import ALIAS_LOCALES @@ -33,15 +33,15 @@ class MetadataOptionsPage(OptionsPage): ACTIVE = True options = [ - TextOption("setting", "va_name", u"Various Artists"), - TextOption("setting", "nat_name", u"[non-album tracks]"), - TextOption("setting", "artist_locale", u"en"), - BoolOption("setting", "translate_artist_names", False), - BoolOption("setting", "release_ars", True), - BoolOption("setting", "track_ars", False), - BoolOption("setting", "folksonomy_tags", False), - BoolOption("setting", "convert_punctuation", True), - BoolOption("setting", "standardize_artists", False), + config.TextOption("setting", "va_name", u"Various Artists"), + config.TextOption("setting", "nat_name", u"[non-album tracks]"), + config.TextOption("setting", "artist_locale", u"en"), + config.BoolOption("setting", "translate_artist_names", False), + config.BoolOption("setting", "release_ars", True), + config.BoolOption("setting", "track_ars", False), + config.BoolOption("setting", "folksonomy_tags", False), + config.BoolOption("setting", "convert_punctuation", True), + config.BoolOption("setting", "standardize_artists", False), ] def __init__(self, parent=None): @@ -52,7 +52,7 @@ class MetadataOptionsPage(OptionsPage): self.ui.nat_name_default.clicked.connect(self.set_nat_name_default) def load(self): - self.ui.translate_artist_names.setChecked(self.config.setting["translate_artist_names"]) + self.ui.translate_artist_names.setChecked(config.setting["translate_artist_names"]) combo_box = self.ui.artist_locale locales = ALIAS_LOCALES.keys() @@ -62,30 +62,30 @@ class MetadataOptionsPage(OptionsPage): if "_" in loc: name = " " + name combo_box.addItem(name, loc) - if loc == self.config.setting["artist_locale"]: + if loc == config.setting["artist_locale"]: combo_box.setCurrentIndex(i) - self.ui.convert_punctuation.setChecked(self.config.setting["convert_punctuation"]) - self.ui.release_ars.setChecked(self.config.setting["release_ars"]) - self.ui.track_ars.setChecked(self.config.setting["track_ars"]) - self.ui.folksonomy_tags.setChecked(self.config.setting["folksonomy_tags"]) - self.ui.va_name.setText(self.config.setting["va_name"]) - self.ui.nat_name.setText(self.config.setting["nat_name"]) - self.ui.standardize_artists.setChecked(self.config.setting["standardize_artists"]) + self.ui.convert_punctuation.setChecked(config.setting["convert_punctuation"]) + self.ui.release_ars.setChecked(config.setting["release_ars"]) + self.ui.track_ars.setChecked(config.setting["track_ars"]) + self.ui.folksonomy_tags.setChecked(config.setting["folksonomy_tags"]) + self.ui.va_name.setText(config.setting["va_name"]) + self.ui.nat_name.setText(config.setting["nat_name"]) + self.ui.standardize_artists.setChecked(config.setting["standardize_artists"]) def save(self): - self.config.setting["translate_artist_names"] = self.ui.translate_artist_names.isChecked() - self.config.setting["artist_locale"] = self.ui.artist_locale.itemData(self.ui.artist_locale.currentIndex()) - self.config.setting["convert_punctuation"] = self.ui.convert_punctuation.isChecked() - self.config.setting["release_ars"] = self.ui.release_ars.isChecked() - self.config.setting["track_ars"] = self.ui.track_ars.isChecked() - self.config.setting["folksonomy_tags"] = self.ui.folksonomy_tags.isChecked() - self.config.setting["va_name"] = self.ui.va_name.text() + config.setting["translate_artist_names"] = self.ui.translate_artist_names.isChecked() + config.setting["artist_locale"] = self.ui.artist_locale.itemData(self.ui.artist_locale.currentIndex()) + config.setting["convert_punctuation"] = self.ui.convert_punctuation.isChecked() + config.setting["release_ars"] = self.ui.release_ars.isChecked() + config.setting["track_ars"] = self.ui.track_ars.isChecked() + config.setting["folksonomy_tags"] = self.ui.folksonomy_tags.isChecked() + config.setting["va_name"] = self.ui.va_name.text() nat_name = unicode(self.ui.nat_name.text()) - if nat_name != self.config.setting["nat_name"]: - self.config.setting["nat_name"] = nat_name + if nat_name != config.setting["nat_name"]: + config.setting["nat_name"] = nat_name self.tagger.nats.update() - self.config.setting["standardize_artists"] = self.ui.standardize_artists.isChecked() + config.setting["standardize_artists"] = self.ui.standardize_artists.isChecked() def set_va_name_default(self): self.ui.va_name.setText(self.options[0].default) diff --git a/picard/ui/options/plugins.py b/picard/ui/options/plugins.py index 21e67e284..b19fd739f 100644 --- a/picard/ui/options/plugins.py +++ b/picard/ui/options/plugins.py @@ -21,7 +21,7 @@ import os.path import sys from PyQt4 import QtCore, QtGui -from picard.config import TextOption +from picard import config from picard.util import encode_filename from picard.ui.options import OptionsPage, register_options_page from picard.ui.ui_options_plugins import Ui_PluginsOptionsPage @@ -40,7 +40,7 @@ class PluginsOptionsPage(OptionsPage): ACTIVE = True options = [ - TextOption("setting", "enabled_plugins", ""), + config.TextOption("setting", "enabled_plugins", ""), ] def __init__(self, parent=None): @@ -63,7 +63,7 @@ class PluginsOptionsPage(OptionsPage): def load(self): plugins = sorted(self.tagger.pluginmanager.plugins, cmp=cmp_plugins) - enabled_plugins = self.config.setting["enabled_plugins"].split() + enabled_plugins = config.setting["enabled_plugins"].split() firstitem = None for plugin in plugins: enabled = plugin.module_name in enabled_plugins @@ -107,7 +107,7 @@ class PluginsOptionsPage(OptionsPage): for item, plugin in self.items.iteritems(): if item.checkState(0) == QtCore.Qt.Checked: enabled_plugins.append(plugin.module_name) - self.config.setting["enabled_plugins"] = " ".join(enabled_plugins) + config.setting["enabled_plugins"] = " ".join(enabled_plugins) def change_details(self): plugin = self.items[self.ui.plugins.selectedItems()[0]] diff --git a/picard/ui/options/proxy.py b/picard/ui/options/proxy.py index a223a297f..9f5c77930 100644 --- a/picard/ui/options/proxy.py +++ b/picard/ui/options/proxy.py @@ -17,7 +17,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -from picard.config import IntOption, TextOption, BoolOption +from picard import config from picard.ui.options import OptionsPage, register_options_page from picard.ui.ui_options_proxy import Ui_ProxyOptionsPage @@ -31,11 +31,11 @@ class ProxyOptionsPage(OptionsPage): ACTIVE = True options = [ - BoolOption("setting", "use_proxy", False), - TextOption("setting", "proxy_server_host", ""), - IntOption("setting", "proxy_server_port", 80), - TextOption("setting", "proxy_username", ""), - TextOption("setting", "proxy_password", ""), + config.BoolOption("setting", "use_proxy", False), + config.TextOption("setting", "proxy_server_host", ""), + config.IntOption("setting", "proxy_server_port", 80), + config.TextOption("setting", "proxy_username", ""), + config.TextOption("setting", "proxy_password", ""), ] def __init__(self, parent=None): @@ -44,18 +44,18 @@ class ProxyOptionsPage(OptionsPage): self.ui.setupUi(self) def load(self): - self.ui.web_proxy.setChecked(self.config.setting["use_proxy"]) - self.ui.server_host.setText(self.config.setting["proxy_server_host"]) - self.ui.server_port.setValue(self.config.setting["proxy_server_port"]) - self.ui.username.setText(self.config.setting["proxy_username"]) - self.ui.password.setText(self.config.setting["proxy_password"]) + self.ui.web_proxy.setChecked(config.setting["use_proxy"]) + self.ui.server_host.setText(config.setting["proxy_server_host"]) + self.ui.server_port.setValue(config.setting["proxy_server_port"]) + self.ui.username.setText(config.setting["proxy_username"]) + self.ui.password.setText(config.setting["proxy_password"]) def save(self): - self.config.setting["use_proxy"] = self.ui.web_proxy.isChecked() - self.config.setting["proxy_server_host"] = unicode(self.ui.server_host.text()) - self.config.setting["proxy_server_port"] = self.ui.server_port.value() - self.config.setting["proxy_username"] = unicode(self.ui.username.text()) - self.config.setting["proxy_password"] = unicode(self.ui.password.text()) + config.setting["use_proxy"] = self.ui.web_proxy.isChecked() + config.setting["proxy_server_host"] = unicode(self.ui.server_host.text()) + config.setting["proxy_server_port"] = self.ui.server_port.value() + config.setting["proxy_username"] = unicode(self.ui.username.text()) + config.setting["proxy_password"] = unicode(self.ui.password.text()) self.tagger.xmlws.setup_proxy() diff --git a/picard/ui/options/ratings.py b/picard/ui/options/ratings.py index 2a7ebf64d..de7e841b5 100644 --- a/picard/ui/options/ratings.py +++ b/picard/ui/options/ratings.py @@ -17,7 +17,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -from picard.config import BoolOption, TextOption, IntOption +from picard import config from picard.ui.options import OptionsPage, register_options_page from picard.ui.ui_options_ratings import Ui_RatingsOptionsPage @@ -31,10 +31,10 @@ class RatingsOptionsPage(OptionsPage): ACTIVE = True options = [ - BoolOption("setting", "enable_ratings", False), - TextOption("setting", "rating_user_email", "users@musicbrainz.org"), - BoolOption("setting", "submit_ratings", True), - IntOption("setting", "rating_steps", 6), + config.BoolOption("setting", "enable_ratings", False), + config.TextOption("setting", "rating_user_email", "users@musicbrainz.org"), + config.BoolOption("setting", "submit_ratings", True), + config.IntOption("setting", "rating_steps", 6), ] def __init__(self, parent=None): @@ -43,14 +43,14 @@ class RatingsOptionsPage(OptionsPage): self.ui.setupUi(self) def load(self): - self.ui.enable_ratings.setChecked(self.config.setting["enable_ratings"]) - self.ui.rating_user_email.setText(self.config.setting["rating_user_email"]) - self.ui.submit_ratings.setChecked(self.config.setting["submit_ratings"]) + self.ui.enable_ratings.setChecked(config.setting["enable_ratings"]) + self.ui.rating_user_email.setText(config.setting["rating_user_email"]) + self.ui.submit_ratings.setChecked(config.setting["submit_ratings"]) def save(self): - self.config.setting["enable_ratings"] = self.ui.enable_ratings.isChecked() - self.config.setting["rating_user_email"] = self.ui.rating_user_email.text() - self.config.setting["submit_ratings"] = self.ui.submit_ratings.isChecked() + config.setting["enable_ratings"] = self.ui.enable_ratings.isChecked() + config.setting["rating_user_email"] = self.ui.rating_user_email.text() + config.setting["submit_ratings"] = self.ui.submit_ratings.isChecked() register_options_page(RatingsOptionsPage) diff --git a/picard/ui/options/releases.py b/picard/ui/options/releases.py index 3e3421f6f..c26942bf9 100644 --- a/picard/ui/options/releases.py +++ b/picard/ui/options/releases.py @@ -20,7 +20,7 @@ from operator import itemgetter from locale import strcoll from PyQt4 import QtCore, QtGui -from picard.config import TextOption +from picard import config from picard.util import load_release_type_scores, save_release_type_scores from picard.ui.options import OptionsPage, register_options_page from picard.ui.ui_options_releases import Ui_ReleasesOptionsPage @@ -36,9 +36,9 @@ class ReleasesOptionsPage(OptionsPage): ACTIVE = True options = [ - TextOption("setting", "release_type_scores", "Album 0.5 Single 0.5 EP 0.5 Compilation 0.5 Soundtrack 0.5 Spokenword 0.5 Interview 0.5 Audiobook 0.5 Live 0.5 Remix 0.5 Other 0.5"), - TextOption("setting", "preferred_release_countries", u""), - TextOption("setting", "preferred_release_formats", u""), + config.TextOption("setting", "release_type_scores", "Album 0.5 Single 0.5 EP 0.5 Compilation 0.5 Soundtrack 0.5 Spokenword 0.5 Interview 0.5 Audiobook 0.5 Live 0.5 Remix 0.5 Other 0.5"), + config.TextOption("setting", "preferred_release_countries", u""), + config.TextOption("setting", "preferred_release_formats", u""), ] _release_type_sliders = {} @@ -70,7 +70,7 @@ class ReleasesOptionsPage(OptionsPage): self.ui.preferred_format_list.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) def load(self): - scores = load_release_type_scores(self.config.setting["release_type_scores"]) + scores = load_release_type_scores(config.setting["release_type_scores"]) for (release_type, release_type_slider) in self._release_type_sliders.iteritems(): release_type_slider.setValue(int(scores.get(release_type, 0.5) * 100)) @@ -83,7 +83,7 @@ class ReleasesOptionsPage(OptionsPage): scores = {} for (release_type, release_type_slider) in self._release_type_sliders.iteritems(): scores[release_type] = float(release_type_slider.value()) / 100.0 - self.config.setting["release_type_scores"] = save_release_type_scores(scores) + config.setting["release_type_scores"] = save_release_type_scores(scores) self._save_list_items("preferred_release_countries", self.ui.preferred_country_list) self._save_list_items("preferred_release_formats", self.ui.preferred_format_list) @@ -115,7 +115,7 @@ class ReleasesOptionsPage(OptionsPage): def _load_list_items(self, setting, source, list1, list2): source_list = [(c[0], _(c[1])) for c in source.items()] source_list.sort(key=itemgetter(1), cmp=strcoll) - saved_data = self.config.setting[setting].split(" ") + saved_data = config.setting[setting].split(" ") move = [] for data, name in source_list: item = QtGui.QListWidgetItem(name) @@ -134,7 +134,7 @@ class ReleasesOptionsPage(OptionsPage): for i in range(list1.count()): item = list1.item(i) data.append(unicode(item.data(QtCore.Qt.UserRole).toString())) - self.config.setting[setting] = " ".join(data) + config.setting[setting] = " ".join(data) register_options_page(ReleasesOptionsPage) diff --git a/picard/ui/options/renaming.py b/picard/ui/options/renaming.py index 4f2cbd774..572213e18 100644 --- a/picard/ui/options/renaming.py +++ b/picard/ui/options/renaming.py @@ -21,13 +21,14 @@ import os.path import sys from PyQt4 import QtCore, QtGui -from picard.config import BoolOption, TextOption +from picard import config from picard.file import File from picard.script import ScriptParser, SyntaxError, UnknownFunction from picard.ui.options import OptionsPage, OptionsCheckError, register_options_page from picard.ui.ui_options_renaming import Ui_RenamingOptionsPage from picard.ui.options.scripting import TaggerScriptSyntaxHighlighter + class RenamingOptionsPage(OptionsPage): NAME = "filerenaming" @@ -37,15 +38,15 @@ class RenamingOptionsPage(OptionsPage): ACTIVE = True options = [ - BoolOption("setting", "windows_compatible_filenames", True), - BoolOption("setting", "ascii_filenames", False), - BoolOption("setting", "rename_files", False), - TextOption("setting", "file_naming_format", "$if2(%albumartist%,%artist%)/%album%/$if($gt(%totaldiscs%,1),%discnumber%-,)$num(%tracknumber%,2)$if(%compilation%, %artist% -,) %title%"), - BoolOption("setting", "move_files", False), - TextOption("setting", "move_files_to", ""), - BoolOption("setting", "move_additional_files", False), - TextOption("setting", "move_additional_files_pattern", "*.jpg *.png"), - BoolOption("setting", "delete_empty_dirs", True), + config.BoolOption("setting", "windows_compatible_filenames", True), + config.BoolOption("setting", "ascii_filenames", False), + config.BoolOption("setting", "rename_files", False), + config.TextOption("setting", "file_naming_format", "$if2(%albumartist%,%artist%)/%album%/$if($gt(%totaldiscs%,1),%discnumber%-,)$num(%tracknumber%,2)$if(%compilation%, %artist% -,) %title%"), + config.BoolOption("setting", "move_files", False), + config.TextOption("setting", "move_files_to", ""), + config.BoolOption("setting", "move_additional_files", False), + config.TextOption("setting", "move_additional_files_pattern", "*.jpg *.png"), + config.BoolOption("setting", "delete_empty_dirs", True), ] def __init__(self, parent=None): @@ -91,8 +92,8 @@ class RenamingOptionsPage(OptionsPage): 'move_files_to': os.path.normpath(unicode(self.ui.move_files_to.text())) } try: - if self.config.setting["enable_tagger_script"]: - script = self.config.setting["tagger_script"] + if config.setting["enable_tagger_script"]: + script = config.setting["tagger_script"] parser = ScriptParser() parser.eval(script, file.metadata) filename = file._make_filename(file.filename, file.metadata, settings) @@ -116,16 +117,16 @@ class RenamingOptionsPage(OptionsPage): self.ui.windows_compatible_filenames.setChecked(True) self.ui.windows_compatible_filenames.setEnabled(False) else: - self.ui.windows_compatible_filenames.setChecked(self.config.setting["windows_compatible_filenames"]) - self.ui.rename_files.setChecked(self.config.setting["rename_files"]) - self.ui.move_files.setChecked(self.config.setting["move_files"]) - self.ui.ascii_filenames.setChecked(self.config.setting["ascii_filenames"]) - self.ui.file_naming_format.setPlainText(self.config.setting["file_naming_format"]) - self.ui.move_files_to.setText(self.config.setting["move_files_to"]) + self.ui.windows_compatible_filenames.setChecked(config.setting["windows_compatible_filenames"]) + self.ui.rename_files.setChecked(config.setting["rename_files"]) + self.ui.move_files.setChecked(config.setting["move_files"]) + self.ui.ascii_filenames.setChecked(config.setting["ascii_filenames"]) + self.ui.file_naming_format.setPlainText(config.setting["file_naming_format"]) + self.ui.move_files_to.setText(config.setting["move_files_to"]) self.ui.move_files_to.setCursorPosition(0) - self.ui.move_additional_files.setChecked(self.config.setting["move_additional_files"]) - self.ui.move_additional_files_pattern.setText(self.config.setting["move_additional_files_pattern"]) - self.ui.delete_empty_dirs.setChecked(self.config.setting["delete_empty_dirs"]) + self.ui.move_additional_files.setChecked(config.setting["move_additional_files"]) + self.ui.move_additional_files_pattern.setText(config.setting["move_additional_files_pattern"]) + self.ui.delete_empty_dirs.setChecked(config.setting["delete_empty_dirs"]) self.update_examples() def check(self): @@ -144,17 +145,17 @@ class RenamingOptionsPage(OptionsPage): raise OptionsCheckError("", _("The file naming format must not be empty.")) def save(self): - self.config.setting["windows_compatible_filenames"] = self.ui.windows_compatible_filenames.isChecked() - self.config.setting["ascii_filenames"] = self.ui.ascii_filenames.isChecked() - self.config.setting["rename_files"] = self.ui.rename_files.isChecked() - self.config.setting["file_naming_format"] = unicode(self.ui.file_naming_format.toPlainText()) - self.tagger.window.enable_renaming_action.setChecked(self.config.setting["rename_files"]) - self.config.setting["move_files"] = self.ui.move_files.isChecked() - self.config.setting["move_files_to"] = os.path.normpath(unicode(self.ui.move_files_to.text())) - self.config.setting["move_additional_files"] = self.ui.move_additional_files.isChecked() - self.config.setting["move_additional_files_pattern"] = unicode(self.ui.move_additional_files_pattern.text()) - self.config.setting["delete_empty_dirs"] = self.ui.delete_empty_dirs.isChecked() - self.tagger.window.enable_moving_action.setChecked(self.config.setting["move_files"]) + config.setting["windows_compatible_filenames"] = self.ui.windows_compatible_filenames.isChecked() + config.setting["ascii_filenames"] = self.ui.ascii_filenames.isChecked() + config.setting["rename_files"] = self.ui.rename_files.isChecked() + config.setting["file_naming_format"] = unicode(self.ui.file_naming_format.toPlainText()) + self.tagger.window.enable_renaming_action.setChecked(config.setting["rename_files"]) + config.setting["move_files"] = self.ui.move_files.isChecked() + config.setting["move_files_to"] = os.path.normpath(unicode(self.ui.move_files_to.text())) + config.setting["move_additional_files"] = self.ui.move_additional_files.isChecked() + config.setting["move_additional_files_pattern"] = unicode(self.ui.move_additional_files_pattern.text()) + config.setting["delete_empty_dirs"] = self.ui.delete_empty_dirs.isChecked() + self.tagger.window.enable_moving_action.setChecked(config.setting["move_files"]) def display_error(self, error): pass @@ -194,8 +195,8 @@ class RenamingOptionsPage(OptionsPage): file.metadata['title'] = 'Why? Oh Why?' file.metadata['artist'] = 'The Fantasys' file.metadata['artistsort'] = 'Fantasys, The' - file.metadata['albumartist'] = self.config.setting['va_name'] - file.metadata['albumartistsort'] = self.config.setting['va_name'] + file.metadata['albumartist'] = config.setting['va_name'] + file.metadata['albumartistsort'] = config.setting['va_name'] file.metadata['tracknumber'] = '5' file.metadata['totaltracks'] = '26' file.metadata['discnumber'] = '2' diff --git a/picard/ui/options/scripting.py b/picard/ui/options/scripting.py index ac7e303c7..a1209cda7 100644 --- a/picard/ui/options/scripting.py +++ b/picard/ui/options/scripting.py @@ -18,7 +18,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. from PyQt4 import QtCore, QtGui -from picard.config import BoolOption, TextOption +from picard import config from picard.script import ScriptParser from picard.ui.options import OptionsPage, OptionsCheckError, register_options_page from picard.ui.ui_options_script import Ui_ScriptingOptionsPage @@ -66,8 +66,8 @@ class ScriptingOptionsPage(OptionsPage): ACTIVE = True options = [ - BoolOption("setting", "enable_tagger_script", False), - TextOption("setting", "tagger_script", ""), + config.BoolOption("setting", "enable_tagger_script", False), + config.TextOption("setting", "tagger_script", ""), ] STYLESHEET_ERROR = "QWidget { background-color: #f55; color: white; font-weight:bold }" @@ -97,12 +97,12 @@ class ScriptingOptionsPage(OptionsPage): raise OptionsCheckError(_("Script Error"), str(e)) def load(self): - self.ui.enable_tagger_script.setChecked(self.config.setting["enable_tagger_script"]) - self.ui.tagger_script.document().setPlainText(self.config.setting["tagger_script"]) + self.ui.enable_tagger_script.setChecked(config.setting["enable_tagger_script"]) + self.ui.tagger_script.document().setPlainText(config.setting["tagger_script"]) def save(self): - self.config.setting["enable_tagger_script"] = self.ui.enable_tagger_script.isChecked() - self.config.setting["tagger_script"] = self.ui.tagger_script.toPlainText() + config.setting["enable_tagger_script"] = self.ui.enable_tagger_script.isChecked() + config.setting["tagger_script"] = self.ui.tagger_script.toPlainText() def display_error(self, error): pass diff --git a/picard/ui/options/tags.py b/picard/ui/options/tags.py index 6eb8587d6..fafff5360 100644 --- a/picard/ui/options/tags.py +++ b/picard/ui/options/tags.py @@ -18,7 +18,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. from PyQt4 import QtCore, QtGui -from picard.config import BoolOption, TextOption +from picard import config from picard.ui.options import OptionsPage, register_options_page from picard.ui.ui_options_tags import Ui_TagsOptionsPage from picard.util.tags import TAG_NAMES @@ -33,16 +33,16 @@ class TagsOptionsPage(OptionsPage): ACTIVE = True options = [ - BoolOption("setting", "clear_existing_tags", False), - TextOption("setting", "preserved_tags", ""), - BoolOption("setting", "write_id3v1", True), - BoolOption("setting", "write_id3v23", True), - TextOption("setting", "id3v2_encoding", "utf-16"), - BoolOption("setting", "remove_id3_from_flac", False), - BoolOption("setting", "remove_ape_from_mp3", False), - BoolOption("setting", "tpe2_albumartist", False), - BoolOption("setting", "dont_write_tags", False), - BoolOption("setting", "preserve_timestamps", False), + config.BoolOption("setting", "clear_existing_tags", False), + config.TextOption("setting", "preserved_tags", ""), + config.BoolOption("setting", "write_id3v1", True), + config.BoolOption("setting", "write_id3v23", True), + config.TextOption("setting", "id3v2_encoding", "utf-16"), + config.BoolOption("setting", "remove_id3_from_flac", False), + config.BoolOption("setting", "remove_ape_from_mp3", False), + config.BoolOption("setting", "tpe2_albumartist", False), + config.BoolOption("setting", "dont_write_tags", False), + config.BoolOption("setting", "preserve_timestamps", False), ] def __init__(self, parent=None): @@ -58,41 +58,41 @@ class TagsOptionsPage(OptionsPage): self.completer.activated.connect(self.completer_activated) def load(self): - self.ui.write_tags.setChecked(not self.config.setting["dont_write_tags"]) - self.ui.preserve_timestamps.setChecked(self.config.setting["preserve_timestamps"]) - self.ui.clear_existing_tags.setChecked(self.config.setting["clear_existing_tags"]) - self.ui.write_id3v1.setChecked(self.config.setting["write_id3v1"]) - self.ui.write_id3v23.setChecked(self.config.setting["write_id3v23"]) - if self.config.setting["id3v2_encoding"] == "iso-8859-1": + self.ui.write_tags.setChecked(not config.setting["dont_write_tags"]) + self.ui.preserve_timestamps.setChecked(config.setting["preserve_timestamps"]) + self.ui.clear_existing_tags.setChecked(config.setting["clear_existing_tags"]) + self.ui.write_id3v1.setChecked(config.setting["write_id3v1"]) + self.ui.write_id3v23.setChecked(config.setting["write_id3v23"]) + if config.setting["id3v2_encoding"] == "iso-8859-1": self.ui.enc_iso88591.setChecked(True) - elif self.config.setting["id3v2_encoding"] == "utf-16": + elif config.setting["id3v2_encoding"] == "utf-16": self.ui.enc_utf16.setChecked(True) else: self.ui.enc_utf8.setChecked(True) - self.ui.remove_ape_from_mp3.setChecked(self.config.setting["remove_ape_from_mp3"]) - self.ui.remove_id3_from_flac.setChecked(self.config.setting["remove_id3_from_flac"]) - self.ui.preserved_tags.setText(self.config.setting["preserved_tags"]) + self.ui.remove_ape_from_mp3.setChecked(config.setting["remove_ape_from_mp3"]) + self.ui.remove_id3_from_flac.setChecked(config.setting["remove_id3_from_flac"]) + self.ui.preserved_tags.setText(config.setting["preserved_tags"]) self.update_encodings() def save(self): - self.config.setting["dont_write_tags"] = not self.ui.write_tags.isChecked() - self.config.setting["preserve_timestamps"] = self.ui.preserve_timestamps.isChecked() + config.setting["dont_write_tags"] = not self.ui.write_tags.isChecked() + config.setting["preserve_timestamps"] = self.ui.preserve_timestamps.isChecked() clear_existing_tags = self.ui.clear_existing_tags.isChecked() - if clear_existing_tags != self.config.setting["clear_existing_tags"]: - self.config.setting["clear_existing_tags"] = clear_existing_tags + if clear_existing_tags != config.setting["clear_existing_tags"]: + config.setting["clear_existing_tags"] = clear_existing_tags self.tagger.window.metadata_box.update() - self.config.setting["write_id3v1"] = self.ui.write_id3v1.isChecked() - self.config.setting["write_id3v23"] = self.ui.write_id3v23.isChecked() + config.setting["write_id3v1"] = self.ui.write_id3v1.isChecked() + config.setting["write_id3v23"] = self.ui.write_id3v23.isChecked() if self.ui.enc_iso88591.isChecked(): - self.config.setting["id3v2_encoding"] = "iso-8859-1" + config.setting["id3v2_encoding"] = "iso-8859-1" elif self.ui.enc_utf16.isChecked(): - self.config.setting["id3v2_encoding"] = "utf-16" + config.setting["id3v2_encoding"] = "utf-16" else: - self.config.setting["id3v2_encoding"] = "utf-8" - self.config.setting["remove_ape_from_mp3"] = self.ui.remove_ape_from_mp3.isChecked() - self.config.setting["remove_id3_from_flac"] = self.ui.remove_id3_from_flac.isChecked() - self.config.setting["preserved_tags"] = unicode(self.ui.preserved_tags.text()) - self.tagger.window.enable_tag_saving_action.setChecked(not self.config.setting["dont_write_tags"]) + config.setting["id3v2_encoding"] = "utf-8" + config.setting["remove_ape_from_mp3"] = self.ui.remove_ape_from_mp3.isChecked() + config.setting["remove_id3_from_flac"] = self.ui.remove_id3_from_flac.isChecked() + config.setting["preserved_tags"] = unicode(self.ui.preserved_tags.text()) + self.tagger.window.enable_tag_saving_action.setChecked(not config.setting["dont_write_tags"]) def update_encodings(self): if self.ui.write_id3v23.isChecked(): diff --git a/picard/ui/passworddialog.py b/picard/ui/passworddialog.py index 3e136640e..804e7e062 100644 --- a/picard/ui/passworddialog.py +++ b/picard/ui/passworddialog.py @@ -18,15 +18,15 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. from PyQt4 import QtCore, QtGui +from picard import config from picard.ui.ui_passworddialog import Ui_PasswordDialog -from picard.config import BoolOption from picard.util import rot13 class PasswordDialog(QtGui.QDialog): options = [ - BoolOption("persist", "save_authentication", True), + config.BoolOption("persist", "save_authentication", True), ] def __init__(self, authenticator, reply, parent=None): @@ -37,9 +37,9 @@ class PasswordDialog(QtGui.QDialog): self.ui.info_text.setText(_("The server %s requires you to login. Please enter your username and password.") % reply.url().host()) # TODO: Implement proper password storage for arbitrary servers if self._is_musicbrainz_server(reply.url().host(), reply.url().port()): - self.ui.save_authentication.setChecked(self.config.persist["save_authentication"]) - self.ui.username.setText(self.config.setting["username"]) - self.ui.password.setText(self.config.setting["password"]) + self.ui.save_authentication.setChecked(config.persist["save_authentication"]) + self.ui.username.setText(config.setting["username"]) + self.ui.password.setText(config.setting["password"]) else: self.ui.username.setText(reply.url().userName()) self.ui.password.setText(reply.url().password()) @@ -48,22 +48,22 @@ class PasswordDialog(QtGui.QDialog): self.ui.buttonbox.accepted.connect(self.set_new_password) def set_new_password(self): - self.config.persist["save_authentication"] = self.ui.save_authentication.isChecked() - if self.config.persist["save_authentication"]: - self.config.setting["username"] = unicode(self.ui.username.text()) - self.config.setting["password"] = rot13(unicode(self.ui.password.text())) + config.persist["save_authentication"] = self.ui.save_authentication.isChecked() + if config.persist["save_authentication"]: + config.setting["username"] = unicode(self.ui.username.text()) + config.setting["password"] = rot13(unicode(self.ui.password.text())) self._authenticator.setUser(unicode(self.ui.username.text())) self._authenticator.setPassword(unicode(self.ui.password.text())) self.accept() def _is_musicbrainz_server(self, host, port): - return host == self.config.setting["server_host"] and port == self.config.setting["server_port"] + return host == config.setting["server_host"] and port == config.setting["server_port"] class ProxyDialog(QtGui.QDialog): options = [ - BoolOption("persist", "save_authentication", True), + config.BoolOption("persist", "save_authentication", True), ] def __init__(self, authenticator, proxy, parent=None): @@ -73,16 +73,16 @@ class ProxyDialog(QtGui.QDialog): self.ui = Ui_PasswordDialog() self.ui.setupUi(self) self.ui.info_text.setText(_("The proxy %s requires you to login. Please enter your username and password.") - % self.config.setting["proxy_server_host"]) - self.ui.save_authentication.setChecked(self.config.persist["save_authentication"]) - self.ui.username.setText(self.config.setting["proxy_username"]) - self.ui.password.setText(self.config.setting["proxy_password"]) + % config.setting["proxy_server_host"]) + self.ui.save_authentication.setChecked(config.persist["save_authentication"]) + self.ui.username.setText(config.setting["proxy_username"]) + self.ui.password.setText(config.setting["proxy_password"]) self.ui.save_authentication.hide() self.ui.buttonbox.accepted.connect(self.set_proxy_password) def set_proxy_password(self): - self.config.setting["proxy_username"] = unicode(self.ui.username.text()) - self.config.setting["proxy_password"] = unicode(self.ui.password.text()) + config.setting["proxy_username"] = unicode(self.ui.username.text()) + config.setting["proxy_password"] = unicode(self.ui.password.text()) self._authenticator.setUser(unicode(self.ui.username.text())) self._authenticator.setPassword(unicode(self.ui.password.text())) self.accept() diff --git a/picard/ui/ratingwidget.py b/picard/ui/ratingwidget.py index e25a14fea..ce95e54ba 100644 --- a/picard/ui/ratingwidget.py +++ b/picard/ui/ratingwidget.py @@ -18,6 +18,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. from PyQt4 import QtCore, QtGui +from picard import config class RatingWidget(QtGui.QWidget): @@ -25,7 +26,7 @@ class RatingWidget(QtGui.QWidget): def __init__(self, parent, track): QtGui.QWidget.__init__(self, parent) self._track = track - self._maximum = self.config.setting["rating_steps"] - 1 + self._maximum = config.setting["rating_steps"] - 1 self._rating = int(track.metadata["~rating"] or 0) self._highlight = 0 self._star_pixmap = QtGui.QPixmap(":/images/star.png") @@ -79,7 +80,7 @@ class RatingWidget(QtGui.QWidget): def _update_track(self): track = self._track track.metadata["~rating"] = unicode(self._rating) - if self.config.setting["submit_ratings"]: + if config.setting["submit_ratings"]: ratings = {("recording", track.id): self._rating} self.tagger.xmlws.submit_ratings(ratings, None) diff --git a/picard/ui/tagsfromfilenames.py b/picard/ui/tagsfromfilenames.py index 175d93bfc..7e2cc4466 100644 --- a/picard/ui/tagsfromfilenames.py +++ b/picard/ui/tagsfromfilenames.py @@ -20,17 +20,18 @@ import re import os.path from PyQt4 import QtCore, QtGui -from picard.config import Option, TextOption +from picard import config from picard.ui.util import StandardButton from picard.ui.ui_tagsfromfilenames import Ui_TagsFromFileNamesDialog from picard.util.tags import display_tag_name + class TagsFromFileNamesDialog(QtGui.QDialog): options = [ - TextOption("persist", "tags_from_filenames_format", ""), - Option("persist", "tags_from_filenames_position", QtCore.QPoint(), QtCore.QVariant.toPoint), - Option("persist", "tags_from_filenames_size", QtCore.QSize(560, 400), QtCore.QVariant.toSize), + config.TextOption("persist", "tags_from_filenames_format", ""), + config.Option("persist", "tags_from_filenames_position", QtCore.QPoint(), QtCore.QVariant.toPoint), + config.Option("persist", "tags_from_filenames_size", QtCore.QSize(560, 400), QtCore.QVariant.toSize), ] def __init__(self, files, parent=None): @@ -42,7 +43,7 @@ class TagsFromFileNamesDialog(QtGui.QDialog): "%artist%/%album%/%tracknumber% - %title%", "%artist%/%album - %tracknumber% - %title%", ] - format = self.config.persist["tags_from_filenames_format"] + format = config.persist["tags_from_filenames_format"] if format and format not in items: items.insert(0, format) self.ui.format.addItems(items) @@ -112,7 +113,7 @@ class TagsFromFileNamesDialog(QtGui.QDialog): for name, value in metadata.iteritems(): file.metadata[name] = value file.update() - self.config.persist["tags_from_filenames_format"] = self.ui.format.currentText() + config.persist["tags_from_filenames_format"] = self.ui.format.currentText() self.saveWindowState() QtGui.QDialog.accept(self) @@ -127,11 +128,11 @@ class TagsFromFileNamesDialog(QtGui.QDialog): def saveWindowState(self): pos = self.pos() if not pos.isNull(): - self.config.persist["tags_from_filenames_position"] = pos - self.config.persist["tags_from_filenames_size"] = self.size() + config.persist["tags_from_filenames_position"] = pos + config.persist["tags_from_filenames_size"] = self.size() def restoreWindowState(self): - pos = self.config.persist["tags_from_filenames_position"] + pos = config.persist["tags_from_filenames_position"] if pos.x() > 0 and pos.y() > 0: self.move(pos) - self.resize(self.config.persist["tags_from_filenames_size"]) + self.resize(config.persist["tags_from_filenames_size"]) diff --git a/picard/util/__init__.py b/picard/util/__init__.py index 7e930ce11..8cafaa19e 100644 --- a/picard/util/__init__.py +++ b/picard/util/__init__.py @@ -80,7 +80,8 @@ _io_encoding = sys.getfilesystemencoding() #// intentionally def check_io_encoding(): if _io_encoding == "ANSI_X3.4-1968": - QtCore.QObject.log.warning(""" + from picard import log + log.warning(""" System locale charset is ANSI_X3.4-1968 Your system's locale charset (i.e. the charset used to encode filenames) is set to ANSI_X3.4-1968. It is highly unlikely that this has been done @@ -294,7 +295,8 @@ def call_next(func): result = func(self, *args, **kwargs) except: import traceback - self.log.error(traceback.format_exc()) + from picard import log + log.error(traceback.format_exc()) next(error=sys.exc_info()[1]) else: next(result=result) diff --git a/picard/util/cdrom.py b/picard/util/cdrom.py index f7484d96a..ce8ec351b 100644 --- a/picard/util/cdrom.py +++ b/picard/util/cdrom.py @@ -19,9 +19,10 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. import sys -from PyQt4.QtCore import (QFile, QRegExp) +from PyQt4.QtCore import QFile, QRegExp -LINUX_CDROM_INFO = '/proc/sys/dev/cdrom/info' + +LINUX_CDROM_INFO = '/proc/sys/dev/cdrom/info' if sys.platform == 'win32': AUTO_DETECT_DRIVES = True @@ -43,7 +44,7 @@ if sys.platform == 'win32': elif sys.platform == 'linux2' and QFile.exists(LINUX_CDROM_INFO): AUTO_DETECT_DRIVES = True from PyQt4.QtCore import QIODevice, QString - + # Read info from /proc/sys/dev/cdrom/info def get_cdrom_drives(): drives = [] @@ -75,8 +76,7 @@ else: AUTO_DETECT_DRIVES = False def get_cdrom_drives(): - from picard.tagger import Tagger - tagger = Tagger.instance() + from picard import config # Need to filter out empty strings, particularly if the device list is empty return filter(lambda string: (string != u''), - [d.strip() for d in tagger.config.setting["cd_lookup_device"].split(",")]) + [d.strip() for d in config.setting["cd_lookup_device"].split(",")]) diff --git a/picard/util/thread.py b/picard/util/thread.py index 3338e346c..a3088c831 100644 --- a/picard/util/thread.py +++ b/picard/util/thread.py @@ -57,7 +57,8 @@ class Thread(QtCore.QThread): try: result = func() except: - self.log.error(traceback.format_exc()) + from picard import log + log.error(traceback.format_exc()) self.to_main(next, priority, error=sys.exc_info()[1]) else: self.to_main(next, priority, result=result) @@ -93,7 +94,8 @@ class ThreadPool(QtCore.QObject): try: event.call() except: - self.log.error(traceback.format_exc()) + from picard import log + log.error(traceback.format_exc()) return True return False diff --git a/picard/webservice.py b/picard/webservice.py index 9e6c814f4..866032594 100644 --- a/picard/webservice.py +++ b/picard/webservice.py @@ -31,7 +31,7 @@ from collections import deque, defaultdict from PyQt4 import QtCore, QtNetwork from PyQt4.QtGui import QDesktopServices from PyQt4.QtCore import QUrl, QXmlStreamReader -from picard import version_string +from picard import version_string, config, log from picard.util import partial from picard.const import ACOUSTID_KEY, ACOUSTID_HOST @@ -145,34 +145,34 @@ class XmlWebService(QtCore.QObject): cache.setCacheDirectory(os.path.join(unicode(location), u'picard')) cache.setMaximumCacheSize(cache_size_in_mb * 1024 * 1024) self.manager.setCache(cache) - self.log.debug("NetworkDiskCache dir: %s", cache.cacheDirectory()) - self.log.debug("NetworkDiskCache size: %s / %s", cache.cacheSize(), + log.debug("NetworkDiskCache dir: %s", cache.cacheDirectory()) + log.debug("NetworkDiskCache size: %s / %s", cache.cacheSize(), cache.maximumCacheSize()) def setup_proxy(self): - self.proxy = QtNetwork.QNetworkProxy() - if self.config.setting["use_proxy"]: - self.proxy.setType(QtNetwork.QNetworkProxy.HttpProxy) - self.proxy.setHostName(self.config.setting["proxy_server_host"]) - self.proxy.setPort(self.config.setting["proxy_server_port"]) - self.proxy.setUser(self.config.setting["proxy_username"]) - self.proxy.setPassword(self.config.setting["proxy_password"]) - self.manager.setProxy(self.proxy) + proxy = QtNetwork.QNetworkProxy() + if config.setting["use_proxy"]: + proxy.setType(QtNetwork.QNetworkProxy.HttpProxy) + proxy.setHostName(config.setting["proxy_server_host"]) + proxy.setPort(config.setting["proxy_server_port"]) + proxy.setUser(config.setting["proxy_username"]) + proxy.setPassword(config.setting["proxy_password"]) + self.manager.setProxy(proxy) def _start_request(self, method, host, port, path, data, handler, xml, mblogin=False, cacheloadcontrol=None): - self.log.debug("%s http://%s:%d%s", method, host, port, path) + log.debug("%s http://%s:%d%s", method, host, port, path) url = QUrl.fromEncoded("http://%s:%d%s" % (host, port, path)) if mblogin: - url.setUserName(self.config.setting["username"]) - url.setPassword(self.config.setting["password"]) + url.setUserName(config.setting["username"]) + url.setPassword(config.setting["password"]) request = QtNetwork.QNetworkRequest(url) if cacheloadcontrol is not None: request.setAttribute(QtNetwork.QNetworkRequest.CacheLoadControlAttribute, cacheloadcontrol) request.setRawHeader("User-Agent", "MusicBrainz-Picard/%s" % version_string) if data is not None: - if method == "POST" and host == self.config.setting["server_host"]: + if method == "POST" and host == config.setting["server_host"]: request.setHeader(QtNetwork.QNetworkRequest.ContentTypeHeader, "application/xml; charset=utf-8") else: request.setHeader(QtNetwork.QNetworkRequest.ContentTypeHeader, "application/x-www-form-urlencoded") @@ -197,13 +197,13 @@ class XmlWebService(QtCore.QObject): try: request, handler, xml = self._active_requests.pop(reply) except KeyError: - self.log.error("Error: Request not found for %s" % str(reply.request().url().toString())) + log.error("Error: Request not found for %s" % str(reply.request().url().toString())) return error = int(reply.error()) redirect = reply.attribute(QtNetwork.QNetworkRequest.RedirectionTargetAttribute).toUrl() fromCache = reply.attribute(QtNetwork.QNetworkRequest.SourceIsFromCacheAttribute).toBool() cached = ' (CACHED)' if fromCache else '' - self.log.debug("Received reply for %s: HTTP %d (%s) %s", + log.debug("Received reply for %s: HTTP %d (%s) %s", reply.request().url().toString(), reply.attribute(QtNetwork.QNetworkRequest.HttpStatusCodeAttribute).toInt()[0], reply.attribute(QtNetwork.QNetworkRequest.HttpReasonPhraseAttribute).toString(), @@ -211,7 +211,7 @@ class XmlWebService(QtCore.QObject): ) if handler is not None: if error: - self.log.error("Network request error for %s: %s (QT code %d, HTTP code %d)", + log.error("Network request error for %s: %s (QT code %d, HTTP code %d)", reply.request().url().toString(), reply.errorString(), error, @@ -219,7 +219,7 @@ class XmlWebService(QtCore.QObject): # Redirect if found and not infinite if not redirect.isEmpty() and not XmlWebService.urls_equivalent(redirect, reply.request().url()): - self.log.debug("Redirect to %s requested", redirect.toString()) + log.debug("Redirect to %s requested", redirect.toString()) redirect_host = str(redirect.host()) redirect_port = redirect.port(80) @@ -229,7 +229,7 @@ class XmlWebService(QtCore.QObject): if ((original_host, original_port) in REQUEST_DELAY and (redirect_host, redirect_port) not in REQUEST_DELAY): - self.log.debug("Setting rate limit for %s:%i to %i" % + log.debug("Setting rate limit for %s:%i to %i" % (redirect_host, redirect_port, REQUEST_DELAY[(original_host, original_port)])) REQUEST_DELAY[(redirect_host, redirect_port)] =\ @@ -255,7 +255,7 @@ class XmlWebService(QtCore.QObject): return self.add_task(func, host, port, priority, important=important) def post(self, host, port, path, data, handler, xml=True, priority=True, important=True, mblogin=True): - self.log.debug("POST-DATA %r", data) + log.debug("POST-DATA %r", data) func = partial(self._start_request, "POST", host, port, path, data, handler, xml, mblogin) return self.add_task(func, host, port, priority, important=important) @@ -284,12 +284,12 @@ class XmlWebService(QtCore.QObject): request_delay = REQUEST_DELAY[key] last_ms = (now - last) * 1000 if last is not None else request_delay if last_ms >= request_delay: - self.log.debug("Last request to %s was %d ms ago, starting another one", key, last_ms) + log.debug("Last request to %s was %d ms ago, starting another one", key, last_ms) d = request_delay queue.popleft()() else: d = request_delay - last_ms - self.log.debug("Waiting %d ms before starting another request to %s", d, key) + log.debug("Waiting %d ms before starting another request to %s", d, key) if d < delay: delay = d if delay < sys.maxint: @@ -324,8 +324,8 @@ class XmlWebService(QtCore.QObject): pass def _get_by_id(self, entitytype, entityid, handler, inc=[], params=[], priority=False, important=False, mblogin=False): - host = self.config.setting["server_host"] - port = self.config.setting["server_port"] + host = config.setting["server_host"] + port = config.setting["server_port"] path = "/ws/2/%s/%s?inc=%s" % (entitytype, entityid, "+".join(inc)) if params: path += "&" + "&".join(params) return self.get(host, port, path, handler, priority=priority, important=important, mblogin=mblogin) @@ -341,8 +341,8 @@ class XmlWebService(QtCore.QObject): return self._get_by_id('discid', discid, handler, inc, params=["cdstubs=no"], priority=priority, important=important) def _find(self, entitytype, handler, kwargs): - host = self.config.setting["server_host"] - port = self.config.setting["server_port"] + host = config.setting["server_host"] + port = config.setting["server_port"] filters = [] query = [] for name, value in kwargs.items(): @@ -366,8 +366,8 @@ class XmlWebService(QtCore.QObject): return self._find('recording', handler, kwargs) def _browse(self, entitytype, handler, kwargs, inc=[], priority=False, important=False): - host = self.config.setting["server_host"] - port = self.config.setting["server_port"] + host = config.setting["server_host"] + port = config.setting["server_port"] params = "&".join(["%s=%s" % (k, v) for k, v in kwargs.items()]) path = "/ws/2/%s?%s&inc=%s" % (entitytype, params, "+".join(inc)) return self.get(host, port, path, handler, priority=priority, important=important) @@ -377,8 +377,8 @@ class XmlWebService(QtCore.QObject): return self._browse("release", handler, kwargs, inc, priority=priority, important=important) def submit_ratings(self, ratings, handler): - host = self.config.setting['server_host'] - port = self.config.setting['server_port'] + host = config.setting['server_host'] + port = config.setting['server_port'] path = '/ws/2/rating/?client=' + USER_AGENT_STRING recordings = (''.join(['%s' % (i[1], j*20) for i, j in ratings.items() if i[0] == 'recording'])) @@ -401,7 +401,7 @@ class XmlWebService(QtCore.QObject): return self.post(host, port, '/v2/lookup', body, handler, mblogin=False) def submit_acoustid_fingerprints(self, submissions, handler): - args = {'user': self.config.setting["acoustid_apikey"]} + args = {'user': config.setting["acoustid_apikey"]} for i, submission in enumerate(submissions): args['fingerprint.%d' % i] = str(submission.fingerprint) args['duration.%d' % i] = str(submission.duration) @@ -418,7 +418,7 @@ class XmlWebService(QtCore.QObject): important=important, cacheloadcontrol=cacheloadcontrol) def get_collection(self, id, handler, limit=100, offset=0): - host, port = self.config.setting['server_host'], self.config.setting['server_port'] + host, port = config.setting['server_host'], config.setting['server_port'] path = "/ws/2/collection" if id is not None: inc = ["releases", "artist-credits", "media"] @@ -435,11 +435,11 @@ class XmlWebService(QtCore.QObject): yield "/ws/2/collection/%s/releases/%s?client=%s" % (id, ids, USER_AGENT_STRING) def put_to_collection(self, id, releases, handler): - host, port = self.config.setting['server_host'], self.config.setting['server_port'] + host, port = config.setting['server_host'], config.setting['server_port'] for path in self._collection_request(id, releases): self.put(host, port, path, "", handler) def delete_from_collection(self, id, releases, handler): - host, port = self.config.setting['server_host'], self.config.setting['server_port'] + host, port = config.setting['server_host'], config.setting['server_port'] for path in self._collection_request(id, releases): self.delete(host, port, path, handler)