wip: split SongIdSelector

This commit is contained in:
2023-09-05 02:26:22 +08:00
parent 565260d6ce
commit a886741079
7 changed files with 441 additions and 349 deletions

View File

@ -26,122 +26,20 @@
<string>songIdSelector.title</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QGroupBox" name="songIdSelectorQuickActionsGroupBox">
<property name="title">
<string>songIdSelector.quickActions</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="nextPackageButton">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>songIdSelector.quickActions.nextPackageButton</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="nextSongIdButton">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>songIdSelector.quickActions.nextSongIdButton</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="previousSongIdButton">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>songIdSelector.quickActions.previousSongIdButton</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="previousPackageButton">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>songIdSelector.quickActions.previousPackageButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widget" native="true">
<property name="minimumSize">
<size>
<width>300</width>
<height>0</height>
</size>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="searchLineEdit">
<property name="frame">
<bool>true</bool>
</property>
<property name="placeholderText">
<string>search.lineEdit.placeholder</string>
</property>
<property name="clearButtonEnabled">
<bool>true</bool>
</property>
</widget>
</item>
<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>
<widget class="QComboBox" name="packComboBox"/>
</item>
<item>
<widget class="QComboBox" name="songIdComboBox"/>
</item>
</layout>
</widget>
<widget class="SongIdSelector" name="songIdSelector" native="true"/>
</item>
</layout>
</widget>
@ -185,6 +83,12 @@
<header>ui.implements.components.ratingClassSelector</header>
<container>1</container>
</customwidget>
<customwidget>
<class>SongIdSelector</class>
<extends>QWidget</extends>
<header>ui.implements.components.songIdSelector</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>

View File

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

View File

@ -0,0 +1,114 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SongIdSelector</class>
<widget class="QWidget" name="SongIdSelector">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>470</width>
<height>350</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">SongIdSelector</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QGroupBox" name="songIdSelectorQuickActionsGroupBox">
<property name="title">
<string>songIdSelector.quickActions</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="nextPackageButton">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>songIdSelector.quickActions.nextPackageButton</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="nextSongIdButton">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>songIdSelector.quickActions.nextSongIdButton</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="previousSongIdButton">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>songIdSelector.quickActions.previousSongIdButton</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="previousPackageButton">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>songIdSelector.quickActions.previousPackageButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QLineEdit" name="searchLineEdit">
<property name="frame">
<bool>true</bool>
</property>
<property name="placeholderText">
<string>search.lineEdit.placeholder</string>
</property>
<property name="clearButtonEnabled">
<bool>true</bool>
</property>
</widget>
</item>
<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>
<widget class="QComboBox" name="packComboBox"/>
</item>
<item>
<widget class="QComboBox" name="songIdComboBox"/>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

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

View File

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

View File

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