diff --git a/ui/designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui b/ui/designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui
index 6955e94..edfa693 100644
--- a/ui/designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui
+++ b/ui/designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui
@@ -6,31 +6,31 @@
0
0
- 700
+ 600
500
TabDb_RemoveDuplicateScores
-
- -
-
-
-
-
-
- scan.title
-
-
-
-
-
-
- scan.option.score
-
-
-
+
+ -
+
+
+ scan.title
+
+
+
-
+
-
+
-
+
+
+ scan.option.score
+
+
+
-
@@ -52,155 +52,235 @@
-
-
- -
-
-
- MAX RECALL
-
-
-
- -
-
-
-
+
- scan.option.clearType
-
-
-
- -
-
-
- scan.option.modifier
+ MAX RECALL
+
+
+ -
+
-
-
+
- scan.scanButton
+ scan.option.date
+
+
+
+ -
+
+
+ scan.option.modifier
+
+
+
+ -
+
+
+ scan.option.clearType
-
-
- -
-
-
- quickSelect.title
-
-
-
-
-
-
- quickSelect.keepSingleLabel
-
-
-
- -
-
-
- -
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 91
-
-
-
-
- -
-
-
- quickSelect.selectButton
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- collapseAllButton
-
-
-
- -
-
-
- expandAllButton
-
-
-
- -
-
-
- resetModelButton
-
-
-
-
-
- -
-
-
- QAbstractItemView::NoEditTriggers
-
-
- QAbstractItemView::NoSelection
-
-
- QAbstractItemView::ScrollPerPixel
-
+
+ -
+
+
+ scan.scanButton
+
+
+
+
- -
-
-
-
- true
-
-
-
- QPushButton { color: red };
-
-
- deleteSelectedButton
-
-
+
-
+
+
-
+
+
+ QAbstractItemView::NoEditTriggers
+
+
+ QAbstractItemView::NoSelection
+
+
+ QAbstractItemView::ScrollPerPixel
+
+
+ true
+
+
+
+ -
+
+
-
+
+
+ quickSelect.title
+
+
+
-
+
+
+ quickSelect.description
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ quickSelect.selectButton
+
+
+
+
+
+
+ -
+
+
+
+
+
+
-
+
+
+ deselectAllButton
+
+
+
+ -
+
+
+ reverseSelectionButton
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ collapseAllButton
+
+
+
+ -
+
+
+ expandAllButton
+
+
+
+ -
+
+
+ resetModelButton
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+
+ true
+
+
+
+ QPushButton { color: red };
+
+
+ deleteSelectionButton
+
+
+
+
+
+
+
+
+
+
+ scan_option_scoreCheckBox
+ scan_option_pureCheckBox
+ scan_option_farCheckBox
+ scan_option_lostCheckBox
+ scan_option_maxRecallCheckBox
+ scan_option_dateCheckBox
+ scan_option_modifierCheckBox
+ scan_option_clearTypeCheckBox
+ scan_scanButton
+ treeView
+ quickSelect_comboBox
+ quickSelect_selectButton
+ deselectAllButton
+ reverseSelectionButton
+ collapseAllButton
+ expandAllButton
+ resetModelButton
+ deleteSelectionButton
+
diff --git a/ui/designer/tabs/tabDb/tabDb_RemoveDuplicateScores_ui.py b/ui/designer/tabs/tabDb/tabDb_RemoveDuplicateScores_ui.py
index cae37a9..f7247e3 100644
--- a/ui/designer/tabs/tabDb/tabDb_RemoveDuplicateScores_ui.py
+++ b/ui/designer/tabs/tabDb/tabDb_RemoveDuplicateScores_ui.py
@@ -16,31 +16,31 @@ from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
QImage, QKeySequence, QLinearGradient, QPainter,
QPalette, QPixmap, QRadialGradient, QTransform)
from PySide6.QtWidgets import (QAbstractItemView, QApplication, QCheckBox, QComboBox,
- QGridLayout, QGroupBox, QHBoxLayout, QHeaderView,
- QLabel, QPushButton, QSizePolicy, QSpacerItem,
- QTreeView, QVBoxLayout, QWidget)
+ QGroupBox, QHBoxLayout, QHeaderView, QLabel,
+ QPushButton, QSizePolicy, QSpacerItem, QTreeView,
+ QVBoxLayout, QWidget)
class Ui_TabDb_RemoveDuplicateScores(object):
def setupUi(self, TabDb_RemoveDuplicateScores):
if not TabDb_RemoveDuplicateScores.objectName():
TabDb_RemoveDuplicateScores.setObjectName(u"TabDb_RemoveDuplicateScores")
- TabDb_RemoveDuplicateScores.resize(700, 500)
+ TabDb_RemoveDuplicateScores.resize(600, 500)
TabDb_RemoveDuplicateScores.setWindowTitle(u"TabDb_RemoveDuplicateScores")
- self.gridLayout = QGridLayout(TabDb_RemoveDuplicateScores)
- self.gridLayout.setObjectName(u"gridLayout")
- self.verticalLayout = QVBoxLayout()
- self.verticalLayout.setObjectName(u"verticalLayout")
+ self.verticalLayout_2 = QVBoxLayout(TabDb_RemoveDuplicateScores)
+ self.verticalLayout_2.setObjectName(u"verticalLayout_2")
self.groupBox_2 = QGroupBox(TabDb_RemoveDuplicateScores)
self.groupBox_2.setObjectName(u"groupBox_2")
- self.verticalLayout_2 = QVBoxLayout(self.groupBox_2)
- self.verticalLayout_2.setObjectName(u"verticalLayout_2")
+ self.verticalLayout = QVBoxLayout(self.groupBox_2)
+ self.verticalLayout.setObjectName(u"verticalLayout")
+ self.verticalLayout_4 = QVBoxLayout()
+ self.verticalLayout_4.setObjectName(u"verticalLayout_4")
+ self.horizontalLayout_2 = QHBoxLayout()
+ self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
self.scan_option_scoreCheckBox = QCheckBox(self.groupBox_2)
self.scan_option_scoreCheckBox.setObjectName(u"scan_option_scoreCheckBox")
- self.verticalLayout_2.addWidget(self.scan_option_scoreCheckBox)
+ self.horizontalLayout_2.addWidget(self.scan_option_scoreCheckBox)
- self.horizontalLayout_2 = QHBoxLayout()
- self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
self.scan_option_pureCheckBox = QCheckBox(self.groupBox_2)
self.scan_option_pureCheckBox.setObjectName(u"scan_option_pureCheckBox")
self.scan_option_pureCheckBox.setText(u"PURE")
@@ -59,38 +59,59 @@ class Ui_TabDb_RemoveDuplicateScores(object):
self.horizontalLayout_2.addWidget(self.scan_option_lostCheckBox)
-
- self.verticalLayout_2.addLayout(self.horizontalLayout_2)
-
self.scan_option_maxRecallCheckBox = QCheckBox(self.groupBox_2)
self.scan_option_maxRecallCheckBox.setObjectName(u"scan_option_maxRecallCheckBox")
self.scan_option_maxRecallCheckBox.setText(u"MAX RECALL")
- self.verticalLayout_2.addWidget(self.scan_option_maxRecallCheckBox)
+ self.horizontalLayout_2.addWidget(self.scan_option_maxRecallCheckBox)
+
+
+ self.verticalLayout_4.addLayout(self.horizontalLayout_2)
+
+
+ self.verticalLayout.addLayout(self.verticalLayout_4)
self.horizontalLayout_3 = QHBoxLayout()
self.horizontalLayout_3.setObjectName(u"horizontalLayout_3")
- self.scan_option_clearTypeCheckBox = QCheckBox(self.groupBox_2)
- self.scan_option_clearTypeCheckBox.setObjectName(u"scan_option_clearTypeCheckBox")
+ self.scan_option_dateCheckBox = QCheckBox(self.groupBox_2)
+ self.scan_option_dateCheckBox.setObjectName(u"scan_option_dateCheckBox")
- self.horizontalLayout_3.addWidget(self.scan_option_clearTypeCheckBox)
+ self.horizontalLayout_3.addWidget(self.scan_option_dateCheckBox)
self.scan_option_modifierCheckBox = QCheckBox(self.groupBox_2)
self.scan_option_modifierCheckBox.setObjectName(u"scan_option_modifierCheckBox")
self.horizontalLayout_3.addWidget(self.scan_option_modifierCheckBox)
+ self.scan_option_clearTypeCheckBox = QCheckBox(self.groupBox_2)
+ self.scan_option_clearTypeCheckBox.setObjectName(u"scan_option_clearTypeCheckBox")
- self.verticalLayout_2.addLayout(self.horizontalLayout_3)
+ self.horizontalLayout_3.addWidget(self.scan_option_clearTypeCheckBox)
+
+
+ self.verticalLayout.addLayout(self.horizontalLayout_3)
self.scan_scanButton = QPushButton(self.groupBox_2)
self.scan_scanButton.setObjectName(u"scan_scanButton")
- self.verticalLayout_2.addWidget(self.scan_scanButton)
+ self.verticalLayout.addWidget(self.scan_scanButton)
- self.verticalLayout.addWidget(self.groupBox_2)
+ self.verticalLayout_2.addWidget(self.groupBox_2)
+ self.horizontalLayout = QHBoxLayout()
+ self.horizontalLayout.setObjectName(u"horizontalLayout")
+ self.treeView = QTreeView(TabDb_RemoveDuplicateScores)
+ self.treeView.setObjectName(u"treeView")
+ self.treeView.setEditTriggers(QAbstractItemView.NoEditTriggers)
+ self.treeView.setSelectionMode(QAbstractItemView.NoSelection)
+ self.treeView.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel)
+ self.treeView.setHeaderHidden(True)
+
+ self.horizontalLayout.addWidget(self.treeView)
+
+ self.verticalLayout_6 = QVBoxLayout()
+ self.verticalLayout_6.setObjectName(u"verticalLayout_6")
self.groupBox = QGroupBox(TabDb_RemoveDuplicateScores)
self.groupBox.setObjectName(u"groupBox")
self.verticalLayout_3 = QVBoxLayout(self.groupBox)
@@ -100,73 +121,103 @@ class Ui_TabDb_RemoveDuplicateScores(object):
self.verticalLayout_3.addWidget(self.label)
- self.quickSelect_timeComboBox = QComboBox(self.groupBox)
- self.quickSelect_timeComboBox.setObjectName(u"quickSelect_timeComboBox")
+ self.quickSelect_comboBox = QComboBox(self.groupBox)
+ self.quickSelect_comboBox.setObjectName(u"quickSelect_comboBox")
+ sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.quickSelect_comboBox.sizePolicy().hasHeightForWidth())
+ self.quickSelect_comboBox.setSizePolicy(sizePolicy)
- self.verticalLayout_3.addWidget(self.quickSelect_timeComboBox)
+ self.verticalLayout_3.addWidget(self.quickSelect_comboBox)
- self.quickSelect_ColumnComboBox = QComboBox(self.groupBox)
- self.quickSelect_ColumnComboBox.setObjectName(u"quickSelect_ColumnComboBox")
+ self.verticalSpacer_2 = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
- self.verticalLayout_3.addWidget(self.quickSelect_ColumnComboBox)
-
- self.verticalSpacer = QSpacerItem(20, 91, QSizePolicy.Minimum, QSizePolicy.Expanding)
-
- self.verticalLayout_3.addItem(self.verticalSpacer)
+ self.verticalLayout_3.addItem(self.verticalSpacer_2)
self.quickSelect_selectButton = QPushButton(self.groupBox)
self.quickSelect_selectButton.setObjectName(u"quickSelect_selectButton")
+ sizePolicy.setHeightForWidth(self.quickSelect_selectButton.sizePolicy().hasHeightForWidth())
+ self.quickSelect_selectButton.setSizePolicy(sizePolicy)
self.verticalLayout_3.addWidget(self.quickSelect_selectButton)
- self.verticalLayout.addWidget(self.groupBox)
+ self.verticalLayout_6.addWidget(self.groupBox)
+ self.groupBox_3 = QGroupBox(TabDb_RemoveDuplicateScores)
+ self.groupBox_3.setObjectName(u"groupBox_3")
+ self.verticalLayout_5 = QVBoxLayout(self.groupBox_3)
+ self.verticalLayout_5.setObjectName(u"verticalLayout_5")
+ self.deselectAllButton = QPushButton(self.groupBox_3)
+ self.deselectAllButton.setObjectName(u"deselectAllButton")
- self.gridLayout.addLayout(self.verticalLayout, 0, 1, 1, 1)
+ self.verticalLayout_5.addWidget(self.deselectAllButton)
- self.horizontalLayout_4 = QHBoxLayout()
- self.horizontalLayout_4.setObjectName(u"horizontalLayout_4")
- self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
+ self.reverseSelectionButton = QPushButton(self.groupBox_3)
+ self.reverseSelectionButton.setObjectName(u"reverseSelectionButton")
- self.horizontalLayout_4.addItem(self.horizontalSpacer)
+ self.verticalLayout_5.addWidget(self.reverseSelectionButton)
- self.collapseAllButton = QPushButton(TabDb_RemoveDuplicateScores)
+ self.verticalSpacer_3 = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
+
+ self.verticalLayout_5.addItem(self.verticalSpacer_3)
+
+ self.collapseAllButton = QPushButton(self.groupBox_3)
self.collapseAllButton.setObjectName(u"collapseAllButton")
- self.horizontalLayout_4.addWidget(self.collapseAllButton)
+ self.verticalLayout_5.addWidget(self.collapseAllButton)
- self.expandAllButton = QPushButton(TabDb_RemoveDuplicateScores)
+ self.expandAllButton = QPushButton(self.groupBox_3)
self.expandAllButton.setObjectName(u"expandAllButton")
- self.horizontalLayout_4.addWidget(self.expandAllButton)
+ self.verticalLayout_5.addWidget(self.expandAllButton)
- self.resetModelButton = QPushButton(TabDb_RemoveDuplicateScores)
+ self.resetModelButton = QPushButton(self.groupBox_3)
self.resetModelButton.setObjectName(u"resetModelButton")
- self.horizontalLayout_4.addWidget(self.resetModelButton)
+ self.verticalLayout_5.addWidget(self.resetModelButton)
+ self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
- self.gridLayout.addLayout(self.horizontalLayout_4, 1, 0, 1, 1)
+ self.verticalLayout_5.addItem(self.verticalSpacer)
- self.treeView = QTreeView(TabDb_RemoveDuplicateScores)
- self.treeView.setObjectName(u"treeView")
- self.treeView.setEditTriggers(QAbstractItemView.NoEditTriggers)
- self.treeView.setSelectionMode(QAbstractItemView.NoSelection)
- self.treeView.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel)
-
- self.gridLayout.addWidget(self.treeView, 0, 0, 1, 1)
-
- self.deleteSelectedButton = QPushButton(TabDb_RemoveDuplicateScores)
- self.deleteSelectedButton.setObjectName(u"deleteSelectedButton")
+ self.deleteSelectionButton = QPushButton(self.groupBox_3)
+ self.deleteSelectionButton.setObjectName(u"deleteSelectionButton")
font = QFont()
font.setBold(True)
- self.deleteSelectedButton.setFont(font)
- self.deleteSelectedButton.setStyleSheet(u"QPushButton { color: red };")
+ self.deleteSelectionButton.setFont(font)
+ self.deleteSelectionButton.setStyleSheet(u"QPushButton { color: red };")
- self.gridLayout.addWidget(self.deleteSelectedButton, 1, 1, 1, 1)
+ self.verticalLayout_5.addWidget(self.deleteSelectionButton)
+ self.verticalLayout_6.addWidget(self.groupBox_3)
+
+
+ self.horizontalLayout.addLayout(self.verticalLayout_6)
+
+
+ self.verticalLayout_2.addLayout(self.horizontalLayout)
+
+ QWidget.setTabOrder(self.scan_option_scoreCheckBox, self.scan_option_pureCheckBox)
+ QWidget.setTabOrder(self.scan_option_pureCheckBox, self.scan_option_farCheckBox)
+ QWidget.setTabOrder(self.scan_option_farCheckBox, self.scan_option_lostCheckBox)
+ QWidget.setTabOrder(self.scan_option_lostCheckBox, self.scan_option_maxRecallCheckBox)
+ QWidget.setTabOrder(self.scan_option_maxRecallCheckBox, self.scan_option_dateCheckBox)
+ QWidget.setTabOrder(self.scan_option_dateCheckBox, self.scan_option_modifierCheckBox)
+ QWidget.setTabOrder(self.scan_option_modifierCheckBox, self.scan_option_clearTypeCheckBox)
+ QWidget.setTabOrder(self.scan_option_clearTypeCheckBox, self.scan_scanButton)
+ QWidget.setTabOrder(self.scan_scanButton, self.treeView)
+ QWidget.setTabOrder(self.treeView, self.quickSelect_comboBox)
+ QWidget.setTabOrder(self.quickSelect_comboBox, self.quickSelect_selectButton)
+ QWidget.setTabOrder(self.quickSelect_selectButton, self.deselectAllButton)
+ QWidget.setTabOrder(self.deselectAllButton, self.reverseSelectionButton)
+ QWidget.setTabOrder(self.reverseSelectionButton, self.collapseAllButton)
+ QWidget.setTabOrder(self.collapseAllButton, self.expandAllButton)
+ QWidget.setTabOrder(self.expandAllButton, self.resetModelButton)
+ QWidget.setTabOrder(self.resetModelButton, self.deleteSelectionButton)
+
self.retranslateUi(TabDb_RemoveDuplicateScores)
QMetaObject.connectSlotsByName(TabDb_RemoveDuplicateScores)
@@ -175,16 +226,20 @@ class Ui_TabDb_RemoveDuplicateScores(object):
def retranslateUi(self, TabDb_RemoveDuplicateScores):
self.groupBox_2.setTitle(QCoreApplication.translate("TabDb_RemoveDuplicateScores", u"scan.title", None))
self.scan_option_scoreCheckBox.setText(QCoreApplication.translate("TabDb_RemoveDuplicateScores", u"scan.option.score", None))
- self.scan_option_clearTypeCheckBox.setText(QCoreApplication.translate("TabDb_RemoveDuplicateScores", u"scan.option.clearType", None))
+ self.scan_option_dateCheckBox.setText(QCoreApplication.translate("TabDb_RemoveDuplicateScores", u"scan.option.date", None))
self.scan_option_modifierCheckBox.setText(QCoreApplication.translate("TabDb_RemoveDuplicateScores", u"scan.option.modifier", None))
+ self.scan_option_clearTypeCheckBox.setText(QCoreApplication.translate("TabDb_RemoveDuplicateScores", u"scan.option.clearType", None))
self.scan_scanButton.setText(QCoreApplication.translate("TabDb_RemoveDuplicateScores", u"scan.scanButton", None))
self.groupBox.setTitle(QCoreApplication.translate("TabDb_RemoveDuplicateScores", u"quickSelect.title", None))
- self.label.setText(QCoreApplication.translate("TabDb_RemoveDuplicateScores", u"quickSelect.keepSingleLabel", None))
+ self.label.setText(QCoreApplication.translate("TabDb_RemoveDuplicateScores", u"quickSelect.description", None))
self.quickSelect_selectButton.setText(QCoreApplication.translate("TabDb_RemoveDuplicateScores", u"quickSelect.selectButton", None))
+ self.groupBox_3.setTitle("")
+ self.deselectAllButton.setText(QCoreApplication.translate("TabDb_RemoveDuplicateScores", u"deselectAllButton", None))
+ self.reverseSelectionButton.setText(QCoreApplication.translate("TabDb_RemoveDuplicateScores", u"reverseSelectionButton", None))
self.collapseAllButton.setText(QCoreApplication.translate("TabDb_RemoveDuplicateScores", u"collapseAllButton", None))
self.expandAllButton.setText(QCoreApplication.translate("TabDb_RemoveDuplicateScores", u"expandAllButton", None))
self.resetModelButton.setText(QCoreApplication.translate("TabDb_RemoveDuplicateScores", u"resetModelButton", None))
- self.deleteSelectedButton.setText(QCoreApplication.translate("TabDb_RemoveDuplicateScores", u"deleteSelectedButton", None))
+ self.deleteSelectionButton.setText(QCoreApplication.translate("TabDb_RemoveDuplicateScores", u"deleteSelectionButton", None))
pass
# retranslateUi
diff --git a/ui/designer/tabs/tabDbEntry.ui b/ui/designer/tabs/tabDbEntry.ui
index 89befa5..de9b19c 100644
--- a/ui/designer/tabs/tabDbEntry.ui
+++ b/ui/designer/tabs/tabDbEntry.ui
@@ -29,6 +29,11 @@
tab.chartInfoEditor
+
+
+ tab.removeDuplicateScores
+
+
@@ -46,6 +51,12 @@
ui.implements.tabs.tabDb.tabDb_ChartInfoEditor
1
+
+ TabDb_RemoveDuplicateScores
+ QWidget
+ ui.implements.tabs.tabDb.tabDb_RemoveDuplicateScores
+ 1
+
diff --git a/ui/designer/tabs/tabDbEntry_ui.py b/ui/designer/tabs/tabDbEntry_ui.py
index 423da36..37ec6f4 100644
--- a/ui/designer/tabs/tabDbEntry_ui.py
+++ b/ui/designer/tabs/tabDbEntry_ui.py
@@ -20,6 +20,7 @@ from PySide6.QtWidgets import (QApplication, QSizePolicy, QTabWidget, QVBoxLayou
from ui.implements.tabs.tabDb.tabDb_ChartInfoEditor import TabDb_ChartInfoEditor
from ui.implements.tabs.tabDb.tabDb_Manage import TabDb_Manage
+from ui.implements.tabs.tabDb.tabDb_RemoveDuplicateScores import TabDb_RemoveDuplicateScores
class Ui_TabDbEntry(object):
def setupUi(self, TabDbEntry):
@@ -37,6 +38,9 @@ class Ui_TabDbEntry(object):
self.tab_chartInfoEditor = TabDb_ChartInfoEditor()
self.tab_chartInfoEditor.setObjectName(u"tab_chartInfoEditor")
self.tabWidget.addTab(self.tab_chartInfoEditor, "")
+ self.tab_removeDuplicateScores = TabDb_RemoveDuplicateScores()
+ self.tab_removeDuplicateScores.setObjectName(u"tab_removeDuplicateScores")
+ self.tabWidget.addTab(self.tab_removeDuplicateScores, "")
self.verticalLayout.addWidget(self.tabWidget)
@@ -52,6 +56,7 @@ class Ui_TabDbEntry(object):
def retranslateUi(self, TabDbEntry):
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_manage), QCoreApplication.translate("TabDbEntry", u"tab.manage", None))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_chartInfoEditor), QCoreApplication.translate("TabDbEntry", u"tab.chartInfoEditor", None))
+ self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_removeDuplicateScores), QCoreApplication.translate("TabDbEntry", u"tab.removeDuplicateScores", None))
pass
# retranslateUi
diff --git a/ui/implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py b/ui/implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py
index 4702681..8d65a9d 100644
--- a/ui/implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py
+++ b/ui/implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py
@@ -1,9 +1,11 @@
+from enum import IntEnum
+
from arcaea_offline.database import Database
from arcaea_offline.models import Chart, Difficulty, Score, Song
-from PySide6.QtCore import QModelIndex, Qt, Slot
+from PySide6.QtCore import QCoreApplication, QModelIndex, Qt, Slot
from PySide6.QtGui import QStandardItem, QStandardItemModel
-from PySide6.QtWidgets import QStyledItemDelegate, QWidget
-from sqlalchemy import func, select
+from PySide6.QtWidgets import QMessageBox, QStyledItemDelegate, QWidget
+from sqlalchemy import delete, func, select
from sqlalchemy.orm import InstrumentedAttribute, Session
from ui.designer.tabs.tabDb.tabDb_RemoveDuplicateScores_ui import (
@@ -11,6 +13,7 @@ from ui.designer.tabs.tabDb.tabDb_RemoveDuplicateScores_ui import (
)
from ui.extends.shared.delegates.chartDelegate import ChartDelegate
from ui.extends.shared.delegates.scoreDelegate import ScoreDelegate
+from ui.extends.shared.language import LanguageChangeEventFilter
class RemoveDuplicateScoresModel(QStandardItemModel):
@@ -40,12 +43,19 @@ class RemoveDuplicateScoresModel(QStandardItemModel):
item.setData(song, self.SongRole)
item.setData(difficulty, self.DifficultyRole)
- def setScores(self, scores: list[Score]):
+ def getGroupKey(self, score: Score, columns: list[InstrumentedAttribute]) -> str:
+ baseKeys = [score.song_id, str(score.rating_class)]
+ for column in columns:
+ key = f"{column.key}{getattr(score,column.key)}"
+ baseKeys.append(key)
+ return "||".join(baseKeys)
+
+ def setScores(self, scores: list[Score], columns: list[InstrumentedAttribute]):
self.clear()
- scoreKeyMap: dict[tuple[str, int], list[Score]] = {}
+ scoreKeyMap: dict[str, list[Score]] = {}
for score in scores:
- key = (score.song_id, score.rating_class)
+ key = self.getGroupKey(score, columns)
if scoreKeyMap.get(key) is None:
scoreKeyMap[key] = [score]
else:
@@ -54,7 +64,8 @@ class RemoveDuplicateScoresModel(QStandardItemModel):
db = Database()
with db.sessionmaker() as session:
for key, scores in scoreKeyMap.items():
- songId, ratingClass = key
+ songId, ratingClass = key.split("||")[:2]
+ ratingClass = int(ratingClass)
parentCheckBoxItem = QStandardItem(f"{len(scores)} items")
parentChartItem = QStandardItem()
@@ -112,26 +123,52 @@ class TreeViewProxyDelegate(QStyledItemDelegate):
QStyledItemDelegate.paint(self, painter, option, index)
+class QuickSelectComboBoxValues(IntEnum):
+ ID_EARLIER = 0
+ DATE_EARLIER = 1
+ COLUMNS_INTEGRAL = 2
+
+
class TabDb_RemoveDuplicateScores(Ui_TabDb_RemoveDuplicateScores, QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
+ self.languageChangeEventFilter = LanguageChangeEventFilter(self)
+ self.installEventFilter(self.languageChangeEventFilter)
+
self.db = Database()
- self.scan_scanButton.clicked.connect(self.fillModel)
-
- self.model = RemoveDuplicateScoresModel(self)
- self.treeView.setModel(self.model)
+ self.removeDuplicateScoresModel = RemoveDuplicateScoresModel(self)
+ self.treeView.setModel(self.removeDuplicateScoresModel)
self.treeViewChartDelegate = TreeViewChartDelegate(self.treeView)
self.treeViewScoreDelegate = TreeViewScoreDelegate(self.treeView)
- self.treeViewDelegate = TreeViewProxyDelegate(
+ self.treeViewProxyDelegate = TreeViewProxyDelegate(
self.treeViewChartDelegate, self.treeViewScoreDelegate, self.treeView
)
- self.treeView.setItemDelegateForColumn(1, self.treeViewDelegate)
+ self.treeView.setItemDelegateForColumn(1, self.treeViewProxyDelegate)
- def getGroupByColumns(self):
+ self.quickSelect_comboBox.addItem(
+ # fmt: off
+ QCoreApplication.translate("TabDb_RemoveDuplicateScores", "quickSelectComboBox.idEarlier"),
+ # fmt: on
+ QuickSelectComboBoxValues.ID_EARLIER
+ )
+ self.quickSelect_comboBox.addItem(
+ # fmt: off
+ QCoreApplication.translate("TabDb_RemoveDuplicateScores", "quickSelectComboBox.dateEarlier"),
+ # fmt: on
+ QuickSelectComboBoxValues.DATE_EARLIER
+ )
+ self.quickSelect_comboBox.addItem(
+ # fmt: off
+ QCoreApplication.translate("TabDb_RemoveDuplicateScores", "quickSelectComboBox.columnsIntegral"),
+ # fmt: on
+ QuickSelectComboBoxValues.COLUMNS_INTEGRAL
+ )
+
+ def getQueryColumns(self):
columns: list[InstrumentedAttribute] = [Score.song_id, Score.rating_class]
if self.scan_option_scoreCheckBox.isChecked():
@@ -144,15 +181,17 @@ class TabDb_RemoveDuplicateScores(Ui_TabDb_RemoveDuplicateScores, QWidget):
columns.append(Score.lost)
if self.scan_option_maxRecallCheckBox.isChecked():
columns.append(Score.max_recall)
- if self.scan_option_clearTypeCheckBox.isChecked():
- columns.append(Score.clear_type)
+ if self.scan_option_dateCheckBox.isChecked():
+ columns.append(Score.date)
if self.scan_option_modifierCheckBox.isChecked():
columns.append(Score.modifier)
+ if self.scan_option_clearTypeCheckBox.isChecked():
+ columns.append(Score.clear_type)
return columns
def getQueryScores(self):
- columns = self.getGroupByColumns()
+ columns = self.getQueryColumns()
with self.db.sessionmaker() as session:
groupBySubquery = (
select(*columns).group_by(*columns).having(func.count() > 1).subquery()
@@ -162,11 +201,137 @@ class TabDb_RemoveDuplicateScores(Ui_TabDb_RemoveDuplicateScores, QWidget):
]
return session.query(Score).where(*selectInClause).all()
- def fillModel(self):
+ def scan(self):
scores = self.getQueryScores()
- self.model.setScores(scores)
+ self.removeDuplicateScoresModel.setScores(scores, self.getQueryColumns())
self.treeView.expandAll()
+ def deselectAll(self):
+ for row in range(self.removeDuplicateScoresModel.rowCount()):
+ parentItem = self.removeDuplicateScoresModel.item(row, 0)
+ for childRow in range(parentItem.rowCount()):
+ childCheckBoxItem = parentItem.child(childRow, 0)
+ childCheckBoxItem.setCheckState(Qt.CheckState.Unchecked)
+
+ def quickSelect(self):
+ mode = self.quickSelect_comboBox.currentData()
+
+ if mode is None:
+ return
+
+ for row in range(self.removeDuplicateScoresModel.rowCount()):
+ parentItem = self.removeDuplicateScoresModel.item(row, 0)
+
+ scores: list[Score] = []
+
+ for childRow in range(parentItem.rowCount()):
+ childScoreItem = parentItem.child(childRow, 1)
+ scores.append(childScoreItem.data(RemoveDuplicateScoresModel.ScoreRole))
+
+ if mode == QuickSelectComboBoxValues.ID_EARLIER:
+ chosenRow = min(enumerate(scores), key=lambda i: i[1].id)[0]
+ elif mode == QuickSelectComboBoxValues.DATE_EARLIER:
+ chosenRow = min(
+ enumerate(scores),
+ key=lambda i: float("inf") if i[1].date is None else i[1].date,
+ )[0]
+ elif mode == QuickSelectComboBoxValues.COLUMNS_INTEGRAL:
+ chosenRow = max(
+ enumerate(scores),
+ key=lambda i: sum(
+ getattr(i[1], col.key) is not None
+ for col in i[1].__table__.columns
+ ),
+ )[0]
+
+ for childRow in range(parentItem.rowCount()):
+ childCheckBoxItem = parentItem.child(childRow, 0)
+ if childRow != chosenRow:
+ childCheckBoxItem.setCheckState(Qt.CheckState.Checked)
+ else:
+ childCheckBoxItem.setCheckState(Qt.CheckState.Unchecked)
+
+ def reverseSelection(self):
+ for row in range(self.removeDuplicateScoresModel.rowCount()):
+ parentItem = self.removeDuplicateScoresModel.item(row, 0)
+ # only when there's a checked item in this group, we perform a reversed selection
+ # otherwise we ignore this group
+ performReverse = any(
+ parentItem.child(childRow, 0).checkState() == Qt.CheckState.Checked
+ for childRow in range(parentItem.rowCount())
+ )
+ if not performReverse:
+ continue
+
+ for childRow in range(parentItem.rowCount()):
+ childCheckBoxItem = parentItem.child(childRow, 0)
+ newCheckState = (
+ Qt.CheckState.Unchecked
+ if childCheckBoxItem.checkState() != Qt.CheckState.Unchecked
+ else Qt.CheckState.Checked
+ )
+ childCheckBoxItem.setCheckState(newCheckState)
+
+ def deleteSelection(self):
+ selectedScores: list[Score] = []
+ for row in range(self.removeDuplicateScoresModel.rowCount()):
+ parentItem = self.removeDuplicateScoresModel.item(row, 0)
+ for childRow in range(parentItem.rowCount()):
+ childCheckBoxItem = parentItem.child(childRow, 0)
+ if childCheckBoxItem.checkState() == Qt.CheckState.Checked:
+ childScoreItem = parentItem.child(childRow, 1)
+ selectedScores.append(
+ childScoreItem.data(RemoveDuplicateScoresModel.ScoreRole)
+ )
+
+ confirm = QMessageBox.warning(
+ self,
+ None,
+ # fmt: off
+ QCoreApplication.translate("TabDb_RemoveDuplicateScores", "deleteSelectionDialog.content {}").format(len(selectedScores)),
+ # fmt: on
+ QMessageBox.StandardButton.Yes,
+ QMessageBox.StandardButton.No,
+ )
+ if confirm != QMessageBox.StandardButton.Yes:
+ return
+
+ with self.db.sessionmaker() as session:
+ ids = [s.id for s in selectedScores]
+ session.execute(delete(Score).where(Score.id.in_(ids)))
+ session.commit()
+
+ self.scan()
+
+ @Slot()
+ def on_scan_scanButton_clicked(self):
+ if len(self.getQueryColumns()) <= 2:
+ result = QMessageBox.warning(
+ self,
+ None,
+ # fmt: off
+ QCoreApplication.translate("TabDb_RemoveDuplicateScores", "scan_noColumnsDialog.content"),
+ # fmt: on
+ QMessageBox.StandardButton.Yes,
+ QMessageBox.StandardButton.No,
+ )
+ if result != QMessageBox.StandardButton.Yes:
+ return
+
+ self.scan()
+
+ @Slot()
+ def on_quickSelect_selectButton_clicked(self):
+ self.quickSelect()
+
+ @Slot()
+ def on_deselectAllButton_clicked(self):
+ self.deselectAll()
+
+ @Slot()
+ def on_reverseSelectionButton_clicked(self):
+ self.reverseSelection()
+
@Slot()
def on_expandAllButton_clicked(self):
self.treeView.expandAll()
@@ -174,3 +339,11 @@ class TabDb_RemoveDuplicateScores(Ui_TabDb_RemoveDuplicateScores, QWidget):
@Slot()
def on_collapseAllButton_clicked(self):
self.treeView.collapseAll()
+
+ @Slot()
+ def on_resetModelButton_clicked(self):
+ self.removeDuplicateScoresModel.clear()
+
+ @Slot()
+ def on_deleteSelectionButton_clicked(self):
+ self.deleteSelection()
diff --git a/ui/resources/lang/en_US.ts b/ui/resources/lang/en_US.ts
index f7ce145..86ecfc3 100644
--- a/ui/resources/lang/en_US.ts
+++ b/ui/resources/lang/en_US.ts
@@ -599,6 +599,11 @@ validation
tab.chartInfoEditor
Chart Info Editor
+
+
+ tab.removeDuplicateScores
+ Remove Duplicate Scores
+
tab.scoreTableViewer
@@ -757,6 +762,109 @@ validation
Export all your scores to <a href="https://smartrte.github.io/b30gen.html">smartrte.github.io</a> compatible CSV file
+
+ TabDb_RemoveDuplicateScores
+
+
+ scan.title
+ Scan Options
+
+
+
+ scan.option.score
+ Score
+
+
+
+ scan.option.date
+ Date
+
+
+
+ scan.option.modifier
+ Modifier
+
+
+
+ scan.option.clearType
+ Clear Type
+
+
+
+ scan.scanButton
+ Scan
+
+
+
+ quickSelect.title
+ Quick Select
+
+
+
+ quickSelect.description
+ Keep the first score item<br>that matches:
+
+
+
+ quickSelect.selectButton
+ Select
+
+
+
+ deselectAllButton
+ Clear Selection
+
+
+
+ reverseSelectionButton
+ Reverse Selection
+
+
+
+ collapseAllButton
+ Collapse All Groups
+
+
+
+ expandAllButton
+ Expand All Groups
+
+
+
+ resetModelButton
+ Reset Model
+
+
+
+ deleteSelectionButton
+ Delete Selected Scores
+
+
+
+ quickSelectComboBox.idEarlier
+ Earlier ID
+
+
+
+ quickSelectComboBox.dateEarlier
+ Earlier date
+
+
+
+ quickSelectComboBox.columnsIntegral
+ More complete data
+
+
+
+ deleteSelectionDialog.content {}
+ Deleting {} scores from database, this cannot be undone!<br>Confirm?
+
+
+
+ scan_noColumnsDialog.content
+ You haven't selected any column! Are you sure to continue?
+
+
TabOcrDisabled
@@ -911,7 +1019,7 @@ validation
TabOverview
-
+
databaseDescribeLabel {} {} {} {} {} {}
There are {} packs, {} songs, {} difficulties, {} chart info ({} complete) and {} scores in database.
@@ -1006,11 +1114,6 @@ validation
sourceCode
Source code
-
-
- <a href="https://github.com/283375/AndrealImageGenerator">283375/AndrealImageGenerator</a><br>(forked from <a href="https://github.com/Awbugl/AndrealImageGenerator">Awbugl/AndrealImageGenerator</a>)
-
-
imageWhatIsThisDialog.description
diff --git a/ui/resources/lang/zh_CN.ts b/ui/resources/lang/zh_CN.ts
index 52f41b8..08e3d24 100644
--- a/ui/resources/lang/zh_CN.ts
+++ b/ui/resources/lang/zh_CN.ts
@@ -598,6 +598,11 @@
tab.chartInfoEditor
谱面信息编辑器
+
+
+ tab.removeDuplicateScores
+ 移除重复分数
+
tab.scoreTableViewer
@@ -756,6 +761,109 @@
将所有分数导出为兼容 <a href="https://smartrte.github.io/b30gen.html">smartrte.github.io</a> 的 CSV 文件
+
+ TabDb_RemoveDuplicateScores
+
+
+ scan.title
+ 扫描选项
+
+
+
+ scan.option.score
+ 分数
+
+
+
+ scan.option.date
+ 时间
+
+
+
+ scan.option.modifier
+ Modifier
+
+
+
+ scan.option.clearType
+ Clear Type
+
+
+
+ scan.scanButton
+ 扫描
+
+
+
+ quickSelect.title
+ 快速选择
+
+
+
+ quickSelect.description
+ 仅保留第一个<br>符合以下条件的分数:
+
+
+
+ quickSelect.selectButton
+ 选择
+
+
+
+ deselectAllButton
+ 清空选择
+
+
+
+ reverseSelectionButton
+ 反选
+
+
+
+ collapseAllButton
+ 折叠所有
+
+
+
+ expandAllButton
+ 展开所有
+
+
+
+ resetModelButton
+ 重置模型
+
+
+
+ deleteSelectionButton
+ 删除已选分数
+
+
+
+ quickSelectComboBox.idEarlier
+ ID 更早
+
+
+
+ quickSelectComboBox.dateEarlier
+ 时间更早
+
+
+
+ quickSelectComboBox.columnsIntegral
+ 数据更完整
+
+
+
+ deleteSelectionDialog.content {}
+ 将从数据库中删除 {} 个分数。此操作无法撤销!<br>确认吗?
+
+
+
+ scan_noColumnsDialog.content
+ 还未选择任何字段!确定继续吗?
+
+
TabOcrDisabled
@@ -910,7 +1018,7 @@
TabOverview
-
+
databaseDescribeLabel {} {} {} {} {} {}
数据库中有 {} 个曲包,{} 首歌曲,{} 个难度,{} 个谱面信息({} 个完整),{} 个分数记录。
@@ -1005,11 +1113,6 @@
sourceCode
源代码
-
-
- <a href="https://github.com/283375/AndrealImageGenerator">283375/AndrealImageGenerator</a><br>(forked from <a href="https://github.com/Awbugl/AndrealImageGenerator">Awbugl/AndrealImageGenerator</a>)
-
-
imageWhatIsThisDialog.description