X-Git-Url: https://git.draconx.ca/gitweb/picard-plugins.git/blobdiff_plain/cf417c90804ad9466662bfcfe35ec290a9a565e6..HEAD:/tweak-filename-filter.py?ds=sidebyside diff --git a/tweak-filename-filter.py b/tweak-filename-filter.py index 6f81515..f1ad2df 100644 --- a/tweak-filename-filter.py +++ b/tweak-filename-filter.py @@ -1,12 +1,12 @@ # -*- coding: utf-8 -*- # -# Copyright © 2018 Nick Bowler +# 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_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
@@ -23,40 +23,137 @@ true)
'''
-PLUGIN_VERSION = "0"
-PLUGIN_API_VERSIONS = ["1.0"]
+PLUGIN_VERSION = "2"
+PLUGIN_API_VERSIONS = ["2.0"]
PLUGIN_LICENSE = "GPL-3.0-or-later"
+from PyQt5 import QtWidgets
+
from picard import (config, log)
+from picard.ui.options import (
+ OptionsPage, OptionsCheckError,
+ register_options_page
+)
import picard.util
+
+import sre_constants
import re
def modulename():
return modulename.__module__[len("picard.plugins."):]
+class UI_TweakFilenameFilter(object):
+ def setupUi(self, TweakFilenameOptionsPage):
+ top = QtWidgets.QVBoxLayout(TweakFilenameOptionsPage)
+
+ group = QtWidgets.QGroupBox(TweakFilenameOptionsPage)
+ group.setTitle("Filename Sanitizer")
+ top.addWidget(group)
+
+ box = QtWidgets.QVBoxLayout(group)
+
+ msg = QtWidgets.QLabel(group)
+ msg.setText('''Picard normally replaces slashes and backslashes
+ with underscores in all metadata tags prior to running the file-naming
+ script. This substitution may be customized here. Replacement text
+ may use backslash sequences supported by 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):
- if config.setting["tweak_file_replace_backslash"]:
+ 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(
- config.setting["tweak_file_replacement_char"],
- string)
+ ret = self.re_match.sub(self.replacement, string)
return ret
-
def install_tweaker():
- picard.util._re_slashes = SanitizeHook()
- log.info("%s activated" % (modulename()))
+ 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)
-config.TextOption("setting", "tweak_file_replacement_char", "_"),
-config.BoolOption("setting", "tweak_file_replace_backslash", True),
+ 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()));
+ log.debug("%s disabled in configuration" % (modulename()))