From a9941e9c87a305ede70eab56d5e4b5793d9e727c Mon Sep 17 00:00:00 2001 From: 283375 Date: Sun, 27 Aug 2023 23:38:17 +0800 Subject: [PATCH] refactor: DatabaseChecker --- ui/startup/databaseChecker.py | 140 +++++++++++++++--------- ui/startup/databaseChecker.ui | 99 +++++++++++------ ui/startup/databaseChecker_ui.py | 178 ++++++++++++++----------------- 3 files changed, 232 insertions(+), 185 deletions(-) diff --git a/ui/startup/databaseChecker.py b/ui/startup/databaseChecker.py index 73d70ea..c86f226 100644 --- a/ui/startup/databaseChecker.py +++ b/ui/startup/databaseChecker.py @@ -1,13 +1,18 @@ +import logging import traceback +from typing import Literal, Optional, Union from arcaea_offline.database import Database -from PySide6.QtCore import QDir, QFile, Qt, QTimer, Slot +from PySide6.QtCore import QCoreApplication, QDir, QFileInfo, Qt, QTimer, QUrl, Slot from PySide6.QtWidgets import QDialog, QMessageBox +from ui.extends.shared.database import create_engine from ui.extends.shared.settings import Settings from .databaseChecker_ui import Ui_DatabaseChecker +logger = logging.getLogger(__name__) + class DatabaseChecker(Ui_DatabaseChecker, QDialog): def __init__(self, parent=None): @@ -16,67 +21,98 @@ class DatabaseChecker(Ui_DatabaseChecker, QDialog): self.setWindowFlag(Qt.WindowType.WindowMinimizeButtonHint, False) self.setWindowFlag(Qt.WindowType.WindowMaximizeButtonHint, False) self.setWindowFlag(Qt.WindowType.WindowCloseButtonHint, True) - self.dbFileSelector.setMode(self.dbFileSelector.getExistingDirectory) - self.dbFileSelector.filesSelected.connect(self.fileSelected) + self.dbDirSelector.setMode(self.dbDirSelector.getExistingDirectory) + self.confirmDbByExistingSettings = False self.settings = Settings(self) - dbDir = self.settings.value("Default/DbDir", None, str) - if dbDir and QFile(QDir(dbDir).filePath(Database.dbFilename)).exists(): - self.dbFileSelector.selectFile(dbDir) - result = self.checkDbVersion() - if result: - QTimer.singleShot(50, self.accept) + dbUrlString = self.settings.databaseUrl() + + if dbUrlString: + dbFileUrl = QUrl(dbUrlString.replace("sqlite://", "file://")) + dbFileInfo = QFileInfo(dbFileUrl.toLocalFile()) + if dbFileInfo.exists(): + self.dbDirSelector.selectFile(dbFileInfo.path()) + self.dbFilenameLineEdit.setText(dbFileInfo.fileName()) + self.confirmDbByExistingSettings = True + self.confirmDbPathButton.click() + else: + self.dbDirSelector.selectFile(QDir.currentPath()) + self.dbFilenameLineEdit.setText("arcaea_offline.db") else: - self.dbFileSelector.selectFile(QDir.currentPath()) + self.dbDirSelector.selectFile(QDir.currentPath()) + self.dbFilenameLineEdit.setText("arcaea_offline.db") - def fileSelected(self): - self.checkDbVersion() - - def checkDbVersion(self) -> str | None: - dbQDir = QDir(self.dbFileSelector.selectedFiles()[0]) - dbDir = dbQDir.absolutePath() - - dbDir = self.dbFileSelector.selectedFiles()[0] - dbQFile = QFile(QDir(dbDir).filePath(Database.dbFilename)) - if not dbQFile.exists(): - result = QMessageBox.question(self, "Database", "Create database file now?") - if result != QMessageBox.StandardButton.Yes: - return - dbQFile.open(QFile.OpenModeFlag.WriteOnly) - dbQFile.close() - - Database.dbDir = dbDir - - try: - with Database().conn as conn: - version = conn.execute( - "SELECT value FROM properties WHERE key = 'db_version'" - ).fetchone()[0] - self.dbVersionLabel.setText(version) - self.continueButton.setEnabled(True) + def updateLabels( + self, + version: Union[Optional[int], Literal["reset"]], + init_status: Union[Optional[bool], Literal["reset"]], + ): + if version is not None: + self.dbVersionLabel.setText(str(version)) + elif version == "reset": + self.dbVersionLabel.setText("-") + if init_status is not None: + if init_status: self.dbCheckConnLabel.setText('OK') - self.settings.setValue("Default/DbDir", dbDir) - return version - except Exception as e: - QMessageBox.critical( - self, "Database Error", "\n".join(traceback.format_exception(e)) - ) - self.dbInitButton.setEnabled(True) + self.continueButton.setEnabled(True) + else: + self.dbCheckConnLabel.setText('Error') + self.continueButton.setEnabled(False) + elif init_status == "reset": + self.dbCheckConnLabel.setText("-") self.continueButton.setEnabled(False) - self.dbCheckConnLabel.setText('Error') - return False @Slot() - def on_dbInitButton_clicked(self): - try: - Database().init() - except Exception as e: - QMessageBox.critical( - self, "Database Error", "\n".join(traceback.format_exception(e)) + def on_confirmDbPathButton_clicked(self): + dbPath = QDir(self.dbDirSelector.selectedFiles()[0]) + dbFileInfo = QFileInfo( + QDir.cleanPath(dbPath.absoluteFilePath(self.dbFilenameLineEdit.text())) + ) + dbFileUrl = QUrl.fromLocalFile(dbFileInfo.filePath()) + # dbSqliteUrl.setScheme("sqlite") + dbSqliteUrl = QUrl(dbFileUrl.toString().replace("file://", "sqlite://")) + if not dbFileInfo.exists(): + confirm_new_database = QMessageBox.question( + self, + None, + # fmt: off + QCoreApplication.translate("DatabaseChecker", "dialog.confirmNewDatabase"), + # fmt: on ) - finally: - self.checkDbVersion() + if confirm_new_database == QMessageBox.StandardButton.Yes: + db = Database(create_engine(dbSqliteUrl)) + db.init() + self.on_confirmDbPathButton_clicked() + else: + db = Database(create_engine(dbSqliteUrl)) + if db.check_init(): + self.updateLabels(db.version(), True) + if self.confirmDbByExistingSettings: + QTimer.singleShot(25, self.accept) + else: + self.settings.setDatabaseUrl(dbSqliteUrl.toString()) + else: + confirm_try_init = QMessageBox.question( + self, + None, + # fmt: off + QCoreApplication.translate("DatabaseChecker", "dialog.tryInit"), + # fmt: on + ) + if confirm_try_init == QMessageBox.StandardButton.Yes: + try: + db.init(checkfirst=True) + except Exception as e: + logger.exception( + "Error while initializing an existing database" + ) + QMessageBox.critical( + self, None, "\n".join(traceback.format_exception(e)) + ) + self.updateLabels("reset", False) + finally: + self.on_confirmDbPathButton_clicked() @Slot() def on_continueButton_clicked(self): diff --git a/ui/startup/databaseChecker.ui b/ui/startup/databaseChecker.ui index 9f42d1f..7cd3080 100644 --- a/ui/startup/databaseChecker.ui +++ b/ui/startup/databaseChecker.ui @@ -25,51 +25,56 @@ - + - + - dbVersionLabel + dbFilenameLabel + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + confirmDbPathButton + + + + + + - - - - - dbInitLabel - - - - - - - dbCheckConnLabel - - - - - - - dbInitButton - - - - - - - ... - - - - + Qt::Vertical @@ -82,7 +87,21 @@ - + + + + dbCheckConnLabel + + + + + + + ... + + + + false @@ -92,6 +111,20 @@ + + + + dbVersionLabel + + + + + + + Qt::Horizontal + + + diff --git a/ui/startup/databaseChecker_ui.py b/ui/startup/databaseChecker_ui.py index e07ca63..8feeb4a 100644 --- a/ui/startup/databaseChecker_ui.py +++ b/ui/startup/databaseChecker_ui.py @@ -3,146 +3,124 @@ ################################################################################ ## Form generated from reading UI file 'databaseChecker.ui' ## -## Created by: Qt User Interface Compiler version 6.5.0 +## 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, - Qt, - QTime, - QUrl, -) -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, - QFormLayout, - QLabel, - QPushButton, - QSizePolicy, - QSpacerItem, - QWidget, -) +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, QFormLayout, QFrame, QHBoxLayout, + QLabel, QLineEdit, QPushButton, QSizePolicy, + QSpacerItem, QWidget) from ui.implements.components.fileSelector import FileSelector - class Ui_DatabaseChecker(object): def setupUi(self, DatabaseChecker): if not DatabaseChecker.objectName(): - DatabaseChecker.setObjectName("DatabaseChecker") + DatabaseChecker.setObjectName(u"DatabaseChecker") DatabaseChecker.resize(350, 250) - DatabaseChecker.setWindowTitle("DatabaseChecker") + DatabaseChecker.setWindowTitle(u"DatabaseChecker") self.formLayout = QFormLayout(DatabaseChecker) - self.formLayout.setObjectName("formLayout") - self.formLayout.setLabelAlignment( - Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter - ) + self.formLayout.setObjectName(u"formLayout") + self.formLayout.setLabelAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) self.label = QLabel(DatabaseChecker) - self.label.setObjectName("label") + self.label.setObjectName(u"label") self.formLayout.setWidget(0, QFormLayout.LabelRole, self.label) - self.dbFileSelector = FileSelector(DatabaseChecker) - self.dbFileSelector.setObjectName("dbFileSelector") + self.dbDirSelector = FileSelector(DatabaseChecker) + self.dbDirSelector.setObjectName(u"dbDirSelector") - self.formLayout.setWidget(0, QFormLayout.FieldRole, self.dbFileSelector) + self.formLayout.setWidget(0, QFormLayout.FieldRole, self.dbDirSelector) - self.label_2 = QLabel(DatabaseChecker) - self.label_2.setObjectName("label_2") + self.label_3 = QLabel(DatabaseChecker) + self.label_3.setObjectName(u"label_3") - self.formLayout.setWidget(1, QFormLayout.LabelRole, self.label_2) + self.formLayout.setWidget(1, QFormLayout.LabelRole, self.label_3) + + self.dbFilenameLineEdit = QLineEdit(DatabaseChecker) + self.dbFilenameLineEdit.setObjectName(u"dbFilenameLineEdit") + + self.formLayout.setWidget(1, QFormLayout.FieldRole, self.dbFilenameLineEdit) + + self.horizontalLayout = QHBoxLayout() + self.horizontalLayout.setObjectName(u"horizontalLayout") + self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) + + self.horizontalLayout.addItem(self.horizontalSpacer) + + self.confirmDbPathButton = QPushButton(DatabaseChecker) + self.confirmDbPathButton.setObjectName(u"confirmDbPathButton") + sizePolicy = QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.confirmDbPathButton.sizePolicy().hasHeightForWidth()) + self.confirmDbPathButton.setSizePolicy(sizePolicy) + + self.horizontalLayout.addWidget(self.confirmDbPathButton) + + + self.formLayout.setLayout(2, QFormLayout.FieldRole, self.horizontalLayout) self.dbVersionLabel = QLabel(DatabaseChecker) - self.dbVersionLabel.setObjectName("dbVersionLabel") - self.dbVersionLabel.setText("-") + self.dbVersionLabel.setObjectName(u"dbVersionLabel") + self.dbVersionLabel.setText(u"-") - self.formLayout.setWidget(1, QFormLayout.FieldRole, self.dbVersionLabel) + self.formLayout.setWidget(4, QFormLayout.FieldRole, self.dbVersionLabel) - self.label_4 = QLabel(DatabaseChecker) - self.label_4.setObjectName("label_4") + self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) - self.formLayout.setWidget(2, QFormLayout.LabelRole, self.label_4) + self.formLayout.setItem(6, QFormLayout.FieldRole, self.verticalSpacer) self.label_5 = QLabel(DatabaseChecker) - self.label_5.setObjectName("label_5") + self.label_5.setObjectName(u"label_5") - self.formLayout.setWidget(4, QFormLayout.LabelRole, self.label_5) - - self.dbInitButton = QPushButton(DatabaseChecker) - self.dbInitButton.setObjectName("dbInitButton") - - self.formLayout.setWidget(2, QFormLayout.FieldRole, self.dbInitButton) + self.formLayout.setWidget(7, QFormLayout.LabelRole, self.label_5) self.dbCheckConnLabel = QLabel(DatabaseChecker) - self.dbCheckConnLabel.setObjectName("dbCheckConnLabel") - self.dbCheckConnLabel.setText("...") + self.dbCheckConnLabel.setObjectName(u"dbCheckConnLabel") + self.dbCheckConnLabel.setText(u"...") - self.formLayout.setWidget(4, QFormLayout.FieldRole, self.dbCheckConnLabel) - - self.verticalSpacer = QSpacerItem( - 20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding - ) - - self.formLayout.setItem(3, QFormLayout.FieldRole, self.verticalSpacer) + self.formLayout.setWidget(7, QFormLayout.FieldRole, self.dbCheckConnLabel) self.continueButton = QPushButton(DatabaseChecker) - self.continueButton.setObjectName("continueButton") + self.continueButton.setObjectName(u"continueButton") self.continueButton.setEnabled(False) - self.formLayout.setWidget(5, QFormLayout.SpanningRole, self.continueButton) + self.formLayout.setWidget(8, QFormLayout.SpanningRole, self.continueButton) + + self.label_2 = QLabel(DatabaseChecker) + self.label_2.setObjectName(u"label_2") + + self.formLayout.setWidget(4, QFormLayout.LabelRole, self.label_2) + + self.line = QFrame(DatabaseChecker) + self.line.setObjectName(u"line") + self.line.setFrameShape(QFrame.HLine) + self.line.setFrameShadow(QFrame.Sunken) + + self.formLayout.setWidget(3, QFormLayout.SpanningRole, self.line) + self.retranslateUi(DatabaseChecker) QMetaObject.connectSlotsByName(DatabaseChecker) - # setupUi def retranslateUi(self, DatabaseChecker): - self.label.setText( - QCoreApplication.translate("DatabaseChecker", "dbPathLabel", None) - ) - self.label_2.setText( - QCoreApplication.translate("DatabaseChecker", "dbVersionLabel", None) - ) - self.label_4.setText( - QCoreApplication.translate("DatabaseChecker", "dbInitLabel", None) - ) - self.label_5.setText( - QCoreApplication.translate("DatabaseChecker", "dbCheckConnLabel", None) - ) - self.dbInitButton.setText( - QCoreApplication.translate("DatabaseChecker", "dbInitButton", None) - ) - self.continueButton.setText( - QCoreApplication.translate("DatabaseChecker", "continueButton", None) - ) + self.label.setText(QCoreApplication.translate("DatabaseChecker", u"dbPathLabel", None)) + self.label_3.setText(QCoreApplication.translate("DatabaseChecker", u"dbFilenameLabel", None)) + self.confirmDbPathButton.setText(QCoreApplication.translate("DatabaseChecker", u"confirmDbPathButton", None)) + self.label_5.setText(QCoreApplication.translate("DatabaseChecker", u"dbCheckConnLabel", None)) + self.continueButton.setText(QCoreApplication.translate("DatabaseChecker", u"continueButton", None)) + self.label_2.setText(QCoreApplication.translate("DatabaseChecker", u"dbVersionLabel", None)) pass - # retranslateUi +