Compare commits

...

2 Commits

Author SHA1 Message Date
a51a67fae3
impr: minor improvements 2023-10-25 17:53:21 +08:00
b48e177ae8
feat: TabDb_RemoveDuplicateScores 2023-10-25 17:41:40 +08:00
10 changed files with 777 additions and 244 deletions

View File

@ -6,22 +6,24 @@
<rect>
<x>0</x>
<y>0</y>
<width>700</width>
<width>600</width>
<height>500</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">TabDb_RemoveDuplicateScores</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<layout class="QVBoxLayout" name="verticalLayout">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>scan.title</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QCheckBox" name="scan_option_scoreCheckBox">
<property name="text">
@ -29,8 +31,6 @@
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QCheckBox" name="scan_option_pureCheckBox">
<property name="text">
@ -52,8 +52,6 @@
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="scan_option_maxRecallCheckBox">
<property name="text">
@ -61,12 +59,16 @@
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QCheckBox" name="scan_option_clearTypeCheckBox">
<widget class="QCheckBox" name="scan_option_dateCheckBox">
<property name="text">
<string>scan.option.clearType</string>
<string>scan.option.date</string>
</property>
</widget>
</item>
@ -77,6 +79,13 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="scan_option_clearTypeCheckBox">
<property name="text">
<string>scan.option.clearType</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
@ -89,6 +98,26 @@
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QTreeView" name="treeView">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="headerHidden">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
@ -98,31 +127,41 @@
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>quickSelect.keepSingleLabel</string>
<string>quickSelect.description</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="quickSelect_timeComboBox"/>
<widget class="QComboBox" name="quickSelect_comboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="quickSelect_ColumnComboBox"/>
</item>
<item>
<spacer name="verticalSpacer">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>91</height>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="quickSelect_selectButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>quickSelect.selectButton</string>
</property>
@ -131,19 +170,35 @@
</layout>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<spacer name="horizontalSpacer">
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string/>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QPushButton" name="deselectAllButton">
<property name="text">
<string>deselectAllButton</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="reverseSelectionButton">
<property name="text">
<string>reverseSelectionButton</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
@ -169,23 +224,21 @@
</property>
</widget>
</item>
</layout>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0">
<widget class="QTreeView" name="treeView">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="deleteSelectedButton">
<item>
<widget class="QPushButton" name="deleteSelectionButton">
<property name="font">
<font>
<bold>true</bold>
@ -195,12 +248,39 @@
<string notr="true">QPushButton { color: red };</string>
</property>
<property name="text">
<string>deleteSelectedButton</string>
<string>deleteSelectionButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<tabstops>
<tabstop>scan_option_scoreCheckBox</tabstop>
<tabstop>scan_option_pureCheckBox</tabstop>
<tabstop>scan_option_farCheckBox</tabstop>
<tabstop>scan_option_lostCheckBox</tabstop>
<tabstop>scan_option_maxRecallCheckBox</tabstop>
<tabstop>scan_option_dateCheckBox</tabstop>
<tabstop>scan_option_modifierCheckBox</tabstop>
<tabstop>scan_option_clearTypeCheckBox</tabstop>
<tabstop>scan_scanButton</tabstop>
<tabstop>treeView</tabstop>
<tabstop>quickSelect_comboBox</tabstop>
<tabstop>quickSelect_selectButton</tabstop>
<tabstop>deselectAllButton</tabstop>
<tabstop>reverseSelectionButton</tabstop>
<tabstop>collapseAllButton</tabstop>
<tabstop>expandAllButton</tabstop>
<tabstop>resetModelButton</tabstop>
<tabstop>deleteSelectionButton</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

View File

@ -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

View File

@ -29,6 +29,11 @@
<string>tab.chartInfoEditor</string>
</attribute>
</widget>
<widget class="TabDb_RemoveDuplicateScores" name="tab_removeDuplicateScores">
<attribute name="title">
<string>tab.removeDuplicateScores</string>
</attribute>
</widget>
</widget>
</item>
</layout>
@ -46,6 +51,12 @@
<header>ui.implements.tabs.tabDb.tabDb_ChartInfoEditor</header>
<container>1</container>
</customwidget>
<customwidget>
<class>TabDb_RemoveDuplicateScores</class>
<extends>QWidget</extends>
<header>ui.implements.tabs.tabDb.tabDb_RemoveDuplicateScores</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>

View File

@ -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

View File

@ -339,7 +339,7 @@
<item row="9" column="1">
<widget class="QLabel" name="label_7">
<property name="text">
<string>&lt;a href=&quot;https://github.com/283375/AndrealImageGenerator&quot;&gt;283375/AndrealImageGenerator&lt;/a&gt;&lt;br&gt;(forked from &lt;a href=&quot;https://github.com/Awbugl/AndrealImageGenerator&quot;&gt;Awbugl/AndrealImageGenerator&lt;/a&gt;)</string>
<string notr="true">&lt;a href=&quot;https://github.com/283375/AndrealImageGenerator&quot;&gt;283375/AndrealImageGenerator&lt;/a&gt;&lt;br&gt;(forked from &lt;a href=&quot;https://github.com/Awbugl/AndrealImageGenerator&quot;&gt;Awbugl/AndrealImageGenerator&lt;/a&gt;)</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>

View File

@ -227,6 +227,7 @@ class Ui_TabTools_Andreal(object):
self.label_7 = QLabel(TabTools_Andreal)
self.label_7.setObjectName(u"label_7")
self.label_7.setText(u"<a href=\"https://github.com/283375/AndrealImageGenerator\">283375/AndrealImageGenerator</a><br>(forked from <a href=\"https://github.com/Awbugl/AndrealImageGenerator\">Awbugl/AndrealImageGenerator</a>)")
self.label_7.setOpenExternalLinks(True)
self.formLayout.setWidget(9, QFormLayout.FieldRole, self.label_7)
@ -257,7 +258,6 @@ class Ui_TabTools_Andreal(object):
self.generatePreviewButton.setText(QCoreApplication.translate("TabTools_Andreal", u"generatePreviewButton", None))
self.generateImageButton.setText(QCoreApplication.translate("TabTools_Andreal", u"generateImageButton", None))
self.label_4.setText(QCoreApplication.translate("TabTools_Andreal", u"sourceCode", None))
self.label_7.setText(QCoreApplication.translate("TabTools_Andreal", u"<a href=\"https://github.com/283375/AndrealImageGenerator\">283375/AndrealImageGenerator</a><br>(forked from <a href=\"https://github.com/Awbugl/AndrealImageGenerator\">Awbugl/AndrealImageGenerator</a>)", None))
pass
# retranslateUi

View File

@ -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()

View File

@ -5,12 +5,12 @@ from arcaea_offline.database import Database
from arcaea_offline.models import Chart, Score
from arcaea_offline.utils.rating import rating_class_to_text
from PySide6.QtCore import QModelIndex, Qt, Slot
from PySide6.QtGui import QColor, QPalette
from PySide6.QtWidgets import QDialog, QLabel, QVBoxLayout, QWidget
from ui.designer.tabs.tabTools.tabTools_ChartRecommend_ui import (
Ui_TabTools_ChartRecommend,
)
from ui.extends.shared.language import LanguageChangeEventFilter
from ui.extends.tabs.tabTools.tabTools_ChartRecommend import (
ChartsModel,
ChartsWithScoreBestModel,
@ -55,6 +55,9 @@ class TabTools_ChartRecommend(Ui_TabTools_ChartRecommend, QWidget):
super().__init__(parent)
self.setupUi(self)
self.languageChangeEventFilter = LanguageChangeEventFilter(self)
self.installEventFilter(self.languageChangeEventFilter)
self.db = Database()
self.chartsByConstantModel = ChartsModel(self)

View File

@ -599,6 +599,11 @@ validation</translation>
<source>tab.chartInfoEditor</source>
<translation>Chart Info Editor</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDbEntry.ui" line="34"/>
<source>tab.removeDuplicateScores</source>
<translation>Remove Duplicate Scores</translation>
</message>
<message>
<location filename="../../implements/tabs/tabDbEntry.py" line="20"/>
<source>tab.scoreTableViewer</source>
@ -757,6 +762,109 @@ validation</translation>
<translation>Export all your scores to &lt;a href=&quot;https://smartrte.github.io/b30gen.html&quot;&gt;smartrte.github.io&lt;/a&gt; compatible CSV file</translation>
</message>
</context>
<context>
<name>TabDb_RemoveDuplicateScores</name>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="20"/>
<source>scan.title</source>
<translation>Scan Options</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="30"/>
<source>scan.option.score</source>
<translation>Score</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="71"/>
<source>scan.option.date</source>
<translation>Date</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="78"/>
<source>scan.option.modifier</source>
<translation>Modifier</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="85"/>
<source>scan.option.clearType</source>
<translation>Clear Type</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="94"/>
<source>scan.scanButton</source>
<translation>Scan</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="124"/>
<source>quickSelect.title</source>
<translation>Quick Select</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="130"/>
<source>quickSelect.description</source>
<translation>Keep the first score item&lt;br&gt;that matches:</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="166"/>
<source>quickSelect.selectButton</source>
<translation>Select</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="182"/>
<source>deselectAllButton</source>
<translation>Clear Selection</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="189"/>
<source>reverseSelectionButton</source>
<translation>Reverse Selection</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="209"/>
<source>collapseAllButton</source>
<translation>Collapse All Groups</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="216"/>
<source>expandAllButton</source>
<translation>Expand All Groups</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="223"/>
<source>resetModelButton</source>
<translation>Reset Model</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="251"/>
<source>deleteSelectionButton</source>
<translation>Delete Selected Scores</translation>
</message>
<message>
<location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="142"/>
<source>quickSelectComboBox.idEarlier</source>
<translation>Earlier ID</translation>
</message>
<message>
<location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="148"/>
<source>quickSelectComboBox.dateEarlier</source>
<translation>Earlier date</translation>
</message>
<message>
<location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="154"/>
<source>quickSelectComboBox.columnsIntegral</source>
<translation>More complete data</translation>
</message>
<message>
<location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="279"/>
<source>deleteSelectionDialog.content {}</source>
<translation>Deleting {} scores from database, this cannot be undone!&lt;br&gt;Confirm?</translation>
</message>
<message>
<location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="301"/>
<source>scan_noColumnsDialog.content</source>
<translation>You haven&apos;t selected any column! Are you sure to continue?</translation>
</message>
</context>
<context>
<name>TabOcrDisabled</name>
<message>
@ -911,7 +1019,7 @@ validation</translation>
<context>
<name>TabOverview</name>
<message>
<location filename="../../implements/tabs/tabOverview.py" line="43"/>
<location filename="../../implements/tabs/tabOverview.py" line="56"/>
<source>databaseDescribeLabel {} {} {} {} {} {}</source>
<translation>There are {} packs, {} songs, {} difficulties, {} chart info ({} complete) and {} scores in database.</translation>
</message>
@ -1006,11 +1114,6 @@ validation</translation>
<source>sourceCode</source>
<translation>Source code</translation>
</message>
<message>
<location filename="../../designer/tabs/tabTools/tabTools_Andreal.ui" line="342"/>
<source>&lt;a href=&quot;https://github.com/283375/AndrealImageGenerator&quot;&gt;283375/AndrealImageGenerator&lt;/a&gt;&lt;br&gt;(forked from &lt;a href=&quot;https://github.com/Awbugl/AndrealImageGenerator&quot;&gt;Awbugl/AndrealImageGenerator&lt;/a&gt;)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../implements/tabs/tabTools/tabTools_Andreal.py" line="138"/>
<source>imageWhatIsThisDialog.description</source>

View File

@ -598,6 +598,11 @@
<source>tab.chartInfoEditor</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/tabs/tabDbEntry.ui" line="34"/>
<source>tab.removeDuplicateScores</source>
<translation></translation>
</message>
<message>
<location filename="../../implements/tabs/tabDbEntry.py" line="20"/>
<source>tab.scoreTableViewer</source>
@ -756,6 +761,109 @@
<translation> &lt;a href=&quot;https://smartrte.github.io/b30gen.html&quot;&gt;smartrte.github.io&lt;/a&gt; 的 CSV 文件</translation>
</message>
</context>
<context>
<name>TabDb_RemoveDuplicateScores</name>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="20"/>
<source>scan.title</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="30"/>
<source>scan.option.score</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="71"/>
<source>scan.option.date</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="78"/>
<source>scan.option.modifier</source>
<translation>Modifier</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="85"/>
<source>scan.option.clearType</source>
<translation>Clear Type</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="94"/>
<source>scan.scanButton</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="124"/>
<source>quickSelect.title</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="130"/>
<source>quickSelect.description</source>
<translation>&lt;br&gt;</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="166"/>
<source>quickSelect.selectButton</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="182"/>
<source>deselectAllButton</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="189"/>
<source>reverseSelectionButton</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="209"/>
<source>collapseAllButton</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="216"/>
<source>expandAllButton</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="223"/>
<source>resetModelButton</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="251"/>
<source>deleteSelectionButton</source>
<translation></translation>
</message>
<message>
<location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="142"/>
<source>quickSelectComboBox.idEarlier</source>
<translation>ID </translation>
</message>
<message>
<location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="148"/>
<source>quickSelectComboBox.dateEarlier</source>
<translation></translation>
</message>
<message>
<location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="154"/>
<source>quickSelectComboBox.columnsIntegral</source>
<translation></translation>
</message>
<message>
<location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="279"/>
<source>deleteSelectionDialog.content {}</source>
<translation> {} &lt;br&gt;</translation>
</message>
<message>
<location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="301"/>
<source>scan_noColumnsDialog.content</source>
<translation></translation>
</message>
</context>
<context>
<name>TabOcrDisabled</name>
<message>
@ -910,7 +1018,7 @@
<context>
<name>TabOverview</name>
<message>
<location filename="../../implements/tabs/tabOverview.py" line="43"/>
<location filename="../../implements/tabs/tabOverview.py" line="56"/>
<source>databaseDescribeLabel {} {} {} {} {} {}</source>
<translation> {} {} {} {} {} {} </translation>
</message>
@ -1005,11 +1113,6 @@
<source>sourceCode</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/tabs/tabTools/tabTools_Andreal.ui" line="342"/>
<source>&lt;a href=&quot;https://github.com/283375/AndrealImageGenerator&quot;&gt;283375/AndrealImageGenerator&lt;/a&gt;&lt;br&gt;(forked from &lt;a href=&quot;https://github.com/Awbugl/AndrealImageGenerator&quot;&gt;Awbugl/AndrealImageGenerator&lt;/a&gt;)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../implements/tabs/tabTools/tabTools_Andreal.py" line="138"/>
<source>imageWhatIsThisDialog.description</source>