# -*- coding: utf-8 -*- # # Copyright © 2018-2020 Nick Bowler # # License GPLv3+: GNU General Public License version 3 or any later version. # This is free software: you are free to change and redistribute it. # There is NO WARRANTY, to the extent permitted by law. PLUGIN_NAME = u"Tweak Filename Filter" PLUGIN_AUTHOR = u"Nick Bowler" PLUGIN_DESCRIPTION = u'''
Adds additional options to tweak file naming.
Currently, this overrides the default methods to substitute forward and back-slashes, allowing alternate behaviours.
re.sub
.''')
msg.setOpenExternalLinks(True)
box.addWidget(msg)
self.replace_slashes = QtWidgets.QCheckBox(group)
self.replace_slashes.setText("Replace slashes in metadata")
self.replace_slashes.setChecked(True)
self.replace_slashes.setEnabled(False)
box.addWidget(self.replace_slashes)
self.replace_backslashes = QtWidgets.QCheckBox(group)
self.replace_backslashes.setText("Replace backslashes in metadata")
box.addWidget(self.replace_backslashes)
label = QtWidgets.QLabel()
label.setText("Replacement text:")
box.addWidget(label)
self.sanitize_replacement = QtWidgets.QLineEdit(group)
box.addWidget(self.sanitize_replacement)
label.setBuddy(self.sanitize_replacement)
top.addStretch()
class TweakFilenameOptionsPage(OptionsPage):
NAME = PLUGIN_NAME
TITLE = PLUGIN_NAME
PARENT = None
SORT_ORDER = 99
ACTIVE = True
options = [
config.TextOption("setting", "tweak_file_replacement_char", "_"),
config.BoolOption("setting", "tweak_file_replace_backslash", True)
]
def __init__(self, parent=None):
super().__init__(parent)
self.ui = UI_TweakFilenameFilter()
self.ui.setupUi(self)
def load(self):
self.ui.replace_backslashes.setChecked(
config.setting["tweak_file_replace_backslash"]
)
self.ui.sanitize_replacement.setText(
config.setting["tweak_file_replacement_char"]
)
def check(self):
test = SanitizeHook(self.ui.replace_backslashes.isChecked())
test.replacement = self.ui.sanitize_replacement.text()
try:
test.sub("xyzzy", "a/b/c")
except sre_constants.error as err:
raise OptionsCheckError(_("Error"),
"Error in substitution: %s" % err);
def save(self):
config.setting["tweak_file_replace_backslash"] = \
self.ui.replace_backslashes.isChecked()
config.setting["tweak_file_replacement_char"] = \
self.ui.sanitize_replacement.text()
install_tweaker()
# Hook picard.util.sanitize_filename by replacing the underying re object.
class SanitizeHook(object):
def __init__(self, bs = config.setting["tweak_file_replace_backslash"]):
if bs:
self.re_match = re.compile(r'[\\/]', re.UNICODE)
else:
self.re_match = re.compile(r'[/]', re.UNICODE)
self.replacement = config.setting["tweak_file_replacement_char"]
def sub(self, repl, string):
ret = self.re_match.sub(self.replacement, string)
return ret
def install_tweaker():
re = SanitizeHook()
if not hasattr(picard.util, "_re_slashes"):
# Harder to globally monkey patch this picard.util function on newer
# Picard, so instead we patch it in the two modules which import it.
orig_sanitize_filename = picard.util.sanitize_filename
def sanitize_filename_hook(string, **kwargs):
return orig_sanitize_filename(re.sub(None, string), **kwargs)
picard.util.scripttofilename.sanitize_filename = sanitize_filename_hook
picard.util.textencoding.sanitize_filename = sanitize_filename_hook
else:
# On older picard we can monkey patch the underlying re object.
picard.util._re_slashes = re
log.info("%s activated" % (modulename()))
if modulename() in config.setting["enabled_plugins"]:
register_options_page(TweakFilenameOptionsPage)
install_tweaker()
else:
log.debug("%s disabled in configuration" % (modulename()))