Compare commits

...

2 Commits

Author SHA1 Message Date
55ef2ba3bb
feat: import from Online 2023-10-18 01:26:12 +08:00
105d5c1dfb
impr: refine DatabaseUpdateSignals 2023-10-17 22:47:16 +08:00
9 changed files with 108 additions and 34 deletions

View File

@ -45,21 +45,21 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="6" column="0" colspan="2"> <item row="7" column="0" colspan="2">
<widget class="Line" name="line"> <widget class="Line" name="line">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
</widget> </widget>
</item> </item>
<item row="7" column="0"> <item row="8" column="0">
<widget class="QPushButton" name="exportScoresButton"> <widget class="QPushButton" name="exportScoresButton">
<property name="text"> <property name="text">
<string>exportScoresButton</string> <string>exportScoresButton</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="7" column="1"> <item row="8" column="1">
<widget class="QLabel" name="label_3"> <widget class="QLabel" name="label_3">
<property name="text"> <property name="text">
<string>exportScores.description</string> <string>exportScores.description</string>
@ -101,14 +101,14 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="8" column="0"> <item row="9" column="0">
<widget class="QPushButton" name="exportArcsongJsonButton"> <widget class="QPushButton" name="exportArcsongJsonButton">
<property name="text"> <property name="text">
<string>exportArcsongJsonButton</string> <string>exportArcsongJsonButton</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="8" column="1"> <item row="9" column="1">
<widget class="QLabel" name="label_6"> <widget class="QLabel" name="label_6">
<property name="text"> <property name="text">
<string>exportArcsongJson.description</string> <string>exportArcsongJson.description</string>
@ -129,6 +129,20 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="6" column="0">
<widget class="QPushButton" name="importOnlineButton">
<property name="text">
<string>importOnlineButton</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLabel" name="label_8">
<property name="text">
<string>importOnline.description</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<resources/> <resources/>

View File

@ -52,17 +52,17 @@ class Ui_TabDb_Manage(object):
self.line.setFrameShape(QFrame.HLine) self.line.setFrameShape(QFrame.HLine)
self.line.setFrameShadow(QFrame.Sunken) self.line.setFrameShadow(QFrame.Sunken)
self.formLayout.setWidget(6, QFormLayout.SpanningRole, self.line) self.formLayout.setWidget(7, QFormLayout.SpanningRole, self.line)
self.exportScoresButton = QPushButton(TabDb_Manage) self.exportScoresButton = QPushButton(TabDb_Manage)
self.exportScoresButton.setObjectName(u"exportScoresButton") self.exportScoresButton.setObjectName(u"exportScoresButton")
self.formLayout.setWidget(7, QFormLayout.LabelRole, self.exportScoresButton) self.formLayout.setWidget(8, QFormLayout.LabelRole, self.exportScoresButton)
self.label_3 = QLabel(TabDb_Manage) self.label_3 = QLabel(TabDb_Manage)
self.label_3.setObjectName(u"label_3") self.label_3.setObjectName(u"label_3")
self.formLayout.setWidget(7, QFormLayout.FieldRole, self.label_3) self.formLayout.setWidget(8, QFormLayout.FieldRole, self.label_3)
self.line_2 = QFrame(TabDb_Manage) self.line_2 = QFrame(TabDb_Manage)
self.line_2.setObjectName(u"line_2") self.line_2.setObjectName(u"line_2")
@ -94,12 +94,12 @@ class Ui_TabDb_Manage(object):
self.exportArcsongJsonButton = QPushButton(TabDb_Manage) self.exportArcsongJsonButton = QPushButton(TabDb_Manage)
self.exportArcsongJsonButton.setObjectName(u"exportArcsongJsonButton") self.exportArcsongJsonButton.setObjectName(u"exportArcsongJsonButton")
self.formLayout.setWidget(8, QFormLayout.LabelRole, self.exportArcsongJsonButton) self.formLayout.setWidget(9, QFormLayout.LabelRole, self.exportArcsongJsonButton)
self.label_6 = QLabel(TabDb_Manage) self.label_6 = QLabel(TabDb_Manage)
self.label_6.setObjectName(u"label_6") self.label_6.setObjectName(u"label_6")
self.formLayout.setWidget(8, QFormLayout.FieldRole, self.label_6) self.formLayout.setWidget(9, QFormLayout.FieldRole, self.label_6)
self.importApkButton = QPushButton(TabDb_Manage) self.importApkButton = QPushButton(TabDb_Manage)
self.importApkButton.setObjectName(u"importApkButton") self.importApkButton.setObjectName(u"importApkButton")
@ -111,6 +111,16 @@ class Ui_TabDb_Manage(object):
self.formLayout.setWidget(4, QFormLayout.FieldRole, self.label_7) self.formLayout.setWidget(4, QFormLayout.FieldRole, self.label_7)
self.importOnlineButton = QPushButton(TabDb_Manage)
self.importOnlineButton.setObjectName(u"importOnlineButton")
self.formLayout.setWidget(6, QFormLayout.LabelRole, self.importOnlineButton)
self.label_8 = QLabel(TabDb_Manage)
self.label_8.setObjectName(u"label_8")
self.formLayout.setWidget(6, QFormLayout.FieldRole, self.label_8)
self.retranslateUi(TabDb_Manage) self.retranslateUi(TabDb_Manage)
@ -132,6 +142,8 @@ class Ui_TabDb_Manage(object):
self.label_6.setText(QCoreApplication.translate("TabDb_Manage", u"exportArcsongJson.description", None)) self.label_6.setText(QCoreApplication.translate("TabDb_Manage", u"exportArcsongJson.description", None))
self.importApkButton.setText(QCoreApplication.translate("TabDb_Manage", u"importApkButton", None)) self.importApkButton.setText(QCoreApplication.translate("TabDb_Manage", u"importApkButton", None))
self.label_7.setText(QCoreApplication.translate("TabDb_Manage", u"importApk.description", None)) self.label_7.setText(QCoreApplication.translate("TabDb_Manage", u"importApk.description", None))
self.importOnlineButton.setText(QCoreApplication.translate("TabDb_Manage", u"importOnlineButton", None))
self.label_8.setText(QCoreApplication.translate("TabDb_Manage", u"importOnline.description", None))
pass pass
# retranslateUi # retranslateUi

View File

@ -12,7 +12,8 @@ def create_engine(_url: str | QUrl, pool: Type[Pool] = NullPool) -> Engine:
class DatabaseUpdateSignals(QObject): class DatabaseUpdateSignals(QObject):
songDataUpdated = Signal() songAddOrDelete = Signal()
chartInfoUpdated = Signal()
databaseUpdateSignals = DatabaseUpdateSignals() databaseUpdateSignals = DatabaseUpdateSignals()

View File

@ -35,10 +35,11 @@ class ChartSelector(Ui_ChartSelector, QWidget):
self.ratingClassSelector.valueChanged.connect(self.valueChanged) self.ratingClassSelector.valueChanged.connect(self.valueChanged)
# handle `songIdSelector.updateDatabase` by this component # handle `songIdSelector.updateDatabase` by this component
databaseUpdateSignals.songDataUpdated.disconnect( databaseUpdateSignals.songAddOrDelete.disconnect(
self.songIdSelector.updateDatabase self.songIdSelector.updateDatabase
) )
databaseUpdateSignals.songDataUpdated.connect(self.updateDatabase) databaseUpdateSignals.songAddOrDelete.connect(self.updateDatabase)
databaseUpdateSignals.chartInfoUpdated.connect(self.updateResultLabel)
def setSongIdSelectorMode(self, mode: SongIdSelectorMode): def setSongIdSelectorMode(self, mode: SongIdSelectorMode):
self.songIdSelector.setMode(mode) self.songIdSelector.setMode(mode)

View File

@ -72,7 +72,7 @@ class SongIdSelector(Ui_SongIdSelector, QWidget):
self.songIdComboBox.currentIndexChanged.connect(self.valueChanged) self.songIdComboBox.currentIndexChanged.connect(self.valueChanged)
self.updateDatabase() self.updateDatabase()
databaseUpdateSignals.songDataUpdated.connect(self.updateDatabase) databaseUpdateSignals.songAddOrDelete.connect(self.updateDatabase)
def setMode(self, mode: SongIdSelectorMode): def setMode(self, mode: SongIdSelectorMode):
self.mode = mode self.mode = mode

View File

@ -48,7 +48,7 @@ class TabDb_ChartInfoEditor(Ui_TabDb_ChartInfoEditor, QWidget):
self.chartSelector.setSongIdSelectorMode(SongIdSelectorMode.SongId) self.chartSelector.setSongIdSelectorMode(SongIdSelectorMode.SongId)
self.chartSelector.valueChanged.connect(self.chartSelectorValueChanged) self.chartSelector.valueChanged.connect(self.chartSelectorValueChanged)
databaseUpdateSignals.songDataUpdated.connect(self.updateChartInfoAbsentModel) databaseUpdateSignals.chartInfoUpdated.connect(self.updateChartInfoAbsentModel)
self.updateChartInfoAbsentModel() self.updateChartInfoAbsentModel()
self.commitButton.clicked.connect(self.commitChartInfo) self.commitButton.clicked.connect(self.commitChartInfo)
@ -193,7 +193,7 @@ class TabDb_ChartInfoEditor(Ui_TabDb_ChartInfoEditor, QWidget):
with self.db.sessionmaker() as session: with self.db.sessionmaker() as session:
session.merge(chartInfo) session.merge(chartInfo)
session.commit() session.commit()
databaseUpdateSignals.songDataUpdated.emit() databaseUpdateSignals.chartInfoUpdated.emit()
def deleteChartInfo(self): def deleteChartInfo(self):
chart = self.chartSelector.value() chart = self.chartSelector.value()
@ -223,4 +223,4 @@ class TabDb_ChartInfoEditor(Ui_TabDb_ChartInfoEditor, QWidget):
with self.db.sessionmaker() as session: with self.db.sessionmaker() as session:
session.delete(chartInfo) session.delete(chartInfo)
session.commit() session.commit()
databaseUpdateSignals.songDataUpdated.emit() databaseUpdateSignals.chartInfoUpdated.emit()

View File

@ -5,6 +5,7 @@ import zipfile
from arcaea_offline.database import Database from arcaea_offline.database import Database
from arcaea_offline.external.arcaea import ( from arcaea_offline.external.arcaea import (
ArcaeaOnlineParser,
PacklistParser, PacklistParser,
SonglistDifficultiesParser, SonglistDifficultiesParser,
SonglistParser, SonglistParser,
@ -46,7 +47,7 @@ class TabDb_Manage(Ui_TabDb_Manage, QWidget):
with db.sessionmaker() as session: with db.sessionmaker() as session:
parser.write_database(session) parser.write_database(session)
session.commit() session.commit()
databaseUpdateSignals.songDataUpdated.emit() databaseUpdateSignals.chartInfoUpdated.emit()
QMessageBox.information(self, None, "OK") QMessageBox.information(self, None, "OK")
except Exception as e: except Exception as e:
logging.exception("Sync arcsong.db error") logging.exception("Sync arcsong.db error")
@ -62,7 +63,7 @@ class TabDb_Manage(Ui_TabDb_Manage, QWidget):
with db.sessionmaker() as session: with db.sessionmaker() as session:
parser.write_database(session) parser.write_database(session)
session.commit() session.commit()
databaseUpdateSignals.songDataUpdated.emit() databaseUpdateSignals.songAddOrDelete.emit()
itemNum = len([item for item in parser.parse() if isinstance(item, instance)]) itemNum = len([item for item in parser.parse() if isinstance(item, instance)])
logger.info(f"updated {itemNum} {logName} from {path}") logger.info(f"updated {itemNum} {logName} from {path}")
return itemNum return itemNum
@ -178,6 +179,31 @@ class TabDb_Manage(Ui_TabDb_Manage, QWidget):
self, "Import Error", "\n".join(traceback.format_exception(e)) self, "Import Error", "\n".join(traceback.format_exception(e))
) )
@Slot()
def on_importOnlineButton_clicked(self):
apiResultFile, filter = QFileDialog.getOpenFileName(
self, "Select API result JSON file"
)
if not apiResultFile:
return
try:
db = Database()
parser = ArcaeaOnlineParser(apiResultFile)
logger.info(
f"Got {len(parser.parse())} items from {apiResultFile}, writing into database..."
)
with db.sessionmaker() as session:
parser.write_database(session)
session.commit()
QMessageBox.information(self, None, "OK")
except Exception as e:
logging.exception("import Arcaea Online error")
QMessageBox.critical(
self, "Import Error", "\n".join(traceback.format_exception(e))
)
@Slot() @Slot()
def on_exportScoresButton_clicked(self): def on_exportScoresButton_clicked(self):
scores = Database().export_scores() scores = Database().export_scores()

View File

@ -102,22 +102,22 @@
<context> <context>
<name>DbScoreTableModel</name> <name>DbScoreTableModel</name>
<message> <message>
<location filename="../../extends/shared/models/tables/score.py" line="22"/> <location filename="../../extends/shared/models/tables/score.py" line="28"/>
<source>horizontalHeader.id</source> <source>horizontalHeader.id</source>
<translation>ID</translation> <translation>ID</translation>
</message> </message>
<message> <message>
<location filename="../../extends/shared/models/tables/score.py" line="23"/> <location filename="../../extends/shared/models/tables/score.py" line="29"/>
<source>horizontalHeader.chart</source> <source>horizontalHeader.chart</source>
<translation>Chart</translation> <translation>Chart</translation>
</message> </message>
<message> <message>
<location filename="../../extends/shared/models/tables/score.py" line="24"/> <location filename="../../extends/shared/models/tables/score.py" line="30"/>
<source>horizontalHeader.score</source> <source>horizontalHeader.score</source>
<translation>Score</translation> <translation>Score</translation>
</message> </message>
<message> <message>
<location filename="../../extends/shared/models/tables/score.py" line="25"/> <location filename="../../extends/shared/models/tables/score.py" line="31"/>
<source>horizontalHeader.potential</source> <source>horizontalHeader.potential</source>
<translation>Potential</translation> <translation>Potential</translation>
</message> </message>
@ -659,12 +659,12 @@ validation</translation>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="37"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="37"/>
<source>importSt3Button</source> <source>importSt3Button</source>
<translation>Import Score Database</translation> <translation>Import from Game Save</translation>
</message> </message>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="44"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="44"/>
<source>importSt3.description</source> <source>importSt3.description</source>
<translation>Import your local score database</translation> <translation>Import scores from your game save</translation>
</message> </message>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="58"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="58"/>
@ -709,13 +709,23 @@ validation</translation>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="121"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="121"/>
<source>importApkButton</source> <source>importApkButton</source>
<translation>Import APK</translation> <translation>Import from APK</translation>
</message> </message>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="128"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="128"/>
<source>importApk.description</source> <source>importApk.description</source>
<translation>Import packlist and songlist from .apk file</translation> <translation>Import packlist and songlist from .apk file</translation>
</message> </message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="135"/>
<source>importOnlineButton</source>
<translation>Import from Arcaea Online</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="142"/>
<source>importOnline.description</source>
<translation>Import scores from the result of Arcaea Online API</translation>
</message>
</context> </context>
<context> <context>
<name>TabOcrDisabled</name> <name>TabOcrDisabled</name>
@ -871,7 +881,7 @@ validation</translation>
<context> <context>
<name>TabOverview</name> <name>TabOverview</name>
<message> <message>
<location filename="../../implements/tabs/tabOverview.py" line="44"/> <location filename="../../implements/tabs/tabOverview.py" line="43"/>
<source>databaseDescribeLabel {} {} {} {} {} {}</source> <source>databaseDescribeLabel {} {} {} {} {} {}</source>
<translation>There are {} packs, {} songs, {} difficulties, {} chart info ({} complete) and {} scores in database.</translation> <translation>There are {} packs, {} songs, {} difficulties, {} chart info ({} complete) and {} scores in database.</translation>
</message> </message>

View File

@ -102,22 +102,22 @@
<context> <context>
<name>DbScoreTableModel</name> <name>DbScoreTableModel</name>
<message> <message>
<location filename="../../extends/shared/models/tables/score.py" line="22"/> <location filename="../../extends/shared/models/tables/score.py" line="28"/>
<source>horizontalHeader.id</source> <source>horizontalHeader.id</source>
<translation>ID</translation> <translation>ID</translation>
</message> </message>
<message> <message>
<location filename="../../extends/shared/models/tables/score.py" line="23"/> <location filename="../../extends/shared/models/tables/score.py" line="29"/>
<source>horizontalHeader.chart</source> <source>horizontalHeader.chart</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../../extends/shared/models/tables/score.py" line="24"/> <location filename="../../extends/shared/models/tables/score.py" line="30"/>
<source>horizontalHeader.score</source> <source>horizontalHeader.score</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../../extends/shared/models/tables/score.py" line="25"/> <location filename="../../extends/shared/models/tables/score.py" line="31"/>
<source>horizontalHeader.potential</source> <source>horizontalHeader.potential</source>
<translation> PTT</translation> <translation> PTT</translation>
</message> </message>
@ -658,7 +658,7 @@
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="37"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="37"/>
<source>importSt3Button</source> <source>importSt3Button</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="44"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="44"/>
@ -708,13 +708,23 @@
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="121"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="121"/>
<source>importApkButton</source> <source>importApkButton</source>
<translation> APK</translation> <translation>APK </translation>
</message> </message>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="128"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="128"/>
<source>importApk.description</source> <source>importApk.description</source>
<translation> .apk packlist songlist</translation> <translation> .apk packlist songlist</translation>
</message> </message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="135"/>
<source>importOnlineButton</source>
<translation> Arcaea Online </translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="142"/>
<source>importOnline.description</source>
<translation> Arcaea Online API </translation>
</message>
</context> </context>
<context> <context>
<name>TabOcrDisabled</name> <name>TabOcrDisabled</name>
@ -870,7 +880,7 @@
<context> <context>
<name>TabOverview</name> <name>TabOverview</name>
<message> <message>
<location filename="../../implements/tabs/tabOverview.py" line="44"/> <location filename="../../implements/tabs/tabOverview.py" line="43"/>
<source>databaseDescribeLabel {} {} {} {} {} {}</source> <source>databaseDescribeLabel {} {} {} {} {} {}</source>
<translation> {} {} {} {} {} {} </translation> <translation> {} {} {} {} {} {} </translation>
</message> </message>