feat: TabTools_Andreal

This commit is contained in:
2023-09-21 23:02:02 +08:00
parent 44915f6d19
commit d29104744d
6 changed files with 514 additions and 283 deletions

View File

@ -7,10 +7,18 @@ from arcaea_offline.external.andreal.api_data import (
AndrealImageGeneratorApiDataConverter,
)
from arcaea_offline.models import Chart
from arcaea_offline.utils.rating import rating_class_to_short_text
from PySide6.QtCore import QDir, QFileInfo, Qt, Slot
from PySide6.QtGui import QImage
from PySide6.QtWidgets import QButtonGroup, QFileDialog, QLabel, QMessageBox, QWidget
from PySide6.QtCore import QCoreApplication, QDir, QFileInfo, Qt, Slot
from PySide6.QtGui import QGuiApplication, QImage, QPainter, QPaintEvent, QPixmap
from PySide6.QtWidgets import (
QButtonGroup,
QDialog,
QDialogButtonBox,
QFileDialog,
QLabel,
QMessageBox,
QVBoxLayout,
QWidget,
)
from ui.designer.tabs.tabTools.tabTools_Andreal_ui import Ui_TabTools_Andreal
from ui.extends.shared.settings import ANDREAL_EXECUTABLE, ANDREAL_FOLDER
@ -22,7 +30,36 @@ logger = logging.getLogger(__name__)
class PreviewLabel(QLabel):
...
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowFlag(Qt.WindowType.Window, True)
def show(self):
super().show()
# center the window
width = self.width()
height = self.height()
screen = QGuiApplication.primaryScreen()
screenWidth = screen.size().width()
screenHeight = screen.size().height()
self.setGeometry(
max(0, screenWidth / 2 - width / 2),
max(0, screenHeight / 2 - height / 2),
min(width, screenWidth),
min(height, screenHeight),
)
def paintEvent(self, e: QPaintEvent) -> None:
size = self.size()
painter = QPainter(self)
scaledPixmap = self.pixmap().scaled(
size,
Qt.AspectRatioMode.KeepAspectRatio,
Qt.TransformationMode.SmoothTransformation,
)
x = (size.width() - scaledPixmap.width()) / 2
y = (size.height() - scaledPixmap.height()) / 2
painter.drawPixmap(x, y, scaledPixmap)
class ChartSelectorDialog(ChartSelector):
@ -32,6 +69,27 @@ class ChartSelectorDialog(ChartSelector):
self.setSongIdSelectorMode(SongIdSelectorMode.Chart)
class ImageTypeWhatIsThisDialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.verticalLayout = QVBoxLayout(self)
self.label = QLabel(
# fmt: off
QCoreApplication.translate('TabTools_Andreal', 'imageWhatIsThisDialog.description')
# fmt: on
)
self.verticalLayout.addWidget(self.label)
self.buttonBox = QDialogButtonBox(Qt.Orientation.Horizontal)
self.buttonBox.addButton(QDialogButtonBox.StandardButton.Ok)
self.buttonBox.accepted.connect(self.close)
self.buttonBox.rejected.connect(self.close)
self.verticalLayout.addWidget(self.buttonBox)
class TabTools_Andreal(Ui_TabTools_Andreal, QWidget):
def __init__(self, parent=None):
super().__init__(parent)
@ -51,6 +109,7 @@ class TabTools_Andreal(Ui_TabTools_Andreal, QWidget):
self.andrealFolderSelector.connectSettings(ANDREAL_FOLDER)
self.andrealExecutableSelector.connectSettings(ANDREAL_EXECUTABLE)
self.generatePreviewButton.clicked.connect(self.requestPreview)
self.generateImageButton.clicked.connect(self.requestGenerate)
self.infoChart: Chart | None = None
@ -59,10 +118,17 @@ class TabTools_Andreal(Ui_TabTools_Andreal, QWidget):
self.generateJsonPath = None
self.generateImageFormat = None
self.andrealHelper.error.connect(self.previewError)
self.andrealHelper.ready.connect(self.previewReady)
self.andrealHelper.finished.connect(self.previewFinished)
self.andrealHelper.error.connect(self.generateError)
self.andrealHelper.ready.connect(self.generateReady)
self.andrealHelper.finished.connect(self.generateFinished)
self.imageTypeWhatIsThisButton.clicked.connect(
lambda: ImageTypeWhatIsThisDialog(self).show()
)
self.imageTypeButtonGroup = QButtonGroup(self)
self.imageTypeButtonGroup.addButton(self.imageType_infoRadioButton, 0)
self.imageTypeButtonGroup.addButton(self.imageType_bestRadioButton, 1)
@ -75,12 +141,24 @@ class TabTools_Andreal(Ui_TabTools_Andreal, QWidget):
self.imageTypeButtonGroup.idToggled.connect(self.fillImageVersionComboBox)
self.fillImageVersionComboBox()
self.chartSelectorDialog = ChartSelectorDialog(self)
self.chartSelectorDialog.valueChanged.connect(self.chartValueUpdated)
self.chartSelectButton.clicked.connect(self.chartSelectorDialog.show)
def setHelperPaths(self):
if selectedFiles := self.andrealFolderSelector.selectedFiles():
self.andrealHelper.andrealFolder = selectedFiles[0]
if selectedFiles := self.andrealExecutableSelector.selectedFiles():
self.andrealHelper.andrealExecutable = selectedFiles[0]
def chartValueUpdated(self):
chart = self.chartSelectorDialog.value()
self.infoChart = chart
if chart:
self.chartSelectLabel.setText(
f"{chart.title}({chart.song_id}), {chart.rating_class}"
)
def imageFormat(self):
buttonId = self.imageFormatButtonGroup.checkedId()
return ["jpg", "png"][buttonId] if buttonId > -1 else None
@ -146,17 +224,23 @@ class TabTools_Andreal(Ui_TabTools_Andreal, QWidget):
return
jsonContentDict = {}
with self.db.sessionmaker() as session:
converter = AndrealImageGeneratorApiDataConverter(session)
if imageType == "info":
jsonContentDict = converter.user_info()
elif imageType == "best":
jsonContentDict = converter.user_best(
self.infoChart.song_id, self.infoChart.rating_class
)
elif imageType == "best30":
jsonContentDict = converter.user_best30()
return json.dumps(jsonContentDict, ensure_ascii=False)
try:
with self.db.sessionmaker() as session:
converter = AndrealImageGeneratorApiDataConverter(session)
if imageType == "info":
jsonContentDict = converter.user_info()
elif imageType == "best":
jsonContentDict = converter.user_best(
self.infoChart.song_id, self.infoChart.rating_class
)
elif imageType == "best30":
jsonContentDict = converter.user_best30()
except Exception as e:
logger.exception("getAndrealJsonContent error")
QMessageBox.critical(self, None, str(e))
return (
json.dumps(jsonContentDict, ensure_ascii=False) if jsonContentDict else None
)
def getAndrealJsonFileName(self):
if not self.requestComplete():
@ -167,12 +251,7 @@ class TabTools_Andreal(Ui_TabTools_Andreal, QWidget):
fileNameParts = ["andreal", imageType]
if imageType == "best":
fileNameParts.extend(
[
self.infoChart.song_id,
rating_class_to_short_text(self.infoChart.rating_class).lower(),
]
)
fileNameParts.extend([self.infoChart.song_id, self.infoChart.rating_class])
fileNameParts.append(timestamp)
fileNameParts = [str(i) for i in fileNameParts]
fileName = "-".join(fileNameParts)
@ -199,14 +278,15 @@ class TabTools_Andreal(Ui_TabTools_Andreal, QWidget):
def requestGenerate(self):
jsonPath = self.getTempAndrealJsonPath()
if not jsonPath:
jsonContent = self.getAndrealJsonContent()
if not jsonPath or not jsonContent:
return
self.generateImageButton.setEnabled(False)
self.generateJsonPath = jsonPath
self.generateImageFormat = self.imageFormat()
with open(jsonPath, "w", encoding="utf-8") as jf:
jf.write(self.getAndrealJsonContent())
jf.write(jsonContent)
self.andrealHelper.request(jsonPath, self.getAndrealArguments(jsonPath))
@ -237,3 +317,46 @@ class TabTools_Andreal(Ui_TabTools_Andreal, QWidget):
if not saveFileName:
return
qImage.save(saveFileName, self.generateImageFormat)
def requestPreview(self):
jsonPath = self.getTempAndrealJsonPath()
jsonContent = self.getAndrealJsonContent()
if not jsonPath or not jsonContent:
return
self.generatePreviewButton.setEnabled(False)
self.previewJsonPath = jsonPath
with open(jsonPath, "w", encoding="utf-8") as jf:
jf.write(jsonContent)
self.andrealHelper.request(
jsonPath, self.getAndrealArguments(jsonPath, preview=True)
)
def previewFinished(self):
self.generatePreviewButton.setEnabled(True)
def previewError(self, jsonPath: str, errorMsg: str):
if jsonPath != self.previewJsonPath:
return
QMessageBox.critical(self, "Preview Error", errorMsg)
def previewReady(self, jsonPath: str, imageBytes: bytes):
if jsonPath != self.previewJsonPath:
return
if not imageBytes:
QMessageBox.critical(self, "Preview Error", "Empty bytes received.")
return
qImage = QImage.fromData(imageBytes)
filePathParts = jsonPath.split(".")
filePathParts.pop()
filePath = ".".join(filePathParts)
fileName = QFileInfo(filePath).fileName()
previewLabel = PreviewLabel(self)
previewLabel.setPixmap(QPixmap.fromImage(qImage))
previewLabel.setWindowTitle(f"preview {fileName}")
previewLabel.show()