From 98b0f327b2c3404fa920626dbf8beef40f7bc244 Mon Sep 17 00:00:00 2001 From: Philipp Wolfer Date: Tue, 14 Jul 2020 17:16:20 +0200 Subject: [PATCH] PICARD-1871: Use TagListEditor for preserved tags --- picard/__init__.py | 2 +- picard/config_upgrade.py | 10 +++++++- picard/ui/options/tags.py | 44 ++++----------------------------- picard/ui/ui_options_tags.py | 14 +++++------ picard/util/preservedtags.py | 4 +-- test/test_util_preservedtags.py | 4 +-- ui/options_tags.ui | 33 +++++++++++-------------- 7 files changed, 40 insertions(+), 71 deletions(-) diff --git a/picard/__init__.py b/picard/__init__.py index 919b16b0a..62fbead25 100644 --- a/picard/__init__.py +++ b/picard/__init__.py @@ -41,7 +41,7 @@ PICARD_APP_NAME = "Picard" PICARD_DISPLAY_NAME = "MusicBrainz Picard" PICARD_APP_ID = "org.musicbrainz.Picard" PICARD_DESKTOP_NAME = PICARD_APP_ID + ".desktop" -PICARD_VERSION = Version(2, 4, 0, 'beta', 2) +PICARD_VERSION = Version(2, 4, 0, 'beta', 3) # optional build version diff --git a/picard/config_upgrade.py b/picard/config_upgrade.py index 1d6d30557..266aa75ab 100644 --- a/picard/config_upgrade.py +++ b/picard/config_upgrade.py @@ -5,7 +5,7 @@ # Copyright (C) 2013-2014 Michael Wiencek # Copyright (C) 2013-2016, 2018-2019 Laurent Monin # Copyright (C) 2014, 2017 Lukáš Lalinský -# Copyright (C) 2014, 2018-2019 Philipp Wolfer +# Copyright (C) 2014, 2018-2020 Philipp Wolfer # Copyright (C) 2015 Ohm Patel # Copyright (C) 2016 Suhas # Copyright (C) 2016-2017 Sambhav Kothari @@ -296,6 +296,13 @@ def upgrade_to_v2_2_0_dev_4(config): _s["file_naming_format"] = DEFAULT_FILE_NAMING_FORMAT +def upgrade_to_v2_4_0_beta_3(config): + """Improved default file naming script""" + _s = config.setting + opt = 'preserved_tags' + _s[opt] = [t.strip() for t in _s.raw_value(opt, qtype='QString').split(',')] + + def rename_option(config, old_opt, new_opt, option_type, default): _s = config.setting if old_opt in _s: @@ -319,4 +326,5 @@ def upgrade_config(config): cfg.register_upgrade_hook(upgrade_to_v2_0_0_dev_3) cfg.register_upgrade_hook(upgrade_to_v2_1_0_dev_1) cfg.register_upgrade_hook(upgrade_to_v2_2_0_dev_3) + cfg.register_upgrade_hook(upgrade_to_v2_4_0_beta_3) cfg.run_upgrade_hooks(log.debug) diff --git a/picard/ui/options/tags.py b/picard/ui/options/tags.py index 2a6bca8ac..61681d921 100644 --- a/picard/ui/options/tags.py +++ b/picard/ui/options/tags.py @@ -4,7 +4,7 @@ # # Copyright (C) 2006-2007, 2011 Lukáš Lalinský # Copyright (C) 2009 Nikolai Prokoschenko -# Copyright (C) 2009-2010, 2018-2019 Philipp Wolfer +# Copyright (C) 2009-2010, 2018-2020 Philipp Wolfer # Copyright (C) 2012 Erik Wasser # Copyright (C) 2012 Johannes Weißl # Copyright (C) 2012-2013 Michael Wiencek @@ -27,15 +27,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -import re - -from PyQt5 import ( - QtCore, - QtWidgets, -) - from picard import config -from picard.util.tags import TAG_NAMES from picard.ui.options import ( OptionsPage, @@ -58,18 +50,13 @@ class TagsOptionsPage(OptionsPage): config.BoolOption("setting", "clear_existing_tags", False), config.BoolOption("setting", "remove_id3_from_flac", False), config.BoolOption("setting", "remove_ape_from_mp3", False), - config.TextOption("setting", "preserved_tags", ""), + config.ListOption("setting", "preserved_tags", []), ] def __init__(self, parent=None): super().__init__(parent) self.ui = Ui_TagsOptionsPage() self.ui.setupUi(self) - self.completer = QtWidgets.QCompleter(sorted(TAG_NAMES.keys()), self) - self.completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive) - self.completer.setWidget(self.ui.preserved_tags) - self.ui.preserved_tags.textEdited.connect(self.preserved_tags_edited) - self.completer.activated.connect(self.completer_activated) def load(self): self.ui.write_tags.setChecked(not config.setting["dont_write_tags"]) @@ -77,7 +64,8 @@ class TagsOptionsPage(OptionsPage): self.ui.clear_existing_tags.setChecked(config.setting["clear_existing_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.ui.preserved_tags.update(config.setting["preserved_tags"]) + self.ui.preserved_tags.set_user_sortable(False) def save(self): config.setting["dont_write_tags"] = not self.ui.write_tags.isChecked() @@ -88,30 +76,8 @@ class TagsOptionsPage(OptionsPage): self.tagger.window.metadata_box.update() 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"] = re.sub(r"[,\s]+$", "", self.ui.preserved_tags.text()) + config.setting["preserved_tags"] = list(self.ui.preserved_tags.tags) self.tagger.window.enable_tag_saving_action.setChecked(not config.setting["dont_write_tags"]) - def preserved_tags_edited(self, text): - prefix = text[:self.ui.preserved_tags.cursorPosition()].split(",")[-1] - self.completer.setCompletionPrefix(prefix.strip()) - if prefix: - self.completer.complete() - else: - self.completer.popup().hide() - - def completer_activated(self, text): - input_field = self.ui.preserved_tags - current = input_field.text() - cursor_pos = input_field.cursorPosition() - prefix_len = len(self.completer.completionPrefix()) - leading_text = current[:cursor_pos - prefix_len].rstrip() - trailing_text = current[cursor_pos:].lstrip() - # Replace the autocompletion prefix with the autocompleted text, - # append a comma so the user can easily enter the next entry - replacement = ("%s %s, " % (leading_text, text)).lstrip() - input_field.setText(replacement + trailing_text) - # Set cursor position to end of autocompleted input - input_field.setCursorPosition(len(replacement)) - register_options_page(TagsOptionsPage) diff --git a/picard/ui/ui_options_tags.py b/picard/ui/ui_options_tags.py index 7ade0c25a..f11d227c1 100644 --- a/picard/ui/ui_options_tags.py +++ b/picard/ui/ui_options_tags.py @@ -39,15 +39,15 @@ class Ui_TagsOptionsPage(object): self.preserved_tags_label = QtWidgets.QLabel(self.before_tagging) self.preserved_tags_label.setObjectName("preserved_tags_label") self.vboxlayout1.addWidget(self.preserved_tags_label) - self.preserved_tags = QtWidgets.QLineEdit(self.before_tagging) + self.preserved_tags = TagListEditor(self.before_tagging) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.preserved_tags.sizePolicy().hasHeightForWidth()) + self.preserved_tags.setSizePolicy(sizePolicy) self.preserved_tags.setObjectName("preserved_tags") self.vboxlayout1.addWidget(self.preserved_tags) - self.preserved_tags_help = QtWidgets.QLabel(self.before_tagging) - self.preserved_tags_help.setObjectName("preserved_tags_help") - self.vboxlayout1.addWidget(self.preserved_tags_help) self.vboxlayout.addWidget(self.before_tagging) - spacerItem1 = QtWidgets.QSpacerItem(274, 41, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - self.vboxlayout.addItem(spacerItem1) self.retranslateUi(TagsOptionsPage) QtCore.QMetaObject.connectSlotsByName(TagsOptionsPage) @@ -66,4 +66,4 @@ class Ui_TagsOptionsPage(object): self.remove_id3_from_flac.setText(_("Remove ID3 tags from FLAC files")) self.remove_ape_from_mp3.setText(_("Remove APEv2 tags from MP3 files")) self.preserved_tags_label.setText(_("Preserve these tags from being cleared or overwritten with MusicBrainz data:")) - self.preserved_tags_help.setText(_("Tags are separated by commas and are case-insensitive.")) +from picard.ui.widgets.taglisteditor import TagListEditor diff --git a/picard/util/preservedtags.py b/picard/util/preservedtags.py index 35af784ae..b18f834f0 100644 --- a/picard/util/preservedtags.py +++ b/picard/util/preservedtags.py @@ -31,10 +31,10 @@ class PreservedTags: self._tags = self._from_config() def _to_config(self): - config.setting[self.opt_name] = ", ".join(sorted(self._tags)) + config.setting[self.opt_name] = sorted(self._tags) def _from_config(self): - tags = config.setting[self.opt_name].split(',') + tags = config.setting[self.opt_name] return set(filter(bool, map(self._normalize_tag, tags))) @staticmethod diff --git a/test/test_util_preservedtags.py b/test/test_util_preservedtags.py index 15fb10ac3..79e6eaacf 100644 --- a/test/test_util_preservedtags.py +++ b/test/test_util_preservedtags.py @@ -28,7 +28,7 @@ from picard.util.preservedtags import PreservedTags class PreservedTagsTest(PicardTestCase): def setUp(self): super().setUp() - config.setting[PreservedTags.opt_name] = "tag1, tag2" + config.setting[PreservedTags.opt_name] = ["tag1", "tag2"] def test_load_and_contains(self): preserved = PreservedTags() @@ -71,4 +71,4 @@ class PreservedTagsTest(PicardTestCase): preserved.add('tag2') preserved.add('tag1') preserved.discard('tag2') - self.assertEqual(config.setting[PreservedTags.opt_name], 'tag1, tag3') + self.assertEqual(config.setting[PreservedTags.opt_name], ['tag1', 'tag3']) diff --git a/ui/options_tags.ui b/ui/options_tags.ui index bb571cbad..8136d1670 100644 --- a/ui/options_tags.ui +++ b/ui/options_tags.ui @@ -85,33 +85,28 @@ - - - - - - Tags are separated by commas and are case-insensitive. + + + + 0 + 0 + - - - - Qt::Vertical - - - - 274 - 41 - - - - + + + TagListEditor + QWidget +
picard.ui.widgets.taglisteditor
+ 1 +
+
write_tags preserve_timestamps