diff --git a/picard/formats/apev2.py b/picard/formats/apev2.py index 777fd7c0f2..0b4edb997b 100644 --- a/picard/formats/apev2.py +++ b/picard/formats/apev2.py @@ -125,6 +125,7 @@ class APEv2File(File): 'replaygain_reference_loudness': 'REPLAYGAIN_REFERENCE_LOUDNESS', } __rtranslate = {v.lower(): k for k, v in __translate.items()} + sanitize_date = sanitize_date def __init__(self, filename): super().__init__(filename) @@ -136,6 +137,8 @@ def _load(self, filename): file = self._File(encode_filename(filename)) metadata = Metadata() if file.tags: + config = get_config() + date_sanitize = self.NAME not in config.setting['formats_to_disable_date_sanitize'] for origname, values in file.tags.items(): name_lower = origname.lower() if (values.kind == mutagen.apev2.BINARY @@ -160,7 +163,8 @@ def _load(self, filename): name = name_lower if name == 'year': name = 'date' - value = sanitize_date(value) + if date_sanitize: + value = sanitize_date(value) elif name == 'track': name = 'tracknumber' track = value.split('/') diff --git a/picard/formats/id3.py b/picard/formats/id3.py index 94a5b7b67e..fcc8c5a4ea 100644 --- a/picard/formats/id3.py +++ b/picard/formats/id3.py @@ -248,6 +248,7 @@ class ID3File(File): __lrc_line_re_parse = re.compile(r'(\[\d\d:\d\d\.\d\d\d\])') __lrc_syllable_re_parse = re.compile(r'(<\d\d:\d\d\.\d\d\d>)') __lrc_both_re_parse = re.compile(r'(\[\d\d:\d\d\.\d\d\d\]|<\d\d:\d\d\.\d\d\d>)') + sanitize_date = sanitize_date def __init__(self, filename): super().__init__(filename) @@ -278,6 +279,7 @@ def _load(self, filename): f = tags.pop(old) tags.add(getattr(id3, new)(encoding=f.encoding, text=f.text)) metadata = Metadata() + date_sanitize = self.NAME not in config.setting['formats_to_disable_date_sanitize'] for frame in tags.values(): frameid = frame.FrameID if frameid in self.__translate: @@ -395,9 +397,12 @@ def _load(self, filename): metadata.add('~rating', rating) if 'date' in metadata: - sanitized = sanitize_date(metadata.getall('date')[0]) - if sanitized: - metadata['date'] = sanitized + if date_sanitize: + sanitized = sanitize_date(metadata.getall('date')[0]) + if sanitized: + metadata['date'] = sanitized + else: + metadata['date'] = metadata.getall('date')[0] self._info(metadata, file) return metadata diff --git a/picard/formats/util.py b/picard/formats/util.py index f4cca633fb..2e6801a5b6 100644 --- a/picard/formats/util.py +++ b/picard/formats/util.py @@ -45,6 +45,12 @@ def supported_formats(): return [(file_format.EXTENSIONS, file_format.NAME) for file_format in _formats] +def formats_with_sanitize_date(): + for fmt in _formats: + if hasattr(fmt, 'sanitize_date'): + yield fmt + + def supported_extensions(): """Returns list of supported extensions.""" return [ext for exts, name in supported_formats() for ext in exts] diff --git a/picard/formats/vorbis.py b/picard/formats/vorbis.py index 25ac86d517..01927ef4d2 100644 --- a/picard/formats/vorbis.py +++ b/picard/formats/vorbis.py @@ -129,6 +129,7 @@ class VCommentFile(File): 'waveformatextensible_channel_mask': '~waveformatextensible_channel_mask', } __rtranslate = {v: k for k, v in __translate.items()} + sanitize_date = sanitize_date def _load(self, filename): log.debug("Loading file %r", filename) @@ -136,13 +137,16 @@ def _load(self, filename): file = self._File(encode_filename(filename)) file.tags = file.tags or {} metadata = Metadata() + config = get_config() + date_sanitize = self.NAME not in config.setting['formats_to_disable_date_sanitize'] for origname, values in file.tags.items(): for value in values: value = value.rstrip('\0') name = origname if name in {'date', 'originaldate', 'releasedate'}: # YYYY-00-00 => YYYY - value = sanitize_date(value) + if date_sanitize: + value = sanitize_date(value) elif name == 'performer' or name == 'comment': # transform "performer=Joe Barr (Piano)" to "performer:Piano=Joe Barr" name += ':' @@ -280,7 +284,8 @@ def _save(self, filename, metadata): name = 'lyrics' elif name in {'date', 'originaldate', 'releasedate'}: # YYYY-00-00 => YYYY - value = sanitize_date(value) + if self.NAME not in config.setting['formats_to_disable_date_sanitize']: + value = sanitize_date(value) elif name.startswith('performer:') or name.startswith('comment:'): # transform "performer:Piano=Joe Barr" to "performer=Joe Barr (Piano)" name, desc = name.split(':', 1) diff --git a/picard/profile.py b/picard/profile.py index 360908b9a5..cdd3b5a86d 100644 --- a/picard/profile.py +++ b/picard/profile.py @@ -70,6 +70,8 @@ class UserProfileGroups(): SettingDesc('convert_punctuation', ['convert_punctuation']), SettingDesc('release_ars', ['release_ars']), SettingDesc('track_ars', ['track_ars']), + SettingDesc('disable_date_sanitize', ['disable_date_sanitize']), + SettingDesc('formats_to_disable_date_sanitize', ['selected_formats']), SettingDesc('guess_tracknumber_and_title', ['guess_tracknumber_and_title']), SettingDesc('va_name', ['va_name']), SettingDesc('nat_name', ['nat_name']), diff --git a/picard/ui/options/metadata.py b/picard/ui/options/metadata.py index f1c34eae00..18428d2746 100644 --- a/picard/ui/options/metadata.py +++ b/picard/ui/options/metadata.py @@ -55,6 +55,7 @@ from picard.ui.ui_multi_locale_selector import Ui_MultiLocaleSelector from picard.ui.ui_options_metadata import Ui_MetadataOptionsPage from picard.ui.util import qlistwidget_items +from picard.formats.util import formats_with_sanitize_date def iter_sorted_locales(locales): @@ -92,6 +93,8 @@ class MetadataOptionsPage(OptionsPage): ListOption('setting', 'script_exceptions', [], title=N_("Translation script exceptions")), BoolOption('setting', 'release_ars', True, title=N_("Use release relationships")), BoolOption('setting', 'track_ars', False, title=N_("Use track and release relationships")), + BoolOption('setting', 'disable_date_sanitize', False, title=N_("Disable date sanitization for APE and Vorbis tags")), + Option('setting', 'formats_to_disable_date_sanitize', set(), title=N_("Formats to disable date sanitize")), BoolOption('setting', 'convert_punctuation', False, title=N_("Convert Unicode punctuation characters to ASCII")), BoolOption('setting', 'standardize_artists', False, title=N_("Use standardized artist names")), BoolOption('setting', 'standardize_instruments', True, title=N_("Use standardized instrument and vocal credits")), @@ -108,6 +111,7 @@ def __init__(self, parent=None): self.ui.select_scripts.clicked.connect(self.open_script_selector) self.ui.translate_artist_names.stateChanged.connect(self.set_enabled_states) self.ui.translate_artist_names_script_exception.stateChanged.connect(self.set_enabled_states) + self.ui.disable_date_sanitize.stateChanged.connect(self.set_enabled_states) def load(self): config = get_config() @@ -117,6 +121,10 @@ def load(self): self.current_scripts = config.setting['script_exceptions'] self.make_scripts_text() self.ui.translate_artist_names_script_exception.setChecked(config.setting['translate_artist_names_script_exception']) + self.ui.disable_date_sanitize.setChecked(config.setting['disable_date_sanitize']) + self.current_formats = config.setting['formats_to_disable_date_sanitize'] + fmt_names = sorted(fmt.NAME for fmt in formats_with_sanitize_date()) + self.ui.selected_formats.addItems(fmt_names) self.ui.convert_punctuation.setChecked(config.setting['convert_punctuation']) self.ui.release_ars.setChecked(config.setting['release_ars']) @@ -152,6 +160,8 @@ def save(self): 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['disable_date_sanitize'] = self.ui.disable_date_sanitize.isChecked() + config.setting['formats_to_disable_date_sanitize'] = self.current_formats config.setting['va_name'] = self.ui.va_name.text() nat_name = self.ui.nat_name.text() if nat_name != config.setting['nat_name']: @@ -179,6 +189,8 @@ def set_enabled_states(self): select_scripts_enabled = translate_checked and translate_exception_checked self.ui.selected_scripts.setEnabled(select_scripts_enabled) self.ui.select_scripts.setEnabled(select_scripts_enabled) + disable_date_sanitize_checked = self.ui.disable_date_sanitize.isChecked() + self.ui.selected_formats.setEnabled(disable_date_sanitize_checked) def open_locale_selector(self): dialog = MultiLocaleSelector(self) diff --git a/picard/ui/ui_options_metadata.py b/picard/ui/ui_options_metadata.py index cd6cfe2a48..7f9bf4f3ab 100644 --- a/picard/ui/ui_options_metadata.py +++ b/picard/ui/ui_options_metadata.py @@ -1,6 +1,6 @@ # Form implementation generated from reading ui file 'ui/options_metadata.ui' # -# Created by: PyQt6 UI code generator 6.3.1 +# Created by: PyQt6 UI code generator 6.6.1 # # WARNING: Any manual changes made to this file will be lost when pyuic6 is # run again. Do not edit this file unless you know what you are doing. @@ -15,7 +15,7 @@ def setupUi(self, MetadataOptionsPage): MetadataOptionsPage.resize(423, 553) self.verticalLayout = QtWidgets.QVBoxLayout(MetadataOptionsPage) self.verticalLayout.setObjectName("verticalLayout") - self.metadata_groupbox = QtWidgets.QGroupBox(MetadataOptionsPage) + self.metadata_groupbox = QtWidgets.QGroupBox(parent=MetadataOptionsPage) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Preferred, QtWidgets.QSizePolicy.Policy.Maximum) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) @@ -26,54 +26,60 @@ def setupUi(self, MetadataOptionsPage): self.metadata_groupbox.setObjectName("metadata_groupbox") self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.metadata_groupbox) self.verticalLayout_3.setObjectName("verticalLayout_3") - self.translate_artist_names = QtWidgets.QCheckBox(self.metadata_groupbox) + self.translate_artist_names = QtWidgets.QCheckBox(parent=self.metadata_groupbox) self.translate_artist_names.setObjectName("translate_artist_names") self.verticalLayout_3.addWidget(self.translate_artist_names) self.horizontalLayout = QtWidgets.QHBoxLayout() self.horizontalLayout.setContentsMargins(-1, -1, -1, 0) self.horizontalLayout.setObjectName("horizontalLayout") - self.selected_locales = QtWidgets.QLineEdit(self.metadata_groupbox) + self.selected_locales = QtWidgets.QLineEdit(parent=self.metadata_groupbox) self.selected_locales.setReadOnly(True) self.selected_locales.setObjectName("selected_locales") self.horizontalLayout.addWidget(self.selected_locales) - self.select_locales = QtWidgets.QPushButton(self.metadata_groupbox) + self.select_locales = QtWidgets.QPushButton(parent=self.metadata_groupbox) self.select_locales.setObjectName("select_locales") self.horizontalLayout.addWidget(self.select_locales) self.verticalLayout_3.addLayout(self.horizontalLayout) - self.translate_artist_names_script_exception = QtWidgets.QCheckBox(self.metadata_groupbox) + self.translate_artist_names_script_exception = QtWidgets.QCheckBox(parent=self.metadata_groupbox) self.translate_artist_names_script_exception.setObjectName("translate_artist_names_script_exception") self.verticalLayout_3.addWidget(self.translate_artist_names_script_exception) self.horizontalLayout_4 = QtWidgets.QHBoxLayout() self.horizontalLayout_4.setContentsMargins(-1, -1, -1, 0) self.horizontalLayout_4.setObjectName("horizontalLayout_4") - self.selected_scripts = QtWidgets.QLineEdit(self.metadata_groupbox) + self.selected_scripts = QtWidgets.QLineEdit(parent=self.metadata_groupbox) self.selected_scripts.setReadOnly(True) self.selected_scripts.setObjectName("selected_scripts") self.horizontalLayout_4.addWidget(self.selected_scripts) - self.select_scripts = QtWidgets.QPushButton(self.metadata_groupbox) + self.select_scripts = QtWidgets.QPushButton(parent=self.metadata_groupbox) self.select_scripts.setObjectName("select_scripts") self.horizontalLayout_4.addWidget(self.select_scripts) self.verticalLayout_3.addLayout(self.horizontalLayout_4) - self.standardize_artists = QtWidgets.QCheckBox(self.metadata_groupbox) + self.standardize_artists = QtWidgets.QCheckBox(parent=self.metadata_groupbox) self.standardize_artists.setObjectName("standardize_artists") self.verticalLayout_3.addWidget(self.standardize_artists) - self.standardize_instruments = QtWidgets.QCheckBox(self.metadata_groupbox) + self.standardize_instruments = QtWidgets.QCheckBox(parent=self.metadata_groupbox) self.standardize_instruments.setObjectName("standardize_instruments") self.verticalLayout_3.addWidget(self.standardize_instruments) - self.convert_punctuation = QtWidgets.QCheckBox(self.metadata_groupbox) + self.convert_punctuation = QtWidgets.QCheckBox(parent=self.metadata_groupbox) self.convert_punctuation.setObjectName("convert_punctuation") self.verticalLayout_3.addWidget(self.convert_punctuation) - self.release_ars = QtWidgets.QCheckBox(self.metadata_groupbox) + self.release_ars = QtWidgets.QCheckBox(parent=self.metadata_groupbox) self.release_ars.setObjectName("release_ars") self.verticalLayout_3.addWidget(self.release_ars) - self.track_ars = QtWidgets.QCheckBox(self.metadata_groupbox) + self.track_ars = QtWidgets.QCheckBox(parent=self.metadata_groupbox) self.track_ars.setObjectName("track_ars") self.verticalLayout_3.addWidget(self.track_ars) - self.guess_tracknumber_and_title = QtWidgets.QCheckBox(self.metadata_groupbox) + self.guess_tracknumber_and_title = QtWidgets.QCheckBox(parent=self.metadata_groupbox) self.guess_tracknumber_and_title.setObjectName("guess_tracknumber_and_title") self.verticalLayout_3.addWidget(self.guess_tracknumber_and_title) + self.disable_date_sanitize = QtWidgets.QCheckBox(parent=self.metadata_groupbox) + self.disable_date_sanitize.setObjectName("disable_date_sanitize") + self.verticalLayout_3.addWidget(self.disable_date_sanitize) + self.selected_formats = MultiComboBox(parent=self.metadata_groupbox) + self.selected_formats.setObjectName("selected_formats") + self.verticalLayout_3.addWidget(self.selected_formats) self.verticalLayout.addWidget(self.metadata_groupbox) - self.custom_fields_groupbox = QtWidgets.QGroupBox(MetadataOptionsPage) + self.custom_fields_groupbox = QtWidgets.QGroupBox(parent=MetadataOptionsPage) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Preferred, QtWidgets.QSizePolicy.Policy.Maximum) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) @@ -84,22 +90,22 @@ def setupUi(self, MetadataOptionsPage): self.gridlayout = QtWidgets.QGridLayout(self.custom_fields_groupbox) self.gridlayout.setSpacing(2) self.gridlayout.setObjectName("gridlayout") - self.label_6 = QtWidgets.QLabel(self.custom_fields_groupbox) + self.label_6 = QtWidgets.QLabel(parent=self.custom_fields_groupbox) self.label_6.setObjectName("label_6") self.gridlayout.addWidget(self.label_6, 0, 0, 1, 2) - self.label_7 = QtWidgets.QLabel(self.custom_fields_groupbox) + self.label_7 = QtWidgets.QLabel(parent=self.custom_fields_groupbox) self.label_7.setObjectName("label_7") self.gridlayout.addWidget(self.label_7, 2, 0, 1, 2) - self.nat_name = QtWidgets.QLineEdit(self.custom_fields_groupbox) + self.nat_name = QtWidgets.QLineEdit(parent=self.custom_fields_groupbox) self.nat_name.setObjectName("nat_name") self.gridlayout.addWidget(self.nat_name, 3, 0, 1, 1) - self.nat_name_default = QtWidgets.QPushButton(self.custom_fields_groupbox) + self.nat_name_default = QtWidgets.QPushButton(parent=self.custom_fields_groupbox) self.nat_name_default.setObjectName("nat_name_default") self.gridlayout.addWidget(self.nat_name_default, 3, 1, 1, 1) - self.va_name_default = QtWidgets.QPushButton(self.custom_fields_groupbox) + self.va_name_default = QtWidgets.QPushButton(parent=self.custom_fields_groupbox) self.va_name_default.setObjectName("va_name_default") self.gridlayout.addWidget(self.va_name_default, 1, 1, 1, 1) - self.va_name = QtWidgets.QLineEdit(self.custom_fields_groupbox) + self.va_name = QtWidgets.QLineEdit(parent=self.custom_fields_groupbox) self.va_name.setObjectName("va_name") self.gridlayout.addWidget(self.va_name, 1, 0, 1, 1) self.verticalLayout.addWidget(self.custom_fields_groupbox) @@ -121,26 +127,30 @@ def setupUi(self, MetadataOptionsPage): MetadataOptionsPage.setTabOrder(self.convert_punctuation, self.release_ars) MetadataOptionsPage.setTabOrder(self.release_ars, self.track_ars) MetadataOptionsPage.setTabOrder(self.track_ars, self.guess_tracknumber_and_title) - MetadataOptionsPage.setTabOrder(self.guess_tracknumber_and_title, self.va_name) + MetadataOptionsPage.setTabOrder(self.guess_tracknumber_and_title, self.disable_date_sanitize) + MetadataOptionsPage.setTabOrder(self.disable_date_sanitize, self.selected_formats) + MetadataOptionsPage.setTabOrder(self.selected_formats, self.va_name) MetadataOptionsPage.setTabOrder(self.va_name, self.va_name_default) MetadataOptionsPage.setTabOrder(self.va_name_default, self.nat_name) MetadataOptionsPage.setTabOrder(self.nat_name, self.nat_name_default) def retranslateUi(self, MetadataOptionsPage): _translate = QtCore.QCoreApplication.translate - self.metadata_groupbox.setTitle(_("Metadata")) - self.translate_artist_names.setText(_("Translate artist names to these locales where possible:")) - self.select_locales.setText(_("Select…")) - self.translate_artist_names_script_exception.setText(_("Ignore artist name translation for these language scripts:")) - self.select_scripts.setText(_("Select…")) - self.standardize_artists.setText(_("Use standardized artist names")) - self.standardize_instruments.setText(_("Use standardized instrument and vocal credits")) - self.convert_punctuation.setText(_("Convert Unicode punctuation characters to ASCII")) - self.release_ars.setText(_("Use release relationships")) - self.track_ars.setText(_("Use track relationships")) - self.guess_tracknumber_and_title.setText(_("Guess track number and title from filename if empty")) - self.custom_fields_groupbox.setTitle(_("Custom Fields")) - self.label_6.setText(_("Various artists:")) - self.label_7.setText(_("Standalone recordings:")) - self.nat_name_default.setText(_("Default")) - self.va_name_default.setText(_("Default")) + self.metadata_groupbox.setTitle(_translate("MetadataOptionsPage", "Metadata")) + self.translate_artist_names.setText(_translate("MetadataOptionsPage", "Translate artist names to these locales where possible:")) + self.select_locales.setText(_translate("MetadataOptionsPage", "Select…")) + self.translate_artist_names_script_exception.setText(_translate("MetadataOptionsPage", "Ignore artist name translation for these language scripts:")) + self.select_scripts.setText(_translate("MetadataOptionsPage", "Select…")) + self.standardize_artists.setText(_translate("MetadataOptionsPage", "Use standardized artist names")) + self.standardize_instruments.setText(_translate("MetadataOptionsPage", "Use standardized instrument and vocal credits")) + self.convert_punctuation.setText(_translate("MetadataOptionsPage", "Convert Unicode punctuation characters to ASCII")) + self.release_ars.setText(_translate("MetadataOptionsPage", "Use release relationships")) + self.track_ars.setText(_translate("MetadataOptionsPage", "Use track relationships")) + self.guess_tracknumber_and_title.setText(_translate("MetadataOptionsPage", "Guess track number and title from filename if empty")) + self.disable_date_sanitize.setText(_translate("MetadataOptionsPage", "Disable the date sanitization for selected formats")) + self.custom_fields_groupbox.setTitle(_translate("MetadataOptionsPage", "Custom Fields")) + self.label_6.setText(_translate("MetadataOptionsPage", "Various artists:")) + self.label_7.setText(_translate("MetadataOptionsPage", "Standalone recordings:")) + self.nat_name_default.setText(_translate("MetadataOptionsPage", "Default")) + self.va_name_default.setText(_translate("MetadataOptionsPage", "Default")) +from picard.ui.widgets.multicombobox import MultiComboBox diff --git a/picard/ui/widgets/multicombobox.py b/picard/ui/widgets/multicombobox.py new file mode 100644 index 0000000000..dc49d6da0a --- /dev/null +++ b/picard/ui/widgets/multicombobox.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- +# +# Picard, the next-generation MusicBrainz tagger +# +# Copyright (C) 2024 Shubham Patel +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +from PyQt6.QtGui import ( + QStandardItemModel, + QStandardItem, +) +from PyQt6.QtWidgets import QComboBox +from PyQt6.QtCore import Qt + + +class MultiComboBox(QComboBox): + def __init__(self, parent=None): + super().__init__(parent) + self.setEditable(True) + self.lineEdit().setReadOnly(True) + self.setModel(QStandardItemModel(self)) + + # Connect to the dataChanged signal to update the text + self.model().dataChanged.connect(self.updateText) + + def addItem(self, text: str, data=None): + item = QStandardItem() + item.setText(text) + item.setFlags(Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsUserCheckable) + item.setData(Qt.CheckState.Unchecked, Qt.ItemDataRole.CheckStateRole) + self.model().appendRow(item) + + def addItems(self, items_list: list): + for text in items_list: + self.addItem(text) + + def updateText(self): + selected_items = [self.model().item(i).text() for i in range(self.model().rowCount()) + if self.model().item(i).checkState() == Qt.CheckState.Checked] + self.lineEdit().setText(", ".join(selected_items)) + + def show_selected_items(self): + selected_items = [self.model().item(i).text() for i in range(self.model().rowCount()) + if self.model().item(i).checkState() == Qt.CheckState.Checked] + return selected_items + + def showPopup(self): + super().showPopup() + # Set the state of each item in the dropdown + for i in range(self.model().rowCount()): + item = self.model().item(i) + combo_box_view = self.view() + combo_box_view.setRowHidden(i, False) + check_box = combo_box_view.indexWidget(item.index()) + if check_box: + check_box.setChecked(item.checkState() == Qt.CheckState.Checked) + + def hidePopup(self): + # Update the check state of each item based on the checkbox state + for i in range(self.model().rowCount()): + item = self.model().item(i) + combo_box_view = self.view() + check_box = combo_box_view.indexWidget(item.index()) + if check_box: + item.setCheckState(Qt.CheckState.Checked if check_box.isChecked() else Qt.CheckState.Unchecked) + super().hidePopup() diff --git a/test/formats/common.py b/test/formats/common.py index b4459e88f0..72c171c72c 100644 --- a/test/formats/common.py +++ b/test/formats/common.py @@ -65,6 +65,8 @@ 'replace_spaces_with_underscores': False, 'replace_dir_separator': '_', 'win_compat_replacements': {}, + 'disable_date_sanitize': False, + 'formats_to_disable_date_sanitize': [], } diff --git a/ui/options_metadata.ui b/ui/options_metadata.ui index e92a3332d1..7e0ef4d5ff 100644 --- a/ui/options_metadata.ui +++ b/ui/options_metadata.ui @@ -130,6 +130,17 @@ + + + + Disable the date sanitization for selected formats + + + + + + + @@ -212,6 +223,13 @@ + + + MultiComboBox + QWidget +
picard.ui.widgets.multicombobox
+
+
translate_artist_names selected_locales @@ -225,6 +243,8 @@ release_ars track_ars guess_tracknumber_and_title + disable_date_sanitize + selected_formats va_name va_name_default nat_name