wip: arcaea-offline==0.2.0

This commit is contained in:
2023-09-16 18:59:59 +08:00
parent 5d68156dba
commit 1d223fe32a
5 changed files with 417 additions and 258 deletions

View File

@ -31,41 +31,104 @@
</property>
</widget>
</item>
<item row="1" column="0">
<item row="5" column="0">
<widget class="QPushButton" name="importSt3Button">
<property name="text">
<string>importSt3Button</string>
</property>
</widget>
</item>
<item row="1" column="1">
<item row="5" column="1">
<widget class="QLabel" name="label_2">
<property name="text">
<string>importSt3.description</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<item row="6" column="0" colspan="2">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="3" column="0">
<item row="7" column="0">
<widget class="QPushButton" name="exportScoresButton">
<property name="text">
<string>exportScoresButton</string>
</property>
</widget>
</item>
<item row="3" column="1">
<item row="7" column="1">
<widget class="QLabel" name="label_3">
<property name="text">
<string>exportScores.description</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QPushButton" name="importPacklistButton">
<property name="text">
<string>importPacklistButton</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QPushButton" name="importSonglistButton">
<property name="text">
<string>importSonglistButton</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_4">
<property name="text">
<string>importPacklist.description</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="label_5">
<property name="text">
<string>importSonglist.description</string>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QPushButton" name="exportArcsongJsonButton">
<property name="text">
<string>exportArcsongJsonButton</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QLabel" name="label_6">
<property name="text">
<string>exportArcsongJson.description</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QPushButton" name="importApkButton">
<property name="text">
<string>importApkButton</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="label_7">
<property name="text">
<string>importApk.description</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>

View File

@ -1,82 +1,137 @@
# -*- coding: utf-8 -*-
################################################################################
## Form generated from reading UI file 'tabDb_Manage.ui'
##
## 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, 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, QLabel,
QPushButton, QSizePolicy, QWidget)
class Ui_TabDb_Manage(object):
def setupUi(self, TabDb_Manage):
if not TabDb_Manage.objectName():
TabDb_Manage.setObjectName(u"TabDb_Manage")
TabDb_Manage.resize(630, 528)
TabDb_Manage.setWindowTitle(u"TabDb_Manage")
self.formLayout = QFormLayout(TabDb_Manage)
self.formLayout.setObjectName(u"formLayout")
self.formLayout.setLabelAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
self.syncArcSongDbButton = QPushButton(TabDb_Manage)
self.syncArcSongDbButton.setObjectName(u"syncArcSongDbButton")
self.formLayout.setWidget(0, QFormLayout.LabelRole, self.syncArcSongDbButton)
self.label = QLabel(TabDb_Manage)
self.label.setObjectName(u"label")
self.formLayout.setWidget(0, QFormLayout.FieldRole, self.label)
self.importSt3Button = QPushButton(TabDb_Manage)
self.importSt3Button.setObjectName(u"importSt3Button")
self.formLayout.setWidget(1, QFormLayout.LabelRole, self.importSt3Button)
self.label_2 = QLabel(TabDb_Manage)
self.label_2.setObjectName(u"label_2")
self.formLayout.setWidget(1, QFormLayout.FieldRole, self.label_2)
self.line = QFrame(TabDb_Manage)
self.line.setObjectName(u"line")
self.line.setFrameShape(QFrame.HLine)
self.line.setFrameShadow(QFrame.Sunken)
self.formLayout.setWidget(2, QFormLayout.SpanningRole, self.line)
self.exportScoresButton = QPushButton(TabDb_Manage)
self.exportScoresButton.setObjectName(u"exportScoresButton")
self.formLayout.setWidget(3, QFormLayout.LabelRole, self.exportScoresButton)
self.label_3 = QLabel(TabDb_Manage)
self.label_3.setObjectName(u"label_3")
self.formLayout.setWidget(3, QFormLayout.FieldRole, self.label_3)
self.retranslateUi(TabDb_Manage)
QMetaObject.connectSlotsByName(TabDb_Manage)
# setupUi
def retranslateUi(self, TabDb_Manage):
self.syncArcSongDbButton.setText(QCoreApplication.translate("TabDb_Manage", u"syncArcSongDbButton", None))
self.label.setText(QCoreApplication.translate("TabDb_Manage", u"syncArcSongDb.description", None))
self.importSt3Button.setText(QCoreApplication.translate("TabDb_Manage", u"importSt3Button", None))
self.label_2.setText(QCoreApplication.translate("TabDb_Manage", u"importSt3.description", None))
self.exportScoresButton.setText(QCoreApplication.translate("TabDb_Manage", u"exportScoresButton", None))
self.label_3.setText(QCoreApplication.translate("TabDb_Manage", u"exportScores.description", None))
pass
# retranslateUi
# -*- coding: utf-8 -*-
################################################################################
## Form generated from reading UI file 'tabDb_Manage.ui'
##
## 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, 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, QLabel,
QPushButton, QSizePolicy, QWidget)
class Ui_TabDb_Manage(object):
def setupUi(self, TabDb_Manage):
if not TabDb_Manage.objectName():
TabDb_Manage.setObjectName(u"TabDb_Manage")
TabDb_Manage.resize(630, 528)
TabDb_Manage.setWindowTitle(u"TabDb_Manage")
self.formLayout = QFormLayout(TabDb_Manage)
self.formLayout.setObjectName(u"formLayout")
self.formLayout.setLabelAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
self.syncArcSongDbButton = QPushButton(TabDb_Manage)
self.syncArcSongDbButton.setObjectName(u"syncArcSongDbButton")
self.formLayout.setWidget(0, QFormLayout.LabelRole, self.syncArcSongDbButton)
self.label = QLabel(TabDb_Manage)
self.label.setObjectName(u"label")
self.formLayout.setWidget(0, QFormLayout.FieldRole, self.label)
self.importSt3Button = QPushButton(TabDb_Manage)
self.importSt3Button.setObjectName(u"importSt3Button")
self.formLayout.setWidget(5, QFormLayout.LabelRole, self.importSt3Button)
self.label_2 = QLabel(TabDb_Manage)
self.label_2.setObjectName(u"label_2")
self.formLayout.setWidget(5, QFormLayout.FieldRole, self.label_2)
self.line = QFrame(TabDb_Manage)
self.line.setObjectName(u"line")
self.line.setFrameShape(QFrame.HLine)
self.line.setFrameShadow(QFrame.Sunken)
self.formLayout.setWidget(6, QFormLayout.SpanningRole, self.line)
self.exportScoresButton = QPushButton(TabDb_Manage)
self.exportScoresButton.setObjectName(u"exportScoresButton")
self.formLayout.setWidget(7, QFormLayout.LabelRole, self.exportScoresButton)
self.label_3 = QLabel(TabDb_Manage)
self.label_3.setObjectName(u"label_3")
self.formLayout.setWidget(7, QFormLayout.FieldRole, self.label_3)
self.line_2 = QFrame(TabDb_Manage)
self.line_2.setObjectName(u"line_2")
self.line_2.setFrameShape(QFrame.HLine)
self.line_2.setFrameShadow(QFrame.Sunken)
self.formLayout.setWidget(1, QFormLayout.SpanningRole, self.line_2)
self.importPacklistButton = QPushButton(TabDb_Manage)
self.importPacklistButton.setObjectName(u"importPacklistButton")
self.formLayout.setWidget(2, QFormLayout.LabelRole, self.importPacklistButton)
self.importSonglistButton = QPushButton(TabDb_Manage)
self.importSonglistButton.setObjectName(u"importSonglistButton")
self.formLayout.setWidget(3, QFormLayout.LabelRole, self.importSonglistButton)
self.label_4 = QLabel(TabDb_Manage)
self.label_4.setObjectName(u"label_4")
self.formLayout.setWidget(2, QFormLayout.FieldRole, self.label_4)
self.label_5 = QLabel(TabDb_Manage)
self.label_5.setObjectName(u"label_5")
self.formLayout.setWidget(3, QFormLayout.FieldRole, self.label_5)
self.exportArcsongJsonButton = QPushButton(TabDb_Manage)
self.exportArcsongJsonButton.setObjectName(u"exportArcsongJsonButton")
self.formLayout.setWidget(8, QFormLayout.LabelRole, self.exportArcsongJsonButton)
self.label_6 = QLabel(TabDb_Manage)
self.label_6.setObjectName(u"label_6")
self.formLayout.setWidget(8, QFormLayout.FieldRole, self.label_6)
self.importApkButton = QPushButton(TabDb_Manage)
self.importApkButton.setObjectName(u"importApkButton")
self.formLayout.setWidget(4, QFormLayout.LabelRole, self.importApkButton)
self.label_7 = QLabel(TabDb_Manage)
self.label_7.setObjectName(u"label_7")
self.formLayout.setWidget(4, QFormLayout.FieldRole, self.label_7)
self.retranslateUi(TabDb_Manage)
QMetaObject.connectSlotsByName(TabDb_Manage)
# setupUi
def retranslateUi(self, TabDb_Manage):
self.syncArcSongDbButton.setText(QCoreApplication.translate("TabDb_Manage", u"syncArcSongDbButton", None))
self.label.setText(QCoreApplication.translate("TabDb_Manage", u"syncArcSongDb.description", None))
self.importSt3Button.setText(QCoreApplication.translate("TabDb_Manage", u"importSt3Button", None))
self.label_2.setText(QCoreApplication.translate("TabDb_Manage", u"importSt3.description", None))
self.exportScoresButton.setText(QCoreApplication.translate("TabDb_Manage", u"exportScoresButton", None))
self.label_3.setText(QCoreApplication.translate("TabDb_Manage", u"exportScores.description", None))
self.importPacklistButton.setText(QCoreApplication.translate("TabDb_Manage", u"importPacklistButton", None))
self.importSonglistButton.setText(QCoreApplication.translate("TabDb_Manage", u"importSonglistButton", None))
self.label_4.setText(QCoreApplication.translate("TabDb_Manage", u"importPacklist.description", None))
self.label_5.setText(QCoreApplication.translate("TabDb_Manage", u"importSonglist.description", None))
self.exportArcsongJsonButton.setText(QCoreApplication.translate("TabDb_Manage", u"exportArcsongJsonButton", None))
self.label_6.setText(QCoreApplication.translate("TabDb_Manage", u"exportArcsongJson.description", None))
self.importApkButton.setText(QCoreApplication.translate("TabDb_Manage", u"importApkButton", None))
self.label_7.setText(QCoreApplication.translate("TabDb_Manage", u"importApk.description", None))
pass
# retranslateUi

View File

@ -1,9 +1,15 @@
import json
import logging
import traceback
import zipfile
from arcaea_offline.database import Database
from arcaea_offline.external.arcaea.st3 import St3ScoreParser
from arcaea_offline.external.arcaea import (
PacklistParser,
SonglistParser,
St3ScoreParser,
)
from arcaea_offline.external.arcaea.common import ArcaeaParser
from arcaea_offline.external.arcsong import ArcsongDbParser
from PySide6.QtCore import QDir, Slot
from PySide6.QtWidgets import QFileDialog, QMessageBox, QWidget
@ -40,6 +46,93 @@ class TabDb_Manage(Ui_TabDb_Manage, QWidget):
self, "Sync Error", "\n".join(traceback.format_exception(e))
)
def importFromArcaeaParser(self, parser: ArcaeaParser, logName, path):
# extracted by sourcery
db = Database()
with db.sessionmaker() as session:
parser.write_database(session)
itemNum = len(parser.parse())
logger.info(f"updated {itemNum} {logName} from {path}")
return itemNum
def importPacklist(self, packlistPath) -> int:
packlistParser = PacklistParser(packlistPath)
return self.importFromArcaeaParser(packlistParser, "packs", packlistPath)
def importSonglist(self, songlistPath) -> int:
songlistParser = SonglistParser(songlistPath)
return self.importFromArcaeaParser(songlistParser, "songs", songlistPath)
@Slot()
def on_importPacklistButton_clicked(self):
try:
packlistFile, filter = QFileDialog.getOpenFileName(
self, "Select packlist file"
)
if not packlistFile:
return
packNum = self.importPacklist(packlistFile)
QMessageBox.information(
self, None, f"Updated {packNum} packs from<br>{packlistFile}"
)
except Exception as e:
logger.exception("import packlist error")
QMessageBox.critical(
self, "Import Error", "\n".join(traceback.format_exception(e))
)
@Slot()
def on_importSonglistButton_clicked(self):
try:
songlistFile, filter = QFileDialog.getOpenFileName(
self, "Select songlist file"
)
if not songlistFile:
return
songNum = self.importSonglist(songlistFile)
QMessageBox.information(
self, None, f"Updated {songNum} songs from<br>{songlistFile}"
)
except Exception as e:
logger.exception("import songlist error")
QMessageBox.critical(
self, "Import Error", "\n".join(traceback.format_exception(e))
)
@Slot()
def on_importApkButton_clicked(self):
apkFile, filter = QFileDialog.getOpenFileName(
self, "Select APK file", "", "APK File (*.apk);;*"
)
if not apkFile:
return
try:
logger.info(f"Importing {apkFile}")
with zipfile.ZipFile(apkFile) as zf:
packlistPath = zipfile.Path(zf) / "assets" / "songs" / "packlist"
songlistPath = zipfile.Path(zf) / "assets" / "songs" / "songlist"
packsNum = self.importPacklist(packlistPath)
songsNum = self.importSonglist(songlistPath)
message = [
f"{packsNum} packs and {songsNum} songs updated from",
str(apkFile),
]
QMessageBox.information(self, None, "<br>".join(message))
except Exception as e:
logging.exception("import apk error")
QMessageBox.critical(
self, "Import Error", "\n".join(traceback.format_exception(e))
)
@Slot()
def on_importSt3Button_clicked(self):
dbFile, filter = QFileDialog.getOpenFileName(self, "Select st3 file")
@ -77,3 +170,17 @@ class TabDb_Manage(Ui_TabDb_Manage, QWidget):
)
with open(exportLocation, "w", encoding="utf-8") as f:
f.write(content)
@Slot()
def on_exportArcsongJsonButton_clicked(self):
scores = Database().generate_arcsong()
content = json.dumps(scores, ensure_ascii=False)
exportLocation, _filter = QFileDialog.getSaveFileName(
self,
"Save your scores to...",
QDir.current().filePath("arcsong.json"),
"JSON (*.json);;*",
)
with open(exportLocation, "w", encoding="utf-8") as f:
f.write(content)

View File

@ -351,58 +351,58 @@ validation</translation>
<translation>Commit</translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="106"/>
<location filename="../../implements/components/scoreEditor.py" line="110"/>
<source>emptyScoreDialog.title</source>
<translation>Empty Score</translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="107"/>
<location filename="../../implements/components/scoreEditor.py" line="111"/>
<source>emptyScoreDialog.content</source>
<translation>Are you sure to commit an empty score?</translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="86"/>
<location filename="../../implements/components/scoreEditor.py" line="87"/>
<location filename="../../implements/components/scoreEditor.py" line="90"/>
<location filename="../../implements/components/scoreEditor.py" line="91"/>
<source>chartInvalidDialog.title</source>
<translation>Chart Invalid</translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="95"/>
<location filename="../../implements/components/scoreEditor.py" line="99"/>
<source>scoreMismatchDialog.title</source>
<translation>Possible Invalid Score</translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="96"/>
<location filename="../../implements/components/scoreEditor.py" line="100"/>
<source>scoreMismatchDialog.content</source>
<translation>The entered score may not match the selected chart. Commit this score anyway?</translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="181"/>
<location filename="../../implements/components/scoreEditor.py" line="185"/>
<source>validate.ok</source>
<translation>OK</translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="183"/>
<location filename="../../implements/components/scoreEditor.py" line="187"/>
<source>validate.chartInvalid</source>
<translation>Chart invalid</translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="185"/>
<location filename="../../implements/components/scoreEditor.py" line="189"/>
<source>validate.scoreMismatch</source>
<translation>Possible invalid score</translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="187"/>
<location filename="../../implements/components/scoreEditor.py" line="191"/>
<source>validate.scoreEmpty</source>
<translation>Empty score</translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="189"/>
<location filename="../../implements/components/scoreEditor.py" line="193"/>
<source>validate.scoreIncomplete</source>
<translation>Score incomplete, cannot verify</translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="192"/>
<location filename="../../implements/components/scoreEditor.py" line="196"/>
<source>validate.unknownState</source>
<translation>Unknown</translation>
</message>
@ -564,6 +564,46 @@ validation</translation>
<source>exportScores.description</source>
<translation>Export all your scores to a JSON file</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="79"/>
<source>importPacklistButton</source>
<translation>Import packlist</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="86"/>
<source>importSonglistButton</source>
<translation>Import songlist</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="93"/>
<source>importPacklist.description</source>
<translation>Import packlist file</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="100"/>
<source>importSonglist.description</source>
<translation>Import songlist file</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="107"/>
<source>exportArcsongJsonButton</source>
<translation>Export arcsong.json</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="114"/>
<source>exportArcsongJson.description</source>
<translation>Export arcsong.json file</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="121"/>
<source>importApkButton</source>
<translation>Import APK</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="128"/>
<source>importApk.description</source>
<translation>Import packlist and songlist from .apk file</translation>
</message>
</context>
<context>
<name>TabInputScore</name>
@ -667,79 +707,6 @@ validation</translation>
<source>tab.infoLookup</source>
<translation>Chart Info Lookup</translation>
</message>
<message>
<location filename="../../designer/tabs/tabToolsEntry.ui" line="29"/>
<source>tab.andreal</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TabTools_Andreal</name>
<message>
<location filename="../../designer/tabs/tabTools/tabTools_Andreal.ui" line="23"/>
<source>andrealPathSelector</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../designer/tabs/tabTools/tabTools_Andreal.ui" line="40"/>
<source>andrealExecutableSelector</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../designer/tabs/tabTools/tabTools_Andreal.ui" line="50"/>
<source>imageType</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../designer/tabs/tabTools/tabTools_Andreal.ui" line="60"/>
<source>imageVersion</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../designer/tabs/tabTools/tabTools_Andreal.ui" line="98"/>
<source>exportJsonButton</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../designer/tabs/tabTools/tabTools_Andreal.ui" line="105"/>
<source>generateButton</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../designer/tabs/tabTools/tabTools_Andreal.ui" line="127"/>
<source>previewImage</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../designer/tabs/tabTools/tabTools_Andreal.ui" line="149"/>
<source>imageType.recent</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../designer/tabs/tabTools/tabTools_Andreal.ui" line="156"/>
<source>imageType.best</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../designer/tabs/tabTools/tabTools_Andreal.ui" line="163"/>
<source>imageType.best30</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../designer/tabs/tabTools/tabTools_Andreal.ui" line="172"/>
<source>imageFormat</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../designer/tabs/tabTools/tabTools_Andreal.ui" line="220"/>
<source>chart</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../designer/tabs/tabTools/tabTools_Andreal.ui" line="227"/>
<source>imageQuality</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TabTools_InfoLookup</name>

View File

@ -350,58 +350,58 @@
<translation></translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="106"/>
<location filename="../../implements/components/scoreEditor.py" line="110"/>
<source>emptyScoreDialog.title</source>
<translation></translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="107"/>
<location filename="../../implements/components/scoreEditor.py" line="111"/>
<source>emptyScoreDialog.content</source>
<translation></translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="86"/>
<location filename="../../implements/components/scoreEditor.py" line="87"/>
<location filename="../../implements/components/scoreEditor.py" line="90"/>
<location filename="../../implements/components/scoreEditor.py" line="91"/>
<source>chartInvalidDialog.title</source>
<translation></translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="95"/>
<location filename="../../implements/components/scoreEditor.py" line="99"/>
<source>scoreMismatchDialog.title</source>
<translation></translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="96"/>
<location filename="../../implements/components/scoreEditor.py" line="100"/>
<source>scoreMismatchDialog.content</source>
<translation></translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="181"/>
<location filename="../../implements/components/scoreEditor.py" line="185"/>
<source>validate.ok</source>
<translation>OK</translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="183"/>
<location filename="../../implements/components/scoreEditor.py" line="187"/>
<source>validate.chartInvalid</source>
<translation></translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="185"/>
<location filename="../../implements/components/scoreEditor.py" line="189"/>
<source>validate.scoreMismatch</source>
<translation></translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="187"/>
<location filename="../../implements/components/scoreEditor.py" line="191"/>
<source>validate.scoreEmpty</source>
<translation></translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="189"/>
<location filename="../../implements/components/scoreEditor.py" line="193"/>
<source>validate.scoreIncomplete</source>
<translation></translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="192"/>
<location filename="../../implements/components/scoreEditor.py" line="196"/>
<source>validate.unknownState</source>
<translation></translation>
</message>
@ -563,6 +563,46 @@
<source>exportScores.description</source>
<translation> JSON </translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="79"/>
<source>importPacklistButton</source>
<translation> packlist</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="86"/>
<source>importSonglistButton</source>
<translation> songlist</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="93"/>
<source>importPacklist.description</source>
<translation> packlist </translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="100"/>
<source>importSonglist.description</source>
<translation> songlist </translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="107"/>
<source>exportArcsongJsonButton</source>
<translation> arcsong.json</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="114"/>
<source>exportArcsongJson.description</source>
<translation> arcsong.json </translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="121"/>
<source>importApkButton</source>
<translation> APK</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="128"/>
<source>importApk.description</source>
<translation> .apk packlist songlist</translation>
</message>
</context>
<context>
<name>TabInputScore</name>
@ -666,79 +706,6 @@
<source>tab.infoLookup</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/tabs/tabToolsEntry.ui" line="29"/>
<source>tab.andreal</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TabTools_Andreal</name>
<message>
<location filename="../../designer/tabs/tabTools/tabTools_Andreal.ui" line="23"/>
<source>andrealPathSelector</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../designer/tabs/tabTools/tabTools_Andreal.ui" line="40"/>
<source>andrealExecutableSelector</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../designer/tabs/tabTools/tabTools_Andreal.ui" line="50"/>
<source>imageType</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../designer/tabs/tabTools/tabTools_Andreal.ui" line="60"/>
<source>imageVersion</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../designer/tabs/tabTools/tabTools_Andreal.ui" line="98"/>
<source>exportJsonButton</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../designer/tabs/tabTools/tabTools_Andreal.ui" line="105"/>
<source>generateButton</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../designer/tabs/tabTools/tabTools_Andreal.ui" line="127"/>
<source>previewImage</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../designer/tabs/tabTools/tabTools_Andreal.ui" line="149"/>
<source>imageType.recent</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../designer/tabs/tabTools/tabTools_Andreal.ui" line="156"/>
<source>imageType.best</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../designer/tabs/tabTools/tabTools_Andreal.ui" line="163"/>
<source>imageType.best30</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../designer/tabs/tabTools/tabTools_Andreal.ui" line="172"/>
<source>imageFormat</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../designer/tabs/tabTools/tabTools_Andreal.ui" line="220"/>
<source>chart</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../designer/tabs/tabTools/tabTools_Andreal.ui" line="227"/>
<source>imageQuality</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TabTools_InfoLookup</name>