mirror of
https://github.com/fergalmoran/picard.git
synced 2026-02-25 17:13:57 +00:00
Make config and log importable
Conflicts: picard/ui/mainwindow.py
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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_()
|
||||
|
||||
105
picard/file.py
105
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()
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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":
|
||||
|
||||
@@ -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"]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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():
|
||||
|
||||
@@ -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"]
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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"])
|
||||
|
||||
@@ -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():
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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_()
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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]]
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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():
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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"])
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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(",")])
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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(['<recording id="%s"><user-rating>%s</user-rating></recording>' %
|
||||
(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)
|
||||
|
||||
Reference in New Issue
Block a user