diff --git a/ui/designer/components/chartSelector.ui b/ui/designer/components/chartSelector.ui
index 62e85fe..6ec23a1 100644
--- a/ui/designer/components/chartSelector.ui
+++ b/ui/designer/components/chartSelector.ui
@@ -26,122 +26,20 @@
songIdSelector.title
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
-
-
-
- songIdSelector.quickActions
-
-
-
-
-
-
-
- 100
- 0
-
-
-
- songIdSelector.quickActions.nextPackageButton
-
-
-
- -
-
-
-
- 100
- 0
-
-
-
- songIdSelector.quickActions.nextSongIdButton
-
-
-
- -
-
-
-
- 100
- 0
-
-
-
- songIdSelector.quickActions.previousSongIdButton
-
-
-
- -
-
-
-
- 100
- 0
-
-
-
- songIdSelector.quickActions.previousPackageButton
-
-
-
-
-
-
- -
-
-
-
- 300
- 0
-
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
-
-
-
- true
-
-
- search.lineEdit.placeholder
-
-
- true
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
- -
-
-
- -
-
-
-
-
+
@@ -185,6 +83,12 @@
ui.implements.components.ratingClassSelector
1
+
+ SongIdSelector
+ QWidget
+ ui.implements.components.songIdSelector
+ 1
+
diff --git a/ui/designer/components/chartSelector_ui.py b/ui/designer/components/chartSelector_ui.py
index 51a79de..d3e8cdb 100644
--- a/ui/designer/components/chartSelector_ui.py
+++ b/ui/designer/components/chartSelector_ui.py
@@ -15,11 +15,11 @@ from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
QFont, QFontDatabase, QGradient, QIcon,
QImage, QKeySequence, QLinearGradient, QPainter,
QPalette, QPixmap, QRadialGradient, QTransform)
-from PySide6.QtWidgets import (QApplication, QComboBox, QGroupBox, QHBoxLayout,
- QLabel, QLineEdit, QPushButton, QSizePolicy,
- QSpacerItem, QVBoxLayout, QWidget)
+from PySide6.QtWidgets import (QApplication, QGroupBox, QHBoxLayout, QLabel,
+ QPushButton, QSizePolicy, QVBoxLayout, QWidget)
from ui.implements.components.ratingClassSelector import RatingClassSelector
+from ui.implements.components.songIdSelector import SongIdSelector
class Ui_ChartSelector(object):
def setupUi(self, ChartSelector):
@@ -38,66 +38,11 @@ class Ui_ChartSelector(object):
self.songIdSelectorGroupBox.setSizePolicy(sizePolicy)
self.verticalLayout_3 = QVBoxLayout(self.songIdSelectorGroupBox)
self.verticalLayout_3.setObjectName(u"verticalLayout_3")
- self.songIdSelectorQuickActionsGroupBox = QGroupBox(self.songIdSelectorGroupBox)
- self.songIdSelectorQuickActionsGroupBox.setObjectName(u"songIdSelectorQuickActionsGroupBox")
- self.horizontalLayout = QHBoxLayout(self.songIdSelectorQuickActionsGroupBox)
- self.horizontalLayout.setObjectName(u"horizontalLayout")
- self.nextPackageButton = QPushButton(self.songIdSelectorQuickActionsGroupBox)
- self.nextPackageButton.setObjectName(u"nextPackageButton")
- self.nextPackageButton.setMinimumSize(QSize(100, 0))
+ self.verticalLayout_3.setContentsMargins(0, 0, 0, 0)
+ self.songIdSelector = SongIdSelector(self.songIdSelectorGroupBox)
+ self.songIdSelector.setObjectName(u"songIdSelector")
- self.horizontalLayout.addWidget(self.nextPackageButton)
-
- self.nextSongIdButton = QPushButton(self.songIdSelectorQuickActionsGroupBox)
- self.nextSongIdButton.setObjectName(u"nextSongIdButton")
- self.nextSongIdButton.setMinimumSize(QSize(100, 0))
-
- self.horizontalLayout.addWidget(self.nextSongIdButton)
-
- self.previousSongIdButton = QPushButton(self.songIdSelectorQuickActionsGroupBox)
- self.previousSongIdButton.setObjectName(u"previousSongIdButton")
- self.previousSongIdButton.setMinimumSize(QSize(100, 0))
-
- self.horizontalLayout.addWidget(self.previousSongIdButton)
-
- self.previousPackageButton = QPushButton(self.songIdSelectorQuickActionsGroupBox)
- self.previousPackageButton.setObjectName(u"previousPackageButton")
- self.previousPackageButton.setMinimumSize(QSize(100, 0))
-
- self.horizontalLayout.addWidget(self.previousPackageButton)
-
-
- self.verticalLayout_3.addWidget(self.songIdSelectorQuickActionsGroupBox)
-
- self.widget = QWidget(self.songIdSelectorGroupBox)
- self.widget.setObjectName(u"widget")
- self.widget.setMinimumSize(QSize(300, 0))
- self.verticalLayout = QVBoxLayout(self.widget)
- self.verticalLayout.setObjectName(u"verticalLayout")
- self.verticalLayout.setContentsMargins(0, 0, 0, 0)
- self.searchLineEdit = QLineEdit(self.widget)
- self.searchLineEdit.setObjectName(u"searchLineEdit")
- self.searchLineEdit.setFrame(True)
- self.searchLineEdit.setClearButtonEnabled(True)
-
- self.verticalLayout.addWidget(self.searchLineEdit)
-
- self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
-
- self.verticalLayout.addItem(self.verticalSpacer)
-
- self.packComboBox = QComboBox(self.widget)
- self.packComboBox.setObjectName(u"packComboBox")
-
- self.verticalLayout.addWidget(self.packComboBox)
-
- self.songIdComboBox = QComboBox(self.widget)
- self.songIdComboBox.setObjectName(u"songIdComboBox")
-
- self.verticalLayout.addWidget(self.songIdComboBox)
-
-
- self.verticalLayout_3.addWidget(self.widget)
+ self.verticalLayout_3.addWidget(self.songIdSelector)
self.mainVerticalLayout.addWidget(self.songIdSelectorGroupBox)
@@ -137,12 +82,6 @@ class Ui_ChartSelector(object):
def retranslateUi(self, ChartSelector):
self.songIdSelectorGroupBox.setTitle(QCoreApplication.translate("ChartSelector", u"songIdSelector.title", None))
- self.songIdSelectorQuickActionsGroupBox.setTitle(QCoreApplication.translate("ChartSelector", u"songIdSelector.quickActions", None))
- self.nextPackageButton.setText(QCoreApplication.translate("ChartSelector", u"songIdSelector.quickActions.nextPackageButton", None))
- self.nextSongIdButton.setText(QCoreApplication.translate("ChartSelector", u"songIdSelector.quickActions.nextSongIdButton", None))
- self.previousSongIdButton.setText(QCoreApplication.translate("ChartSelector", u"songIdSelector.quickActions.previousSongIdButton", None))
- self.previousPackageButton.setText(QCoreApplication.translate("ChartSelector", u"songIdSelector.quickActions.previousPackageButton", None))
- self.searchLineEdit.setPlaceholderText(QCoreApplication.translate("ChartSelector", u"search.lineEdit.placeholder", None))
self.resetButton.setText(QCoreApplication.translate("ChartSelector", u"resetButton", None))
pass
# retranslateUi
diff --git a/ui/designer/components/songIdSelector.ui b/ui/designer/components/songIdSelector.ui
new file mode 100644
index 0000000..4b6022f
--- /dev/null
+++ b/ui/designer/components/songIdSelector.ui
@@ -0,0 +1,114 @@
+
+
+ SongIdSelector
+
+
+
+ 0
+ 0
+ 470
+ 350
+
+
+
+ SongIdSelector
+
+
+ -
+
+
+ songIdSelector.quickActions
+
+
+
-
+
+
+
+ 100
+ 0
+
+
+
+ songIdSelector.quickActions.nextPackageButton
+
+
+
+ -
+
+
+
+ 100
+ 0
+
+
+
+ songIdSelector.quickActions.nextSongIdButton
+
+
+
+ -
+
+
+
+ 100
+ 0
+
+
+
+ songIdSelector.quickActions.previousSongIdButton
+
+
+
+ -
+
+
+
+ 100
+ 0
+
+
+
+ songIdSelector.quickActions.previousPackageButton
+
+
+
+
+
+
+ -
+
+
+ true
+
+
+ search.lineEdit.placeholder
+
+
+ true
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
+
+
diff --git a/ui/designer/components/songIdSelector_ui.py b/ui/designer/components/songIdSelector_ui.py
new file mode 100644
index 0000000..6f978cc
--- /dev/null
+++ b/ui/designer/components/songIdSelector_ui.py
@@ -0,0 +1,97 @@
+# -*- coding: utf-8 -*-
+
+################################################################################
+## Form generated from reading UI file 'songIdSelector.ui'
+##
+## Created by: Qt User Interface Compiler version 6.5.2
+##
+## WARNING! All changes made in this file will be lost when recompiling UI file!
+################################################################################
+
+from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
+ QMetaObject, QObject, QPoint, QRect,
+ QSize, QTime, QUrl, Qt)
+from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
+ QFont, QFontDatabase, QGradient, QIcon,
+ QImage, QKeySequence, QLinearGradient, QPainter,
+ QPalette, QPixmap, QRadialGradient, QTransform)
+from PySide6.QtWidgets import (QApplication, QComboBox, QGroupBox, QHBoxLayout,
+ QLineEdit, QPushButton, QSizePolicy, QSpacerItem,
+ QVBoxLayout, QWidget)
+
+class Ui_SongIdSelector(object):
+ def setupUi(self, SongIdSelector):
+ if not SongIdSelector.objectName():
+ SongIdSelector.setObjectName(u"SongIdSelector")
+ SongIdSelector.resize(470, 350)
+ SongIdSelector.setWindowTitle(u"SongIdSelector")
+ self.verticalLayout_2 = QVBoxLayout(SongIdSelector)
+ self.verticalLayout_2.setObjectName(u"verticalLayout_2")
+ self.songIdSelectorQuickActionsGroupBox = QGroupBox(SongIdSelector)
+ self.songIdSelectorQuickActionsGroupBox.setObjectName(u"songIdSelectorQuickActionsGroupBox")
+ self.horizontalLayout = QHBoxLayout(self.songIdSelectorQuickActionsGroupBox)
+ self.horizontalLayout.setObjectName(u"horizontalLayout")
+ self.nextPackageButton = QPushButton(self.songIdSelectorQuickActionsGroupBox)
+ self.nextPackageButton.setObjectName(u"nextPackageButton")
+ self.nextPackageButton.setMinimumSize(QSize(100, 0))
+
+ self.horizontalLayout.addWidget(self.nextPackageButton)
+
+ self.nextSongIdButton = QPushButton(self.songIdSelectorQuickActionsGroupBox)
+ self.nextSongIdButton.setObjectName(u"nextSongIdButton")
+ self.nextSongIdButton.setMinimumSize(QSize(100, 0))
+
+ self.horizontalLayout.addWidget(self.nextSongIdButton)
+
+ self.previousSongIdButton = QPushButton(self.songIdSelectorQuickActionsGroupBox)
+ self.previousSongIdButton.setObjectName(u"previousSongIdButton")
+ self.previousSongIdButton.setMinimumSize(QSize(100, 0))
+
+ self.horizontalLayout.addWidget(self.previousSongIdButton)
+
+ self.previousPackageButton = QPushButton(self.songIdSelectorQuickActionsGroupBox)
+ self.previousPackageButton.setObjectName(u"previousPackageButton")
+ self.previousPackageButton.setMinimumSize(QSize(100, 0))
+
+ self.horizontalLayout.addWidget(self.previousPackageButton)
+
+
+ self.verticalLayout_2.addWidget(self.songIdSelectorQuickActionsGroupBox)
+
+ self.searchLineEdit = QLineEdit(SongIdSelector)
+ self.searchLineEdit.setObjectName(u"searchLineEdit")
+ self.searchLineEdit.setFrame(True)
+ self.searchLineEdit.setClearButtonEnabled(True)
+
+ self.verticalLayout_2.addWidget(self.searchLineEdit)
+
+ self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
+
+ self.verticalLayout_2.addItem(self.verticalSpacer)
+
+ self.packComboBox = QComboBox(SongIdSelector)
+ self.packComboBox.setObjectName(u"packComboBox")
+
+ self.verticalLayout_2.addWidget(self.packComboBox)
+
+ self.songIdComboBox = QComboBox(SongIdSelector)
+ self.songIdComboBox.setObjectName(u"songIdComboBox")
+
+ self.verticalLayout_2.addWidget(self.songIdComboBox)
+
+
+ self.retranslateUi(SongIdSelector)
+
+ QMetaObject.connectSlotsByName(SongIdSelector)
+ # setupUi
+
+ def retranslateUi(self, SongIdSelector):
+ self.songIdSelectorQuickActionsGroupBox.setTitle(QCoreApplication.translate("SongIdSelector", u"songIdSelector.quickActions", None))
+ self.nextPackageButton.setText(QCoreApplication.translate("SongIdSelector", u"songIdSelector.quickActions.nextPackageButton", None))
+ self.nextSongIdButton.setText(QCoreApplication.translate("SongIdSelector", u"songIdSelector.quickActions.nextSongIdButton", None))
+ self.previousSongIdButton.setText(QCoreApplication.translate("SongIdSelector", u"songIdSelector.quickActions.previousSongIdButton", None))
+ self.previousPackageButton.setText(QCoreApplication.translate("SongIdSelector", u"songIdSelector.quickActions.previousPackageButton", None))
+ self.searchLineEdit.setPlaceholderText(QCoreApplication.translate("SongIdSelector", u"search.lineEdit.placeholder", None))
+ pass
+ # retranslateUi
+
diff --git a/ui/extends/components/chartSelector.py b/ui/extends/components/songIdSelector.py
similarity index 100%
rename from ui/extends/components/chartSelector.py
rename to ui/extends/components/songIdSelector.py
diff --git a/ui/implements/components/chartSelector.py b/ui/implements/components/chartSelector.py
index b1fe55e..7618ae0 100644
--- a/ui/implements/components/chartSelector.py
+++ b/ui/implements/components/chartSelector.py
@@ -1,17 +1,13 @@
import logging
-import re
-from typing import Literal
from arcaea_offline.database import Database
from arcaea_offline.models import Chart
from arcaea_offline.utils.rating import rating_class_to_text
-from PySide6.QtCore import QModelIndex, Qt, Signal, Slot
+from PySide6.QtCore import Signal, Slot
from PySide6.QtGui import QShowEvent
-from PySide6.QtWidgets import QCompleter, QWidget
+from PySide6.QtWidgets import QWidget
from ui.designer.components.chartSelector_ui import Ui_ChartSelector
-from ui.extends.components.chartSelector import SearchCompleterModel
-from ui.extends.shared.delegates.descriptionDelegate import DescriptionDelegate
logger = logging.getLogger(__name__)
@@ -24,89 +20,24 @@ class ChartSelector(Ui_ChartSelector, QWidget):
self.db = Database()
self.setupUi(self)
- self.previousPackageButton.clicked.connect(
- lambda: self.quickSwitchSelection("previous", "package")
- )
- self.previousSongIdButton.clicked.connect(
- lambda: self.quickSwitchSelection("previous", "songId")
- )
- self.nextSongIdButton.clicked.connect(
- lambda: self.quickSwitchSelection("next", "songId")
- )
- self.nextPackageButton.clicked.connect(
- lambda: self.quickSwitchSelection("next", "package")
- )
-
self.valueChanged.connect(self.updateResultLabel)
+ self.songIdSelector.valueChanged.connect(self.updateRatingClassEnabled)
- self.fillPackComboBox()
- self.packComboBox.setCurrentIndex(-1)
- self.songIdComboBox.setCurrentIndex(-1)
-
- self.searchCompleterModel = SearchCompleterModel()
- self.searchCompleter = QCompleter(self.searchCompleterModel)
- self.searchCompleter.popup().setItemDelegate(
- DescriptionDelegate(self.searchCompleter.popup())
- )
- self.searchCompleter.activated[QModelIndex].connect(
- self.searchCompleterSetSelection
- )
- self.searchLineEdit.setCompleter(self.searchCompleter)
-
- self.packComboBox.setItemDelegate(DescriptionDelegate(self.packComboBox))
- self.songIdComboBox.setItemDelegate(DescriptionDelegate(self.songIdComboBox))
-
+ self.songIdSelector.valueChanged.connect(self.valueChanged)
self.ratingClassSelector.valueChanged.connect(self.valueChanged)
- self.packComboBox.currentIndexChanged.connect(self.valueChanged)
- self.songIdComboBox.currentIndexChanged.connect(self.valueChanged)
-
- def quickSwitchSelection(
- self,
- direction: Literal["previous", "next"],
- model: Literal["package", "songId"],
- ):
- minIndex = 0
- if model == "package":
- maxIndex = self.packComboBox.count() - 1
- currentIndex = self.packComboBox.currentIndex() + (
- 1 if direction == "next" else -1
- )
- currentIndex = max(min(maxIndex, currentIndex), minIndex)
- self.packComboBox.setCurrentIndex(currentIndex)
- elif model == "songId":
- maxIndex = self.songIdComboBox.count() - 1
- currentIndex = self.songIdComboBox.currentIndex() + (
- 1 if direction == "next" else -1
- )
- currentIndex = max(min(maxIndex, currentIndex), minIndex)
- self.songIdComboBox.setCurrentIndex(currentIndex)
- else:
- return
def value(self):
- packId = self.packComboBox.currentData()
- songId = self.songIdComboBox.currentData()
+ songId = self.songIdSelector.value()
ratingClass = self.ratingClassSelector.value()
- if packId and songId and isinstance(ratingClass, int):
+ if songId and isinstance(ratingClass, int):
return self.db.get_chart(songId, ratingClass)
return None
def showEvent(self, event: QShowEvent):
- # update database results when widget visible
- self.searchCompleterModel.updateSearcherSongs()
-
# remember selection and restore later
- pack = self.packComboBox.currentData()
- songId = self.songIdComboBox.currentData()
ratingClass = self.ratingClassSelector.value()
- self.fillPackComboBox()
-
- if pack:
- self.selectPack(pack)
- if songId:
- self.selectSongId(songId)
if ratingClass is not None:
self.ratingClassSelector.select(ratingClass)
return super().showEvent(event)
@@ -132,106 +63,22 @@ class ChartSelector(Ui_ChartSelector, QWidget):
else:
self.resultLabel.setText("...")
- def fillPackComboBox(self):
- self.packComboBox.clear()
- packs = self.db.get_packs()
- for pack in packs:
- isAppendPack = re.search(r"_append_.*$", pack.id)
- if isAppendPack:
- basePackId = re.sub(r"_append_.*$", "", pack.id)
- basePackName = self.db.get_pack_by_id(basePackId).name
- packName = f"{basePackName} - {pack.name}"
- else:
- packName = pack.name
- self.packComboBox.addItem(f"{packName} ({pack.id})", pack.id)
- row = self.packComboBox.count() - 1
- self.packComboBox.setItemData(
- row, packName, DescriptionDelegate.MainTextRole
- )
- self.packComboBox.setItemData(
- row, pack.id, DescriptionDelegate.DescriptionTextRole
- )
-
- self.packComboBox.setCurrentIndex(-1)
-
- def fillSongIdComboBox(self):
- self.songIdComboBox.clear()
- packId = self.packComboBox.currentData()
- if packId:
- charts = self.db.get_charts_by_pack_id(packId)
- inserted_song_ids = []
- for chart in charts:
- if chart.song_id not in inserted_song_ids:
- self.songIdComboBox.addItem(
- f"{chart.title} ({chart.song_id})", chart.song_id
- )
- inserted_song_ids.append(chart.song_id)
- row = self.songIdComboBox.count() - 1
- self.songIdComboBox.setItemData(
- row, chart.title, DescriptionDelegate.MainTextRole
- )
- self.songIdComboBox.setItemData(
- row, chart.song_id, DescriptionDelegate.DescriptionTextRole
- )
- self.songIdComboBox.setCurrentIndex(-1)
-
- @Slot()
- def on_packComboBox_activated(self):
- self.fillSongIdComboBox()
-
- @Slot(int)
- def on_songIdComboBox_currentIndexChanged(self, index: int):
+ def updateRatingClassEnabled(self):
ratingClasses = []
- if index > -1:
- charts = self.db.get_charts_by_song_id(self.songIdComboBox.currentData())
+ songId = self.songIdSelector.value()
+ if songId:
+ charts = self.db.get_charts_by_song_id(songId)
ratingClasses = [chart.rating_class for chart in charts]
self.ratingClassSelector.setButtonsEnabled(ratingClasses)
@Slot()
def on_resetButton_clicked(self):
- self.packComboBox.setCurrentIndex(-1)
- self.songIdComboBox.setCurrentIndex(-1)
-
- @Slot(str)
- def on_searchLineEdit_textChanged(self, text: str):
- if text:
- self.searchCompleterModel.getSearchResult(text)
- else:
- self.searchCompleterModel.clear()
-
- def selectPack(self, packId: str) -> bool:
- packIdIndex = self.packComboBox.findData(packId)
- if packIdIndex > -1:
- self.packComboBox.setCurrentIndex(packIdIndex)
- self.fillSongIdComboBox()
- return True
- else:
- logger.warning(f'Attempting to select an unknown pack "{packId}"')
- return False
-
- def selectSongId(self, songId: str) -> bool:
- songIdIndex = self.songIdComboBox.findData(songId)
- if songIdIndex > -1:
- self.songIdComboBox.setCurrentIndex(songIdIndex)
- return True
- else:
- logger.warning(
- f'Attempting to select an unknown song "{songId}", maybe try selecting a pack first?'
- )
- return False
+ self.songIdSelector.reset()
def selectChart(self, chart: Chart):
- if not self.selectPack(chart.set):
+ if not self.songIdSelector.selectPack(chart.set):
return False
- if not self.selectSongId(chart.song_id):
+ if not self.songIdSelector.selectSongId(chart.song_id):
return False
self.ratingClassSelector.select(chart.rating_class)
return True
-
- @Slot(QModelIndex)
- def searchCompleterSetSelection(self, index: QModelIndex):
- chart = index.data(Qt.ItemDataRole.UserRole + 10) # type: Chart
- self.selectChart(chart)
-
- self.searchLineEdit.clear()
- self.searchLineEdit.clearFocus()
diff --git a/ui/implements/components/songIdSelector.py b/ui/implements/components/songIdSelector.py
new file mode 100644
index 0000000..6b88f0f
--- /dev/null
+++ b/ui/implements/components/songIdSelector.py
@@ -0,0 +1,191 @@
+import logging
+import re
+from typing import Literal
+
+from arcaea_offline.database import Database
+from arcaea_offline.models import Chart
+from PySide6.QtCore import QModelIndex, Qt, Signal, Slot
+from PySide6.QtGui import QShowEvent
+from PySide6.QtWidgets import QCompleter, QWidget
+
+from ui.designer.components.songIdSelector_ui import Ui_SongIdSelector
+from ui.extends.components.songIdSelector import SearchCompleterModel
+from ui.extends.shared.delegates.descriptionDelegate import DescriptionDelegate
+
+logger = logging.getLogger(__name__)
+
+
+class SongIdSelector(Ui_SongIdSelector, QWidget):
+ valueChanged = Signal()
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.db = Database()
+ self.setupUi(self)
+
+ self.previousPackageButton.clicked.connect(
+ lambda: self.quickSwitchSelection("previous", "package")
+ )
+ self.previousSongIdButton.clicked.connect(
+ lambda: self.quickSwitchSelection("previous", "songId")
+ )
+ self.nextSongIdButton.clicked.connect(
+ lambda: self.quickSwitchSelection("next", "songId")
+ )
+ self.nextPackageButton.clicked.connect(
+ lambda: self.quickSwitchSelection("next", "package")
+ )
+
+ self.fillPackComboBox()
+ self.packComboBox.setCurrentIndex(-1)
+ self.songIdComboBox.setCurrentIndex(-1)
+
+ self.searchCompleterModel = SearchCompleterModel()
+ self.searchCompleter = QCompleter(self.searchCompleterModel)
+ self.searchCompleter.popup().setItemDelegate(
+ DescriptionDelegate(self.searchCompleter.popup())
+ )
+ self.searchCompleter.activated[QModelIndex].connect(
+ self.searchCompleterSetSelection
+ )
+ self.searchLineEdit.setCompleter(self.searchCompleter)
+
+ self.packComboBox.setItemDelegate(DescriptionDelegate(self.packComboBox))
+ self.songIdComboBox.setItemDelegate(DescriptionDelegate(self.songIdComboBox))
+
+ self.packComboBox.currentIndexChanged.connect(self.valueChanged)
+ self.songIdComboBox.currentIndexChanged.connect(self.valueChanged)
+
+ def quickSwitchSelection(
+ self,
+ direction: Literal["previous", "next"],
+ model: Literal["package", "songId"],
+ ):
+ minIndex = 0
+ if model == "package":
+ maxIndex = self.packComboBox.count() - 1
+ currentIndex = self.packComboBox.currentIndex() + (
+ 1 if direction == "next" else -1
+ )
+ currentIndex = max(min(maxIndex, currentIndex), minIndex)
+ self.packComboBox.setCurrentIndex(currentIndex)
+ elif model == "songId":
+ maxIndex = self.songIdComboBox.count() - 1
+ currentIndex = self.songIdComboBox.currentIndex() + (
+ 1 if direction == "next" else -1
+ )
+ currentIndex = max(min(maxIndex, currentIndex), minIndex)
+ self.songIdComboBox.setCurrentIndex(currentIndex)
+ else:
+ return
+
+ def value(self):
+ return self.songIdComboBox.currentData()
+
+ def reset(self):
+ self.packComboBox.setCurrentIndex(-1)
+ self.songIdComboBox.setCurrentIndex(-1)
+
+ def showEvent(self, event: QShowEvent):
+ # update database results when widget visible
+ self.searchCompleterModel.updateSearcherSongs()
+
+ # remember selection and restore later
+ pack = self.packComboBox.currentData()
+ songId = self.songIdComboBox.currentData()
+
+ self.fillPackComboBox()
+
+ if pack:
+ self.selectPack(pack)
+ if songId:
+ self.selectSongId(songId)
+ return super().showEvent(event)
+
+ def fillPackComboBox(self):
+ self.packComboBox.clear()
+ packs = self.db.get_packs()
+ for pack in packs:
+ isAppendPack = re.search(r"_append_.*$", pack.id)
+ if isAppendPack:
+ basePackId = re.sub(r"_append_.*$", "", pack.id)
+ basePackName = self.db.get_pack_by_id(basePackId).name
+ packName = f"{basePackName} - {pack.name}"
+ else:
+ packName = pack.name
+ self.packComboBox.addItem(f"{packName} ({pack.id})", pack.id)
+ row = self.packComboBox.count() - 1
+ self.packComboBox.setItemData(
+ row, packName, DescriptionDelegate.MainTextRole
+ )
+ self.packComboBox.setItemData(
+ row, pack.id, DescriptionDelegate.DescriptionTextRole
+ )
+
+ self.packComboBox.setCurrentIndex(-1)
+
+ def fillSongIdComboBox(self):
+ self.songIdComboBox.clear()
+ packId = self.packComboBox.currentData()
+ if packId:
+ charts = self.db.get_charts_by_pack_id(packId)
+ inserted_song_ids = []
+ for chart in charts:
+ if chart.song_id not in inserted_song_ids:
+ self.songIdComboBox.addItem(
+ f"{chart.title} ({chart.song_id})", chart.song_id
+ )
+ inserted_song_ids.append(chart.song_id)
+ row = self.songIdComboBox.count() - 1
+ self.songIdComboBox.setItemData(
+ row, chart.title, DescriptionDelegate.MainTextRole
+ )
+ self.songIdComboBox.setItemData(
+ row, chart.song_id, DescriptionDelegate.DescriptionTextRole
+ )
+ self.songIdComboBox.setCurrentIndex(-1)
+
+ @Slot()
+ def on_packComboBox_activated(self):
+ self.fillSongIdComboBox()
+
+ @Slot(str)
+ def on_searchLineEdit_textChanged(self, text: str):
+ if text:
+ self.searchCompleterModel.getSearchResult(text)
+ else:
+ self.searchCompleterModel.clear()
+
+ def selectPack(self, packId: str) -> bool:
+ packIdIndex = self.packComboBox.findData(packId)
+ if packIdIndex > -1:
+ self.packComboBox.setCurrentIndex(packIdIndex)
+ self.fillSongIdComboBox()
+ return True
+ else:
+ logger.warning(f'Attempting to select an unknown pack "{packId}"')
+ return False
+
+ def selectSongId(self, songId: str) -> bool:
+ songIdIndex = self.songIdComboBox.findData(songId)
+ if songIdIndex > -1:
+ self.songIdComboBox.setCurrentIndex(songIdIndex)
+ return True
+ else:
+ logger.warning(
+ f'Attempting to select an unknown song "{songId}", maybe try selecting a pack first?'
+ )
+ return False
+
+ def selectChart(self, chart: Chart):
+ if not self.selectPack(chart.set):
+ return False
+ return self.selectSongId(chart.song_id)
+
+ @Slot(QModelIndex)
+ def searchCompleterSetSelection(self, index: QModelIndex):
+ chart = index.data(Qt.ItemDataRole.UserRole + 10) # type: Chart
+ self.selectChart(chart)
+
+ self.searchLineEdit.clear()
+ self.searchLineEdit.clearFocus()