mirror of
https://github.com/283375/arcaea-offline-pyside-ui.git
synced 2025-07-01 12:26:26 +00:00
feat: TabTools_Andreal
This commit is contained in:
@ -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()
|
||||
|
Reference in New Issue
Block a user