diff --git a/ui/extends/components/chartSelector.py b/ui/extends/components/chartSelector.py index abf69cc..ea4437b 100644 --- a/ui/extends/components/chartSelector.py +++ b/ui/extends/components/chartSelector.py @@ -1,6 +1,6 @@ from arcaea_offline.database import Database from arcaea_offline.models import Chart -from arcaea_offline.utils import rating_class_to_short_text +from arcaea_offline.utils.rating import rating_class_to_short_text from PySide6.QtCore import Qt from PySide6.QtGui import QStandardItem, QStandardItemModel diff --git a/ui/extends/components/ocrQueue.py b/ui/extends/components/ocrQueue.py index 3e4d731..0ed77f6 100644 --- a/ui/extends/components/ocrQueue.py +++ b/ui/extends/components/ocrQueue.py @@ -3,7 +3,7 @@ from typing import Any, Callable, Optional, overload from arcaea_offline.calculate import calculate_score_range from arcaea_offline.database import Database -from arcaea_offline.models import Chart, ScoreInsert +from arcaea_offline.models import Chart, Score from arcaea_offline_ocr.b30.shared import B30OcrResultItem from arcaea_offline_ocr.device.shared import DeviceOcrResult from PySide6.QtCore import ( @@ -47,14 +47,14 @@ class OcrQueueModel(QAbstractListModel): ImagePixmapRole = Qt.ItemDataRole.UserRole + 3 OcrResultRole = Qt.ItemDataRole.UserRole + 10 - ScoreInsertRole = Qt.ItemDataRole.UserRole + 11 + ScoreRole = Qt.ItemDataRole.UserRole + 11 ChartRole = Qt.ItemDataRole.UserRole + 12 ScoreValidateOkRole = Qt.ItemDataRole.UserRole + 13 OcrRunnableRole = Qt.ItemDataRole.UserRole + 20 ProcessOcrResultFuncRole = ( Qt.ItemDataRole.UserRole + 21 - ) # Callable[[imageStr, DeviceOcrResult], tuple[Chart, ScoreInsert]] + ) # Callable[[imageStr, DeviceOcrResult], tuple[Chart, Score]] started = Signal() progress = Signal(int) @@ -107,8 +107,8 @@ class OcrQueueModel(QAbstractListModel): self.updateScoreValidateOk(index.row()) updateRole = role - if role == self.ScoreInsertRole and isinstance(value, ScoreInsert): - item[self.ScoreInsertRole] = value + if role == self.ScoreRole and isinstance(value, Score): + item[self.ScoreRole] = value self.updateScoreValidateOk(index.row()) updateRole = role @@ -138,7 +138,7 @@ class OcrQueueModel(QAbstractListModel): self, image: str, runnable: OcrRunnable = None, - process_func: Callable[[Optional[str], QImage, Any], ScoreInsert] = None, + process_func: Callable[[Optional[str], QImage, Any], Score] = None, ): ... @@ -147,7 +147,7 @@ class OcrQueueModel(QAbstractListModel): self, image: QImage, runnable: OcrRunnable = None, - process_func: Callable[[Optional[str], QImage, Any], ScoreInsert] = None, + process_func: Callable[[Optional[str], QImage, Any], Score] = None, ): ... @@ -178,7 +178,7 @@ class OcrQueueModel(QAbstractListModel): self.ImageQImageRole: qImage, self.ImagePixmapRole: qPixmap, self.OcrResultRole: None, - self.ScoreInsertRole: None, + self.ScoreRole: None, self.ChartRole: None, self.ScoreValidateOkRole: False, self.OcrRunnableRole: runnable, @@ -201,7 +201,7 @@ class OcrQueueModel(QAbstractListModel): self.setData(index, result, self.OcrResultRole) self.setData(index, chart, self.ChartRole) - self.setData(index, scoreInsert, self.ScoreInsertRole) + self.setData(index, scoreInsert, self.ScoreRole) return True @Slot(DeviceOcrResult) @@ -234,8 +234,8 @@ class OcrQueueModel(QAbstractListModel): index = self.index(row, 0) chart = index.data(self.ChartRole) - score = index.data(self.ScoreInsertRole) - if isinstance(chart, Chart) and isinstance(score, ScoreInsert): + score = index.data(self.ScoreRole) + if isinstance(chart, Chart) and isinstance(score, Score): scoreRange = calculate_score_range(chart, score.pure, score.far) scoreValidateOk = scoreRange[0] <= score.score <= scoreRange[1] self.setData(index, scoreValidateOk, self.ScoreValidateOkRole) @@ -247,8 +247,8 @@ class OcrQueueModel(QAbstractListModel): return item = self.__items[row] - score = item[self.ScoreInsertRole] - if not isinstance(score, ScoreInsert) or ( + score = item[self.ScoreRole] + if not isinstance(score, Score) or ( not item[self.ScoreValidateOkRole] and not ignoreValidate ): return @@ -301,7 +301,7 @@ class OcrQueueTableProxyModel(QAbstractTableModel): ], [ OcrQueueModel.OcrResultRole, - OcrQueueModel.ScoreInsertRole, + OcrQueueModel.ScoreRole, OcrQueueModel.ChartRole, OcrQueueModel.ScoreValidateOkRole, ], @@ -364,7 +364,7 @@ class OcrQueueTableProxyModel(QAbstractTableModel): def setData(self, index, value, role): if index.column() == 2 and role == OcrQueueModel.ChartRole: return self.sourceModel().setData(index, value, role) - if index.column() == 3 and role == OcrQueueModel.ScoreInsertRole: + if index.column() == 3 and role == OcrQueueModel.ScoreRole: return self.sourceModel().setData(index, value, role) return False @@ -403,8 +403,8 @@ class OcrChartDelegate(ChartDelegate): class OcrScoreDelegate(ScoreDelegate): - def getScoreInsert(self, index: QModelIndex): - return index.data(OcrQueueModel.ScoreInsertRole) + def getScore(self, index: QModelIndex): + return index.data(OcrQueueModel.ScoreRole) def getChart(self, index: QModelIndex): return index.data(OcrQueueModel.ChartRole) @@ -415,7 +415,7 @@ class OcrScoreDelegate(ScoreDelegate): def paintWarningBackground(self, index: QModelIndex) -> bool: return True # return isinstance(self.getChart(index), Chart) and isinstance( - # self.getScore(index), ScoreInsert + # self.getScore(index), Score # ) # return isinstance( # index.data(OcrQueueModel.OcrResultRole), (DeviceOcrResult, B30OcrResultItem) @@ -423,4 +423,4 @@ class OcrScoreDelegate(ScoreDelegate): def setModelData(self, editor, model: OcrQueueTableProxyModel, index): if super().confirmSetModelData(editor): - model.setData(index, editor.value(), OcrQueueModel.ScoreInsertRole) + model.setData(index, editor.value(), OcrQueueModel.ScoreRole) diff --git a/ui/extends/shared/database.py b/ui/extends/shared/database.py new file mode 100644 index 0000000..e6a623c --- /dev/null +++ b/ui/extends/shared/database.py @@ -0,0 +1,11 @@ +from typing import Type + +from PySide6.QtCore import QUrl +from sqlalchemy import Engine +from sqlalchemy import create_engine as sa_create_engine +from sqlalchemy.pool import NullPool, Pool + + +def create_engine(_url: str | QUrl, pool: Type[Pool] = NullPool) -> Engine: + url = _url.toString() if isinstance(_url, QUrl) else _url + return sa_create_engine(url, poolclass=pool) diff --git a/ui/extends/shared/delegates/chartDelegate.py b/ui/extends/shared/delegates/chartDelegate.py index 93ca7a4..36934ff 100644 --- a/ui/extends/shared/delegates/chartDelegate.py +++ b/ui/extends/shared/delegates/chartDelegate.py @@ -1,9 +1,7 @@ -from typing import Union - from arcaea_offline.models import Chart -from arcaea_offline.utils import rating_class_to_short_text, rating_class_to_text -from PySide6.QtCore import QDateTime, QModelIndex, Qt, Signal -from PySide6.QtGui import QBrush, QColor +from arcaea_offline.utils.rating import rating_class_to_short_text, rating_class_to_text +from PySide6.QtCore import QModelIndex, Qt, Signal +from PySide6.QtGui import QColor from PySide6.QtWidgets import ( QFrame, QHBoxLayout, diff --git a/ui/extends/shared/delegates/scoreDelegate.py b/ui/extends/shared/delegates/scoreDelegate.py index 381a65e..db59fc7 100644 --- a/ui/extends/shared/delegates/scoreDelegate.py +++ b/ui/extends/shared/delegates/scoreDelegate.py @@ -1,16 +1,12 @@ from typing import Union from arcaea_offline.calculate import calculate_score_range -from arcaea_offline.models import Chart, Score, ScoreInsert -from arcaea_offline.utils import ( - rating_class_to_text, - score_to_grade_text, - zip_score_grade, -) +from arcaea_offline.models import Chart, Score +from arcaea_offline.utils.rating import rating_class_to_text +from arcaea_offline.utils.score import score_to_grade_text, zip_score_grade from PySide6.QtCore import QAbstractItemModel, QDateTime, QModelIndex, Qt, Signal from PySide6.QtGui import QColor, QFont, QLinearGradient from PySide6.QtWidgets import ( - QAbstractItemDelegate, QFrame, QHBoxLayout, QLabel, @@ -53,7 +49,7 @@ class ScoreEditorDelegateWrapper(ScoreEditor): self.formLayout.insertRow(0, self.delegateHeader) - def setText(self, score: Score | ScoreInsert, _extra: str = None): + def setText(self, score: Score, _extra: str = None): text = "Editing " text += _extra or "" text += f"score {score.score}" @@ -91,22 +87,14 @@ class ScoreDelegate(TextSegmentDelegate): def getScore(self, index: QModelIndex) -> Score | None: return None - def getScoreInsert(self, index: QModelIndex) -> ScoreInsert | None: - return None - - def _getScore(self, index: QModelIndex): - score = self.getScore(index) - scoreInsert = self.getScoreInsert(index) - return scoreInsert if score is None else score - def getChart(self, index: QModelIndex) -> Chart | None: return None def getScoreValidateOk(self, index: QModelIndex) -> bool | None: - score = self._getScore(index) + score = self.getScore(index) chart = self.getChart(index) - if isinstance(score, (Score, ScoreInsert)) and isinstance(chart, Chart): + if isinstance(score, Score) and isinstance(chart, Chart): scoreRange = calculate_score_range(chart, score.pure, score.far) return scoreRange[0] <= score.score <= scoreRange[1] @@ -114,9 +102,9 @@ class ScoreDelegate(TextSegmentDelegate): return zip_score_grade(score, self.GradeGradientsWrappers) def getTextSegments(self, index, option): - score = self._getScore(index) + score = self.getScore(index) chart = self.getChart(index) - if not (isinstance(score, (Score, ScoreInsert)) and isinstance(chart, Chart)): + if not (isinstance(score, Score) and isinstance(chart, Chart)): return [ [ { @@ -176,10 +164,10 @@ class ScoreDelegate(TextSegmentDelegate): def paint(self, painter, option, index): # draw scoreMismatch warning background - score = self._getScore(index) + score = self.getScore(index) chart = self.getChart(index) if ( - isinstance(score, (Score, ScoreInsert)) + isinstance(score, Score) and isinstance(chart, Chart) and self.paintWarningBackground(index) ): @@ -206,16 +194,16 @@ class ScoreDelegate(TextSegmentDelegate): self.closeEditor.emit(editor) def createEditor(self, parent, option, index) -> ScoreEditorDelegateWrapper: - score = self._getScore(index) + score = self.getScore(index) chart = self.getChart(index) - if isinstance(score, (Score, ScoreInsert)) and isinstance(chart, Chart): + if isinstance(score, Score) and isinstance(chart, Chart): editor = ScoreEditorDelegateWrapper(parent) editor.setWindowFlag(Qt.WindowType.Sheet, True) editor.setWindowFlag(Qt.WindowType.FramelessWindowHint, True) editor.setWindowTitle( f"{chart.name_en}({chart.song_id}) | {rating_class_to_text(chart.rating_class)} | {chart.package_id}" ) - editor.setText(self._getScore(index)) + editor.setText(self.getScore(index)) editor.setValidateBeforeAccept(False) editor.move(parent.mapToGlobal(parent.pos())) editor.accepted.connect(self._commitEditor) @@ -231,9 +219,9 @@ class ScoreDelegate(TextSegmentDelegate): keepWidgetInScreen(editor) def setEditorData(self, editor: ScoreEditorDelegateWrapper, index) -> None: - score = self._getScore(index) + score = self.getScore(index) chart = self.getChart(index) - if isinstance(score, (Score, ScoreInsert)) and isinstance(chart, Chart): + if isinstance(score, Score) and isinstance(chart, Chart): editor.setChart(chart) editor.setValue(score) diff --git a/ui/extends/shared/models/tables/score.py b/ui/extends/shared/models/tables/score.py index 69f3f11..b22cdcf 100644 --- a/ui/extends/shared/models/tables/score.py +++ b/ui/extends/shared/models/tables/score.py @@ -1,5 +1,5 @@ -from arcaea_offline.calculate import calculate_score -from arcaea_offline.models import Chart, Score, ScoreInsert +# from arcaea_offline.calculate import calculate_score +from arcaea_offline.models import Chart, Score from PySide6.QtCore import QCoreApplication, QModelIndex, QSortFilterProxyModel, Qt from .base import DbTableModel diff --git a/ui/extends/shared/settings.py b/ui/extends/shared/settings.py index 0d56844..ddbdb68 100644 --- a/ui/extends/shared/settings.py +++ b/ui/extends/shared/settings.py @@ -1,7 +1,7 @@ -from PySide6.QtCore import QDir, QSettings +from PySide6.QtCore import QDir, QSettings, QUrl __all__ = [ - "DATABASE_PATH", + "DATABASE_URL", "DEVICES_JSON_FILE", "DEVICE_UUID", "TESSERACT_FILE", @@ -10,7 +10,7 @@ __all__ = [ "Settings", ] -DATABASE_PATH = "General/DatabasePath" +DATABASE_URL = "General/DatabaseUrl" DEVICES_JSON_FILE = "Ocr/DevicesJsonFile" DEVICE_UUID = "Ocr/DeviceUuid" @@ -27,6 +27,13 @@ class Settings(QSettings): parent, ) + def databaseUrl(self) -> str | None: + return self.value(DATABASE_URL, None, str) + + def setDatabaseUrl(self, value: str): + self.setValue(DATABASE_URL, value) + self.sync() + def devicesJsonFile(self) -> str | None: return self.value(DEVICES_JSON_FILE, None, str) diff --git a/ui/extends/tabs/tabOcr/tabOcr_B30.py b/ui/extends/tabs/tabOcr/tabOcr_B30.py index c58dab2..b0d7b62 100644 --- a/ui/extends/tabs/tabOcr/tabOcr_B30.py +++ b/ui/extends/tabs/tabOcr/tabOcr_B30.py @@ -1,7 +1,7 @@ import logging from arcaea_offline.database import Database -from arcaea_offline.models import Chart, ScoreInsert +from arcaea_offline.models import Chart, Score from arcaea_offline_ocr.b30.chieri.v4.ocr import ChieriBotV4Ocr from arcaea_offline_ocr.b30.shared import B30OcrResultItem from PySide6.QtGui import QImage diff --git a/ui/extends/tabs/tabOcr/tabOcr_Device.py b/ui/extends/tabs/tabOcr/tabOcr_Device.py index 14a0598..eadde12 100644 --- a/ui/extends/tabs/tabOcr/tabOcr_Device.py +++ b/ui/extends/tabs/tabOcr/tabOcr_Device.py @@ -3,7 +3,7 @@ import logging from typing import Tuple from arcaea_offline.database import Database -from arcaea_offline.models import Chart, ScoreInsert +from arcaea_offline.models import Chart, Score from arcaea_offline_ocr.device.shared import DeviceOcrResult from arcaea_offline_ocr.device.v2.ocr import DeviceV2Ocr from arcaea_offline_ocr.device.v2.rois import DeviceV2Rois @@ -52,9 +52,7 @@ def getImageDate(imagePath: str) -> QDateTime: class ScoreInsertConverter: @staticmethod - def deviceV2( - imagePath: str, _, result: DeviceOcrResult - ) -> Tuple[Chart, ScoreInsert]: + def deviceV2(imagePath: str, _, result: DeviceOcrResult) -> Tuple[Chart, Score]: db = Database() scoreInsert = ScoreInsert( song_id=result.song_id, diff --git a/ui/implements/components/chartSelector.py b/ui/implements/components/chartSelector.py index 8e3208a..687c48b 100644 --- a/ui/implements/components/chartSelector.py +++ b/ui/implements/components/chartSelector.py @@ -1,10 +1,11 @@ +import re from typing import Literal from arcaea_offline.database import Database -from arcaea_offline.models import Chart, Package -from arcaea_offline.utils import rating_class_to_text +from arcaea_offline.models import Chart, Pack +from arcaea_offline.utils.rating import rating_class_to_text from PySide6.QtCore import QModelIndex, Qt, Signal, Slot -from PySide6.QtGui import QColor +from PySide6.QtGui import QColor, QShowEvent from PySide6.QtWidgets import QCompleter, QWidget from ui.designer.components.chartSelector_ui import Ui_ChartSelector @@ -19,7 +20,6 @@ class ChartSelector(Ui_ChartSelector, QWidget): def __init__(self, parent=None): super().__init__(parent) self.db = Database() - self.db.register_update_hook(self.fillPackageComboBox) self.setupUi(self) self.pstButton.setColors(QColor("#399bb2"), QColor("#f0f8fa")) @@ -107,19 +107,28 @@ class ChartSelector(Ui_ChartSelector, QWidget): ratingClass = self.selectedRatingClass() if packageId and songId and isinstance(ratingClass, int): - return Chart.from_db_row(self.db.get_chart(songId, ratingClass)) + return self.db.get_chart(songId, ratingClass) return None + def showEvent(self, event: QShowEvent): + # update database results when widget visible + self.fillPackageComboBox() + return super().showEvent(event) + @Slot() def updateResultLabel(self): chart = self.value() if isinstance(chart, Chart): - package = Package.from_db_row( - self.db.get_package_by_package_id(chart.package_id) - ) + pack = self.db.get_pack_by_id(chart.set) texts = [ - [package.name, chart.name_en, rating_class_to_text(chart.rating_class)], - [package.id, chart.song_id, str(chart.rating_class)], + [ + pack.name, + chart.title, + f"{rating_class_to_text(chart.rating_class)} " + f"{chart.rating}{'+' if chart.rating_plus else ''}" + f"({chart.constant / 10})", + ], + [pack.id, chart.song_id, str(chart.rating_class)], ] texts = [" | ".join(t) for t in texts] text = f'{texts[0]}
{texts[1]}' @@ -129,37 +138,41 @@ class ChartSelector(Ui_ChartSelector, QWidget): def fillPackageComboBox(self): self.packageComboBox.clear() - packages = [Package.from_db_row(dbRow) for dbRow in self.db.get_packages()] - for package in packages: - self.packageComboBox.addItem(f"{package.name} ({package.id})", package.id) + 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.packageComboBox.addItem(f"{packName} ({pack.id})", pack.id) row = self.packageComboBox.count() - 1 self.packageComboBox.setItemData( - row, package.name, DescriptionDelegate.MainTextRole + row, packName, DescriptionDelegate.MainTextRole ) self.packageComboBox.setItemData( - row, package.id, DescriptionDelegate.DescriptionTextRole + row, pack.id, DescriptionDelegate.DescriptionTextRole ) self.packageComboBox.setCurrentIndex(-1) def fillSongIdComboBox(self): self.songIdComboBox.clear() - packageId = self.packageComboBox.currentData() - if packageId: - charts = [ - Chart.from_db_row(dbRow) - for dbRow in self.db.get_charts_by_package_id(packageId) - ] + packId = self.packageComboBox.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.name_en} ({chart.song_id})", chart.song_id + 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.name_en, DescriptionDelegate.MainTextRole + row, chart.title, DescriptionDelegate.MainTextRole ) self.songIdComboBox.setItemData( row, chart.song_id, DescriptionDelegate.DescriptionTextRole @@ -174,12 +187,7 @@ class ChartSelector(Ui_ChartSelector, QWidget): def on_songIdComboBox_currentIndexChanged(self, index: int): rating_classes = [] if index > -1: - charts = [ - Chart.from_db_row(dbRow) - for dbRow in self.db.get_charts_by_song_id( - self.songIdComboBox.currentData() - ) - ] + charts = self.db.get_charts_by_song_id(self.songIdComboBox.currentData()) rating_classes = [chart.rating_class for chart in charts] self.updateRatingClassButtonsEnabled(rating_classes) @@ -196,7 +204,7 @@ class ChartSelector(Ui_ChartSelector, QWidget): self.fuzzySearchCompleterModel.clear() def selectChart(self, chart: Chart): - packageIdIndex = self.packageComboBox.findData(chart.package_id) + packageIdIndex = self.packageComboBox.findData(chart.set) if packageIdIndex > -1: self.packageComboBox.setCurrentIndex(packageIdIndex) else: diff --git a/ui/implements/components/scoreEditor.py b/ui/implements/components/scoreEditor.py index 0ed7803..bdd7233 100644 --- a/ui/implements/components/scoreEditor.py +++ b/ui/implements/components/scoreEditor.py @@ -2,7 +2,7 @@ from enum import IntEnum from typing import Optional from arcaea_offline.calculate import calculate_score_range -from arcaea_offline.models import Chart, Score, ScoreInsert +from arcaea_offline.models import Chart, Score from PySide6.QtCore import QCoreApplication, QDateTime, Signal, Slot from PySide6.QtWidgets import QMessageBox, QWidget @@ -37,9 +37,9 @@ class ScoreEditor(Ui_ScoreEditor, QWidget): self.valueChanged.connect(self.validateScore) self.valueChanged.connect(self.updateValidateLabel) - self.clearTypeComboBox.addItem("HARD LOST", -1) self.clearTypeComboBox.addItem("TRACK LOST", 0) self.clearTypeComboBox.addItem("TRACK COMPLETE", 1) + self.clearTypeComboBox.addItem("HARD LOST", 2) self.clearTypeComboBox.setCurrentIndex(-1) def setValidateBeforeAccept(self, __bool: bool): @@ -159,33 +159,33 @@ class ScoreEditor(Ui_ScoreEditor, QWidget): def value(self): if isinstance(self.__chart, Chart): - return ScoreInsert( + return Score( song_id=self.__chart.song_id, rating_class=self.__chart.rating_class, score=self.score(), pure=self.pureSpinBox.value(), far=self.farSpinBox.value(), lost=self.lostSpinBox.value(), - time=self.dateTimeEdit.dateTime().toSecsSinceEpoch(), + date=self.dateTimeEdit.dateTime().toSecsSinceEpoch(), max_recall=self.maxRecallSpinBox.value() if self.maxRecallSpinBox.value() > -1 else None, - clear_type=None, + r10_clear_type=None, ) - def setValue(self, score: Score | ScoreInsert): - if isinstance(score, (Score, ScoreInsert)): + def setValue(self, score: Score): + if isinstance(score, Score): scoreText = str(score.score) scoreText = scoreText.rjust(8, "0") self.scoreLineEdit.setText(scoreText) self.pureSpinBox.setValue(score.pure) self.farSpinBox.setValue(score.far) self.lostSpinBox.setValue(score.lost) - self.dateTimeEdit.setDateTime(QDateTime.fromSecsSinceEpoch(score.time)) + self.dateTimeEdit.setDateTime(QDateTime.fromSecsSinceEpoch(score.date)) if score.max_recall is not None: self.maxRecallSpinBox.setValue(score.max_recall) - if score.clear_type is not None: - self.clearTypeComboBox.setCurrentIndex(score.clear_type) + if score.r10_clear_type is not None: + self.clearTypeComboBox.setCurrentIndex(score.r10_clear_type) def reset(self): self.setChart(None) diff --git a/ui/implements/tabs/tabDb/tabDb_B30TableViewer.py b/ui/implements/tabs/tabDb/tabDb_B30TableViewer.py index b113d2d..8d8aafc 100644 --- a/ui/implements/tabs/tabDb/tabDb_B30TableViewer.py +++ b/ui/implements/tabs/tabDb/tabDb_B30TableViewer.py @@ -1,4 +1,3 @@ -from arcaea_offline.models import ScoreInsert from PySide6.QtCore import QModelIndex, Qt, Slot from PySide6.QtGui import QColor, QPalette from PySide6.QtWidgets import QMessageBox @@ -21,7 +20,7 @@ class TableScoreDelegate(ScoreDelegate): def getChart(self, index): return index.data(DbB30TableModel.ChartRole) - def getScoreInsert(self, index: QModelIndex) -> ScoreInsert | None: + def getScoreInsert(self, index: QModelIndex): return super().getScoreInsert(index) def getScore(self, index): diff --git a/ui/implements/tabs/tabDb/tabDb_Manage.py b/ui/implements/tabs/tabDb/tabDb_Manage.py index 986ca47..59c78c5 100644 --- a/ui/implements/tabs/tabDb/tabDb_Manage.py +++ b/ui/implements/tabs/tabDb/tabDb_Manage.py @@ -2,7 +2,8 @@ import logging import traceback from arcaea_offline.database import Database -from arcaea_offline.external import St3ScoreSource +from arcaea_offline.external.arcaea.st3 import St3ScoreParser +from arcaea_offline.external.arcsong import ArcsongDbParser from PySide6.QtCore import Slot from PySide6.QtWidgets import QFileDialog, QMessageBox, QWidget @@ -26,7 +27,11 @@ class TabDb_Manage(Ui_TabDb_Manage, QWidget): return try: - Database().update_arcsong_db(dbFile) + db = Database() + parser = ArcsongDbParser(dbFile) + with db.sessionmaker() as session: + parser.write_database(session) + session.commit() QMessageBox.information(self, None, "OK") except Exception as e: logging.exception("Sync arcsong.db error") @@ -42,11 +47,14 @@ class TabDb_Manage(Ui_TabDb_Manage, QWidget): return try: - scores = St3ScoreSource(dbFile).get_score_items() + db = Database() + parser = St3ScoreParser(dbFile) logger.info( - f"Got {len(scores)} items from {dbFile}, writing into database..." + f"Got {len(parser.parse())} items from {dbFile}, writing into database..." ) - Database().import_external(scores) + with db.sessionmaker() as session: + parser.write_database(session) + session.commit() QMessageBox.information(self, None, "OK") except Exception as e: logging.exception("import st3 error") diff --git a/ui/implements/tabs/tabDb/tabDb_ScoreTableViewer.py b/ui/implements/tabs/tabDb/tabDb_ScoreTableViewer.py index 8e117fe..36982bd 100644 --- a/ui/implements/tabs/tabDb/tabDb_ScoreTableViewer.py +++ b/ui/implements/tabs/tabDb/tabDb_ScoreTableViewer.py @@ -1,4 +1,4 @@ -from arcaea_offline.models import ScoreInsert +from arcaea_offline.models import Score from PySide6.QtCore import QModelIndex, Qt, Slot from PySide6.QtGui import QColor, QPalette from PySide6.QtWidgets import QMessageBox @@ -21,9 +21,6 @@ class TableScoreDelegate(ScoreDelegate): def getChart(self, index): return index.data(DbScoreTableModel.ChartRole) - def getScoreInsert(self, index: QModelIndex) -> ScoreInsert | None: - return super().getScoreInsert(index) - def getScore(self, index): return index.data(DbScoreTableModel.ScoreRole) diff --git a/ui/implements/tabs/tabOcr/tabOcr_Device.py b/ui/implements/tabs/tabOcr/tabOcr_Device.py index a06a768..87fd302 100644 --- a/ui/implements/tabs/tabOcr/tabOcr_Device.py +++ b/ui/implements/tabs/tabOcr/tabOcr_Device.py @@ -1,7 +1,6 @@ import logging import cv2 -import pytesseract # from arcaea_offline_ocr_device_creation_wizard.implements.wizard import Wizard from arcaea_offline_ocr.device.v1.definition import DeviceV1 diff --git a/ui/implements/tabs/tabOverview.py b/ui/implements/tabs/tabOverview.py index 7ef4d44..757f106 100644 --- a/ui/implements/tabs/tabOverview.py +++ b/ui/implements/tabs/tabOverview.py @@ -1,4 +1,5 @@ from arcaea_offline.database import Database +from PySide6.QtGui import QShowEvent from PySide6.QtWidgets import QWidget from ui.designer.tabs.tabOverview_ui import Ui_TabOverview @@ -10,8 +11,12 @@ class TabOverview(Ui_TabOverview, QWidget): self.setupUi(self) self.db = Database() - self.db.register_update_hook(self.updateOverview) + # self.db.register_update_hook(self.updateOverview) + # self.updateOverview() + + def showEvent(self, event: QShowEvent) -> None: self.updateOverview() + return super().showEvent(event) def updateOverview(self): b30 = self.db.get_b30() or 0.00 diff --git a/ui/startup/databaseChecker_ui.py b/ui/startup/databaseChecker_ui.py index 8feeb4a..41b5eb1 100644 --- a/ui/startup/databaseChecker_ui.py +++ b/ui/startup/databaseChecker_ui.py @@ -8,119 +8,173 @@ ## 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, QFormLayout, QFrame, QHBoxLayout, - QLabel, QLineEdit, QPushButton, QSizePolicy, - QSpacerItem, QWidget) +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, + 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(u"DatabaseChecker") + DatabaseChecker.setObjectName("DatabaseChecker") DatabaseChecker.resize(350, 250) - DatabaseChecker.setWindowTitle(u"DatabaseChecker") + DatabaseChecker.setWindowTitle("DatabaseChecker") self.formLayout = QFormLayout(DatabaseChecker) - self.formLayout.setObjectName(u"formLayout") - self.formLayout.setLabelAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) + self.formLayout.setObjectName("formLayout") + self.formLayout.setLabelAlignment( + Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter + ) self.label = QLabel(DatabaseChecker) - self.label.setObjectName(u"label") + self.label.setObjectName("label") self.formLayout.setWidget(0, QFormLayout.LabelRole, self.label) self.dbDirSelector = FileSelector(DatabaseChecker) - self.dbDirSelector.setObjectName(u"dbDirSelector") + self.dbDirSelector.setObjectName("dbDirSelector") self.formLayout.setWidget(0, QFormLayout.FieldRole, self.dbDirSelector) self.label_3 = QLabel(DatabaseChecker) - self.label_3.setObjectName(u"label_3") + self.label_3.setObjectName("label_3") self.formLayout.setWidget(1, QFormLayout.LabelRole, self.label_3) self.dbFilenameLineEdit = QLineEdit(DatabaseChecker) - self.dbFilenameLineEdit.setObjectName(u"dbFilenameLineEdit") + self.dbFilenameLineEdit.setObjectName("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.setObjectName("horizontalLayout") + self.horizontalSpacer = QSpacerItem( + 40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum + ) self.horizontalLayout.addItem(self.horizontalSpacer) self.confirmDbPathButton = QPushButton(DatabaseChecker) - self.confirmDbPathButton.setObjectName(u"confirmDbPathButton") + self.confirmDbPathButton.setObjectName("confirmDbPathButton") sizePolicy = QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.confirmDbPathButton.sizePolicy().hasHeightForWidth()) + 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(u"dbVersionLabel") - self.dbVersionLabel.setText(u"-") + self.dbVersionLabel.setObjectName("dbVersionLabel") + self.dbVersionLabel.setText("-") self.formLayout.setWidget(4, QFormLayout.FieldRole, self.dbVersionLabel) - self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) + self.verticalSpacer = QSpacerItem( + 20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding + ) self.formLayout.setItem(6, QFormLayout.FieldRole, self.verticalSpacer) self.label_5 = QLabel(DatabaseChecker) - self.label_5.setObjectName(u"label_5") + self.label_5.setObjectName("label_5") self.formLayout.setWidget(7, QFormLayout.LabelRole, self.label_5) self.dbCheckConnLabel = QLabel(DatabaseChecker) - self.dbCheckConnLabel.setObjectName(u"dbCheckConnLabel") - self.dbCheckConnLabel.setText(u"...") + self.dbCheckConnLabel.setObjectName("dbCheckConnLabel") + self.dbCheckConnLabel.setText("...") self.formLayout.setWidget(7, QFormLayout.FieldRole, self.dbCheckConnLabel) self.continueButton = QPushButton(DatabaseChecker) - self.continueButton.setObjectName(u"continueButton") + self.continueButton.setObjectName("continueButton") self.continueButton.setEnabled(False) self.formLayout.setWidget(8, QFormLayout.SpanningRole, self.continueButton) self.label_2 = QLabel(DatabaseChecker) - self.label_2.setObjectName(u"label_2") + self.label_2.setObjectName("label_2") self.formLayout.setWidget(4, QFormLayout.LabelRole, self.label_2) self.line = QFrame(DatabaseChecker) - self.line.setObjectName(u"line") + self.line.setObjectName("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", 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)) + self.label.setText( + QCoreApplication.translate("DatabaseChecker", "dbPathLabel", None) + ) + self.label_3.setText( + QCoreApplication.translate("DatabaseChecker", "dbFilenameLabel", None) + ) + self.confirmDbPathButton.setText( + QCoreApplication.translate("DatabaseChecker", "confirmDbPathButton", None) + ) + self.label_5.setText( + QCoreApplication.translate("DatabaseChecker", "dbCheckConnLabel", None) + ) + self.continueButton.setText( + QCoreApplication.translate("DatabaseChecker", "continueButton", None) + ) + self.label_2.setText( + QCoreApplication.translate("DatabaseChecker", "dbVersionLabel", None) + ) pass - # retranslateUi + # retranslateUi