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