16 Commits

Author SHA1 Message Date
d5895fe230 chore: v0.3.8 2024-04-01 01:00:46 +08:00
cd2e3f51ca ci: update build actions 2024-04-01 01:00:27 +08:00
4a09dc210a Merge pull request #7 from ArcaeaOffline/fix-issue-6
fix: rating class selection logic
2024-03-24 16:40:24 +08:00
cc8ab11b78 fix: rating class selection logic 2024-03-24 16:17:48 +08:00
48c5682e55 Merge pull request #5 from ArcaeaOffline/fix-issue-4
fix: linux dbUrl issue
2024-03-23 19:08:23 +08:00
ee03770764 chore: update README 2024-03-23 18:21:48 +08:00
b45c7f7de5 chore: dependencies 2024-03-23 18:18:53 +08:00
15bc56e6f9 fix: linux dbUrl issue 2024-03-23 17:41:36 +08:00
39ee379010 feat: ETERNAL rating class support 2024-03-20 15:52:26 +08:00
5a71a5822b feat: sync chart info database 2024-03-16 02:14:47 +08:00
c888b312b3 feat: DEF v2 scores export support 2024-02-27 17:24:49 +08:00
8e4fdc30b5 refactor(ui): TabDb_Manage 2024-02-15 17:59:14 +08:00
1ca868cfc6 ci: get full repo history for VERSION generating 2023-11-09 21:53:55 +08:00
d63d2f0d8b ci: build actions improve 2023-11-01 21:30:31 +08:00
3cd187fde3 ci: github actions 2023-11-01 20:00:16 +08:00
cce918a121 chore: update dependencies 2023-11-01 15:57:11 +08:00
14 changed files with 655 additions and 250 deletions

View File

@ -0,0 +1,40 @@
name: Build UI from latest `arcaea-offline-*` dependencies
run-name: ${{ github.actor }} started a build request.
on:
workflow_dispatch:
jobs:
build-windows:
runs-on: windows-2022
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-python@v5
with:
python-version: "3.11"
# install dependencies
- run: "pip install -r requirements.txt"
- run: "pip uninstall arcaea-offline arcaea-offline-ocr -y"
- run: "pip install git+https://github.com/283375/arcaea-offline"
- run: "pip install git+https://github.com/283375/arcaea-offline-ocr"
- run: "pip install nuitka imageio"
- name: Install UPX
uses: crazy-max/ghaction-upx@v3
with:
install-only: true
# release builtin files
- run: 'pyside6-lrelease.exe .\ui\resources\lang\en_US.ts .\ui\resources\lang\zh_CN.ts'
- run: "python prebuild.py"
- run: 'pyside6-rcc.exe .\ui\resources\resources.qrc -o .\ui\resources\resources_rc.py'
# build
- run: "python -m nuitka --plugin-enable=upx --enable-plugin=pyside6 --assume-yes-for-downloads --windows-icon-from-ico=./ui/resources/images/icon.png --standalone --onefile index.py"
- uses: actions/upload-artifact@v3
with:
name: build-windows
path: index.exe

49
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,49 @@
name: Build UI
run-name: ${{ github.actor }} started a build request.
on:
workflow_dispatch:
push:
tags:
- "v[0-9]+.[0-9]+.[0-9]+"
permissions:
contents: write
discussions: write
jobs:
build-windows:
runs-on: windows-2022
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-python@v5
with:
python-version: "3.11"
cache: "pip"
# install dependencies
- run: "pip install -r requirements.txt"
- run: "pip install nuitka imageio"
- name: Install UPX
uses: crazy-max/ghaction-upx@v3
with:
install-only: true
# release builtin files
- run: 'pyside6-lrelease.exe .\ui\resources\lang\en_US.ts .\ui\resources\lang\zh_CN.ts'
- run: "python prebuild.py"
- run: 'pyside6-rcc.exe .\ui\resources\resources.qrc -o .\ui\resources\resources_rc.py'
# build
- run: "python -m nuitka --plugin-enable=upx --enable-plugin=pyside6 --assume-yes-for-downloads --windows-icon-from-ico=./ui/resources/images/icon.png --standalone --onefile index.py"
- name: Draft a release
uses: softprops/action-gh-release@v2
with:
discussion_category_name: New releases
draft: true
generate_release_notes: true
files: |
index.exe

View File

@ -1,9 +1,27 @@
# Arcaea Offline PySide UI # Arcaea Offline PySide UI
GUI for both [283375/arcaea-offline](https://github.com/283375/arcaea-offline) and [283375/arcaea-offline-ocr](https://github.com/283375/arcaea-offline-ocr) GUI for both [283375/arcaea-offline](https://github.com/283375/arcaea-offline) and [ArcaeaOffline/core-ocr](https://github.com/ArcaeaOffline/core-ocr).
## Before you run `python index.py`... ## Prerequisites
* Install requirements * Install requirements
* Release translation files from `ui/resources/lang/*.ts` * Release translation files from `ui/resources/lang/*.ts`
* Run `prebuild.py`
* Compile `ui/resources/resources.qrc` to `ui/resources/resources_rc.py` * Compile `ui/resources/resources.qrc` to `ui/resources/resources_rc.py`
You can refer to the [GitHub Actions file](./.github/workflows/build.yml) for a rough reference.
```
pip install -r ./requirements.txt
pyside6-lrelease ./ui/resources/lang/en_US.ts ./ui/resources/lang/zh_CN.ts
python prebuild.py
pyside6-rcc ./ui/resources/resources.qrc -o ./ui/resources/resources_rc.py
```
Sometimes you have to install the latest, unpublished version of `arcaea-offline` and `arcaea-offline-ocr`.
```
pip uninstall -y arcaea-offline arcaea-offline-ocr
pip install git+https://github.com/283375/arcaea-offline
pip install git+https://github.com/ArcaeaOffline/core-ocr
```

View File

@ -40,7 +40,6 @@ def getBuildToolsVer():
def writeVersionFile(): def writeVersionFile():
versionFile = Path("ui/resources/VERSION") versionFile = Path("ui/resources/VERSION")
assert versionFile.exists()
versionText = ( versionText = (
"arcaea-offline-pyside-ui\n{gitDesc}\n{buildToolsVer}\n\n" "arcaea-offline-pyside-ui\n{gitDesc}\n{buildToolsVer}\n\n"

View File

@ -4,14 +4,14 @@ build-backend = "setuptools.build_meta"
[project] [project]
name = "arcaea-offline-pyside-ui" name = "arcaea-offline-pyside-ui"
version = "0.1.0" version = "0.3.8"
authors = [{ name = "283375", email = "log_283375@163.com" }] authors = [{ name = "283375", email = "log_283375@163.com" }]
description = "No description." description = "No description."
readme = "README.md" readme = "README.md"
requires-python = ">=3.9" requires-python = ">=3.9"
dependencies = [ dependencies = [
"arcaea-offline==0.1.0", "arcaea-offline==0.2.2",
"arcaea-offline-ocr==0.1.0", "arcaea-offline-ocr==0.0.98",
"exif==1.6.0", "exif==1.6.0",
"PySide6==6.5.2", "PySide6==6.5.2",
] ]
@ -21,8 +21,8 @@ classifiers = [
] ]
[project.urls] [project.urls]
"Homepage" = "https://github.com/283375/arcaea-offline-pyside-ui" "Homepage" = "https://github.com/ArcaeaOffline/client-pyside6"
"Bug Tracker" = "https://github.com/283375/arcaea-offline-pyside-ui/issues" "Bug Tracker" = "https://github.com/ArcaeaOffline/client-pyside6/issues"
[tool.black] [tool.black]
force-exclude = ''' force-exclude = '''

View File

@ -1,4 +1,5 @@
arcaea-offline==0.1.0 arcaea-offline==0.2.2
arcaea-offline-ocr==0.1.0 arcaea-offline-ocr==0.0.98
exif==1.6.0 exif==1.6.0
Pillow==10.1.0
PySide6==6.5.2 PySide6==6.5.2

View File

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>630</width> <width>580</width>
<height>528</height> <height>551</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -17,70 +17,21 @@
<property name="labelAlignment"> <property name="labelAlignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property> </property>
<item row="0" column="0"> <item row="1" column="0">
<widget class="QPushButton" name="syncArcSongDbButton">
<property name="text">
<string>syncArcSongDbButton</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label">
<property name="text">
<string>syncArcSongDb.description</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QPushButton" name="importSt3Button">
<property name="text">
<string>importSt3Button</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLabel" name="label_2">
<property name="text">
<string>importSt3.description</string>
</property>
</widget>
</item>
<item row="7" column="0" colspan="2">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QPushButton" name="exportScoresButton">
<property name="text">
<string>exportScoresButton</string>
</property>
</widget>
</item>
<item row="8" 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"> <widget class="QPushButton" name="importPacklistButton">
<property name="text"> <property name="text">
<string>importPacklistButton</string> <string>importPacklistButton</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="0"> <item row="1" column="1">
<widget class="QLabel" name="label_4">
<property name="text">
<string>importPacklist.description</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QPushButton" name="importSonglistButton"> <widget class="QPushButton" name="importSonglistButton">
<property name="text"> <property name="text">
<string>importSonglistButton</string> <string>importSonglistButton</string>
@ -88,69 +39,129 @@
</widget> </widget>
</item> </item>
<item row="2" column="1"> <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"> <widget class="QLabel" name="label_5">
<property name="text"> <property name="text">
<string>importSonglist.description</string> <string>importSonglist.description</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="9" column="0"> <item row="3" column="0">
<widget class="QPushButton" name="exportArcsongJsonButton">
<property name="text">
<string>exportArcsongJsonButton</string>
</property>
</widget>
</item>
<item row="9" 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"> <widget class="QPushButton" name="importApkButton">
<property name="text"> <property name="text">
<string>importApkButton</string> <string>importApkButton</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="1"> <item row="3" column="1">
<widget class="QLabel" name="label_7"> <widget class="QLabel" name="label_7">
<property name="text"> <property name="text">
<string>importApk.description</string> <string>importApk.description</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="0" colspan="2">
<widget class="QLabel" name="label_11">
<property name="font">
<font>
<pointsize>12</pointsize>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>chartInfoGroup</string>
</property>
</widget>
</item>
<item row="6" column="0"> <item row="6" column="0">
<widget class="QPushButton" name="syncArcSongDbButton">
<property name="text">
<string>syncArcSongDbButton</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLabel" name="label">
<property name="text">
<string>syncArcSongDb.description</string>
</property>
</widget>
</item>
<item row="9" column="0" colspan="2">
<widget class="QLabel" name="label_12">
<property name="font">
<font>
<pointsize>12</pointsize>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>importScoreGroup</string>
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QPushButton" name="importSt3Button">
<property name="text">
<string>importSt3Button</string>
</property>
</widget>
</item>
<item row="10" column="1">
<widget class="QLabel" name="label_2">
<property name="text">
<string>importSt3.description</string>
</property>
</widget>
</item>
<item row="11" column="0">
<widget class="QPushButton" name="importOnlineButton"> <widget class="QPushButton" name="importOnlineButton">
<property name="text"> <property name="text">
<string>importOnlineButton</string> <string>importOnlineButton</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="6" column="1"> <item row="11" column="1">
<widget class="QLabel" name="label_8"> <widget class="QLabel" name="label_8">
<property name="text"> <property name="text">
<string>importOnline.description</string> <string>importOnline.description</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="10" column="0"> <item row="13" column="0" colspan="2">
<widget class="QLabel" name="label_13">
<property name="font">
<font>
<pointsize>12</pointsize>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>exportScoreGroup</string>
</property>
</widget>
</item>
<item row="14" column="0">
<widget class="QPushButton" name="exportScoresButton">
<property name="text">
<string>exportScoresButton</string>
</property>
</widget>
</item>
<item row="14" column="1">
<widget class="QLabel" name="label_3">
<property name="text">
<string>exportScores.description</string>
</property>
</widget>
</item>
<item row="15" column="0">
<widget class="QPushButton" name="exportSmartRteB30Button"> <widget class="QPushButton" name="exportSmartRteB30Button">
<property name="text"> <property name="text">
<string>exportSmartRteB30Button</string> <string>exportSmartRteB30Button</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="10" column="1"> <item row="15" column="1">
<widget class="QLabel" name="label_9"> <widget class="QLabel" name="label_9">
<property name="text"> <property name="text">
<string>exportSmartRteB30.description</string> <string>exportSmartRteB30.description</string>
@ -163,6 +174,124 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="17" column="0" colspan="2">
<widget class="QLabel" name="label_14">
<property name="font">
<font>
<pointsize>12</pointsize>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>miscGroup</string>
</property>
</widget>
</item>
<item row="18" column="0">
<widget class="QPushButton" name="exportArcsongJsonButton">
<property name="text">
<string>exportArcsongJsonButton</string>
</property>
</widget>
</item>
<item row="18" column="1">
<widget class="QLabel" name="label_6">
<property name="text">
<string>exportArcsongJson.description</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="label_10">
<property name="font">
<font>
<pointsize>12</pointsize>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>packSongInfoGroup</string>
</property>
</widget>
</item>
<item row="4" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="8" column="0">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="12" column="0">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="16" column="0">
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="7" column="0">
<widget class="QPushButton" name="syncChartInfoDbButton">
<property name="text">
<string>syncChartInfoDbButton</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QLabel" name="label_15">
<property name="text">
<string>syncChartInfoDb.description</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<resources/> <resources/>

View File

@ -15,123 +15,168 @@ from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
QFont, QFontDatabase, QGradient, QIcon, QFont, QFontDatabase, QGradient, QIcon,
QImage, QKeySequence, QLinearGradient, QPainter, QImage, QKeySequence, QLinearGradient, QPainter,
QPalette, QPixmap, QRadialGradient, QTransform) QPalette, QPixmap, QRadialGradient, QTransform)
from PySide6.QtWidgets import (QApplication, QFormLayout, QFrame, QLabel, from PySide6.QtWidgets import (QApplication, QFormLayout, QLabel, QPushButton,
QPushButton, QSizePolicy, QWidget) QSizePolicy, QSpacerItem, QWidget)
class Ui_TabDb_Manage(object): class Ui_TabDb_Manage(object):
def setupUi(self, TabDb_Manage): def setupUi(self, TabDb_Manage):
if not TabDb_Manage.objectName(): if not TabDb_Manage.objectName():
TabDb_Manage.setObjectName(u"TabDb_Manage") TabDb_Manage.setObjectName(u"TabDb_Manage")
TabDb_Manage.resize(630, 528) TabDb_Manage.resize(580, 551)
TabDb_Manage.setWindowTitle(u"TabDb_Manage") TabDb_Manage.setWindowTitle(u"TabDb_Manage")
self.formLayout = QFormLayout(TabDb_Manage) self.formLayout = QFormLayout(TabDb_Manage)
self.formLayout.setObjectName(u"formLayout") self.formLayout.setObjectName(u"formLayout")
self.formLayout.setLabelAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) 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(7, QFormLayout.SpanningRole, self.line)
self.exportScoresButton = QPushButton(TabDb_Manage)
self.exportScoresButton.setObjectName(u"exportScoresButton")
self.formLayout.setWidget(8, QFormLayout.LabelRole, self.exportScoresButton)
self.label_3 = QLabel(TabDb_Manage)
self.label_3.setObjectName(u"label_3")
self.formLayout.setWidget(8, 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 = QPushButton(TabDb_Manage)
self.importPacklistButton.setObjectName(u"importPacklistButton") self.importPacklistButton.setObjectName(u"importPacklistButton")
self.formLayout.setWidget(2, QFormLayout.LabelRole, self.importPacklistButton) self.formLayout.setWidget(1, 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 = QLabel(TabDb_Manage)
self.label_4.setObjectName(u"label_4") self.label_4.setObjectName(u"label_4")
self.formLayout.setWidget(2, QFormLayout.FieldRole, self.label_4) self.formLayout.setWidget(1, QFormLayout.FieldRole, self.label_4)
self.importSonglistButton = QPushButton(TabDb_Manage)
self.importSonglistButton.setObjectName(u"importSonglistButton")
self.formLayout.setWidget(2, QFormLayout.LabelRole, self.importSonglistButton)
self.label_5 = QLabel(TabDb_Manage) self.label_5 = QLabel(TabDb_Manage)
self.label_5.setObjectName(u"label_5") self.label_5.setObjectName(u"label_5")
self.formLayout.setWidget(3, QFormLayout.FieldRole, self.label_5) self.formLayout.setWidget(2, QFormLayout.FieldRole, self.label_5)
self.exportArcsongJsonButton = QPushButton(TabDb_Manage)
self.exportArcsongJsonButton.setObjectName(u"exportArcsongJsonButton")
self.formLayout.setWidget(9, QFormLayout.LabelRole, self.exportArcsongJsonButton)
self.label_6 = QLabel(TabDb_Manage)
self.label_6.setObjectName(u"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")
self.formLayout.setWidget(4, QFormLayout.LabelRole, self.importApkButton) self.formLayout.setWidget(3, QFormLayout.LabelRole, self.importApkButton)
self.label_7 = QLabel(TabDb_Manage) self.label_7 = QLabel(TabDb_Manage)
self.label_7.setObjectName(u"label_7") self.label_7.setObjectName(u"label_7")
self.formLayout.setWidget(4, QFormLayout.FieldRole, self.label_7) self.formLayout.setWidget(3, QFormLayout.FieldRole, self.label_7)
self.label_11 = QLabel(TabDb_Manage)
self.label_11.setObjectName(u"label_11")
font = QFont()
font.setPointSize(12)
font.setBold(False)
self.label_11.setFont(font)
self.formLayout.setWidget(5, QFormLayout.SpanningRole, self.label_11)
self.syncArcSongDbButton = QPushButton(TabDb_Manage)
self.syncArcSongDbButton.setObjectName(u"syncArcSongDbButton")
self.formLayout.setWidget(6, QFormLayout.LabelRole, self.syncArcSongDbButton)
self.label = QLabel(TabDb_Manage)
self.label.setObjectName(u"label")
self.formLayout.setWidget(6, QFormLayout.FieldRole, self.label)
self.label_12 = QLabel(TabDb_Manage)
self.label_12.setObjectName(u"label_12")
self.label_12.setFont(font)
self.formLayout.setWidget(9, QFormLayout.SpanningRole, self.label_12)
self.importSt3Button = QPushButton(TabDb_Manage)
self.importSt3Button.setObjectName(u"importSt3Button")
self.formLayout.setWidget(10, QFormLayout.LabelRole, self.importSt3Button)
self.label_2 = QLabel(TabDb_Manage)
self.label_2.setObjectName(u"label_2")
self.formLayout.setWidget(10, QFormLayout.FieldRole, self.label_2)
self.importOnlineButton = QPushButton(TabDb_Manage) self.importOnlineButton = QPushButton(TabDb_Manage)
self.importOnlineButton.setObjectName(u"importOnlineButton") self.importOnlineButton.setObjectName(u"importOnlineButton")
self.formLayout.setWidget(6, QFormLayout.LabelRole, self.importOnlineButton) self.formLayout.setWidget(11, QFormLayout.LabelRole, self.importOnlineButton)
self.label_8 = QLabel(TabDb_Manage) self.label_8 = QLabel(TabDb_Manage)
self.label_8.setObjectName(u"label_8") self.label_8.setObjectName(u"label_8")
self.formLayout.setWidget(6, QFormLayout.FieldRole, self.label_8) self.formLayout.setWidget(11, QFormLayout.FieldRole, self.label_8)
self.label_13 = QLabel(TabDb_Manage)
self.label_13.setObjectName(u"label_13")
self.label_13.setFont(font)
self.formLayout.setWidget(13, QFormLayout.SpanningRole, self.label_13)
self.exportScoresButton = QPushButton(TabDb_Manage)
self.exportScoresButton.setObjectName(u"exportScoresButton")
self.formLayout.setWidget(14, QFormLayout.LabelRole, self.exportScoresButton)
self.label_3 = QLabel(TabDb_Manage)
self.label_3.setObjectName(u"label_3")
self.formLayout.setWidget(14, QFormLayout.FieldRole, self.label_3)
self.exportSmartRteB30Button = QPushButton(TabDb_Manage) self.exportSmartRteB30Button = QPushButton(TabDb_Manage)
self.exportSmartRteB30Button.setObjectName(u"exportSmartRteB30Button") self.exportSmartRteB30Button.setObjectName(u"exportSmartRteB30Button")
self.formLayout.setWidget(10, QFormLayout.LabelRole, self.exportSmartRteB30Button) self.formLayout.setWidget(15, QFormLayout.LabelRole, self.exportSmartRteB30Button)
self.label_9 = QLabel(TabDb_Manage) self.label_9 = QLabel(TabDb_Manage)
self.label_9.setObjectName(u"label_9") self.label_9.setObjectName(u"label_9")
self.label_9.setOpenExternalLinks(True) self.label_9.setOpenExternalLinks(True)
self.label_9.setTextInteractionFlags(Qt.LinksAccessibleByKeyboard|Qt.LinksAccessibleByMouse) self.label_9.setTextInteractionFlags(Qt.LinksAccessibleByKeyboard|Qt.LinksAccessibleByMouse)
self.formLayout.setWidget(10, QFormLayout.FieldRole, self.label_9) self.formLayout.setWidget(15, QFormLayout.FieldRole, self.label_9)
self.label_14 = QLabel(TabDb_Manage)
self.label_14.setObjectName(u"label_14")
self.label_14.setFont(font)
self.formLayout.setWidget(17, QFormLayout.SpanningRole, self.label_14)
self.exportArcsongJsonButton = QPushButton(TabDb_Manage)
self.exportArcsongJsonButton.setObjectName(u"exportArcsongJsonButton")
self.formLayout.setWidget(18, QFormLayout.LabelRole, self.exportArcsongJsonButton)
self.label_6 = QLabel(TabDb_Manage)
self.label_6.setObjectName(u"label_6")
self.formLayout.setWidget(18, QFormLayout.FieldRole, self.label_6)
self.label_10 = QLabel(TabDb_Manage)
self.label_10.setObjectName(u"label_10")
self.label_10.setFont(font)
self.formLayout.setWidget(0, QFormLayout.SpanningRole, self.label_10)
self.verticalSpacer = QSpacerItem(20, 20, QSizePolicy.Minimum, QSizePolicy.Minimum)
self.formLayout.setItem(4, QFormLayout.LabelRole, self.verticalSpacer)
self.verticalSpacer_2 = QSpacerItem(20, 20, QSizePolicy.Minimum, QSizePolicy.Minimum)
self.formLayout.setItem(8, QFormLayout.LabelRole, self.verticalSpacer_2)
self.verticalSpacer_3 = QSpacerItem(20, 20, QSizePolicy.Minimum, QSizePolicy.Minimum)
self.formLayout.setItem(12, QFormLayout.LabelRole, self.verticalSpacer_3)
self.verticalSpacer_4 = QSpacerItem(20, 20, QSizePolicy.Minimum, QSizePolicy.Minimum)
self.formLayout.setItem(16, QFormLayout.LabelRole, self.verticalSpacer_4)
self.syncChartInfoDbButton = QPushButton(TabDb_Manage)
self.syncChartInfoDbButton.setObjectName(u"syncChartInfoDbButton")
self.formLayout.setWidget(7, QFormLayout.LabelRole, self.syncChartInfoDbButton)
self.label_15 = QLabel(TabDb_Manage)
self.label_15.setObjectName(u"label_15")
self.formLayout.setWidget(7, QFormLayout.FieldRole, self.label_15)
self.retranslateUi(TabDb_Manage) self.retranslateUi(TabDb_Manage)
@ -140,24 +185,30 @@ class Ui_TabDb_Manage(object):
# setupUi # setupUi
def retranslateUi(self, TabDb_Manage): 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.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_4.setText(QCoreApplication.translate("TabDb_Manage", u"importPacklist.description", None))
self.importSonglistButton.setText(QCoreApplication.translate("TabDb_Manage", u"importSonglistButton", None))
self.label_5.setText(QCoreApplication.translate("TabDb_Manage", u"importSonglist.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.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.label_11.setText(QCoreApplication.translate("TabDb_Manage", u"chartInfoGroup", None))
self.syncArcSongDbButton.setText(QCoreApplication.translate("TabDb_Manage", u"syncArcSongDbButton", None))
self.label.setText(QCoreApplication.translate("TabDb_Manage", u"syncArcSongDb.description", None))
self.label_12.setText(QCoreApplication.translate("TabDb_Manage", u"importScoreGroup", None))
self.importSt3Button.setText(QCoreApplication.translate("TabDb_Manage", u"importSt3Button", None))
self.label_2.setText(QCoreApplication.translate("TabDb_Manage", u"importSt3.description", None))
self.importOnlineButton.setText(QCoreApplication.translate("TabDb_Manage", u"importOnlineButton", None)) self.importOnlineButton.setText(QCoreApplication.translate("TabDb_Manage", u"importOnlineButton", None))
self.label_8.setText(QCoreApplication.translate("TabDb_Manage", u"importOnline.description", None)) self.label_8.setText(QCoreApplication.translate("TabDb_Manage", u"importOnline.description", None))
self.label_13.setText(QCoreApplication.translate("TabDb_Manage", u"exportScoreGroup", None))
self.exportScoresButton.setText(QCoreApplication.translate("TabDb_Manage", u"exportScoresButton", None))
self.label_3.setText(QCoreApplication.translate("TabDb_Manage", u"exportScores.description", None))
self.exportSmartRteB30Button.setText(QCoreApplication.translate("TabDb_Manage", u"exportSmartRteB30Button", None)) self.exportSmartRteB30Button.setText(QCoreApplication.translate("TabDb_Manage", u"exportSmartRteB30Button", None))
self.label_9.setText(QCoreApplication.translate("TabDb_Manage", u"exportSmartRteB30.description", None)) self.label_9.setText(QCoreApplication.translate("TabDb_Manage", u"exportSmartRteB30.description", None))
self.label_14.setText(QCoreApplication.translate("TabDb_Manage", u"miscGroup", None))
self.exportArcsongJsonButton.setText(QCoreApplication.translate("TabDb_Manage", u"exportArcsongJsonButton", None))
self.label_6.setText(QCoreApplication.translate("TabDb_Manage", u"exportArcsongJson.description", None))
self.label_10.setText(QCoreApplication.translate("TabDb_Manage", u"packSongInfoGroup", None))
self.syncChartInfoDbButton.setText(QCoreApplication.translate("TabDb_Manage", u"syncChartInfoDbButton", None))
self.label_15.setText(QCoreApplication.translate("TabDb_Manage", u"syncChartInfoDb.description", None))
pass pass
# retranslateUi # retranslateUi

View File

@ -82,6 +82,7 @@ class ChartDelegate(TextSegmentDelegate):
QColor("#809955"), QColor("#809955"),
QColor("#702d60"), QColor("#702d60"),
QColor("#710f25"), QColor("#710f25"),
QColor("#8b77a4"),
] ]
ChartInvalidBackgroundColor = QColor("#e6a23c") ChartInvalidBackgroundColor = QColor("#e6a23c")

View File

@ -1,3 +1,4 @@
import logging
from typing import Type from typing import Type
from PySide6.QtCore import Signal from PySide6.QtCore import Signal
@ -6,6 +7,8 @@ from PySide6.QtWidgets import QHBoxLayout, QSizePolicy, QVBoxLayout, QWidget
from ui.implements.components.ratingClassRadioButton import RatingClassRadioButton from ui.implements.components.ratingClassRadioButton import RatingClassRadioButton
logger = logging.getLogger(__name__)
class RatingClassSelector(QWidget): class RatingClassSelector(QWidget):
valueChanged = Signal() valueChanged = Signal()
@ -41,16 +44,30 @@ class RatingClassSelector(QWidget):
self.bydButton.setAutoExclusive(False) self.bydButton.setAutoExclusive(False)
self.preferredLayout.addWidget(self.bydButton) self.preferredLayout.addWidget(self.bydButton)
self.buttons = [self.pstButton, self.prsButton, self.ftrButton, self.bydButton] self.etrButton = RatingClassRadioButton(self)
self.etrButton.setObjectName("etrButton")
self.etrButton.setText("ETERNAL")
self.etrButton.setAutoExclusive(False)
self.preferredLayout.addWidget(self.etrButton)
self.buttons = [
self.pstButton,
self.prsButton,
self.ftrButton,
self.bydButton,
self.etrButton,
]
self.pstButton.setColors(QColor("#399bb2"), QColor("#f0f8fa")) self.pstButton.setColors(QColor("#399bb2"), QColor("#f0f8fa"))
self.prsButton.setColors(QColor("#809955"), QColor("#f7f9f4")) self.prsButton.setColors(QColor("#809955"), QColor("#f7f9f4"))
self.ftrButton.setColors(QColor("#702d60"), QColor("#f7ebf4")) self.ftrButton.setColors(QColor("#702d60"), QColor("#f7ebf4"))
self.bydButton.setColors(QColor("#710f25"), QColor("#f9ced8")) self.bydButton.setColors(QColor("#710f25"), QColor("#f9ced8"))
self.etrButton.setColors(QColor("#4f2c7a"), QColor("#e4daf1"))
self.pstButton.clicked.connect(self.select) self.pstButton.clicked.connect(self.select)
self.prsButton.clicked.connect(self.select) self.prsButton.clicked.connect(self.select)
self.ftrButton.clicked.connect(self.select) self.ftrButton.clicked.connect(self.select)
self.bydButton.clicked.connect(self.select) self.bydButton.clicked.connect(self.select)
self.etrButton.clicked.connect(self.select)
self.reset() self.reset()
self.setButtonsEnabled([]) self.setButtonsEnabled([])
@ -106,9 +123,10 @@ class RatingClassSelector(QWidget):
if ratingClass is None or isinstance(ratingClass, bool): if ratingClass is None or isinstance(ratingClass, bool):
button = self.sender() button = self.sender()
elif ratingClass in range(4): elif ratingClass in range(len(self.buttons)):
button = self.buttons[ratingClass] button = self.buttons[ratingClass]
else: else:
logger.debug(f"Cannot select {ratingClass=}, condition check failed")
return return
if not button.isEnabled(): if not button.isEnabled():

View File

@ -14,9 +14,10 @@ from arcaea_offline.external.arcaea import (
) )
from arcaea_offline.external.arcaea.common import ArcaeaParser from arcaea_offline.external.arcaea.common import ArcaeaParser
from arcaea_offline.external.arcsong import ArcsongDbParser from arcaea_offline.external.arcsong import ArcsongDbParser
from arcaea_offline.external.chart_info_db import ChartInfoDbParser
from arcaea_offline.external.smartrte import SmartRteB30CsvConverter from arcaea_offline.external.smartrte import SmartRteB30CsvConverter
from arcaea_offline.models import Difficulty, Pack, Song from arcaea_offline.models import Difficulty, Pack, Song
from PySide6.QtCore import QDir, Slot from PySide6.QtCore import QDateTime, QDir, Slot
from PySide6.QtWidgets import QFileDialog, QMessageBox, QWidget from PySide6.QtWidgets import QFileDialog, QMessageBox, QWidget
from ui.designer.tabs.tabDb.tabDb_Manage_ui import Ui_TabDb_Manage from ui.designer.tabs.tabDb.tabDb_Manage_ui import Ui_TabDb_Manage
@ -57,6 +58,29 @@ class TabDb_Manage(Ui_TabDb_Manage, QWidget):
self, "Sync Error", "\n".join(traceback.format_exception(e)) self, "Sync Error", "\n".join(traceback.format_exception(e))
) )
@Slot()
def on_syncChartInfoDbButton_clicked(self):
dbFile, filter = QFileDialog.getOpenFileName(
self, None, "", "DB File (*.db);;*"
)
if not dbFile:
return
try:
db = Database()
parser = ChartInfoDbParser(dbFile)
with db.sessionmaker() as session:
parser.write_database(session)
session.commit()
databaseUpdateSignals.chartInfoUpdated.emit()
QMessageBox.information(self, None, "OK")
except Exception as e:
logging.exception("Sync chart info database error")
QMessageBox.critical(
self, "Sync Error", "\n".join(traceback.format_exception(e))
)
def importFromArcaeaParser( def importFromArcaeaParser(
self, parser: ArcaeaParser, instance, logName, path self, parser: ArcaeaParser, instance, logName, path
) -> int: ) -> int:
@ -208,14 +232,14 @@ class TabDb_Manage(Ui_TabDb_Manage, QWidget):
@Slot() @Slot()
def on_exportScoresButton_clicked(self): def on_exportScoresButton_clicked(self):
scores = Database().export_scores() scores = Database().export_scores_def_v2()
version = Database().version() timestamp = QDateTime.currentMSecsSinceEpoch()
content = json.dumps(scores, ensure_ascii=False) content = json.dumps(scores, ensure_ascii=False)
exportLocation, _filter = QFileDialog.getSaveFileName( exportLocation, _filter = QFileDialog.getSaveFileName(
self, self,
"Save your scores to...", "Save your scores to...",
QDir.current().filePath(f"arcaea-offline-scores-v{version}.json"), QDir.current().filePath(f"arcaea-offline-def-v2-scores-{timestamp}.json"),
"JSON (*.json);;*", "JSON (*.json);;*",
) )
with open(exportLocation, "w", encoding="utf-8") as f: with open(exportLocation, "w", encoding="utf-8") as f:

View File

@ -672,92 +672,127 @@ validation</translation>
<context> <context>
<name>TabDb_Manage</name> <name>TabDb_Manage</name>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="23"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="78"/>
<source>syncArcSongDbButton</source> <source>syncArcSongDbButton</source>
<translation>Sync arcsong.db</translation> <translation>Sync arcsong.db</translation>
</message> </message>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="30"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="85"/>
<source>syncArcSongDb.description</source> <source>syncArcSongDb.description</source>
<translation>Update chart info</translation> <translation>Update chart info</translation>
</message> </message>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="37"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="98"/>
<source>importScoreGroup</source>
<translation>Import Score</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="105"/>
<source>importSt3Button</source> <source>importSt3Button</source>
<translation>Import from Game Save</translation> <translation>Game Save Database</translation>
</message> </message>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="44"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="112"/>
<source>importSt3.description</source> <source>importSt3.description</source>
<translation>Import scores from your game save</translation> <translation>Import scores from your game save database</translation>
</message> </message>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="58"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="139"/>
<source>exportScoresButton</source> <source>exportScoreGroup</source>
<translation>Export Scores</translation> <translation>Export Scores</translation>
</message> </message>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="65"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="146"/>
<source>exportScores.description</source> <source>exportScoresButton</source>
<translation>Export all your scores to a JSON file</translation> <translation>D.E.F. V2</translation>
</message> </message>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="79"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="153"/>
<source>exportScores.description</source>
<translation>Export all your scores in &lt;i&gt;Arcaea Offline Data Exchange Format V2&lt;/i&gt; formed JSON file</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="186"/>
<source>miscGroup</source>
<translation>Miscellaneous</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="284"/>
<source>syncChartInfoDbButton</source>
<translation>Sync Chart Info Database</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="291"/>
<source>syncChartInfoDb.description</source>
<translation>Update chart info</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="23"/>
<source>importPacklistButton</source> <source>importPacklistButton</source>
<translation>Import packlist</translation> <translation>Import packlist</translation>
</message> </message>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="86"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="37"/>
<source>importSonglistButton</source> <source>importSonglistButton</source>
<translation>Import songlist</translation> <translation>Import songlist</translation>
</message> </message>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="93"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="30"/>
<source>importPacklist.description</source> <source>importPacklist.description</source>
<translation>Import packlist file</translation> <translation>Import packlist file</translation>
</message> </message>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="100"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="44"/>
<source>importSonglist.description</source> <source>importSonglist.description</source>
<translation>Import songlist file</translation> <translation>Import songlist file</translation>
</message> </message>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="107"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="193"/>
<source>exportArcsongJsonButton</source> <source>exportArcsongJsonButton</source>
<translation>Export arcsong.json</translation> <translation>Export arcsong.json</translation>
</message> </message>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="114"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="200"/>
<source>exportArcsongJson.description</source> <source>exportArcsongJson.description</source>
<translation>Export arcsong.json file</translation> <translation>Export arcsong.json file based on the information in database</translation>
</message> </message>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="121"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="51"/>
<source>importApkButton</source> <source>importApkButton</source>
<translation>Import from 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="213"/>
<source>packSongInfoGroup</source>
<translation>Pack/Song Info</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="58"/>
<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> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="135"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="71"/>
<source>chartInfoGroup</source>
<translation>Chart Info</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="119"/>
<source>importOnlineButton</source> <source>importOnlineButton</source>
<translation>Import from Arcaea Online</translation> <translation>Arcaea Online</translation>
</message> </message>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="142"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="126"/>
<source>importOnline.description</source> <source>importOnline.description</source>
<translation>Import scores from the result of Arcaea Online API</translation> <translation>Import scores from the Arcaea Online API result</translation>
</message> </message>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="149"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="160"/>
<source>exportSmartRteB30Button</source> <source>exportSmartRteB30Button</source>
<translation>Export Scores (CSV, SmartRTE B30)</translation> <translation>SmartRTE B30</translation>
</message> </message>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="156"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="167"/>
<source>exportSmartRteB30.description</source> <source>exportSmartRteB30.description</source>
<translation>Export all your scores to &lt;a href=&quot;https://smartrte.github.io/b30gen.html&quot;&gt;smartrte.github.io&lt;/a&gt; compatible CSV file</translation> <translation>Export all your scores to &lt;a href=&quot;https://smartrte.github.io/b30gen.html&quot;&gt;smartrte.github.io&lt;/a&gt; compatible CSV file</translation>
</message> </message>
@ -840,27 +875,27 @@ validation</translation>
<translation>Delete Selected Scores</translation> <translation>Delete Selected Scores</translation>
</message> </message>
<message> <message>
<location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="142"/> <location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="158"/>
<source>quickSelectComboBox.idEarlier</source> <source>quickSelectComboBox.idEarlier</source>
<translation>Earlier ID</translation> <translation>Earlier ID</translation>
</message> </message>
<message> <message>
<location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="148"/> <location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="164"/>
<source>quickSelectComboBox.dateEarlier</source> <source>quickSelectComboBox.dateEarlier</source>
<translation>Earlier date</translation> <translation>Earlier date</translation>
</message> </message>
<message> <message>
<location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="154"/> <location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="170"/>
<source>quickSelectComboBox.columnsIntegral</source> <source>quickSelectComboBox.columnsIntegral</source>
<translation>More complete data</translation> <translation>More complete data</translation>
</message> </message>
<message> <message>
<location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="279"/> <location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="295"/>
<source>deleteSelectionDialog.content {}</source> <source>deleteSelectionDialog.content {}</source>
<translation>Deleting {} scores from database, this cannot be undone!&lt;br&gt;Confirm?</translation> <translation>Deleting {} scores from database, this cannot be undone!&lt;br&gt;Confirm?</translation>
</message> </message>
<message> <message>
<location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="301"/> <location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="317"/>
<source>scan_noColumnsDialog.content</source> <source>scan_noColumnsDialog.content</source>
<translation>You haven&apos;t selected any column! Are you sure to continue?</translation> <translation>You haven&apos;t selected any column! Are you sure to continue?</translation>
</message> </message>

View File

@ -671,92 +671,127 @@
<context> <context>
<name>TabDb_Manage</name> <name>TabDb_Manage</name>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="23"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="78"/>
<source>syncArcSongDbButton</source> <source>syncArcSongDbButton</source>
<translation> arcsong.db</translation> <translation> arcsong.db</translation>
</message> </message>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="30"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="85"/>
<source>syncArcSongDb.description</source> <source>syncArcSongDb.description</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="37"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="98"/>
<source>importSt3Button</source> <source>importScoreGroup</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="105"/>
<source>importSt3Button</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="112"/>
<source>importSt3.description</source> <source>importSt3.description</source>
<translation>姿&lt;br&gt;退</translation> <translation>姿&lt;br&gt;退</translation>
</message> </message>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="58"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="139"/>
<source>exportScoresButton</source> <source>exportScoreGroup</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="65"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="146"/>
<source>exportScores.description</source> <source>exportScoresButton</source>
<translation> JSON </translation> <translation> V2</translation>
</message> </message>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="79"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="153"/>
<source>exportScores.description</source>
<translation> &lt;i&gt;Arcaea Offline V2&lt;/i&gt; JSON </translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="186"/>
<source>miscGroup</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="284"/>
<source>syncChartInfoDbButton</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="291"/>
<source>syncChartInfoDb.description</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="23"/>
<source>importPacklistButton</source> <source>importPacklistButton</source>
<translation> packlist</translation> <translation> packlist</translation>
</message> </message>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="86"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="37"/>
<source>importSonglistButton</source> <source>importSonglistButton</source>
<translation> songlist</translation> <translation> songlist</translation>
</message> </message>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="93"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="30"/>
<source>importPacklist.description</source> <source>importPacklist.description</source>
<translation> packlist </translation> <translation> packlist </translation>
</message> </message>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="100"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="44"/>
<source>importSonglist.description</source> <source>importSonglist.description</source>
<translation> songlist </translation> <translation> songlist </translation>
</message> </message>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="107"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="193"/>
<source>exportArcsongJsonButton</source> <source>exportArcsongJsonButton</source>
<translation> arcsong.json</translation> <translation> arcsong.json</translation>
</message> </message>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="114"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="200"/>
<source>exportArcsongJson.description</source> <source>exportArcsongJson.description</source>
<translation> arcsong.json </translation> <translation> arcsong.json </translation>
</message> </message>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="121"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="51"/>
<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="213"/>
<source>packSongInfoGroup</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="58"/>
<source>importApk.description</source> <source>importApk.description</source>
<translation> .apk packlist songlist</translation> <translation> .apk packlist songlist</translation>
</message> </message>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="135"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="71"/>
<source>importOnlineButton</source> <source>chartInfoGroup</source>
<translation> Arcaea Online </translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="142"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="119"/>
<source>importOnlineButton</source>
<translation>Arcaea Online</translation>
</message>
<message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="126"/>
<source>importOnline.description</source> <source>importOnline.description</source>
<translation> Arcaea Online API </translation> <translation> Arcaea Online API </translation>
</message> </message>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="149"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="160"/>
<source>exportSmartRteB30Button</source> <source>exportSmartRteB30Button</source>
<translation>CSVSmartRTE B30</translation> <translation>SmartRTE B30</translation>
</message> </message>
<message> <message>
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="156"/> <location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="167"/>
<source>exportSmartRteB30.description</source> <source>exportSmartRteB30.description</source>
<translation> &lt;a href=&quot;https://smartrte.github.io/b30gen.html&quot;&gt;smartrte.github.io&lt;/a&gt; 的 CSV 文件</translation> <translation> &lt;a href=&quot;https://smartrte.github.io/b30gen.html&quot;&gt;smartrte.github.io&lt;/a&gt; 的 CSV 文件</translation>
</message> </message>
@ -839,27 +874,27 @@
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="142"/> <location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="158"/>
<source>quickSelectComboBox.idEarlier</source> <source>quickSelectComboBox.idEarlier</source>
<translation>ID </translation> <translation>ID </translation>
</message> </message>
<message> <message>
<location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="148"/> <location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="164"/>
<source>quickSelectComboBox.dateEarlier</source> <source>quickSelectComboBox.dateEarlier</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="154"/> <location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="170"/>
<source>quickSelectComboBox.columnsIntegral</source> <source>quickSelectComboBox.columnsIntegral</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="279"/> <location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="295"/>
<source>deleteSelectionDialog.content {}</source> <source>deleteSelectionDialog.content {}</source>
<translation> {} &lt;br&gt;</translation> <translation> {} &lt;br&gt;</translation>
</message> </message>
<message> <message>
<location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="301"/> <location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="317"/>
<source>scan_noColumnsDialog.content</source> <source>scan_noColumnsDialog.content</source>
<translation></translation> <translation></translation>
</message> </message>

View File

@ -3,7 +3,7 @@ import traceback
from enum import IntEnum from enum import IntEnum
from arcaea_offline.database import Database from arcaea_offline.database import Database
from PySide6.QtCore import QCoreApplication, QDir, QFileInfo, Qt, QUrl, Slot from PySide6.QtCore import QCoreApplication, QDir, QFileInfo, QSysInfo, Qt, QUrl, Slot
from PySide6.QtWidgets import QDialog, QMessageBox from PySide6.QtWidgets import QDialog, QMessageBox
from ui.extends.shared.database import create_engine from ui.extends.shared.database import create_engine
@ -59,8 +59,13 @@ class DatabaseChecker(Ui_DatabaseChecker, QDialog):
return QUrl.fromLocalFile(self.dbFileInfo().filePath()) return QUrl.fromLocalFile(self.dbFileInfo().filePath())
def dbSqliteUrl(self): def dbSqliteUrl(self):
# dbSqliteUrl.setScheme("sqlite") kernelType = QSysInfo.kernelType()
# the slash count varies depending on the kernel
# https://docs.sqlalchemy.org/en/20/core/engines.html#sqlite
if kernelType == "winnt":
return QUrl(self.dbFileUrl().toString().replace("file://", "sqlite://")) return QUrl(self.dbFileUrl().toString().replace("file://", "sqlite://"))
else:
return QUrl(self.dbFileUrl().toString().replace("file://", "sqlite:///"))
def confirmDb(self) -> DatabaseCheckerResult: def confirmDb(self) -> DatabaseCheckerResult:
flags = 0x000 flags = 0x000