diff --git a/picard/file.py b/picard/file.py
index ff7914698..7b767dc6a 100644
--- a/picard/file.py
+++ b/picard/file.py
@@ -545,15 +545,17 @@ class File(QtCore.QObject, Item):
names = set(new_metadata.keys())
names.update(self.orig_metadata.keys())
clear_existing_tags = config.setting["clear_existing_tags"]
+ ignored_tags = config.setting["compare_ignore_tags"]
for name in names:
- if not name.startswith('~') and self.supports_tag(name):
+ if (not name.startswith('~') and self.supports_tag(name)
+ and name not in ignored_tags):
new_values = new_metadata.getall(name)
if not (new_values or clear_existing_tags
or name in new_metadata.deleted_tags):
continue
orig_values = self.orig_metadata.getall(name)
if orig_values != new_values:
- self.similarity = self.orig_metadata.compare(new_metadata)
+ self.similarity = self.orig_metadata.compare(new_metadata, ignored_tags)
if self.state == File.NORMAL:
self.state = File.CHANGED
break
diff --git a/picard/metadata.py b/picard/metadata.py
index 3d216da4d..e4b83254b 100644
--- a/picard/metadata.py
+++ b/picard/metadata.py
@@ -102,14 +102,18 @@ class Metadata(MutableMapping):
return (1.0 - min(abs(a - b),
LENGTH_SCORE_THRES_MS) / float(LENGTH_SCORE_THRES_MS))
- def compare(self, other):
+ def compare(self, other, ignored=None):
parts = []
+ if ignored is None:
+ ignored = []
- if self.length and other.length:
+ if self.length and other.length and '~length' not in ignored:
score = self.length_score(self.length, other.length)
parts.append((score, 8))
for name, weight in self.__weights:
+ if name in ignored:
+ continue
a = self[name]
b = other[name]
if a and b:
diff --git a/picard/ui/options/advanced.py b/picard/ui/options/advanced.py
index 5315dfd37..aee4ee2f4 100644
--- a/picard/ui/options/advanced.py
+++ b/picard/ui/options/advanced.py
@@ -43,6 +43,7 @@ class AdvancedOptionsPage(OptionsPage):
config.BoolOption("setting", "completeness_ignore_pregap", False),
config.BoolOption("setting", "completeness_ignore_data", False),
config.BoolOption("setting", "completeness_ignore_silence", False),
+ config.ListOption("setting", "compare_ignore_tags", []),
]
def __init__(self, parent=None):
@@ -60,6 +61,7 @@ class AdvancedOptionsPage(OptionsPage):
self.ui.completeness_ignore_pregap.setChecked(config.setting["completeness_ignore_pregap"])
self.ui.completeness_ignore_data.setChecked(config.setting["completeness_ignore_data"])
self.ui.completeness_ignore_silence.setChecked(config.setting["completeness_ignore_silence"])
+ self.ui.compare_ignore_tags.update(config.setting["compare_ignore_tags"])
def save(self):
config.setting["ignore_regex"] = self.ui.ignore_regex.text()
@@ -70,6 +72,13 @@ class AdvancedOptionsPage(OptionsPage):
config.setting["completeness_ignore_pregap"] = self.ui.completeness_ignore_pregap.isChecked()
config.setting["completeness_ignore_data"] = self.ui.completeness_ignore_data.isChecked()
config.setting["completeness_ignore_silence"] = self.ui.completeness_ignore_silence.isChecked()
+ tags = list(self.ui.compare_ignore_tags.tags)
+ if tags != config.setting["compare_ignore_tags"]:
+ config.setting["compare_ignore_tags"] = tags
+
+ def restore_defaults(self):
+ self.ui.compare_ignore_tags.clear()
+ super().restore_defaults()
register_options_page(AdvancedOptionsPage)
diff --git a/picard/ui/options/interface_top_tags.py b/picard/ui/options/interface_top_tags.py
index 870f3d777..fc7748430 100644
--- a/picard/ui/options/interface_top_tags.py
+++ b/picard/ui/options/interface_top_tags.py
@@ -51,9 +51,6 @@ class InterfaceTopTagsOptionsPage(OptionsPage):
super().__init__(parent)
self.ui = Ui_InterfaceTopTagsOptionsPage()
self.ui.setupUi(self)
- selection = self.ui.top_tags_list.selectionModel()
- selection.selectionChanged.connect(self.on_selection_changed)
- self.on_selection_changed([], [])
def load(self):
tags = config.setting["metadatabox_top_tags"]
@@ -69,11 +66,5 @@ class InterfaceTopTagsOptionsPage(OptionsPage):
self.ui.top_tags_list.clear()
super().restore_defaults()
- def on_selection_changed(self, selected, deselected):
- buttons_enabled = len(self.ui.top_tags_list.selectedIndexes()) > 0
- self.ui.tags_remove_btn.setEnabled(buttons_enabled)
- self.ui.tags_move_up_btn.setEnabled(buttons_enabled)
- self.ui.tags_move_down_btn.setEnabled(buttons_enabled)
-
register_options_page(InterfaceTopTagsOptionsPage)
diff --git a/picard/ui/ui_options_advanced.py b/picard/ui/ui_options_advanced.py
index 808404f8d..affa06ffc 100644
--- a/picard/ui/ui_options_advanced.py
+++ b/picard/ui/ui_options_advanced.py
@@ -86,8 +86,17 @@ class Ui_AdvancedOptionsPage(object):
self.completeness_ignore_silence.setObjectName("completeness_ignore_silence")
self.verticalLayout_2.addWidget(self.completeness_ignore_silence)
self.vboxlayout.addWidget(self.groupBox_completeness)
- spacerItem = QtWidgets.QSpacerItem(181, 21, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
- self.vboxlayout.addItem(spacerItem)
+ self.compare_ignore_tags_label = QtWidgets.QLabel(AdvancedOptionsPage)
+ self.compare_ignore_tags_label.setObjectName("compare_ignore_tags_label")
+ self.vboxlayout.addWidget(self.compare_ignore_tags_label)
+ self.compare_ignore_tags = TagListEditor(AdvancedOptionsPage)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.compare_ignore_tags.sizePolicy().hasHeightForWidth())
+ self.compare_ignore_tags.setSizePolicy(sizePolicy)
+ self.compare_ignore_tags.setObjectName("compare_ignore_tags")
+ self.vboxlayout.addWidget(self.compare_ignore_tags)
self.retranslateUi(AdvancedOptionsPage)
QtCore.QMetaObject.connectSlotsByName(AdvancedOptionsPage)
@@ -111,3 +120,5 @@ class Ui_AdvancedOptionsPage(object):
self.completeness_ignore_pregap.setText(_("Pregap tracks"))
self.completeness_ignore_data.setText(_("Data tracks"))
self.completeness_ignore_silence.setText(_("Silent tracks"))
+ self.compare_ignore_tags_label.setText(_("Tags to ignore for comparisson:"))
+from picard.ui.widgets.taglisteditor import TagListEditor
diff --git a/picard/ui/ui_options_interface_top_tags.py b/picard/ui/ui_options_interface_top_tags.py
index dccf49e13..438a2516c 100644
--- a/picard/ui/ui_options_interface_top_tags.py
+++ b/picard/ui/ui_options_interface_top_tags.py
@@ -10,7 +10,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_InterfaceTopTagsOptionsPage(object):
def setupUi(self, InterfaceTopTagsOptionsPage):
InterfaceTopTagsOptionsPage.setObjectName("InterfaceTopTagsOptionsPage")
- InterfaceTopTagsOptionsPage.resize(893, 698)
+ InterfaceTopTagsOptionsPage.resize(418, 310)
self.vboxlayout = QtWidgets.QVBoxLayout(InterfaceTopTagsOptionsPage)
self.vboxlayout.setContentsMargins(9, 9, 9, 9)
self.vboxlayout.setSpacing(6)
@@ -18,65 +18,19 @@ class Ui_InterfaceTopTagsOptionsPage(object):
self.label = QtWidgets.QLabel(InterfaceTopTagsOptionsPage)
self.label.setObjectName("label")
self.vboxlayout.addWidget(self.label)
- self.horizontalLayout = QtWidgets.QHBoxLayout()
- self.horizontalLayout.setObjectName("horizontalLayout")
- self.verticalLayout_2 = QtWidgets.QVBoxLayout()
- self.verticalLayout_2.setObjectName("verticalLayout_2")
- self.top_tags_list = EditableTagListView(InterfaceTopTagsOptionsPage)
- self.top_tags_list.setDragEnabled(True)
- self.top_tags_list.setDragDropMode(QtWidgets.QAbstractItemView.InternalMove)
+ self.top_tags_list = TagListEditor(InterfaceTopTagsOptionsPage)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.top_tags_list.sizePolicy().hasHeightForWidth())
+ self.top_tags_list.setSizePolicy(sizePolicy)
self.top_tags_list.setObjectName("top_tags_list")
- self.verticalLayout_2.addWidget(self.top_tags_list)
- self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
- self.horizontalLayout_2.setObjectName("horizontalLayout_2")
- spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
- self.horizontalLayout_2.addItem(spacerItem)
- self.tags_remove_btn = QtWidgets.QPushButton(InterfaceTopTagsOptionsPage)
- self.tags_remove_btn.setObjectName("tags_remove_btn")
- self.horizontalLayout_2.addWidget(self.tags_remove_btn)
- self.tags_add_btn = QtWidgets.QPushButton(InterfaceTopTagsOptionsPage)
- self.tags_add_btn.setAccessibleName("")
- self.tags_add_btn.setObjectName("tags_add_btn")
- self.horizontalLayout_2.addWidget(self.tags_add_btn)
- self.verticalLayout_2.addLayout(self.horizontalLayout_2)
- self.horizontalLayout.addLayout(self.verticalLayout_2)
- self.verticalLayout = QtWidgets.QVBoxLayout()
- self.verticalLayout.setObjectName("verticalLayout")
- spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
- self.verticalLayout.addItem(spacerItem1)
- self.tags_move_up_btn = QtWidgets.QPushButton(InterfaceTopTagsOptionsPage)
- self.tags_move_up_btn.setText("")
- icon = QtGui.QIcon.fromTheme("go-up")
- self.tags_move_up_btn.setIcon(icon)
- self.tags_move_up_btn.setObjectName("tags_move_up_btn")
- self.verticalLayout.addWidget(self.tags_move_up_btn)
- self.tags_move_down_btn = QtWidgets.QPushButton(InterfaceTopTagsOptionsPage)
- self.tags_move_down_btn.setText("")
- icon = QtGui.QIcon.fromTheme("go-down")
- self.tags_move_down_btn.setIcon(icon)
- self.tags_move_down_btn.setObjectName("tags_move_down_btn")
- self.verticalLayout.addWidget(self.tags_move_down_btn)
- spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
- self.verticalLayout.addItem(spacerItem2)
- self.horizontalLayout.addLayout(self.verticalLayout)
- self.vboxlayout.addLayout(self.horizontalLayout)
+ self.vboxlayout.addWidget(self.top_tags_list)
self.retranslateUi(InterfaceTopTagsOptionsPage)
- self.tags_add_btn.clicked.connect(self.top_tags_list.add_empty_row)
- self.tags_remove_btn.clicked.connect(self.top_tags_list.remove_selected_rows)
- self.tags_move_up_btn.clicked.connect(self.top_tags_list.move_selected_rows_up)
- self.tags_move_down_btn.clicked.connect(self.top_tags_list.move_selected_rows_down)
QtCore.QMetaObject.connectSlotsByName(InterfaceTopTagsOptionsPage)
def retranslateUi(self, InterfaceTopTagsOptionsPage):
_translate = QtCore.QCoreApplication.translate
self.label.setText(_("Show the below tags above all other tags in the metadata view"))
- self.tags_remove_btn.setToolTip(_("Remove selected tags"))
- self.tags_remove_btn.setAccessibleName(_("Remove selected tags"))
- self.tags_remove_btn.setText(_("Remove tags"))
- self.tags_add_btn.setText(_("Add new tag"))
- self.tags_move_up_btn.setToolTip(_("Move tag up"))
- self.tags_move_up_btn.setAccessibleName(_("Move tag up"))
- self.tags_move_down_btn.setToolTip(_("Move tag down"))
- self.tags_move_down_btn.setAccessibleName(_("Move tag down"))
-from picard.ui.taglistview import EditableTagListView
+from picard.ui.widgets.taglisteditor import TagListEditor
diff --git a/picard/ui/ui_widget_taglisteditor.py b/picard/ui/ui_widget_taglisteditor.py
new file mode 100644
index 000000000..818f5377d
--- /dev/null
+++ b/picard/ui/ui_widget_taglisteditor.py
@@ -0,0 +1,73 @@
+# -*- coding: utf-8 -*-
+
+# Automatically generated - don't edit.
+# Use `python setup.py build_ui` to update it.
+
+
+from PyQt5 import QtCore, QtGui, QtWidgets
+
+
+class Ui_TagListEditor(object):
+ def setupUi(self, TagListEditor):
+ TagListEditor.setObjectName("TagListEditor")
+ TagListEditor.resize(400, 300)
+ self.horizontalLayout = QtWidgets.QHBoxLayout(TagListEditor)
+ self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
+ self.horizontalLayout.setSpacing(6)
+ self.horizontalLayout.setObjectName("horizontalLayout")
+ self.verticalLayout = QtWidgets.QVBoxLayout()
+ self.verticalLayout.setObjectName("verticalLayout")
+ self.tag_list_view = EditableListView(TagListEditor)
+ self.tag_list_view.setObjectName("tag_list_view")
+ self.verticalLayout.addWidget(self.tag_list_view)
+ self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_2.setObjectName("horizontalLayout_2")
+ spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.horizontalLayout_2.addItem(spacerItem)
+ self.tags_remove_btn = QtWidgets.QPushButton(TagListEditor)
+ self.tags_remove_btn.setObjectName("tags_remove_btn")
+ self.horizontalLayout_2.addWidget(self.tags_remove_btn)
+ self.tags_add_btn = QtWidgets.QPushButton(TagListEditor)
+ self.tags_add_btn.setObjectName("tags_add_btn")
+ self.horizontalLayout_2.addWidget(self.tags_add_btn)
+ self.verticalLayout.addLayout(self.horizontalLayout_2)
+ self.horizontalLayout.addLayout(self.verticalLayout)
+ self.verticalLayout_2 = QtWidgets.QVBoxLayout()
+ self.verticalLayout_2.setObjectName("verticalLayout_2")
+ spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+ self.verticalLayout_2.addItem(spacerItem1)
+ self.tags_move_up_btn = QtWidgets.QPushButton(TagListEditor)
+ self.tags_move_up_btn.setText("")
+ icon = QtGui.QIcon.fromTheme("go-up")
+ self.tags_move_up_btn.setIcon(icon)
+ self.tags_move_up_btn.setObjectName("tags_move_up_btn")
+ self.verticalLayout_2.addWidget(self.tags_move_up_btn)
+ self.tags_move_down_btn = QtWidgets.QPushButton(TagListEditor)
+ self.tags_move_down_btn.setText("")
+ icon = QtGui.QIcon.fromTheme("go-down")
+ self.tags_move_down_btn.setIcon(icon)
+ self.tags_move_down_btn.setObjectName("tags_move_down_btn")
+ self.verticalLayout_2.addWidget(self.tags_move_down_btn)
+ spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+ self.verticalLayout_2.addItem(spacerItem2)
+ self.horizontalLayout.addLayout(self.verticalLayout_2)
+
+ self.retranslateUi(TagListEditor)
+ self.tags_remove_btn.clicked.connect(self.tag_list_view.remove_selected_rows)
+ self.tags_add_btn.clicked.connect(self.tag_list_view.add_empty_row)
+ self.tags_move_up_btn.clicked.connect(self.tag_list_view.move_selected_rows_up)
+ self.tags_move_down_btn.clicked.connect(self.tag_list_view.move_selected_rows_down)
+ QtCore.QMetaObject.connectSlotsByName(TagListEditor)
+
+ def retranslateUi(self, TagListEditor):
+ _translate = QtCore.QCoreApplication.translate
+ TagListEditor.setWindowTitle(_("Form"))
+ self.tags_remove_btn.setToolTip(_("Remove selected tags"))
+ self.tags_remove_btn.setAccessibleName(_("Remove selected tags"))
+ self.tags_remove_btn.setText(_("Remove tags"))
+ self.tags_add_btn.setText(_("Add new tag"))
+ self.tags_move_up_btn.setToolTip(_("Move tag up"))
+ self.tags_move_up_btn.setAccessibleName(_("Move tag up"))
+ self.tags_move_down_btn.setToolTip(_("Move tag down"))
+ self.tags_move_down_btn.setAccessibleName(_("Move tag down"))
+from picard.ui.widgets.editablelistview import EditableListView
diff --git a/picard/ui/taglistview.py b/picard/ui/widgets/editablelistview.py
similarity index 80%
rename from picard/ui/taglistview.py
rename to picard/ui/widgets/editablelistview.py
index 214cc0c50..eb350ba71 100644
--- a/picard/ui/taglistview.py
+++ b/picard/ui/widgets/editablelistview.py
@@ -22,18 +22,10 @@ from PyQt5 import (
QtWidgets,
)
-from picard.util.tags import (
- TAG_NAMES,
- display_tag_name,
-)
-
-class EditableTagListView(QtWidgets.QListView):
+class EditableListView(QtWidgets.QListView):
def __init__(self, parent=None):
super().__init__(parent)
- model = TagListModel()
- self.setModel(model)
- self.setItemDelegate(TagItemDelegate())
self.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
def keyPressEvent(self, event):
@@ -60,26 +52,26 @@ class EditableTagListView(QtWidgets.QListView):
else:
super().closeEditor(editor, hint)
- def add_tag(self, tag=""):
+ def add_item(self, value=""):
model = self.model()
row = model.rowCount()
model.insertRow(row)
index = model.createIndex(row, 0)
- model.setData(index, tag)
+ model.setData(index, value)
return index
def clear(self):
self.model().update([])
- def update(self, tags):
- self.model().update(tags)
+ def update(self, values):
+ self.model().update(values)
@property
- def tags(self):
- return self.model().tags
+ def items(self):
+ return self.model().items
def add_empty_row(self):
- index = self.add_tag()
+ index = self.add_item()
self.setCurrentIndex(index)
self.edit(index)
@@ -128,20 +120,23 @@ class EditableTagListView(QtWidgets.QListView):
selection.setCurrentIndex(new_index, QtCore.QItemSelectionModel.Current)
-class TagListModel(QtCore.QAbstractListModel):
- def __init__(self, tags=None, parent=None):
+class EditableListModel(QtCore.QAbstractListModel):
+ def __init__(self, items=None, parent=None):
super().__init__(parent)
- self._tags = [(tag, display_tag_name(tag)) for tag in tags or []]
+ self._items = [(item, self.get_display_name(item)) for item in items or []]
+
+ def get_display_name(self, item): # pylint: disable=no-self-use
+ return item
def rowCount(self, parent=QtCore.QModelIndex()):
- return len(self._tags)
+ return len(self._items)
def data(self, index, role=QtCore.Qt.DisplayRole):
if not index.isValid() or role not in (QtCore.Qt.DisplayRole, QtCore.Qt.EditRole):
return None
field = 1 if role == QtCore.Qt.DisplayRole else 0
try:
- return self._tags[index.row()][field]
+ return self._items[index.row()][field]
except IndexError:
return None
@@ -151,11 +146,11 @@ class TagListModel(QtCore.QAbstractListModel):
i = index.row()
try:
if role == QtCore.Qt.EditRole:
- display_name = display_tag_name(value) if value else value
- self._tags[i] = (value, display_name)
+ display_name = self.get_display_name(value) if value else value
+ self._items[i] = (value, display_name)
elif role == QtCore.Qt.DisplayRole:
- current = self._tags[i]
- self._tags[i] = (current[0], value)
+ current = self._items[i]
+ self._items[i] = (current[0], value)
return True
except IndexError:
return False
@@ -174,13 +169,13 @@ class TagListModel(QtCore.QAbstractListModel):
def insertRows(self, row, count, parent=QtCore.QModelIndex()):
super().beginInsertRows(parent, row, row + count - 1)
for i in range(count):
- self._tags.insert(row, ("", ""))
+ self._items.insert(row, ("", ""))
super().endInsertRows()
return True
def removeRows(self, row, count, parent=QtCore.QModelIndex()):
super().beginRemoveRows(parent, row, row + count - 1)
- self._tags = self._tags[:row] + self._tags[row + count:]
+ self._items = self._items[:row] + self._items[row + count:]
super().endRemoveRows()
return True
@@ -192,13 +187,13 @@ class TagListModel(QtCore.QAbstractListModel):
def supportedDropActions():
return QtCore.Qt.MoveAction
- def update(self, tags):
+ def update(self, items):
self.beginResetModel()
- self._tags = [(tag, display_tag_name(tag)) for tag in tags]
+ self._items = [(item, self.get_display_name(item)) for item in items]
self.endResetModel()
def move_row(self, row, new_row):
- item = self._tags[row]
+ item = self._items[row]
self.removeRow(row)
self.insertRow(new_row)
index = self.index(new_row, 0)
@@ -206,15 +201,18 @@ class TagListModel(QtCore.QAbstractListModel):
self.setData(index, item[1], QtCore.Qt.DisplayRole)
@property
- def tags(self):
- return (t[0] for t in self._tags)
+ def items(self):
+ return (t[0] for t in self._items)
-class TagItemDelegate(QtWidgets.QItemDelegate):
- @staticmethod
- def createEditor(parent, option, index):
+class AutocompleteItemDelegate(QtWidgets.QItemDelegate):
+ def __init__(self, completions, parent=None):
+ super().__init__(parent)
+ self._completions = completions
+
+ def createEditor(self, parent, option, index):
editor = QtWidgets.QLineEdit(parent)
- completer = QtWidgets.QCompleter(TAG_NAMES.keys(), parent)
+ completer = QtWidgets.QCompleter(self._completions, parent)
def complete(text):
parent.setFocus()
diff --git a/picard/ui/widgets/taglisteditor.py b/picard/ui/widgets/taglisteditor.py
new file mode 100644
index 000000000..88de90fef
--- /dev/null
+++ b/picard/ui/widgets/taglisteditor.py
@@ -0,0 +1,68 @@
+# -*- coding: utf-8 -*-
+#
+# Picard, the next-generation MusicBrainz tagger
+# Copyright (C) 2019 Philipp Wolfer
+#
+# 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 PyQt5 import QtWidgets
+
+from picard.util.tags import (
+ TAG_NAMES,
+ display_tag_name,
+)
+
+from picard.ui.ui_widget_taglisteditor import Ui_TagListEditor
+from picard.ui.widgets.editablelistview import (
+ AutocompleteItemDelegate,
+ EditableListModel,
+)
+
+
+class TagListEditor(QtWidgets.QWidget):
+ def __init__(self, parent):
+ super().__init__(parent)
+ self.ui = Ui_TagListEditor()
+ self.ui.setupUi(self)
+ list_view = self.ui.tag_list_view
+ model = TagListModel()
+ list_view.setModel(model)
+ list_view.setItemDelegate(AutocompleteItemDelegate(
+ sorted(TAG_NAMES.keys())))
+
+ selection = list_view.selectionModel()
+ selection.selectionChanged.connect(self.on_selection_changed)
+ self.on_selection_changed([], [])
+
+ def on_selection_changed(self, selected, deselected):
+ buttons_enabled = len(self.ui.tag_list_view.selectedIndexes()) > 0
+ self.ui.tags_remove_btn.setEnabled(buttons_enabled)
+ self.ui.tags_move_up_btn.setEnabled(buttons_enabled)
+ self.ui.tags_move_down_btn.setEnabled(buttons_enabled)
+
+ def clear(self):
+ self.ui.tag_list_view.update([])
+
+ def update(self, tags):
+ self.ui.tag_list_view.update(tags)
+
+ @property
+ def tags(self):
+ return self.ui.tag_list_view.tags
+
+
+class TagListModel(EditableListModel):
+ def get_display_name(self, item):
+ return display_tag_name(item)
diff --git a/test/test_metadata.py b/test/test_metadata.py
index f4450fa0c..a878e1b23 100644
--- a/test/test_metadata.py
+++ b/test/test_metadata.py
@@ -223,6 +223,18 @@ class MetadataTest(PicardTestCase):
self.assertEqual(m1.compare(m2), m2.compare(m1))
self.assertEqual(m1.compare(m2), 1)
+ def test_compare_with_ignored(self):
+ m1 = Metadata()
+ m1["title"] = "title1"
+ m1["tracknumber"] = "2"
+ m1.length = 360
+ m2 = Metadata()
+ m2["title"] = "title1"
+ m2["tracknumber"] = "3"
+ m2.length = 300
+ self.assertNotEqual(m1.compare(m2), 1)
+ self.assertEqual(m1.compare(m2, ignored=['tracknumber', '~length']), 1)
+
def test_compare_lengths(self):
m1 = Metadata()
m1.length = 360
diff --git a/ui/options_advanced.ui b/ui/options_advanced.ui
index 66c26780c..e5a3d2cb1 100644
--- a/ui/options_advanced.ui
+++ b/ui/options_advanced.ui
@@ -155,20 +155,32 @@
-
-
-
- Qt::Vertical
+
+
+ Tags to ignore for comparisson:
-
-
- 181
- 21
-
+
+
+ -
+
+
+
+ 0
+ 0
+
-
+
+
+
+ TagListEditor
+ QWidget
+ picard.ui.widgets.taglisteditor
+ 1
+
+
ignore_regex
ignore_hidden_files
diff --git a/ui/options_interface_top_tags.ui b/ui/options_interface_top_tags.ui
index 324b08e15..2abfb5cc0 100644
--- a/ui/options_interface_top_tags.ui
+++ b/ui/options_interface_top_tags.ui
@@ -6,8 +6,8 @@
0
0
- 893
- 698
+ 418
+ 310
@@ -34,207 +34,25 @@
-
-
-
-
-
-
-
-
-
- true
-
-
- QAbstractItemView::InternalMove
-
-
-
- -
-
-
-
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- Remove selected tags
-
-
- Remove selected tags
-
-
- Remove tags
-
-
-
- -
-
-
-
-
-
- Add new tag
-
-
-
-
-
-
-
- -
-
-
-
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
- -
-
-
- Move tag up
-
-
- Move tag up
-
-
-
-
-
-
- ..
-
-
-
- -
-
-
- Move tag down
-
-
- Move tag down
-
-
-
-
-
-
- ..
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
-
-
-
+
+
+
+ 0
+ 0
+
+
+
- EditableTagListView
- QListView
-
-
- add_empty_row()
- remove_selected_rows()
- move_selected_rows_up()
- move_selected_rows_down()
-
+ TagListEditor
+ QWidget
+ picard.ui.widgets.taglisteditor
+ 1
-
-
- tags_add_btn
- clicked()
- top_tags_list
- add_empty_row()
-
-
- 804
- 673
-
-
- 428
- 343
-
-
-
-
- tags_remove_btn
- clicked()
- top_tags_list
- remove_selected_rows()
-
-
- 716
- 673
-
-
- 428
- 343
-
-
-
-
- tags_move_up_btn
- clicked()
- top_tags_list
- move_selected_rows_up()
-
-
- 867
- 344
-
-
- 428
- 343
-
-
-
-
- tags_move_down_btn
- clicked()
- top_tags_list
- move_selected_rows_down()
-
-
- 867
- 374
-
-
- 428
- 343
-
-
-
-
+
diff --git a/ui/widget_taglisteditor.ui b/ui/widget_taglisteditor.ui
new file mode 100644
index 000000000..41dc04bc4
--- /dev/null
+++ b/ui/widget_taglisteditor.ui
@@ -0,0 +1,220 @@
+
+
+ TagListEditor
+
+
+
+ 0
+ 0
+ 400
+ 300
+
+
+
+ Form
+
+
+
+ 6
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
-
+
+
+ -
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Remove selected tags
+
+
+ Remove selected tags
+
+
+ Remove tags
+
+
+
+ -
+
+
+ Add new tag
+
+
+
+
+
+
+
+ -
+
+
-
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ Move tag up
+
+
+ Move tag up
+
+
+
+
+
+
+
+
+
+ -
+
+
+ Move tag down
+
+
+ Move tag down
+
+
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+
+
+ EditableListView
+ QListView
+ picard.ui.widgets.editablelistview
+
+ add_empty_row()
+ remove_selected_rows()
+ move_selected_rows_up()
+ move_selected_rows_down()
+
+
+
+
+
+
+ tags_remove_btn
+ clicked()
+ tag_list_view
+ remove_selected_rows()
+
+
+ 182
+ 285
+
+
+ 155
+ 133
+
+
+
+
+ tags_add_btn
+ clicked()
+ tag_list_view
+ add_empty_row()
+
+
+ 269
+ 285
+
+
+ 155
+ 133
+
+
+
+
+ tags_move_up_btn
+ clicked()
+ tag_list_view
+ move_selected_rows_up()
+
+
+ 384
+ 134
+
+
+ 181
+ 133
+
+
+
+
+ tags_move_down_btn
+ clicked()
+ tag_list_view
+ move_selected_rows_down()
+
+
+ 384
+ 164
+
+
+ 181
+ 133
+
+
+
+
+