mirror of
https://github.com/283375/arcaea-offline-pyside-ui.git
synced 2025-07-01 04:16:26 +00:00
wip: arcaea-offline==0.2.0
- fix imports
This commit is contained in:
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
11
ui/extends/shared/database.py
Normal file
11
ui/extends/shared/database.py
Normal file
@ -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)
|
@ -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,
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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]}<br><font color="gray">{texts[1]}</font>'
|
||||
@ -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:
|
||||
|
@ -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)
|
||||
|
@ -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):
|
||||
|
@ -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")
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user