mirror of
https://github.com/283375/arcaea-offline-pyside-ui.git
synced 2025-07-01 20:36:26 +00:00
Compare commits
57 Commits
cf913d296e
...
v0.3.8
Author | SHA1 | Date | |
---|---|---|---|
d5895fe230
|
|||
cd2e3f51ca
|
|||
4a09dc210a | |||
cc8ab11b78
|
|||
48c5682e55 | |||
ee03770764
|
|||
b45c7f7de5
|
|||
15bc56e6f9
|
|||
39ee379010
|
|||
5a71a5822b
|
|||
c888b312b3
|
|||
8e4fdc30b5
|
|||
1ca868cfc6
|
|||
d63d2f0d8b
|
|||
3cd187fde3
|
|||
cce918a121
|
|||
1ec302d98c
|
|||
3d6e5f997e | |||
495f6dc424
|
|||
0b599e3d9c
|
|||
a51a67fae3
|
|||
b48e177ae8
|
|||
865fc8b7c8
|
|||
1eeec6f745
|
|||
8558f5e403
|
|||
1a37310091
|
|||
d460e935b4
|
|||
38d2e4ad5a
|
|||
28599cfb04
|
|||
1d01356327
|
|||
738975a83d
|
|||
5adea908f9
|
|||
21ca1018db
|
|||
51e15c68e0
|
|||
00f680edd3
|
|||
7dee8114bf
|
|||
90e66a43fe
|
|||
381f27db87
|
|||
e0d92b7784
|
|||
5aedf91c09
|
|||
b193b82d95
|
|||
01457f3559
|
|||
dd647d6963
|
|||
7de2eda517
|
|||
d918032b9c
|
|||
55ef2ba3bb
|
|||
105d5c1dfb
|
|||
52e618e664
|
|||
b1af1f622e
|
|||
7271eaab55
|
|||
263386e2f1
|
|||
dc795f739e
|
|||
6b28de247e
|
|||
86b1653fe3
|
|||
3e2e96b00b
|
|||
9bb6f5b3d9
|
|||
8628399469
|
40
.github/workflows/build-from-latest-dependency.yml
vendored
Normal file
40
.github/workflows/build-from-latest-dependency.yml
vendored
Normal 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
49
.github/workflows/build.yml
vendored
Normal 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
|
14
.pre-commit-config.yaml
Normal file
14
.pre-commit-config.yaml
Normal file
@ -0,0 +1,14 @@
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.4.0
|
||||
hooks:
|
||||
- id: end-of-file-fixer
|
||||
- id: trailing-whitespace
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 23.1.0
|
||||
hooks:
|
||||
- id: black
|
||||
- repo: https://github.com/PyCQA/isort
|
||||
rev: 5.12.0
|
||||
hooks:
|
||||
- id: isort
|
22
README.md
22
README.md
@ -1,9 +1,27 @@
|
||||
# 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
|
||||
* Release translation files from `ui/resources/lang/*.ts`
|
||||
* Run `prebuild.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
|
||||
```
|
||||
|
19
index.py
19
index.py
@ -6,7 +6,7 @@ from pathlib import Path
|
||||
|
||||
from arcaea_offline.database import Database
|
||||
from PySide6.QtCore import QCoreApplication, QLocale
|
||||
from PySide6.QtGui import QIcon
|
||||
from PySide6.QtGui import QFontDatabase, QIcon
|
||||
from PySide6.QtWidgets import QApplication, QDialog, QMessageBox
|
||||
|
||||
import ui.resources.resources_rc
|
||||
@ -23,6 +23,19 @@ rootLoggerFormatter = logging.Formatter(
|
||||
)
|
||||
|
||||
|
||||
def handle_exception(exc_type, exc_value, exc_traceback):
|
||||
if issubclass(exc_type, KeyboardInterrupt):
|
||||
sys.__excepthook__(exc_type, exc_value, exc_traceback)
|
||||
return
|
||||
|
||||
rootLogger.critical(
|
||||
"Uncaught exception", exc_info=(exc_type, exc_value, exc_traceback)
|
||||
)
|
||||
|
||||
|
||||
sys.excepthook = handle_exception
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
QCoreApplication.setApplicationName("Arcaea Offline")
|
||||
|
||||
@ -51,9 +64,11 @@ if __name__ == "__main__":
|
||||
)
|
||||
changeAppLanguage(locale)
|
||||
|
||||
QFontDatabase.addApplicationFont(":/fonts/GeosansLight.ttf")
|
||||
|
||||
databaseChecker = DatabaseChecker()
|
||||
databaseChecker.setWindowIcon(QIcon(":/images/icon.png"))
|
||||
databaseCheckResult = databaseChecker.confirmDb()
|
||||
databaseCheckResult = databaseChecker.confirmDb() if Settings().databaseUrl() else 0
|
||||
|
||||
if not databaseCheckResult & DatabaseCheckerResult.Initted:
|
||||
result = databaseChecker.exec()
|
||||
|
128
prebuild.py
128
prebuild.py
@ -1,70 +1,86 @@
|
||||
import os
|
||||
import platform
|
||||
import subprocess
|
||||
from importlib import metadata
|
||||
from pathlib import Path
|
||||
|
||||
# fill VERSION file
|
||||
versionFile = Path("ui/resources/VERSION")
|
||||
assert versionFile.exists()
|
||||
|
||||
versionTexts = []
|
||||
def getGitDesc():
|
||||
gitDescribe = subprocess.run(
|
||||
["git", "describe", "--tags", "--long"],
|
||||
capture_output=True,
|
||||
encoding="utf-8",
|
||||
)
|
||||
if gitDescribe.returncode == 0:
|
||||
return gitDescribe.stdout.replace("\n", "")
|
||||
|
||||
projectVersionText = "arcaea-offline-pyside-ui\n"
|
||||
gitDescribe = os.popen("git describe --tags --long")
|
||||
gitDescribeContent = gitDescribe.read().replace("\n", "")
|
||||
if gitDescribe.close() is None:
|
||||
projectVersionText += f"{gitDescribeContent}"
|
||||
else:
|
||||
gitRevParse = os.popen("git rev-parse --short HEAD")
|
||||
gitRevParseContent = gitRevParse.read().replace("\n", "")
|
||||
projectVersionText += f"commit {gitRevParseContent}"
|
||||
gitRevParse.close()
|
||||
projectVersionText += "\n"
|
||||
# describe failed, try rev-parse
|
||||
gitRevParse = subprocess.run(
|
||||
["git", "rev-parse", "--short", "HEAD"],
|
||||
capture_output=True,
|
||||
encoding="utf-8",
|
||||
)
|
||||
if gitRevParse.returncode == 0:
|
||||
return f"commit {gitRevParse.stdout}".replace("\n", "")
|
||||
|
||||
versionTexts.append(projectVersionText)
|
||||
return "version/commit unknown"
|
||||
|
||||
|
||||
# detect pip
|
||||
pipName = None
|
||||
possiblePipNames = ["pip3", "pip"]
|
||||
for possiblePipName in possiblePipNames:
|
||||
result = os.popen(possiblePipName).read()
|
||||
if (
|
||||
"<command> [options]" in result
|
||||
and "install" in result
|
||||
and "--upgrade" in result
|
||||
):
|
||||
pipName = possiblePipName
|
||||
break
|
||||
def getBuildToolsVer():
|
||||
texts = []
|
||||
possibleBuildTools = ["Nuitka", "pyinstaller"]
|
||||
for possibleBuildTool in possibleBuildTools:
|
||||
try:
|
||||
version = metadata.version(possibleBuildTool)
|
||||
texts.append(f"{possibleBuildTool}=={version}")
|
||||
except metadata.PackageNotFoundError:
|
||||
texts.append(f"{possibleBuildTool} not installed")
|
||||
return ", ".join(texts)
|
||||
|
||||
|
||||
# if possiblePipName:
|
||||
# pipFreezeLines = os.popen(f"{possiblePipName} freeze").read().split("\n")
|
||||
# text = [
|
||||
# pipFreezeResult
|
||||
# for pipFreezeResult in pipFreezeLines
|
||||
# if (
|
||||
# "arcaea-offline" in pipFreezeResult
|
||||
# or "PySide6" in pipFreezeResult
|
||||
# or "exif" in pipFreezeResult
|
||||
# or "opencv-python" in pipFreezeResult
|
||||
# or "SQLAlchemy" in pipFreezeResult
|
||||
# )
|
||||
# ]
|
||||
# versionTexts.append("\n".join(text))
|
||||
def writeVersionFile():
|
||||
versionFile = Path("ui/resources/VERSION")
|
||||
|
||||
importLibTexts = [
|
||||
f"{module}=={metadata.version(module)}"
|
||||
for module in [
|
||||
"arcaea-offline",
|
||||
"arcaea-offline-ocr",
|
||||
"exif",
|
||||
"opencv-python",
|
||||
"PySide6",
|
||||
"SQLAlchemy",
|
||||
"SQLAlchemy-Utils",
|
||||
versionText = (
|
||||
"arcaea-offline-pyside-ui\n{gitDesc}\n{buildToolsVer}\n\n"
|
||||
"{pythonVer}\n\n"
|
||||
"{depsVer}\n"
|
||||
)
|
||||
|
||||
gitDesc = getGitDesc()
|
||||
buildToolsVer = getBuildToolsVer()
|
||||
|
||||
pythonVer = f"{platform.python_implementation()} {platform.python_version()} ({platform.python_build()[0]})"
|
||||
|
||||
importLibTexts = [
|
||||
f"{module}=={metadata.version(module)}"
|
||||
for module in sorted(
|
||||
[
|
||||
"arcaea-offline",
|
||||
"arcaea-offline-ocr",
|
||||
"exif",
|
||||
"numpy",
|
||||
"opencv-python",
|
||||
"Pillow",
|
||||
"PySide6",
|
||||
"SQLAlchemy",
|
||||
"SQLAlchemy-Utils",
|
||||
"Whoosh",
|
||||
],
|
||||
key=lambda s: s.lower(),
|
||||
)
|
||||
]
|
||||
]
|
||||
versionTexts.append("\n".join(importLibTexts))
|
||||
importLibText = "\n".join(importLibTexts)
|
||||
|
||||
with versionFile.open("w", encoding="utf-8") as vf:
|
||||
vf.write("\n".join(versionTexts))
|
||||
with versionFile.open("w", encoding="utf-8") as vf:
|
||||
vf.write(
|
||||
versionText.format(
|
||||
gitDesc=gitDesc,
|
||||
buildToolsVer=buildToolsVer,
|
||||
pythonVer=pythonVer,
|
||||
depsVer=importLibText,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
writeVersionFile()
|
||||
|
@ -4,14 +4,14 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "arcaea-offline-pyside-ui"
|
||||
version = "0.1.0"
|
||||
version = "0.3.8"
|
||||
authors = [{ name = "283375", email = "log_283375@163.com" }]
|
||||
description = "No description."
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.9"
|
||||
dependencies = [
|
||||
"arcaea-offline==0.1.0",
|
||||
"arcaea-offline-ocr==0.1.0",
|
||||
"arcaea-offline==0.2.2",
|
||||
"arcaea-offline-ocr==0.0.98",
|
||||
"exif==1.6.0",
|
||||
"PySide6==6.5.2",
|
||||
]
|
||||
@ -21,13 +21,14 @@ classifiers = [
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
"Homepage" = "https://github.com/283375/arcaea-offline-pyside-ui"
|
||||
"Bug Tracker" = "https://github.com/283375/arcaea-offline-pyside-ui/issues"
|
||||
"Homepage" = "https://github.com/ArcaeaOffline/client-pyside6"
|
||||
"Bug Tracker" = "https://github.com/ArcaeaOffline/client-pyside6/issues"
|
||||
|
||||
[tool.black]
|
||||
force-exclude = '''
|
||||
(
|
||||
ui/designer
|
||||
| .*_ui.py
|
||||
| .*_rc.py
|
||||
)
|
||||
'''
|
||||
@ -35,7 +36,7 @@ force-exclude = '''
|
||||
[tool.isort]
|
||||
profile = "black"
|
||||
extend_skip = ["ui/designer"]
|
||||
extend_skip_glob = ["*_rc.py"]
|
||||
extend_skip_glob = ["*_ui.py", "*_rc.py"]
|
||||
|
||||
[tool.pyright]
|
||||
ignore = ["**/__debug*.*"]
|
||||
|
@ -1,2 +1,4 @@
|
||||
black == 23.7.0
|
||||
isort == 5.12.0
|
||||
imageio==2.31.4
|
||||
Nuitka==1.8.4
|
||||
|
@ -1,4 +1,5 @@
|
||||
arcaea-offline==0.1.0
|
||||
arcaea-offline-ocr==0.1.0
|
||||
arcaea-offline==0.2.2
|
||||
arcaea-offline-ocr==0.0.98
|
||||
exif==1.6.0
|
||||
Pillow==10.1.0
|
||||
PySide6==6.5.2
|
||||
|
@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>476</width>
|
||||
<height>347</height>
|
||||
<height>93</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -16,12 +16,6 @@
|
||||
<layout class="QVBoxLayout" name="mainVerticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="songIdSelectorGroupBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>songIdSelector.title</string>
|
||||
</property>
|
||||
|
@ -25,17 +25,12 @@ class Ui_ChartSelector(object):
|
||||
def setupUi(self, ChartSelector):
|
||||
if not ChartSelector.objectName():
|
||||
ChartSelector.setObjectName(u"ChartSelector")
|
||||
ChartSelector.resize(476, 347)
|
||||
ChartSelector.resize(476, 93)
|
||||
ChartSelector.setWindowTitle(u"ChartSelector")
|
||||
self.mainVerticalLayout = QVBoxLayout(ChartSelector)
|
||||
self.mainVerticalLayout.setObjectName(u"mainVerticalLayout")
|
||||
self.songIdSelectorGroupBox = QGroupBox(ChartSelector)
|
||||
self.songIdSelectorGroupBox.setObjectName(u"songIdSelectorGroupBox")
|
||||
sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.songIdSelectorGroupBox.sizePolicy().hasHeightForWidth())
|
||||
self.songIdSelectorGroupBox.setSizePolicy(sizePolicy)
|
||||
self.verticalLayout_3 = QVBoxLayout(self.songIdSelectorGroupBox)
|
||||
self.verticalLayout_3.setObjectName(u"verticalLayout_3")
|
||||
self.verticalLayout_3.setContentsMargins(0, 0, 0, 0)
|
||||
@ -56,11 +51,11 @@ class Ui_ChartSelector(object):
|
||||
self.resultsHorizontalLayout.setObjectName(u"resultsHorizontalLayout")
|
||||
self.resultLabel = QLabel(ChartSelector)
|
||||
self.resultLabel.setObjectName(u"resultLabel")
|
||||
sizePolicy1 = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
|
||||
sizePolicy1.setHorizontalStretch(0)
|
||||
sizePolicy1.setVerticalStretch(0)
|
||||
sizePolicy1.setHeightForWidth(self.resultLabel.sizePolicy().hasHeightForWidth())
|
||||
self.resultLabel.setSizePolicy(sizePolicy1)
|
||||
sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.resultLabel.sizePolicy().hasHeightForWidth())
|
||||
self.resultLabel.setSizePolicy(sizePolicy)
|
||||
self.resultLabel.setText(u"...")
|
||||
self.resultLabel.setTextFormat(Qt.RichText)
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>350</width>
|
||||
<height>250</height>
|
||||
<height>102</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -27,19 +27,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
|
@ -16,14 +16,13 @@ from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
|
||||
QImage, QKeySequence, QLinearGradient, QPainter,
|
||||
QPalette, QPixmap, QRadialGradient, QTransform)
|
||||
from PySide6.QtWidgets import (QApplication, QComboBox, QHBoxLayout, QLineEdit,
|
||||
QPushButton, QSizePolicy, QSpacerItem, QVBoxLayout,
|
||||
QWidget)
|
||||
QPushButton, QSizePolicy, QVBoxLayout, QWidget)
|
||||
|
||||
class Ui_SongIdSelector(object):
|
||||
def setupUi(self, SongIdSelector):
|
||||
if not SongIdSelector.objectName():
|
||||
SongIdSelector.setObjectName(u"SongIdSelector")
|
||||
SongIdSelector.resize(350, 250)
|
||||
SongIdSelector.resize(350, 102)
|
||||
SongIdSelector.setWindowTitle(u"SongIdSelector")
|
||||
self.verticalLayout_2 = QVBoxLayout(SongIdSelector)
|
||||
self.verticalLayout_2.setObjectName(u"verticalLayout_2")
|
||||
@ -34,10 +33,6 @@ class Ui_SongIdSelector(object):
|
||||
|
||||
self.verticalLayout_2.addWidget(self.searchLineEdit)
|
||||
|
||||
self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
|
||||
|
||||
self.verticalLayout_2.addItem(self.verticalSpacer)
|
||||
|
||||
self.horizontalLayout_2 = QHBoxLayout()
|
||||
self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
|
||||
self.previousPackageButton = QPushButton(SongIdSelector)
|
||||
|
270
ui/designer/tabs/tabDb/tabDb_ChartInfoEditor.ui
Normal file
270
ui/designer/tabs/tabDb/tabDb_ChartInfoEditor.ui
Normal file
@ -0,0 +1,270 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TabDb_ChartInfoEditor</class>
|
||||
<widget class="QWidget" name="TabDb_ChartInfoEditor">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>659</width>
|
||||
<height>570</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">TabDb_ChartInfoEditor</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="1">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>editor.title</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="labelAlignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>editor.constant</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>editor.notes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="notesLineEdit">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>GeosansLight</family>
|
||||
<pointsize>14</pointsize>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="jacketLabel">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="titleLabel">
|
||||
<property name="text">
|
||||
<string notr="true">...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="ratingLabel">
|
||||
<property name="text">
|
||||
<string notr="true">...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QWidget" name="horizontalWidget_2" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="constantLineEdit">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>GeosansLight</family>
|
||||
<pointsize>14</pointsize>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="constantPreviewLabel">
|
||||
<property name="text">
|
||||
<string notr="true">> ...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>editor.tip</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>editor.tip.content</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="deleteButton">
|
||||
<property name="text">
|
||||
<string>editor.delete</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="commitButton">
|
||||
<property name="text">
|
||||
<string>editor.commit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="ChartSelector" name="chartSelector" native="true"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QListView" name="listView">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="verticalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>ChartSelector</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>ui.implements.components.chartSelector</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>listView</tabstop>
|
||||
<tabstop>constantLineEdit</tabstop>
|
||||
<tabstop>notesLineEdit</tabstop>
|
||||
<tabstop>commitButton</tabstop>
|
||||
<tabstop>deleteButton</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
202
ui/designer/tabs/tabDb/tabDb_ChartInfoEditor_ui.py
Normal file
202
ui/designer/tabs/tabDb/tabDb_ChartInfoEditor_ui.py
Normal file
@ -0,0 +1,202 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
################################################################################
|
||||
## Form generated from reading UI file 'tabDb_ChartInfoEditor.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 (QAbstractItemView, QApplication, QFormLayout, QGridLayout,
|
||||
QGroupBox, QHBoxLayout, QLabel, QLineEdit,
|
||||
QListView, QPushButton, QSizePolicy, QSpacerItem,
|
||||
QVBoxLayout, QWidget)
|
||||
|
||||
from ui.implements.components.chartSelector import ChartSelector
|
||||
|
||||
class Ui_TabDb_ChartInfoEditor(object):
|
||||
def setupUi(self, TabDb_ChartInfoEditor):
|
||||
if not TabDb_ChartInfoEditor.objectName():
|
||||
TabDb_ChartInfoEditor.setObjectName(u"TabDb_ChartInfoEditor")
|
||||
TabDb_ChartInfoEditor.resize(659, 570)
|
||||
TabDb_ChartInfoEditor.setWindowTitle(u"TabDb_ChartInfoEditor")
|
||||
self.gridLayout = QGridLayout(TabDb_ChartInfoEditor)
|
||||
self.gridLayout.setObjectName(u"gridLayout")
|
||||
self.groupBox = QGroupBox(TabDb_ChartInfoEditor)
|
||||
self.groupBox.setObjectName(u"groupBox")
|
||||
self.verticalLayout_2 = QVBoxLayout(self.groupBox)
|
||||
self.verticalLayout_2.setObjectName(u"verticalLayout_2")
|
||||
self.widget = QWidget(self.groupBox)
|
||||
self.widget.setObjectName(u"widget")
|
||||
self.formLayout = QFormLayout(self.widget)
|
||||
self.formLayout.setObjectName(u"formLayout")
|
||||
self.formLayout.setLabelAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
|
||||
self.label = QLabel(self.widget)
|
||||
self.label.setObjectName(u"label")
|
||||
|
||||
self.formLayout.setWidget(1, QFormLayout.LabelRole, self.label)
|
||||
|
||||
self.label_2 = QLabel(self.widget)
|
||||
self.label_2.setObjectName(u"label_2")
|
||||
|
||||
self.formLayout.setWidget(2, QFormLayout.LabelRole, self.label_2)
|
||||
|
||||
self.notesLineEdit = QLineEdit(self.widget)
|
||||
self.notesLineEdit.setObjectName(u"notesLineEdit")
|
||||
font = QFont()
|
||||
font.setFamilies([u"GeosansLight"])
|
||||
font.setPointSize(14)
|
||||
font.setBold(True)
|
||||
self.notesLineEdit.setFont(font)
|
||||
|
||||
self.formLayout.setWidget(2, QFormLayout.FieldRole, self.notesLineEdit)
|
||||
|
||||
self.jacketLabel = QLabel(self.widget)
|
||||
self.jacketLabel.setObjectName(u"jacketLabel")
|
||||
self.jacketLabel.setMinimumSize(QSize(100, 100))
|
||||
self.jacketLabel.setMaximumSize(QSize(100, 100))
|
||||
self.jacketLabel.setText(u"")
|
||||
|
||||
self.formLayout.setWidget(0, QFormLayout.LabelRole, self.jacketLabel)
|
||||
|
||||
self.verticalLayout = QVBoxLayout()
|
||||
self.verticalLayout.setObjectName(u"verticalLayout")
|
||||
self.verticalSpacer = QSpacerItem(20, 0, QSizePolicy.Minimum, QSizePolicy.Expanding)
|
||||
|
||||
self.verticalLayout.addItem(self.verticalSpacer)
|
||||
|
||||
self.titleLabel = QLabel(self.widget)
|
||||
self.titleLabel.setObjectName(u"titleLabel")
|
||||
self.titleLabel.setText(u"...")
|
||||
|
||||
self.verticalLayout.addWidget(self.titleLabel)
|
||||
|
||||
self.ratingLabel = QLabel(self.widget)
|
||||
self.ratingLabel.setObjectName(u"ratingLabel")
|
||||
self.ratingLabel.setText(u"...")
|
||||
|
||||
self.verticalLayout.addWidget(self.ratingLabel)
|
||||
|
||||
self.verticalSpacer_2 = QSpacerItem(20, 0, QSizePolicy.Minimum, QSizePolicy.Expanding)
|
||||
|
||||
self.verticalLayout.addItem(self.verticalSpacer_2)
|
||||
|
||||
|
||||
self.formLayout.setLayout(0, QFormLayout.FieldRole, self.verticalLayout)
|
||||
|
||||
self.horizontalWidget_2 = QWidget(self.widget)
|
||||
self.horizontalWidget_2.setObjectName(u"horizontalWidget_2")
|
||||
sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.horizontalWidget_2.sizePolicy().hasHeightForWidth())
|
||||
self.horizontalWidget_2.setSizePolicy(sizePolicy)
|
||||
self.horizontalLayout_2 = QHBoxLayout(self.horizontalWidget_2)
|
||||
self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
|
||||
self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
|
||||
self.constantLineEdit = QLineEdit(self.horizontalWidget_2)
|
||||
self.constantLineEdit.setObjectName(u"constantLineEdit")
|
||||
self.constantLineEdit.setFont(font)
|
||||
|
||||
self.horizontalLayout_2.addWidget(self.constantLineEdit)
|
||||
|
||||
self.constantPreviewLabel = QLabel(self.horizontalWidget_2)
|
||||
self.constantPreviewLabel.setObjectName(u"constantPreviewLabel")
|
||||
self.constantPreviewLabel.setText(u"> ...")
|
||||
|
||||
self.horizontalLayout_2.addWidget(self.constantPreviewLabel)
|
||||
|
||||
|
||||
self.formLayout.setWidget(1, QFormLayout.FieldRole, self.horizontalWidget_2)
|
||||
|
||||
self.label_3 = QLabel(self.widget)
|
||||
self.label_3.setObjectName(u"label_3")
|
||||
sizePolicy1 = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.MinimumExpanding)
|
||||
sizePolicy1.setHorizontalStretch(0)
|
||||
sizePolicy1.setVerticalStretch(0)
|
||||
sizePolicy1.setHeightForWidth(self.label_3.sizePolicy().hasHeightForWidth())
|
||||
self.label_3.setSizePolicy(sizePolicy1)
|
||||
|
||||
self.formLayout.setWidget(3, QFormLayout.LabelRole, self.label_3)
|
||||
|
||||
self.label_4 = QLabel(self.widget)
|
||||
self.label_4.setObjectName(u"label_4")
|
||||
|
||||
self.formLayout.setWidget(3, QFormLayout.FieldRole, self.label_4)
|
||||
|
||||
|
||||
self.verticalLayout_2.addWidget(self.widget)
|
||||
|
||||
self.verticalSpacer_3 = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
|
||||
|
||||
self.verticalLayout_2.addItem(self.verticalSpacer_3)
|
||||
|
||||
self.horizontalLayout = QHBoxLayout()
|
||||
self.horizontalLayout.setObjectName(u"horizontalLayout")
|
||||
self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
|
||||
|
||||
self.horizontalLayout.addItem(self.horizontalSpacer)
|
||||
|
||||
self.deleteButton = QPushButton(self.groupBox)
|
||||
self.deleteButton.setObjectName(u"deleteButton")
|
||||
|
||||
self.horizontalLayout.addWidget(self.deleteButton)
|
||||
|
||||
self.commitButton = QPushButton(self.groupBox)
|
||||
self.commitButton.setObjectName(u"commitButton")
|
||||
|
||||
self.horizontalLayout.addWidget(self.commitButton)
|
||||
|
||||
|
||||
self.verticalLayout_2.addLayout(self.horizontalLayout)
|
||||
|
||||
|
||||
self.gridLayout.addWidget(self.groupBox, 1, 1, 1, 1)
|
||||
|
||||
self.chartSelector = ChartSelector(TabDb_ChartInfoEditor)
|
||||
self.chartSelector.setObjectName(u"chartSelector")
|
||||
|
||||
self.gridLayout.addWidget(self.chartSelector, 0, 0, 1, 2)
|
||||
|
||||
self.listView = QListView(TabDb_ChartInfoEditor)
|
||||
self.listView.setObjectName(u"listView")
|
||||
sizePolicy2 = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
|
||||
sizePolicy2.setHorizontalStretch(0)
|
||||
sizePolicy2.setVerticalStretch(0)
|
||||
sizePolicy2.setHeightForWidth(self.listView.sizePolicy().hasHeightForWidth())
|
||||
self.listView.setSizePolicy(sizePolicy2)
|
||||
self.listView.setEditTriggers(QAbstractItemView.NoEditTriggers)
|
||||
self.listView.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel)
|
||||
self.listView.setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel)
|
||||
|
||||
self.gridLayout.addWidget(self.listView, 1, 0, 1, 1)
|
||||
|
||||
QWidget.setTabOrder(self.listView, self.constantLineEdit)
|
||||
QWidget.setTabOrder(self.constantLineEdit, self.notesLineEdit)
|
||||
QWidget.setTabOrder(self.notesLineEdit, self.commitButton)
|
||||
QWidget.setTabOrder(self.commitButton, self.deleteButton)
|
||||
|
||||
self.retranslateUi(TabDb_ChartInfoEditor)
|
||||
|
||||
QMetaObject.connectSlotsByName(TabDb_ChartInfoEditor)
|
||||
# setupUi
|
||||
|
||||
def retranslateUi(self, TabDb_ChartInfoEditor):
|
||||
self.groupBox.setTitle(QCoreApplication.translate("TabDb_ChartInfoEditor", u"editor.title", None))
|
||||
self.label.setText(QCoreApplication.translate("TabDb_ChartInfoEditor", u"editor.constant", None))
|
||||
self.label_2.setText(QCoreApplication.translate("TabDb_ChartInfoEditor", u"editor.notes", None))
|
||||
self.label_3.setText(QCoreApplication.translate("TabDb_ChartInfoEditor", u"editor.tip", None))
|
||||
self.label_4.setText(QCoreApplication.translate("TabDb_ChartInfoEditor", u"editor.tip.content", None))
|
||||
self.deleteButton.setText(QCoreApplication.translate("TabDb_ChartInfoEditor", u"editor.delete", None))
|
||||
self.commitButton.setText(QCoreApplication.translate("TabDb_ChartInfoEditor", u"editor.commit", None))
|
||||
pass
|
||||
# retranslateUi
|
||||
|
@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>630</width>
|
||||
<height>528</height>
|
||||
<width>580</width>
|
||||
<height>551</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -17,70 +17,21 @@
|
||||
<property name="labelAlignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<item row="0" 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="6" column="0" colspan="2">
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QPushButton" name="exportScoresButton">
|
||||
<property name="text">
|
||||
<string>exportScoresButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<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">
|
||||
<item row="1" column="0">
|
||||
<widget class="QPushButton" name="importPacklistButton">
|
||||
<property name="text">
|
||||
<string>importPacklistButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</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">
|
||||
<property name="text">
|
||||
<string>importSonglistButton</string>
|
||||
@ -88,47 +39,259 @@
|
||||
</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">
|
||||
<item row="3" column="0">
|
||||
<widget class="QPushButton" name="importApkButton">
|
||||
<property name="text">
|
||||
<string>importApkButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>importApk.description</string>
|
||||
</property>
|
||||
</widget>
|
||||
</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">
|
||||
<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">
|
||||
<property name="text">
|
||||
<string>importOnlineButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="1">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>importOnline.description</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<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">
|
||||
<property name="text">
|
||||
<string>exportSmartRteB30Button</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="1">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>exportSmartRteB30.description</string>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</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>
|
||||
</widget>
|
||||
<resources/>
|
||||
|
@ -15,101 +15,168 @@ 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)
|
||||
from PySide6.QtWidgets import (QApplication, QFormLayout, QLabel, QPushButton,
|
||||
QSizePolicy, QSpacerItem, 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.resize(580, 551)
|
||||
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.formLayout.setWidget(1, QFormLayout.LabelRole, self.importPacklistButton)
|
||||
|
||||
self.label_4 = QLabel(TabDb_Manage)
|
||||
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.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.formLayout.setWidget(2, QFormLayout.FieldRole, self.label_5)
|
||||
|
||||
self.importApkButton = QPushButton(TabDb_Manage)
|
||||
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.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.setObjectName(u"importOnlineButton")
|
||||
|
||||
self.formLayout.setWidget(11, QFormLayout.LabelRole, self.importOnlineButton)
|
||||
|
||||
self.label_8 = QLabel(TabDb_Manage)
|
||||
self.label_8.setObjectName(u"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.setObjectName(u"exportSmartRteB30Button")
|
||||
|
||||
self.formLayout.setWidget(15, QFormLayout.LabelRole, self.exportSmartRteB30Button)
|
||||
|
||||
self.label_9 = QLabel(TabDb_Manage)
|
||||
self.label_9.setObjectName(u"label_9")
|
||||
self.label_9.setOpenExternalLinks(True)
|
||||
self.label_9.setTextInteractionFlags(Qt.LinksAccessibleByKeyboard|Qt.LinksAccessibleByMouse)
|
||||
|
||||
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)
|
||||
@ -118,20 +185,30 @@ class Ui_TabDb_Manage(object):
|
||||
# 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.importSonglistButton.setText(QCoreApplication.translate("TabDb_Manage", u"importSonglistButton", 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))
|
||||
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.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.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
|
||||
# retranslateUi
|
||||
|
||||
|
286
ui/designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui
Normal file
286
ui/designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui
Normal file
@ -0,0 +1,286 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TabDb_RemoveDuplicateScores</class>
|
||||
<widget class="QWidget" name="TabDb_RemoveDuplicateScores">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>600</width>
|
||||
<height>500</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">TabDb_RemoveDuplicateScores</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>scan.title</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="scan_option_scoreCheckBox">
|
||||
<property name="text">
|
||||
<string>scan.option.score</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="scan_option_pureCheckBox">
|
||||
<property name="text">
|
||||
<string notr="true">PURE</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="scan_option_farCheckBox">
|
||||
<property name="text">
|
||||
<string notr="true">FAR</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="scan_option_lostCheckBox">
|
||||
<property name="text">
|
||||
<string notr="true">LOST</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="scan_option_maxRecallCheckBox">
|
||||
<property name="text">
|
||||
<string notr="true">MAX RECALL</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="scan_option_dateCheckBox">
|
||||
<property name="text">
|
||||
<string>scan.option.date</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="scan_option_modifierCheckBox">
|
||||
<property name="text">
|
||||
<string>scan.option.modifier</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="scan_option_clearTypeCheckBox">
|
||||
<property name="text">
|
||||
<string>scan.option.clearType</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="scan_scanButton">
|
||||
<property name="text">
|
||||
<string>scan.scanButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QTreeView" name="treeView">
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::NoSelection</enum>
|
||||
</property>
|
||||
<property name="verticalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<property name="headerHidden">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>quickSelect.title</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>quickSelect.description</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="quickSelect_comboBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="quickSelect_selectButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>quickSelect.selectButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
<string/>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<widget class="QPushButton" name="deselectAllButton">
|
||||
<property name="text">
|
||||
<string>deselectAllButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="reverseSelectionButton">
|
||||
<property name="text">
|
||||
<string>reverseSelectionButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="collapseAllButton">
|
||||
<property name="text">
|
||||
<string>collapseAllButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="expandAllButton">
|
||||
<property name="text">
|
||||
<string>expandAllButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="resetModelButton">
|
||||
<property name="text">
|
||||
<string>resetModelButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="deleteSelectionButton">
|
||||
<property name="font">
|
||||
<font>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QPushButton { color: red };</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>deleteSelectionButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>scan_option_scoreCheckBox</tabstop>
|
||||
<tabstop>scan_option_pureCheckBox</tabstop>
|
||||
<tabstop>scan_option_farCheckBox</tabstop>
|
||||
<tabstop>scan_option_lostCheckBox</tabstop>
|
||||
<tabstop>scan_option_maxRecallCheckBox</tabstop>
|
||||
<tabstop>scan_option_dateCheckBox</tabstop>
|
||||
<tabstop>scan_option_modifierCheckBox</tabstop>
|
||||
<tabstop>scan_option_clearTypeCheckBox</tabstop>
|
||||
<tabstop>scan_scanButton</tabstop>
|
||||
<tabstop>treeView</tabstop>
|
||||
<tabstop>quickSelect_comboBox</tabstop>
|
||||
<tabstop>quickSelect_selectButton</tabstop>
|
||||
<tabstop>deselectAllButton</tabstop>
|
||||
<tabstop>reverseSelectionButton</tabstop>
|
||||
<tabstop>collapseAllButton</tabstop>
|
||||
<tabstop>expandAllButton</tabstop>
|
||||
<tabstop>resetModelButton</tabstop>
|
||||
<tabstop>deleteSelectionButton</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
245
ui/designer/tabs/tabDb/tabDb_RemoveDuplicateScores_ui.py
Normal file
245
ui/designer/tabs/tabDb/tabDb_RemoveDuplicateScores_ui.py
Normal file
@ -0,0 +1,245 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
################################################################################
|
||||
## Form generated from reading UI file 'tabDb_RemoveDuplicateScores.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 (QAbstractItemView, QApplication, QCheckBox, QComboBox,
|
||||
QGroupBox, QHBoxLayout, QHeaderView, QLabel,
|
||||
QPushButton, QSizePolicy, QSpacerItem, QTreeView,
|
||||
QVBoxLayout, QWidget)
|
||||
|
||||
class Ui_TabDb_RemoveDuplicateScores(object):
|
||||
def setupUi(self, TabDb_RemoveDuplicateScores):
|
||||
if not TabDb_RemoveDuplicateScores.objectName():
|
||||
TabDb_RemoveDuplicateScores.setObjectName(u"TabDb_RemoveDuplicateScores")
|
||||
TabDb_RemoveDuplicateScores.resize(600, 500)
|
||||
TabDb_RemoveDuplicateScores.setWindowTitle(u"TabDb_RemoveDuplicateScores")
|
||||
self.verticalLayout_2 = QVBoxLayout(TabDb_RemoveDuplicateScores)
|
||||
self.verticalLayout_2.setObjectName(u"verticalLayout_2")
|
||||
self.groupBox_2 = QGroupBox(TabDb_RemoveDuplicateScores)
|
||||
self.groupBox_2.setObjectName(u"groupBox_2")
|
||||
self.verticalLayout = QVBoxLayout(self.groupBox_2)
|
||||
self.verticalLayout.setObjectName(u"verticalLayout")
|
||||
self.verticalLayout_4 = QVBoxLayout()
|
||||
self.verticalLayout_4.setObjectName(u"verticalLayout_4")
|
||||
self.horizontalLayout_2 = QHBoxLayout()
|
||||
self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
|
||||
self.scan_option_scoreCheckBox = QCheckBox(self.groupBox_2)
|
||||
self.scan_option_scoreCheckBox.setObjectName(u"scan_option_scoreCheckBox")
|
||||
|
||||
self.horizontalLayout_2.addWidget(self.scan_option_scoreCheckBox)
|
||||
|
||||
self.scan_option_pureCheckBox = QCheckBox(self.groupBox_2)
|
||||
self.scan_option_pureCheckBox.setObjectName(u"scan_option_pureCheckBox")
|
||||
self.scan_option_pureCheckBox.setText(u"PURE")
|
||||
|
||||
self.horizontalLayout_2.addWidget(self.scan_option_pureCheckBox)
|
||||
|
||||
self.scan_option_farCheckBox = QCheckBox(self.groupBox_2)
|
||||
self.scan_option_farCheckBox.setObjectName(u"scan_option_farCheckBox")
|
||||
self.scan_option_farCheckBox.setText(u"FAR")
|
||||
|
||||
self.horizontalLayout_2.addWidget(self.scan_option_farCheckBox)
|
||||
|
||||
self.scan_option_lostCheckBox = QCheckBox(self.groupBox_2)
|
||||
self.scan_option_lostCheckBox.setObjectName(u"scan_option_lostCheckBox")
|
||||
self.scan_option_lostCheckBox.setText(u"LOST")
|
||||
|
||||
self.horizontalLayout_2.addWidget(self.scan_option_lostCheckBox)
|
||||
|
||||
self.scan_option_maxRecallCheckBox = QCheckBox(self.groupBox_2)
|
||||
self.scan_option_maxRecallCheckBox.setObjectName(u"scan_option_maxRecallCheckBox")
|
||||
self.scan_option_maxRecallCheckBox.setText(u"MAX RECALL")
|
||||
|
||||
self.horizontalLayout_2.addWidget(self.scan_option_maxRecallCheckBox)
|
||||
|
||||
|
||||
self.verticalLayout_4.addLayout(self.horizontalLayout_2)
|
||||
|
||||
|
||||
self.verticalLayout.addLayout(self.verticalLayout_4)
|
||||
|
||||
self.horizontalLayout_3 = QHBoxLayout()
|
||||
self.horizontalLayout_3.setObjectName(u"horizontalLayout_3")
|
||||
self.scan_option_dateCheckBox = QCheckBox(self.groupBox_2)
|
||||
self.scan_option_dateCheckBox.setObjectName(u"scan_option_dateCheckBox")
|
||||
|
||||
self.horizontalLayout_3.addWidget(self.scan_option_dateCheckBox)
|
||||
|
||||
self.scan_option_modifierCheckBox = QCheckBox(self.groupBox_2)
|
||||
self.scan_option_modifierCheckBox.setObjectName(u"scan_option_modifierCheckBox")
|
||||
|
||||
self.horizontalLayout_3.addWidget(self.scan_option_modifierCheckBox)
|
||||
|
||||
self.scan_option_clearTypeCheckBox = QCheckBox(self.groupBox_2)
|
||||
self.scan_option_clearTypeCheckBox.setObjectName(u"scan_option_clearTypeCheckBox")
|
||||
|
||||
self.horizontalLayout_3.addWidget(self.scan_option_clearTypeCheckBox)
|
||||
|
||||
|
||||
self.verticalLayout.addLayout(self.horizontalLayout_3)
|
||||
|
||||
self.scan_scanButton = QPushButton(self.groupBox_2)
|
||||
self.scan_scanButton.setObjectName(u"scan_scanButton")
|
||||
|
||||
self.verticalLayout.addWidget(self.scan_scanButton)
|
||||
|
||||
|
||||
self.verticalLayout_2.addWidget(self.groupBox_2)
|
||||
|
||||
self.horizontalLayout = QHBoxLayout()
|
||||
self.horizontalLayout.setObjectName(u"horizontalLayout")
|
||||
self.treeView = QTreeView(TabDb_RemoveDuplicateScores)
|
||||
self.treeView.setObjectName(u"treeView")
|
||||
self.treeView.setEditTriggers(QAbstractItemView.NoEditTriggers)
|
||||
self.treeView.setSelectionMode(QAbstractItemView.NoSelection)
|
||||
self.treeView.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel)
|
||||
self.treeView.setHeaderHidden(True)
|
||||
|
||||
self.horizontalLayout.addWidget(self.treeView)
|
||||
|
||||
self.verticalLayout_6 = QVBoxLayout()
|
||||
self.verticalLayout_6.setObjectName(u"verticalLayout_6")
|
||||
self.groupBox = QGroupBox(TabDb_RemoveDuplicateScores)
|
||||
self.groupBox.setObjectName(u"groupBox")
|
||||
self.verticalLayout_3 = QVBoxLayout(self.groupBox)
|
||||
self.verticalLayout_3.setObjectName(u"verticalLayout_3")
|
||||
self.label = QLabel(self.groupBox)
|
||||
self.label.setObjectName(u"label")
|
||||
|
||||
self.verticalLayout_3.addWidget(self.label)
|
||||
|
||||
self.quickSelect_comboBox = QComboBox(self.groupBox)
|
||||
self.quickSelect_comboBox.setObjectName(u"quickSelect_comboBox")
|
||||
sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.quickSelect_comboBox.sizePolicy().hasHeightForWidth())
|
||||
self.quickSelect_comboBox.setSizePolicy(sizePolicy)
|
||||
|
||||
self.verticalLayout_3.addWidget(self.quickSelect_comboBox)
|
||||
|
||||
self.verticalSpacer_2 = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
|
||||
|
||||
self.verticalLayout_3.addItem(self.verticalSpacer_2)
|
||||
|
||||
self.quickSelect_selectButton = QPushButton(self.groupBox)
|
||||
self.quickSelect_selectButton.setObjectName(u"quickSelect_selectButton")
|
||||
sizePolicy.setHeightForWidth(self.quickSelect_selectButton.sizePolicy().hasHeightForWidth())
|
||||
self.quickSelect_selectButton.setSizePolicy(sizePolicy)
|
||||
|
||||
self.verticalLayout_3.addWidget(self.quickSelect_selectButton)
|
||||
|
||||
|
||||
self.verticalLayout_6.addWidget(self.groupBox)
|
||||
|
||||
self.groupBox_3 = QGroupBox(TabDb_RemoveDuplicateScores)
|
||||
self.groupBox_3.setObjectName(u"groupBox_3")
|
||||
self.verticalLayout_5 = QVBoxLayout(self.groupBox_3)
|
||||
self.verticalLayout_5.setObjectName(u"verticalLayout_5")
|
||||
self.deselectAllButton = QPushButton(self.groupBox_3)
|
||||
self.deselectAllButton.setObjectName(u"deselectAllButton")
|
||||
|
||||
self.verticalLayout_5.addWidget(self.deselectAllButton)
|
||||
|
||||
self.reverseSelectionButton = QPushButton(self.groupBox_3)
|
||||
self.reverseSelectionButton.setObjectName(u"reverseSelectionButton")
|
||||
|
||||
self.verticalLayout_5.addWidget(self.reverseSelectionButton)
|
||||
|
||||
self.verticalSpacer_3 = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
|
||||
|
||||
self.verticalLayout_5.addItem(self.verticalSpacer_3)
|
||||
|
||||
self.collapseAllButton = QPushButton(self.groupBox_3)
|
||||
self.collapseAllButton.setObjectName(u"collapseAllButton")
|
||||
|
||||
self.verticalLayout_5.addWidget(self.collapseAllButton)
|
||||
|
||||
self.expandAllButton = QPushButton(self.groupBox_3)
|
||||
self.expandAllButton.setObjectName(u"expandAllButton")
|
||||
|
||||
self.verticalLayout_5.addWidget(self.expandAllButton)
|
||||
|
||||
self.resetModelButton = QPushButton(self.groupBox_3)
|
||||
self.resetModelButton.setObjectName(u"resetModelButton")
|
||||
|
||||
self.verticalLayout_5.addWidget(self.resetModelButton)
|
||||
|
||||
self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
|
||||
|
||||
self.verticalLayout_5.addItem(self.verticalSpacer)
|
||||
|
||||
self.deleteSelectionButton = QPushButton(self.groupBox_3)
|
||||
self.deleteSelectionButton.setObjectName(u"deleteSelectionButton")
|
||||
font = QFont()
|
||||
font.setBold(True)
|
||||
self.deleteSelectionButton.setFont(font)
|
||||
self.deleteSelectionButton.setStyleSheet(u"QPushButton { color: red };")
|
||||
|
||||
self.verticalLayout_5.addWidget(self.deleteSelectionButton)
|
||||
|
||||
|
||||
self.verticalLayout_6.addWidget(self.groupBox_3)
|
||||
|
||||
|
||||
self.horizontalLayout.addLayout(self.verticalLayout_6)
|
||||
|
||||
|
||||
self.verticalLayout_2.addLayout(self.horizontalLayout)
|
||||
|
||||
QWidget.setTabOrder(self.scan_option_scoreCheckBox, self.scan_option_pureCheckBox)
|
||||
QWidget.setTabOrder(self.scan_option_pureCheckBox, self.scan_option_farCheckBox)
|
||||
QWidget.setTabOrder(self.scan_option_farCheckBox, self.scan_option_lostCheckBox)
|
||||
QWidget.setTabOrder(self.scan_option_lostCheckBox, self.scan_option_maxRecallCheckBox)
|
||||
QWidget.setTabOrder(self.scan_option_maxRecallCheckBox, self.scan_option_dateCheckBox)
|
||||
QWidget.setTabOrder(self.scan_option_dateCheckBox, self.scan_option_modifierCheckBox)
|
||||
QWidget.setTabOrder(self.scan_option_modifierCheckBox, self.scan_option_clearTypeCheckBox)
|
||||
QWidget.setTabOrder(self.scan_option_clearTypeCheckBox, self.scan_scanButton)
|
||||
QWidget.setTabOrder(self.scan_scanButton, self.treeView)
|
||||
QWidget.setTabOrder(self.treeView, self.quickSelect_comboBox)
|
||||
QWidget.setTabOrder(self.quickSelect_comboBox, self.quickSelect_selectButton)
|
||||
QWidget.setTabOrder(self.quickSelect_selectButton, self.deselectAllButton)
|
||||
QWidget.setTabOrder(self.deselectAllButton, self.reverseSelectionButton)
|
||||
QWidget.setTabOrder(self.reverseSelectionButton, self.collapseAllButton)
|
||||
QWidget.setTabOrder(self.collapseAllButton, self.expandAllButton)
|
||||
QWidget.setTabOrder(self.expandAllButton, self.resetModelButton)
|
||||
QWidget.setTabOrder(self.resetModelButton, self.deleteSelectionButton)
|
||||
|
||||
self.retranslateUi(TabDb_RemoveDuplicateScores)
|
||||
|
||||
QMetaObject.connectSlotsByName(TabDb_RemoveDuplicateScores)
|
||||
# setupUi
|
||||
|
||||
def retranslateUi(self, TabDb_RemoveDuplicateScores):
|
||||
self.groupBox_2.setTitle(QCoreApplication.translate("TabDb_RemoveDuplicateScores", u"scan.title", None))
|
||||
self.scan_option_scoreCheckBox.setText(QCoreApplication.translate("TabDb_RemoveDuplicateScores", u"scan.option.score", None))
|
||||
self.scan_option_dateCheckBox.setText(QCoreApplication.translate("TabDb_RemoveDuplicateScores", u"scan.option.date", None))
|
||||
self.scan_option_modifierCheckBox.setText(QCoreApplication.translate("TabDb_RemoveDuplicateScores", u"scan.option.modifier", None))
|
||||
self.scan_option_clearTypeCheckBox.setText(QCoreApplication.translate("TabDb_RemoveDuplicateScores", u"scan.option.clearType", None))
|
||||
self.scan_scanButton.setText(QCoreApplication.translate("TabDb_RemoveDuplicateScores", u"scan.scanButton", None))
|
||||
self.groupBox.setTitle(QCoreApplication.translate("TabDb_RemoveDuplicateScores", u"quickSelect.title", None))
|
||||
self.label.setText(QCoreApplication.translate("TabDb_RemoveDuplicateScores", u"quickSelect.description", None))
|
||||
self.quickSelect_selectButton.setText(QCoreApplication.translate("TabDb_RemoveDuplicateScores", u"quickSelect.selectButton", None))
|
||||
self.groupBox_3.setTitle("")
|
||||
self.deselectAllButton.setText(QCoreApplication.translate("TabDb_RemoveDuplicateScores", u"deselectAllButton", None))
|
||||
self.reverseSelectionButton.setText(QCoreApplication.translate("TabDb_RemoveDuplicateScores", u"reverseSelectionButton", None))
|
||||
self.collapseAllButton.setText(QCoreApplication.translate("TabDb_RemoveDuplicateScores", u"collapseAllButton", None))
|
||||
self.expandAllButton.setText(QCoreApplication.translate("TabDb_RemoveDuplicateScores", u"expandAllButton", None))
|
||||
self.resetModelButton.setText(QCoreApplication.translate("TabDb_RemoveDuplicateScores", u"resetModelButton", None))
|
||||
self.deleteSelectionButton.setText(QCoreApplication.translate("TabDb_RemoveDuplicateScores", u"deleteSelectionButton", None))
|
||||
pass
|
||||
# retranslateUi
|
||||
|
@ -24,6 +24,16 @@
|
||||
<string>tab.manage</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
<widget class="TabDb_ChartInfoEditor" name="tab_chartInfoEditor">
|
||||
<attribute name="title">
|
||||
<string>tab.chartInfoEditor</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
<widget class="TabDb_RemoveDuplicateScores" name="tab_removeDuplicateScores">
|
||||
<attribute name="title">
|
||||
<string>tab.removeDuplicateScores</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
@ -35,6 +45,18 @@
|
||||
<header>ui.implements.tabs.tabDb.tabDb_Manage</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>TabDb_ChartInfoEditor</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>ui.implements.tabs.tabDb.tabDb_ChartInfoEditor</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>TabDb_RemoveDuplicateScores</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>ui.implements.tabs.tabDb.tabDb_RemoveDuplicateScores</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
@ -3,7 +3,7 @@
|
||||
################################################################################
|
||||
## Form generated from reading UI file 'tabDbEntry.ui'
|
||||
##
|
||||
## Created by: Qt User Interface Compiler version 6.5.0
|
||||
## Created by: Qt User Interface Compiler version 6.5.2
|
||||
##
|
||||
## WARNING! All changes made in this file will be lost when recompiling UI file!
|
||||
################################################################################
|
||||
@ -18,7 +18,9 @@ from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
|
||||
from PySide6.QtWidgets import (QApplication, QSizePolicy, QTabWidget, QVBoxLayout,
|
||||
QWidget)
|
||||
|
||||
from ui.implements.tabs.tabDb.tabDb_ChartInfoEditor import TabDb_ChartInfoEditor
|
||||
from ui.implements.tabs.tabDb.tabDb_Manage import TabDb_Manage
|
||||
from ui.implements.tabs.tabDb.tabDb_RemoveDuplicateScores import TabDb_RemoveDuplicateScores
|
||||
|
||||
class Ui_TabDbEntry(object):
|
||||
def setupUi(self, TabDbEntry):
|
||||
@ -33,6 +35,12 @@ class Ui_TabDbEntry(object):
|
||||
self.tab_manage = TabDb_Manage()
|
||||
self.tab_manage.setObjectName(u"tab_manage")
|
||||
self.tabWidget.addTab(self.tab_manage, "")
|
||||
self.tab_chartInfoEditor = TabDb_ChartInfoEditor()
|
||||
self.tab_chartInfoEditor.setObjectName(u"tab_chartInfoEditor")
|
||||
self.tabWidget.addTab(self.tab_chartInfoEditor, "")
|
||||
self.tab_removeDuplicateScores = TabDb_RemoveDuplicateScores()
|
||||
self.tab_removeDuplicateScores.setObjectName(u"tab_removeDuplicateScores")
|
||||
self.tabWidget.addTab(self.tab_removeDuplicateScores, "")
|
||||
|
||||
self.verticalLayout.addWidget(self.tabWidget)
|
||||
|
||||
@ -47,6 +55,8 @@ class Ui_TabDbEntry(object):
|
||||
|
||||
def retranslateUi(self, TabDbEntry):
|
||||
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_manage), QCoreApplication.translate("TabDbEntry", u"tab.manage", None))
|
||||
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_chartInfoEditor), QCoreApplication.translate("TabDbEntry", u"tab.chartInfoEditor", None))
|
||||
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_removeDuplicateScores), QCoreApplication.translate("TabDbEntry", u"tab.removeDuplicateScores", None))
|
||||
pass
|
||||
# retranslateUi
|
||||
|
||||
|
@ -329,6 +329,36 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>sourceCode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string notr="true"><a href="https://github.com/283375/AndrealImageGenerator">283375/AndrealImageGenerator</a><br>(forked from <a href="https://github.com/Awbugl/AndrealImageGenerator">Awbugl/AndrealImageGenerator</a>)</string>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0" colspan="2">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
|
@ -220,6 +220,22 @@ class Ui_TabTools_Andreal(object):
|
||||
|
||||
self.formLayout.setLayout(7, QFormLayout.SpanningRole, self.horizontalLayout_5)
|
||||
|
||||
self.label_4 = QLabel(TabTools_Andreal)
|
||||
self.label_4.setObjectName(u"label_4")
|
||||
|
||||
self.formLayout.setWidget(9, QFormLayout.LabelRole, self.label_4)
|
||||
|
||||
self.label_7 = QLabel(TabTools_Andreal)
|
||||
self.label_7.setObjectName(u"label_7")
|
||||
self.label_7.setText(u"<a href=\"https://github.com/283375/AndrealImageGenerator\">283375/AndrealImageGenerator</a><br>(forked from <a href=\"https://github.com/Awbugl/AndrealImageGenerator\">Awbugl/AndrealImageGenerator</a>)")
|
||||
self.label_7.setOpenExternalLinks(True)
|
||||
|
||||
self.formLayout.setWidget(9, QFormLayout.FieldRole, self.label_7)
|
||||
|
||||
self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
|
||||
|
||||
self.formLayout.setItem(8, QFormLayout.SpanningRole, self.verticalSpacer)
|
||||
|
||||
|
||||
self.retranslateUi(TabTools_Andreal)
|
||||
self.imageFormat_jpgRadioButton.toggled.connect(self.jpgQualityHolderWidget.setEnabled)
|
||||
@ -241,6 +257,7 @@ class Ui_TabTools_Andreal(object):
|
||||
self.exportJsonButton.setText(QCoreApplication.translate("TabTools_Andreal", u"exportJsonButton", None))
|
||||
self.generatePreviewButton.setText(QCoreApplication.translate("TabTools_Andreal", u"generatePreviewButton", None))
|
||||
self.generateImageButton.setText(QCoreApplication.translate("TabTools_Andreal", u"generateImageButton", None))
|
||||
self.label_4.setText(QCoreApplication.translate("TabTools_Andreal", u"sourceCode", None))
|
||||
pass
|
||||
# retranslateUi
|
||||
|
||||
|
@ -6,113 +6,15 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>668</width>
|
||||
<height>546</height>
|
||||
<width>616</width>
|
||||
<height>500</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">TabTools_ChartRecommend</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>constantRangeFromPlayRating</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="rangeFromPlayRating_playRatingSpinBox">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>100.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string notr="true">AA</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string notr="true">EX</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string notr="true">EX+</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="rangeFromPlayRating_ExPlusLabel">
|
||||
<property name="text">
|
||||
<string notr="true">...</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="rangeFromPlayRating_ExLabel">
|
||||
<property name="text">
|
||||
<string notr="true">...</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QLabel" name="rangeFromPlayRating_AaLabel">
|
||||
<property name="text">
|
||||
<string notr="true">...</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="1">
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>chartsByConstant</string>
|
||||
@ -147,51 +49,200 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="chartsByConstant_numLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="chartsByConstant_refreshButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>refreshButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<widget class="QListView" name="chartsByConstant_modelView">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="chartsByConstant_gridLayout"/>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::NoSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<property name="verticalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>constantRangeFromPlayRating</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="rangeFromPlayRating_playRatingSpinBox">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>100.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="labelAlignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="formAlignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string notr="true">EX+</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="rangeFromPlayRating_ExPlusLabel">
|
||||
<property name="text">
|
||||
<string notr="true">...</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string notr="true">EX</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="rangeFromPlayRating_ExLabel">
|
||||
<property name="text">
|
||||
<string notr="true">...</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string notr="true">AA</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="rangeFromPlayRating_AaLabel">
|
||||
<property name="text">
|
||||
<string notr="true">...</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string notr="true">A</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="rangeFromPlayRating_ALabel">
|
||||
<property name="text">
|
||||
<string notr="true">...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string notr="true">B</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="rangeFromPlayRating_BLabel">
|
||||
<property name="text">
|
||||
<string notr="true">...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string notr="true">C</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLabel" name="rangeFromPlayRating_CLabel">
|
||||
<property name="text">
|
||||
<string notr="true">...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
<string>chartsRecommendFromPlayRating</string>
|
||||
@ -246,45 +297,48 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="chartsRecommendFromPlayRating_numLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="chartsRecommendFromPlayRating_refreshButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>refreshButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="widget_2" native="true">
|
||||
<widget class="QTableView" name="chartsRecommendFromPlayRating_modelView">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="chartsRecommendFromPlayRating_gridLayout"/>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::NoSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<property name="verticalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
@ -15,82 +15,19 @@ 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, QDoubleSpinBox, QGridLayout, QGroupBox,
|
||||
QHBoxLayout, QLabel, QPushButton, QSizePolicy,
|
||||
QSpacerItem, QVBoxLayout, QWidget)
|
||||
from PySide6.QtWidgets import (QAbstractItemView, QApplication, QDoubleSpinBox, QFormLayout,
|
||||
QGridLayout, QGroupBox, QHBoxLayout, QHeaderView,
|
||||
QLabel, QListView, QSizePolicy, QTableView,
|
||||
QVBoxLayout, QWidget)
|
||||
|
||||
class Ui_TabTools_ChartRecommend(object):
|
||||
def setupUi(self, TabTools_ChartRecommend):
|
||||
if not TabTools_ChartRecommend.objectName():
|
||||
TabTools_ChartRecommend.setObjectName(u"TabTools_ChartRecommend")
|
||||
TabTools_ChartRecommend.resize(668, 546)
|
||||
TabTools_ChartRecommend.resize(616, 500)
|
||||
TabTools_ChartRecommend.setWindowTitle(u"TabTools_ChartRecommend")
|
||||
self.verticalLayout = QVBoxLayout(TabTools_ChartRecommend)
|
||||
self.verticalLayout.setObjectName(u"verticalLayout")
|
||||
self.groupBox = QGroupBox(TabTools_ChartRecommend)
|
||||
self.groupBox.setObjectName(u"groupBox")
|
||||
self.verticalLayout_2 = QVBoxLayout(self.groupBox)
|
||||
self.verticalLayout_2.setObjectName(u"verticalLayout_2")
|
||||
self.rangeFromPlayRating_playRatingSpinBox = QDoubleSpinBox(self.groupBox)
|
||||
self.rangeFromPlayRating_playRatingSpinBox.setObjectName(u"rangeFromPlayRating_playRatingSpinBox")
|
||||
self.rangeFromPlayRating_playRatingSpinBox.setMinimumSize(QSize(100, 0))
|
||||
self.rangeFromPlayRating_playRatingSpinBox.setMaximumSize(QSize(100, 16777215))
|
||||
self.rangeFromPlayRating_playRatingSpinBox.setDecimals(3)
|
||||
self.rangeFromPlayRating_playRatingSpinBox.setMaximum(100.000000000000000)
|
||||
self.rangeFromPlayRating_playRatingSpinBox.setSingleStep(0.100000000000000)
|
||||
|
||||
self.verticalLayout_2.addWidget(self.rangeFromPlayRating_playRatingSpinBox)
|
||||
|
||||
self.gridLayout_3 = QGridLayout()
|
||||
self.gridLayout_3.setObjectName(u"gridLayout_3")
|
||||
self.label_3 = QLabel(self.groupBox)
|
||||
self.label_3.setObjectName(u"label_3")
|
||||
self.label_3.setText(u"AA")
|
||||
self.label_3.setAlignment(Qt.AlignBottom|Qt.AlignLeading|Qt.AlignLeft)
|
||||
|
||||
self.gridLayout_3.addWidget(self.label_3, 0, 2, 1, 1)
|
||||
|
||||
self.label_2 = QLabel(self.groupBox)
|
||||
self.label_2.setObjectName(u"label_2")
|
||||
self.label_2.setText(u"EX")
|
||||
self.label_2.setAlignment(Qt.AlignBottom|Qt.AlignLeading|Qt.AlignLeft)
|
||||
|
||||
self.gridLayout_3.addWidget(self.label_2, 0, 1, 1, 1)
|
||||
|
||||
self.label = QLabel(self.groupBox)
|
||||
self.label.setObjectName(u"label")
|
||||
self.label.setText(u"EX+")
|
||||
self.label.setAlignment(Qt.AlignBottom|Qt.AlignLeading|Qt.AlignLeft)
|
||||
|
||||
self.gridLayout_3.addWidget(self.label, 0, 0, 1, 1)
|
||||
|
||||
self.rangeFromPlayRating_ExPlusLabel = QLabel(self.groupBox)
|
||||
self.rangeFromPlayRating_ExPlusLabel.setObjectName(u"rangeFromPlayRating_ExPlusLabel")
|
||||
self.rangeFromPlayRating_ExPlusLabel.setText(u"...")
|
||||
self.rangeFromPlayRating_ExPlusLabel.setAlignment(Qt.AlignLeading|Qt.AlignLeft|Qt.AlignTop)
|
||||
|
||||
self.gridLayout_3.addWidget(self.rangeFromPlayRating_ExPlusLabel, 1, 0, 1, 1)
|
||||
|
||||
self.rangeFromPlayRating_ExLabel = QLabel(self.groupBox)
|
||||
self.rangeFromPlayRating_ExLabel.setObjectName(u"rangeFromPlayRating_ExLabel")
|
||||
self.rangeFromPlayRating_ExLabel.setText(u"...")
|
||||
self.rangeFromPlayRating_ExLabel.setAlignment(Qt.AlignLeading|Qt.AlignLeft|Qt.AlignTop)
|
||||
|
||||
self.gridLayout_3.addWidget(self.rangeFromPlayRating_ExLabel, 1, 1, 1, 1)
|
||||
|
||||
self.rangeFromPlayRating_AaLabel = QLabel(self.groupBox)
|
||||
self.rangeFromPlayRating_AaLabel.setObjectName(u"rangeFromPlayRating_AaLabel")
|
||||
self.rangeFromPlayRating_AaLabel.setText(u"...")
|
||||
self.rangeFromPlayRating_AaLabel.setAlignment(Qt.AlignLeading|Qt.AlignLeft|Qt.AlignTop)
|
||||
|
||||
self.gridLayout_3.addWidget(self.rangeFromPlayRating_AaLabel, 1, 2, 1, 1)
|
||||
|
||||
|
||||
self.verticalLayout_2.addLayout(self.gridLayout_3)
|
||||
|
||||
|
||||
self.verticalLayout.addWidget(self.groupBox)
|
||||
|
||||
self.gridLayout = QGridLayout(TabTools_ChartRecommend)
|
||||
self.gridLayout.setObjectName(u"gridLayout")
|
||||
self.groupBox_2 = QGroupBox(TabTools_ChartRecommend)
|
||||
self.groupBox_2.setObjectName(u"groupBox_2")
|
||||
self.verticalLayout_3 = QVBoxLayout(self.groupBox_2)
|
||||
@ -109,37 +46,138 @@ class Ui_TabTools_ChartRecommend(object):
|
||||
|
||||
self.chartsByConstant_numLabel = QLabel(self.groupBox_2)
|
||||
self.chartsByConstant_numLabel.setObjectName(u"chartsByConstant_numLabel")
|
||||
sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.chartsByConstant_numLabel.sizePolicy().hasHeightForWidth())
|
||||
self.chartsByConstant_numLabel.setSizePolicy(sizePolicy)
|
||||
self.chartsByConstant_numLabel.setText(u"...")
|
||||
|
||||
self.horizontalLayout_3.addWidget(self.chartsByConstant_numLabel)
|
||||
|
||||
self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
|
||||
|
||||
self.horizontalLayout_3.addItem(self.horizontalSpacer)
|
||||
|
||||
self.chartsByConstant_refreshButton = QPushButton(self.groupBox_2)
|
||||
self.chartsByConstant_refreshButton.setObjectName(u"chartsByConstant_refreshButton")
|
||||
self.chartsByConstant_refreshButton.setEnabled(False)
|
||||
|
||||
self.horizontalLayout_3.addWidget(self.chartsByConstant_refreshButton)
|
||||
|
||||
|
||||
self.verticalLayout_3.addLayout(self.horizontalLayout_3)
|
||||
|
||||
self.widget = QWidget(self.groupBox_2)
|
||||
self.widget.setObjectName(u"widget")
|
||||
sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.widget.sizePolicy().hasHeightForWidth())
|
||||
self.widget.setSizePolicy(sizePolicy)
|
||||
self.chartsByConstant_gridLayout = QGridLayout(self.widget)
|
||||
self.chartsByConstant_gridLayout.setObjectName(u"chartsByConstant_gridLayout")
|
||||
self.chartsByConstant_modelView = QListView(self.groupBox_2)
|
||||
self.chartsByConstant_modelView.setObjectName(u"chartsByConstant_modelView")
|
||||
sizePolicy1 = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
|
||||
sizePolicy1.setHorizontalStretch(0)
|
||||
sizePolicy1.setVerticalStretch(0)
|
||||
sizePolicy1.setHeightForWidth(self.chartsByConstant_modelView.sizePolicy().hasHeightForWidth())
|
||||
self.chartsByConstant_modelView.setSizePolicy(sizePolicy1)
|
||||
self.chartsByConstant_modelView.setMinimumSize(QSize(150, 0))
|
||||
self.chartsByConstant_modelView.setEditTriggers(QAbstractItemView.NoEditTriggers)
|
||||
self.chartsByConstant_modelView.setSelectionMode(QAbstractItemView.NoSelection)
|
||||
self.chartsByConstant_modelView.setSelectionBehavior(QAbstractItemView.SelectRows)
|
||||
self.chartsByConstant_modelView.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel)
|
||||
self.chartsByConstant_modelView.setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel)
|
||||
|
||||
self.verticalLayout_3.addWidget(self.widget)
|
||||
self.verticalLayout_3.addWidget(self.chartsByConstant_modelView)
|
||||
|
||||
|
||||
self.verticalLayout.addWidget(self.groupBox_2)
|
||||
self.gridLayout.addWidget(self.groupBox_2, 0, 1, 1, 1)
|
||||
|
||||
self.groupBox = QGroupBox(TabTools_ChartRecommend)
|
||||
self.groupBox.setObjectName(u"groupBox")
|
||||
self.verticalLayout_2 = QVBoxLayout(self.groupBox)
|
||||
self.verticalLayout_2.setObjectName(u"verticalLayout_2")
|
||||
self.rangeFromPlayRating_playRatingSpinBox = QDoubleSpinBox(self.groupBox)
|
||||
self.rangeFromPlayRating_playRatingSpinBox.setObjectName(u"rangeFromPlayRating_playRatingSpinBox")
|
||||
self.rangeFromPlayRating_playRatingSpinBox.setMinimumSize(QSize(100, 0))
|
||||
self.rangeFromPlayRating_playRatingSpinBox.setMaximumSize(QSize(100, 16777215))
|
||||
self.rangeFromPlayRating_playRatingSpinBox.setDecimals(3)
|
||||
self.rangeFromPlayRating_playRatingSpinBox.setMaximum(100.000000000000000)
|
||||
self.rangeFromPlayRating_playRatingSpinBox.setSingleStep(0.100000000000000)
|
||||
|
||||
self.verticalLayout_2.addWidget(self.rangeFromPlayRating_playRatingSpinBox)
|
||||
|
||||
self.formLayout = QFormLayout()
|
||||
self.formLayout.setObjectName(u"formLayout")
|
||||
self.formLayout.setLabelAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
|
||||
self.formLayout.setFormAlignment(Qt.AlignLeading|Qt.AlignLeft|Qt.AlignVCenter)
|
||||
self.label = QLabel(self.groupBox)
|
||||
self.label.setObjectName(u"label")
|
||||
self.label.setText(u"EX+")
|
||||
self.label.setAlignment(Qt.AlignBottom|Qt.AlignLeading|Qt.AlignLeft)
|
||||
|
||||
self.formLayout.setWidget(0, QFormLayout.LabelRole, self.label)
|
||||
|
||||
self.rangeFromPlayRating_ExPlusLabel = QLabel(self.groupBox)
|
||||
self.rangeFromPlayRating_ExPlusLabel.setObjectName(u"rangeFromPlayRating_ExPlusLabel")
|
||||
self.rangeFromPlayRating_ExPlusLabel.setText(u"...")
|
||||
self.rangeFromPlayRating_ExPlusLabel.setAlignment(Qt.AlignLeading|Qt.AlignLeft|Qt.AlignTop)
|
||||
|
||||
self.formLayout.setWidget(0, QFormLayout.FieldRole, self.rangeFromPlayRating_ExPlusLabel)
|
||||
|
||||
self.label_2 = QLabel(self.groupBox)
|
||||
self.label_2.setObjectName(u"label_2")
|
||||
self.label_2.setText(u"EX")
|
||||
self.label_2.setAlignment(Qt.AlignBottom|Qt.AlignLeading|Qt.AlignLeft)
|
||||
|
||||
self.formLayout.setWidget(1, QFormLayout.LabelRole, self.label_2)
|
||||
|
||||
self.rangeFromPlayRating_ExLabel = QLabel(self.groupBox)
|
||||
self.rangeFromPlayRating_ExLabel.setObjectName(u"rangeFromPlayRating_ExLabel")
|
||||
self.rangeFromPlayRating_ExLabel.setText(u"...")
|
||||
self.rangeFromPlayRating_ExLabel.setAlignment(Qt.AlignLeading|Qt.AlignLeft|Qt.AlignTop)
|
||||
|
||||
self.formLayout.setWidget(1, QFormLayout.FieldRole, self.rangeFromPlayRating_ExLabel)
|
||||
|
||||
self.label_3 = QLabel(self.groupBox)
|
||||
self.label_3.setObjectName(u"label_3")
|
||||
self.label_3.setText(u"AA")
|
||||
self.label_3.setAlignment(Qt.AlignBottom|Qt.AlignLeading|Qt.AlignLeft)
|
||||
|
||||
self.formLayout.setWidget(2, QFormLayout.LabelRole, self.label_3)
|
||||
|
||||
self.rangeFromPlayRating_AaLabel = QLabel(self.groupBox)
|
||||
self.rangeFromPlayRating_AaLabel.setObjectName(u"rangeFromPlayRating_AaLabel")
|
||||
self.rangeFromPlayRating_AaLabel.setText(u"...")
|
||||
self.rangeFromPlayRating_AaLabel.setAlignment(Qt.AlignLeading|Qt.AlignLeft|Qt.AlignTop)
|
||||
|
||||
self.formLayout.setWidget(2, QFormLayout.FieldRole, self.rangeFromPlayRating_AaLabel)
|
||||
|
||||
self.label_5 = QLabel(self.groupBox)
|
||||
self.label_5.setObjectName(u"label_5")
|
||||
self.label_5.setText(u"A")
|
||||
|
||||
self.formLayout.setWidget(3, QFormLayout.LabelRole, self.label_5)
|
||||
|
||||
self.rangeFromPlayRating_ALabel = QLabel(self.groupBox)
|
||||
self.rangeFromPlayRating_ALabel.setObjectName(u"rangeFromPlayRating_ALabel")
|
||||
self.rangeFromPlayRating_ALabel.setText(u"...")
|
||||
|
||||
self.formLayout.setWidget(3, QFormLayout.FieldRole, self.rangeFromPlayRating_ALabel)
|
||||
|
||||
self.label_8 = QLabel(self.groupBox)
|
||||
self.label_8.setObjectName(u"label_8")
|
||||
self.label_8.setText(u"B")
|
||||
|
||||
self.formLayout.setWidget(4, QFormLayout.LabelRole, self.label_8)
|
||||
|
||||
self.rangeFromPlayRating_BLabel = QLabel(self.groupBox)
|
||||
self.rangeFromPlayRating_BLabel.setObjectName(u"rangeFromPlayRating_BLabel")
|
||||
self.rangeFromPlayRating_BLabel.setText(u"...")
|
||||
|
||||
self.formLayout.setWidget(4, QFormLayout.FieldRole, self.rangeFromPlayRating_BLabel)
|
||||
|
||||
self.label_10 = QLabel(self.groupBox)
|
||||
self.label_10.setObjectName(u"label_10")
|
||||
self.label_10.setText(u"C")
|
||||
|
||||
self.formLayout.setWidget(5, QFormLayout.LabelRole, self.label_10)
|
||||
|
||||
self.rangeFromPlayRating_CLabel = QLabel(self.groupBox)
|
||||
self.rangeFromPlayRating_CLabel.setObjectName(u"rangeFromPlayRating_CLabel")
|
||||
self.rangeFromPlayRating_CLabel.setText(u"...")
|
||||
|
||||
self.formLayout.setWidget(5, QFormLayout.FieldRole, self.rangeFromPlayRating_CLabel)
|
||||
|
||||
|
||||
self.verticalLayout_2.addLayout(self.formLayout)
|
||||
|
||||
|
||||
self.gridLayout.addWidget(self.groupBox, 0, 0, 1, 1)
|
||||
|
||||
self.groupBox_3 = QGroupBox(TabTools_ChartRecommend)
|
||||
self.groupBox_3.setObjectName(u"groupBox_3")
|
||||
@ -173,34 +211,33 @@ class Ui_TabTools_ChartRecommend(object):
|
||||
|
||||
self.chartsRecommendFromPlayRating_numLabel = QLabel(self.groupBox_3)
|
||||
self.chartsRecommendFromPlayRating_numLabel.setObjectName(u"chartsRecommendFromPlayRating_numLabel")
|
||||
sizePolicy.setHeightForWidth(self.chartsRecommendFromPlayRating_numLabel.sizePolicy().hasHeightForWidth())
|
||||
self.chartsRecommendFromPlayRating_numLabel.setSizePolicy(sizePolicy)
|
||||
self.chartsRecommendFromPlayRating_numLabel.setText(u"...")
|
||||
|
||||
self.horizontalLayout_2.addWidget(self.chartsRecommendFromPlayRating_numLabel)
|
||||
|
||||
self.horizontalSpacer_2 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
|
||||
|
||||
self.horizontalLayout_2.addItem(self.horizontalSpacer_2)
|
||||
|
||||
self.chartsRecommendFromPlayRating_refreshButton = QPushButton(self.groupBox_3)
|
||||
self.chartsRecommendFromPlayRating_refreshButton.setObjectName(u"chartsRecommendFromPlayRating_refreshButton")
|
||||
self.chartsRecommendFromPlayRating_refreshButton.setEnabled(False)
|
||||
|
||||
self.horizontalLayout_2.addWidget(self.chartsRecommendFromPlayRating_refreshButton)
|
||||
|
||||
|
||||
self.verticalLayout_4.addLayout(self.horizontalLayout_2)
|
||||
|
||||
self.widget_2 = QWidget(self.groupBox_3)
|
||||
self.widget_2.setObjectName(u"widget_2")
|
||||
sizePolicy.setHeightForWidth(self.widget_2.sizePolicy().hasHeightForWidth())
|
||||
self.widget_2.setSizePolicy(sizePolicy)
|
||||
self.chartsRecommendFromPlayRating_gridLayout = QGridLayout(self.widget_2)
|
||||
self.chartsRecommendFromPlayRating_gridLayout.setObjectName(u"chartsRecommendFromPlayRating_gridLayout")
|
||||
self.chartsRecommendFromPlayRating_modelView = QTableView(self.groupBox_3)
|
||||
self.chartsRecommendFromPlayRating_modelView.setObjectName(u"chartsRecommendFromPlayRating_modelView")
|
||||
sizePolicy2 = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
||||
sizePolicy2.setHorizontalStretch(0)
|
||||
sizePolicy2.setVerticalStretch(0)
|
||||
sizePolicy2.setHeightForWidth(self.chartsRecommendFromPlayRating_modelView.sizePolicy().hasHeightForWidth())
|
||||
self.chartsRecommendFromPlayRating_modelView.setSizePolicy(sizePolicy2)
|
||||
self.chartsRecommendFromPlayRating_modelView.setMinimumSize(QSize(200, 0))
|
||||
self.chartsRecommendFromPlayRating_modelView.setEditTriggers(QAbstractItemView.NoEditTriggers)
|
||||
self.chartsRecommendFromPlayRating_modelView.setSelectionMode(QAbstractItemView.NoSelection)
|
||||
self.chartsRecommendFromPlayRating_modelView.setSelectionBehavior(QAbstractItemView.SelectRows)
|
||||
self.chartsRecommendFromPlayRating_modelView.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel)
|
||||
self.chartsRecommendFromPlayRating_modelView.setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel)
|
||||
|
||||
self.verticalLayout_4.addWidget(self.widget_2)
|
||||
self.verticalLayout_4.addWidget(self.chartsRecommendFromPlayRating_modelView)
|
||||
|
||||
|
||||
self.verticalLayout.addWidget(self.groupBox_3)
|
||||
self.gridLayout.addWidget(self.groupBox_3, 1, 0, 1, 2)
|
||||
|
||||
|
||||
self.retranslateUi(TabTools_ChartRecommend)
|
||||
@ -209,11 +246,9 @@ class Ui_TabTools_ChartRecommend(object):
|
||||
# setupUi
|
||||
|
||||
def retranslateUi(self, TabTools_ChartRecommend):
|
||||
self.groupBox.setTitle(QCoreApplication.translate("TabTools_ChartRecommend", u"constantRangeFromPlayRating", None))
|
||||
self.groupBox_2.setTitle(QCoreApplication.translate("TabTools_ChartRecommend", u"chartsByConstant", None))
|
||||
self.chartsByConstant_refreshButton.setText(QCoreApplication.translate("TabTools_ChartRecommend", u"refreshButton", None))
|
||||
self.groupBox.setTitle(QCoreApplication.translate("TabTools_ChartRecommend", u"constantRangeFromPlayRating", None))
|
||||
self.groupBox_3.setTitle(QCoreApplication.translate("TabTools_ChartRecommend", u"chartsRecommendFromPlayRating", None))
|
||||
self.chartsRecommendFromPlayRating_refreshButton.setText(QCoreApplication.translate("TabTools_ChartRecommend", u"refreshButton", None))
|
||||
pass
|
||||
# retranslateUi
|
||||
|
||||
|
@ -694,57 +694,9 @@
|
||||
<property name="title">
|
||||
<string>playRatingCalculate</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="playRatingCalculateScoreLineEdit">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="inputMask">
|
||||
<string notr="true">B9'999'999;_</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string notr="true">></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="playRatingCalculateResultLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
<widget class="PlayRatingCalculator" name="playRatingCalculator" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
@ -764,6 +716,12 @@
|
||||
<header>ui.implements.components.ratingClassSelector</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>PlayRatingCalculator</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>ui.implements.components.playRatingCalculator</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
@ -16,9 +16,10 @@ from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
|
||||
QImage, QKeySequence, QLinearGradient, QPainter,
|
||||
QPalette, QPixmap, QRadialGradient, QTransform)
|
||||
from PySide6.QtWidgets import (QApplication, QComboBox, QFrame, QGridLayout,
|
||||
QGroupBox, QHBoxLayout, QLabel, QLineEdit,
|
||||
QSizePolicy, QSpacerItem, QVBoxLayout, QWidget)
|
||||
QGroupBox, QHBoxLayout, QLabel, QSizePolicy,
|
||||
QVBoxLayout, QWidget)
|
||||
|
||||
from ui.implements.components.playRatingCalculator import PlayRatingCalculator
|
||||
from ui.implements.components.ratingClassSelector import RatingClassSelector
|
||||
from ui.implements.components.songIdSelector import SongIdSelector
|
||||
|
||||
@ -502,34 +503,12 @@ class Ui_TabTools_InfoLookup(object):
|
||||
|
||||
self.groupBox_6 = QGroupBox(TabTools_InfoLookup)
|
||||
self.groupBox_6.setObjectName(u"groupBox_6")
|
||||
self.horizontalLayout_5 = QHBoxLayout(self.groupBox_6)
|
||||
self.horizontalLayout_5.setObjectName(u"horizontalLayout_5")
|
||||
self.playRatingCalculateScoreLineEdit = QLineEdit(self.groupBox_6)
|
||||
self.playRatingCalculateScoreLineEdit.setObjectName(u"playRatingCalculateScoreLineEdit")
|
||||
self.playRatingCalculateScoreLineEdit.setMinimumSize(QSize(100, 0))
|
||||
self.playRatingCalculateScoreLineEdit.setMaximumSize(QSize(150, 16777215))
|
||||
self.playRatingCalculateScoreLineEdit.setInputMask(u"B9'999'999;_")
|
||||
self.verticalLayout_2 = QVBoxLayout(self.groupBox_6)
|
||||
self.verticalLayout_2.setObjectName(u"verticalLayout_2")
|
||||
self.playRatingCalculator = PlayRatingCalculator(self.groupBox_6)
|
||||
self.playRatingCalculator.setObjectName(u"playRatingCalculator")
|
||||
|
||||
self.horizontalLayout_5.addWidget(self.playRatingCalculateScoreLineEdit)
|
||||
|
||||
self.label = QLabel(self.groupBox_6)
|
||||
self.label.setObjectName(u"label")
|
||||
self.label.setText(u">")
|
||||
|
||||
self.horizontalLayout_5.addWidget(self.label)
|
||||
|
||||
self.playRatingCalculateResultLabel = QLabel(self.groupBox_6)
|
||||
self.playRatingCalculateResultLabel.setObjectName(u"playRatingCalculateResultLabel")
|
||||
font = QFont()
|
||||
font.setBold(True)
|
||||
self.playRatingCalculateResultLabel.setFont(font)
|
||||
self.playRatingCalculateResultLabel.setText(u"...")
|
||||
|
||||
self.horizontalLayout_5.addWidget(self.playRatingCalculateResultLabel)
|
||||
|
||||
self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
|
||||
|
||||
self.horizontalLayout_5.addItem(self.horizontalSpacer)
|
||||
self.verticalLayout_2.addWidget(self.playRatingCalculator)
|
||||
|
||||
|
||||
self.verticalLayout.addWidget(self.groupBox_6)
|
||||
|
@ -165,7 +165,7 @@
|
||||
<widget class="QRadioButton" name="legacyPlayPlus_x125fragRadioButton">
|
||||
<property name="text">
|
||||
<string notr="true">x1.25
|
||||
125</string>
|
||||
250</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -361,6 +361,13 @@
|
||||
<property name="labelAlignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>calculate.toStep.playResultLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QDoubleSpinBox" name="calculate_toStep_playResultSpinBox">
|
||||
<property name="sizePolicy">
|
||||
@ -380,10 +387,10 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="calculate_toStep_calculatePlayResultFromScoreButton">
|
||||
<property name="text">
|
||||
<string>calculate.toStep.playResultLabel</string>
|
||||
<string>calculate.toStep.calculatePlayResultFromScoreButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -401,24 +408,36 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="calculate_toStep_resultLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="calculate_toStep_calculatePlayResultFromScoreButton">
|
||||
<property name="text">
|
||||
<string>calculate.toStep.calculatePlayResultFromScoreButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||
<item>
|
||||
<widget class="QLabel" name="calculate_toStep_resultLabel">
|
||||
<property name="text">
|
||||
<string notr="true">...</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="calculate_toStep_detailedResultLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QLabel { color: gray; }</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">...</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
@ -463,17 +482,36 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="calculate_fromStep_resultLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">...</string>
|
||||
</property>
|
||||
</widget>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_10">
|
||||
<item>
|
||||
<widget class="QLabel" name="calculate_fromStep_resultLabel">
|
||||
<property name="text">
|
||||
<string notr="true">...</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="calculate_fromStep_detailedResultLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QLabel { color: gray; }</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">...</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
@ -137,7 +137,7 @@ class Ui_TabTools_StepCalculator(object):
|
||||
self.legacyPlayPlus_x125fragRadioButton = QRadioButton(self.legacyPlayPlus_useFragmentsGroupBox)
|
||||
self.legacyPlayPlus_x125fragRadioButton.setObjectName(u"legacyPlayPlus_x125fragRadioButton")
|
||||
self.legacyPlayPlus_x125fragRadioButton.setText(u"x1.25\n"
|
||||
"125")
|
||||
"250")
|
||||
|
||||
self.horizontalLayout_3.addWidget(self.legacyPlayPlus_x125fragRadioButton)
|
||||
|
||||
@ -288,6 +288,11 @@ class Ui_TabTools_StepCalculator(object):
|
||||
self.formLayout_2 = QFormLayout(self.groupBox)
|
||||
self.formLayout_2.setObjectName(u"formLayout_2")
|
||||
self.formLayout_2.setLabelAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
|
||||
self.label_2 = QLabel(self.groupBox)
|
||||
self.label_2.setObjectName(u"label_2")
|
||||
|
||||
self.formLayout_2.setWidget(0, QFormLayout.LabelRole, self.label_2)
|
||||
|
||||
self.calculate_toStep_playResultSpinBox = QDoubleSpinBox(self.groupBox)
|
||||
self.calculate_toStep_playResultSpinBox.setObjectName(u"calculate_toStep_playResultSpinBox")
|
||||
sizePolicy2.setHeightForWidth(self.calculate_toStep_playResultSpinBox.sizePolicy().hasHeightForWidth())
|
||||
@ -298,10 +303,10 @@ class Ui_TabTools_StepCalculator(object):
|
||||
|
||||
self.formLayout_2.setWidget(0, QFormLayout.FieldRole, self.calculate_toStep_playResultSpinBox)
|
||||
|
||||
self.label_2 = QLabel(self.groupBox)
|
||||
self.label_2.setObjectName(u"label_2")
|
||||
self.calculate_toStep_calculatePlayResultFromScoreButton = QPushButton(self.groupBox)
|
||||
self.calculate_toStep_calculatePlayResultFromScoreButton.setObjectName(u"calculate_toStep_calculatePlayResultFromScoreButton")
|
||||
|
||||
self.formLayout_2.setWidget(0, QFormLayout.LabelRole, self.label_2)
|
||||
self.formLayout_2.setWidget(1, QFormLayout.FieldRole, self.calculate_toStep_calculatePlayResultFromScoreButton)
|
||||
|
||||
self.label_7 = QLabel(self.groupBox)
|
||||
self.label_7.setObjectName(u"label_7")
|
||||
@ -310,18 +315,28 @@ class Ui_TabTools_StepCalculator(object):
|
||||
|
||||
self.formLayout_2.setWidget(2, QFormLayout.LabelRole, self.label_7)
|
||||
|
||||
self.verticalLayout_9 = QVBoxLayout()
|
||||
self.verticalLayout_9.setObjectName(u"verticalLayout_9")
|
||||
self.calculate_toStep_resultLabel = QLabel(self.groupBox)
|
||||
self.calculate_toStep_resultLabel.setObjectName(u"calculate_toStep_resultLabel")
|
||||
sizePolicy4.setHeightForWidth(self.calculate_toStep_resultLabel.sizePolicy().hasHeightForWidth())
|
||||
self.calculate_toStep_resultLabel.setSizePolicy(sizePolicy4)
|
||||
self.calculate_toStep_resultLabel.setText(u"...")
|
||||
self.calculate_toStep_resultLabel.setAlignment(Qt.AlignBottom|Qt.AlignLeading|Qt.AlignLeft)
|
||||
|
||||
self.formLayout_2.setWidget(2, QFormLayout.FieldRole, self.calculate_toStep_resultLabel)
|
||||
self.verticalLayout_9.addWidget(self.calculate_toStep_resultLabel)
|
||||
|
||||
self.calculate_toStep_calculatePlayResultFromScoreButton = QPushButton(self.groupBox)
|
||||
self.calculate_toStep_calculatePlayResultFromScoreButton.setObjectName(u"calculate_toStep_calculatePlayResultFromScoreButton")
|
||||
self.calculate_toStep_detailedResultLabel = QLabel(self.groupBox)
|
||||
self.calculate_toStep_detailedResultLabel.setObjectName(u"calculate_toStep_detailedResultLabel")
|
||||
font = QFont()
|
||||
font.setPointSize(8)
|
||||
self.calculate_toStep_detailedResultLabel.setFont(font)
|
||||
self.calculate_toStep_detailedResultLabel.setStyleSheet(u"QLabel { color: gray; }")
|
||||
self.calculate_toStep_detailedResultLabel.setText(u"...")
|
||||
self.calculate_toStep_detailedResultLabel.setAlignment(Qt.AlignLeading|Qt.AlignLeft|Qt.AlignTop)
|
||||
|
||||
self.formLayout_2.setWidget(1, QFormLayout.FieldRole, self.calculate_toStep_calculatePlayResultFromScoreButton)
|
||||
self.verticalLayout_9.addWidget(self.calculate_toStep_detailedResultLabel)
|
||||
|
||||
|
||||
self.formLayout_2.setLayout(2, QFormLayout.FieldRole, self.verticalLayout_9)
|
||||
|
||||
|
||||
self.horizontalLayout_4.addWidget(self.groupBox)
|
||||
@ -350,13 +365,26 @@ class Ui_TabTools_StepCalculator(object):
|
||||
|
||||
self.formLayout_3.setWidget(1, QFormLayout.LabelRole, self.label_9)
|
||||
|
||||
self.verticalLayout_10 = QVBoxLayout()
|
||||
self.verticalLayout_10.setObjectName(u"verticalLayout_10")
|
||||
self.calculate_fromStep_resultLabel = QLabel(self.groupBox_2)
|
||||
self.calculate_fromStep_resultLabel.setObjectName(u"calculate_fromStep_resultLabel")
|
||||
sizePolicy4.setHeightForWidth(self.calculate_fromStep_resultLabel.sizePolicy().hasHeightForWidth())
|
||||
self.calculate_fromStep_resultLabel.setSizePolicy(sizePolicy4)
|
||||
self.calculate_fromStep_resultLabel.setText(u"...")
|
||||
self.calculate_fromStep_resultLabel.setAlignment(Qt.AlignBottom|Qt.AlignLeading|Qt.AlignLeft)
|
||||
|
||||
self.formLayout_3.setWidget(1, QFormLayout.FieldRole, self.calculate_fromStep_resultLabel)
|
||||
self.verticalLayout_10.addWidget(self.calculate_fromStep_resultLabel)
|
||||
|
||||
self.calculate_fromStep_detailedResultLabel = QLabel(self.groupBox_2)
|
||||
self.calculate_fromStep_detailedResultLabel.setObjectName(u"calculate_fromStep_detailedResultLabel")
|
||||
self.calculate_fromStep_detailedResultLabel.setFont(font)
|
||||
self.calculate_fromStep_detailedResultLabel.setStyleSheet(u"QLabel { color: gray; }")
|
||||
self.calculate_fromStep_detailedResultLabel.setText(u"...")
|
||||
self.calculate_fromStep_detailedResultLabel.setAlignment(Qt.AlignLeading|Qt.AlignLeft|Qt.AlignTop)
|
||||
|
||||
self.verticalLayout_10.addWidget(self.calculate_fromStep_detailedResultLabel)
|
||||
|
||||
|
||||
self.formLayout_3.setLayout(1, QFormLayout.FieldRole, self.verticalLayout_10)
|
||||
|
||||
|
||||
self.horizontalLayout_4.addWidget(self.groupBox_2)
|
||||
@ -394,8 +422,8 @@ class Ui_TabTools_StepCalculator(object):
|
||||
self.partnerSkillPresetButton_maya.setText(QCoreApplication.translate("TabTools_StepCalculator", u"partner.skill.presets.maya", None))
|
||||
self.groupBox.setTitle(QCoreApplication.translate("TabTools_StepCalculator", u"calculate.toStep", None))
|
||||
self.label_2.setText(QCoreApplication.translate("TabTools_StepCalculator", u"calculate.toStep.playResultLabel", None))
|
||||
self.label_7.setText(QCoreApplication.translate("TabTools_StepCalculator", u"calculate.toStep.resultLabel", None))
|
||||
self.calculate_toStep_calculatePlayResultFromScoreButton.setText(QCoreApplication.translate("TabTools_StepCalculator", u"calculate.toStep.calculatePlayResultFromScoreButton", None))
|
||||
self.label_7.setText(QCoreApplication.translate("TabTools_StepCalculator", u"calculate.toStep.resultLabel", None))
|
||||
self.groupBox_2.setTitle(QCoreApplication.translate("TabTools_StepCalculator", u"calculate.fromStep", None))
|
||||
self.label_4.setText(QCoreApplication.translate("TabTools_StepCalculator", u"calculate.fromStep.targetStepLabel", None))
|
||||
self.label_9.setText(QCoreApplication.translate("TabTools_StepCalculator", u"calculate.fromStep.resultLabel", None))
|
||||
|
@ -7,7 +7,7 @@ import numpy as np
|
||||
from arcaea_offline_ocr.phash_db import phash_opencv
|
||||
|
||||
|
||||
def preprocess_char_icon(img_gray: cv2.Mat):
|
||||
def preprocess_char_icon(img_gray: np.ndarray):
|
||||
h, w = img_gray.shape[:2]
|
||||
img = cv2.fillPoly(
|
||||
img_gray,
|
||||
@ -23,7 +23,7 @@ def preprocess_char_icon(img_gray: cv2.Mat):
|
||||
|
||||
|
||||
def build_image_phash_database(
|
||||
images: list[cv2.Mat],
|
||||
images: list[np.ndarray],
|
||||
labels: list[str],
|
||||
*,
|
||||
hash_size: int = 16,
|
||||
|
@ -12,7 +12,8 @@ def create_engine(_url: str | QUrl, pool: Type[Pool] = NullPool) -> Engine:
|
||||
|
||||
|
||||
class DatabaseUpdateSignals(QObject):
|
||||
songDataUpdated = Signal()
|
||||
songAddOrDelete = Signal()
|
||||
chartInfoUpdated = Signal()
|
||||
|
||||
|
||||
databaseUpdateSignals = DatabaseUpdateSignals()
|
||||
|
@ -25,12 +25,28 @@ class TextSegmentDelegate(QStyledItemDelegate):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
|
||||
# TODO: make this differ by index
|
||||
self.baseXOffset = 0
|
||||
self.baseYOffset = 0
|
||||
self.baseXOffsets: dict[str, int] = {}
|
||||
self.baseYOffsets: dict[str, int] = {}
|
||||
|
||||
self.verticalAlign = TextSegmentDelegateVerticalAlign.Middle
|
||||
|
||||
def indexOffsetKey(self, index: QModelIndex):
|
||||
return f"{index.row()},{index.column()}"
|
||||
|
||||
def setBaseXOffset(self, index: QModelIndex, offset: int):
|
||||
key = self.indexOffsetKey(index)
|
||||
if not offset:
|
||||
self.baseXOffsets.pop(key, None)
|
||||
else:
|
||||
self.baseXOffsets[key] = offset
|
||||
|
||||
def setBaseYOffset(self, index: QModelIndex, offset: int):
|
||||
key = self.indexOffsetKey(index)
|
||||
if not offset:
|
||||
self.baseYOffsets.pop(key, None)
|
||||
else:
|
||||
self.baseYOffsets[key] = offset
|
||||
|
||||
def setVerticalAlign(self, align: Literal["top", "middle", "bottom"]):
|
||||
if not isinstance(align, str) and align not in ["top", "middle", "bottom"]:
|
||||
raise ValueError(
|
||||
@ -60,12 +76,14 @@ class TextSegmentDelegate(QStyledItemDelegate):
|
||||
]:
|
||||
return []
|
||||
|
||||
def sizeHint(self, option, index) -> QSize:
|
||||
def textsSizeHint(self, option: QStyleOptionViewItem, index: QModelIndex) -> QSize:
|
||||
width = 0
|
||||
height = self.VerticalPadding
|
||||
height = 0
|
||||
fm: QFontMetrics = option.fontMetrics
|
||||
for line in self.getTextSegments(index, option):
|
||||
lineWidth = 4 * self.HorizontalPadding
|
||||
segments = self.getTextSegments(index, option)
|
||||
for i in range(len(segments)):
|
||||
line = segments[i]
|
||||
lineWidth = 2 * self.HorizontalPadding
|
||||
lineHeight = 0
|
||||
for textFrag in line:
|
||||
font = textFrag.get(self.FontRole)
|
||||
@ -76,14 +94,30 @@ class TextSegmentDelegate(QStyledItemDelegate):
|
||||
lineWidth += textWidth
|
||||
lineHeight = max(lineHeight, textHeight)
|
||||
width = max(lineWidth, width)
|
||||
height += lineHeight + self.VerticalPadding
|
||||
height += lineHeight
|
||||
if i != len(segments) - 1:
|
||||
height += self.VerticalPadding
|
||||
return QSize(width, height)
|
||||
|
||||
def sizeHint(self, option: QStyleOptionViewItem, index: QModelIndex) -> QSize:
|
||||
width = self.HorizontalPadding * 2
|
||||
height = self.VerticalPadding * 2
|
||||
textsSizeHint = self.textsSizeHint(option, index)
|
||||
return QSize(textsSizeHint.width() + width, textsSizeHint.height() + height)
|
||||
|
||||
def baseX(self, option: QStyleOptionViewItem, index: QModelIndex):
|
||||
return option.rect.x() + self.HorizontalPadding + self.baseXOffset
|
||||
return (
|
||||
option.rect.x()
|
||||
+ self.HorizontalPadding
|
||||
+ self.baseXOffsets.get(self.indexOffsetKey(index), 0)
|
||||
)
|
||||
|
||||
def baseY(self, option: QStyleOptionViewItem, index: QModelIndex):
|
||||
baseY = option.rect.y() + self.VerticalPadding + self.baseYOffset
|
||||
baseY = (
|
||||
option.rect.y()
|
||||
+ self.VerticalPadding
|
||||
+ self.baseYOffsets.get(self.indexOffsetKey(index), 0)
|
||||
)
|
||||
if self.verticalAlign != TextSegmentDelegateVerticalAlign.Top:
|
||||
paintAreaSize: QSize = option.rect.size()
|
||||
delegateSize = self.sizeHint(option, index)
|
||||
@ -94,7 +128,11 @@ class TextSegmentDelegate(QStyledItemDelegate):
|
||||
return baseY
|
||||
|
||||
def textMaxWidth(self, option: QStyleOptionViewItem, index: QModelIndex):
|
||||
return option.rect.width() - (2 * self.HorizontalPadding) - self.baseXOffset
|
||||
return (
|
||||
option.rect.width()
|
||||
- (2 * self.HorizontalPadding)
|
||||
- self.baseXOffsets.get(self.indexOffsetKey(index), 0)
|
||||
)
|
||||
|
||||
def paint(
|
||||
self, painter: QPainter, option: QStyleOptionViewItem, index: QModelIndex
|
||||
|
@ -1,7 +1,7 @@
|
||||
from arcaea_offline.models import Chart, Difficulty, Song
|
||||
from arcaea_offline.utils.rating import rating_class_to_short_text, rating_class_to_text
|
||||
from PIL import Image
|
||||
from PySide6.QtCore import QModelIndex, Qt, Signal
|
||||
from PySide6.QtCore import QModelIndex, QRect, Qt, Signal
|
||||
from PySide6.QtGui import QColor, QPainter, QPixmap
|
||||
from PySide6.QtWidgets import (
|
||||
QFrame,
|
||||
@ -82,6 +82,7 @@ class ChartDelegate(TextSegmentDelegate):
|
||||
QColor("#809955"),
|
||||
QColor("#702d60"),
|
||||
QColor("#710f25"),
|
||||
QColor("#8b77a4"),
|
||||
]
|
||||
ChartInvalidBackgroundColor = QColor("#e6a23c")
|
||||
|
||||
@ -138,7 +139,7 @@ class ChartDelegate(TextSegmentDelegate):
|
||||
ratingClass = None
|
||||
|
||||
ratingText = (
|
||||
f"{rating_class_to_text(chart.rating_class)} {chartConstantString}"
|
||||
f"{rating_class_to_text(ratingClass)} {chartConstantString}"
|
||||
if ratingClass is not None
|
||||
else "Unknown ?"
|
||||
)
|
||||
@ -173,7 +174,9 @@ class ChartDelegate(TextSegmentDelegate):
|
||||
|
||||
def sizeHint(self, option, index):
|
||||
size = super().sizeHint(option, index)
|
||||
size.setWidth(size.width() + self.HorizontalPadding + size.height())
|
||||
minWidth = size.height() + 2 * self.HorizontalPadding # jacket size
|
||||
width = size.width() + self.HorizontalPadding + size.height()
|
||||
size.setWidth(max(minWidth, width))
|
||||
return size
|
||||
|
||||
def paint(self, painter, option, index):
|
||||
@ -193,12 +196,13 @@ class ChartDelegate(TextSegmentDelegate):
|
||||
jacketPath = "__TEXT_ONLY__"
|
||||
|
||||
if jacketPath == "__TEXT_ONLY__":
|
||||
self.setBaseXOffset(index, 0)
|
||||
super().paint(painter, option, index)
|
||||
return
|
||||
|
||||
textSizeHint = super().sizeHint(option, index)
|
||||
jacketSize = textSizeHint.height()
|
||||
self.baseXOffset = self.HorizontalPadding + jacketSize
|
||||
textsSizeHint = super().textsSizeHint(option, index)
|
||||
jacketSize = textsSizeHint.height()
|
||||
self.setBaseXOffset(index, self.HorizontalPadding + jacketSize)
|
||||
|
||||
jacketSizeTuple = (jacketSize, jacketSize)
|
||||
if jacketPath:
|
||||
@ -214,11 +218,21 @@ class ChartDelegate(TextSegmentDelegate):
|
||||
.toqpixmap()
|
||||
)
|
||||
|
||||
pixmapAvailableWidth = option.rect.width() - self.HorizontalPadding
|
||||
pixmapAvailableHeight = option.rect.height()
|
||||
|
||||
if pixmapAvailableWidth < jacketSize or pixmapAvailableHeight < jacketSize:
|
||||
cropRect = QRect(0, 0, pixmapAvailableWidth, pixmapAvailableHeight)
|
||||
pixmap = pixmap.copy(cropRect)
|
||||
|
||||
painter.save()
|
||||
painter.setRenderHint(QPainter.RenderHint.LosslessImageRendering, True)
|
||||
painter.setRenderHint(QPainter.RenderHint.Antialiasing, True)
|
||||
pixmapBaseY = self.baseY(option, index)
|
||||
painter.drawPixmap(
|
||||
option.rect.x() + self.HorizontalPadding, self.baseY(option, index), pixmap
|
||||
option.rect.x() + self.HorizontalPadding,
|
||||
pixmapBaseY,
|
||||
pixmap,
|
||||
)
|
||||
painter.restore()
|
||||
super().paint(painter, option, index)
|
||||
|
@ -1,5 +1,5 @@
|
||||
from arcaea_offline.calculate import calculate_score_range
|
||||
from arcaea_offline.models import Chart, Score
|
||||
from arcaea_offline.models import Chart, Score, ScoreBest
|
||||
from arcaea_offline.utils.rating import rating_class_to_text
|
||||
from arcaea_offline.utils.score import (
|
||||
clear_type_to_text,
|
||||
@ -78,20 +78,24 @@ class ScoreDelegate(TextSegmentDelegate):
|
||||
createGradeGradientWrapper(QColor("#5d1d35"), QColor("#9f3c55")),
|
||||
]
|
||||
|
||||
def getScore(self, index: QModelIndex) -> Score | None:
|
||||
def getScore(self, index: QModelIndex) -> Score | ScoreBest | None:
|
||||
return None
|
||||
|
||||
def getChart(self, index: QModelIndex) -> Chart | None:
|
||||
return None
|
||||
|
||||
def isScoreInstance(self, index: QModelIndex) -> bool:
|
||||
return isinstance(self.getScore(index), (Score, ScoreBest))
|
||||
|
||||
def getScoreValidateOk(self, index: QModelIndex) -> bool | None:
|
||||
score = self.getScore(index)
|
||||
chart = self.getChart(index)
|
||||
|
||||
if (
|
||||
isinstance(score, Score)
|
||||
self.isScoreInstance(index)
|
||||
and isinstance(chart, Chart)
|
||||
and chart.notes is not None
|
||||
and chart.notes != 0
|
||||
and score.pure is not None
|
||||
and score.far is not None
|
||||
):
|
||||
@ -104,11 +108,11 @@ class ScoreDelegate(TextSegmentDelegate):
|
||||
def getTextSegments(self, index, option):
|
||||
score = self.getScore(index)
|
||||
|
||||
if not isinstance(score, Score):
|
||||
if not self.isScoreInstance(index):
|
||||
return [
|
||||
[
|
||||
{
|
||||
self.TextRole: "Chart/Score Invalid",
|
||||
self.TextRole: "Score Invalid",
|
||||
self.ColorRole: QColor("#ff0000"),
|
||||
}
|
||||
]
|
||||
@ -199,7 +203,7 @@ class ScoreDelegate(TextSegmentDelegate):
|
||||
score = self.getScore(index)
|
||||
chart = self.getChart(index)
|
||||
if (
|
||||
isinstance(score, Score)
|
||||
self.isScoreInstance(index)
|
||||
and isinstance(chart, Chart)
|
||||
and self.paintWarningBackground(index)
|
||||
):
|
||||
@ -239,7 +243,7 @@ class ScoreDelegate(TextSegmentDelegate):
|
||||
else:
|
||||
editor.setWindowTitle("-")
|
||||
|
||||
if isinstance(score, Score):
|
||||
if self.isScoreInstance(index):
|
||||
editor.setText(score)
|
||||
|
||||
editor.setValidateBeforeAccept(False)
|
||||
@ -260,7 +264,7 @@ class ScoreDelegate(TextSegmentDelegate):
|
||||
chart = self.getChart(index)
|
||||
if isinstance(chart, Chart):
|
||||
editor.setChart(chart)
|
||||
if isinstance(score, Score):
|
||||
if self.isScoreInstance(index):
|
||||
editor.setValue(score)
|
||||
|
||||
def confirmSetModelData(self, editor: ScoreEditorDelegateWrapper):
|
||||
|
@ -1,6 +1,5 @@
|
||||
from arcaea_offline.models import Chart, Score, ScoreBest
|
||||
from PySide6.QtCore import QCoreApplication, QModelIndex, QSortFilterProxyModel, Qt
|
||||
from sqlalchemy import select
|
||||
|
||||
from .base import DbTableModel
|
||||
|
||||
@ -18,50 +17,45 @@ class DbB30TableModel(DbTableModel):
|
||||
def retranslateHeaders(self):
|
||||
self._horizontalHeaders = [
|
||||
# fmt: off
|
||||
QCoreApplication.translate("DB30TableModel", "horizontalHeader.id"),
|
||||
QCoreApplication.translate("DB30TableModel", "horizontalHeader.chart"),
|
||||
QCoreApplication.translate("DB30TableModel", "horizontalHeader.score"),
|
||||
QCoreApplication.translate("DB30TableModel", "horizontalHeader.potential"),
|
||||
QCoreApplication.translate("DbB30TableModel", "horizontalHeader.id"),
|
||||
QCoreApplication.translate("DbB30TableModel", "horizontalHeader.chart"),
|
||||
QCoreApplication.translate("DbB30TableModel", "horizontalHeader.score"),
|
||||
QCoreApplication.translate("DbB30TableModel", "horizontalHeader.potential"),
|
||||
# fmt: on
|
||||
]
|
||||
|
||||
def syncDb(self):
|
||||
self.beginResetModel()
|
||||
self.beginRemoveRows(QModelIndex(), 0, self.rowCount())
|
||||
self.__items.clear()
|
||||
self.endRemoveRows()
|
||||
self.endResetModel()
|
||||
|
||||
with self._db.sessionmaker() as session:
|
||||
results = list(
|
||||
session.scalars(
|
||||
select(ScoreBest).order_by(ScoreBest.potential.desc()).limit(40)
|
||||
results = (
|
||||
session.query(ScoreBest, Chart)
|
||||
.join(
|
||||
Chart,
|
||||
(ScoreBest.song_id == Chart.song_id)
|
||||
& (ScoreBest.rating_class == Chart.rating_class),
|
||||
)
|
||||
.order_by(ScoreBest.potential)
|
||||
.limit(50)
|
||||
.all()
|
||||
)
|
||||
|
||||
songIds = [r.id for r in results]
|
||||
ptts = [r.potential for r in results]
|
||||
|
||||
for scoreId, ptt in zip(songIds, ptts):
|
||||
score = self._db.get_score(scoreId)
|
||||
chart = self._db.get_chart(score.song_id, score.rating_class)
|
||||
|
||||
self.beginInsertRows(QModelIndex(), self.rowCount(), self.rowCount())
|
||||
self.__items.append(
|
||||
{
|
||||
self.IdRole: score.id,
|
||||
self.ChartRole: chart,
|
||||
self.ScoreRole: score,
|
||||
self.PttRole: ptt,
|
||||
}
|
||||
)
|
||||
self.beginInsertRows(QModelIndex(), 0, len(results) - 1)
|
||||
for scoreBest, chart in results:
|
||||
self.__items.append(
|
||||
{
|
||||
self.IdRole: scoreBest.id,
|
||||
self.ChartRole: chart,
|
||||
self.ScoreRole: scoreBest,
|
||||
self.PttRole: scoreBest.potential,
|
||||
}
|
||||
)
|
||||
self.endInsertRows()
|
||||
|
||||
# trigger view update
|
||||
topLeft = self.index(0, 0)
|
||||
bottomRight = self.index(self.rowCount() - 1, self.columnCount() - 1)
|
||||
self.dataChanged.emit(
|
||||
topLeft,
|
||||
bottomRight,
|
||||
[Qt.ItemDataRole.DisplayRole, self.IdRole, self.ChartRole, self.ScoreRole],
|
||||
)
|
||||
|
||||
def rowCount(self, *args):
|
||||
return len(self.__items)
|
||||
|
||||
@ -117,30 +111,35 @@ class DbB30TableSortFilterProxyModel(QSortFilterProxyModel):
|
||||
return super().headerData(section, orientation, role)
|
||||
return section + 1
|
||||
|
||||
def lessThan(self, source_left, source_right) -> bool:
|
||||
if source_left.column() != source_right.column():
|
||||
def lessThan(self, sourceLeft: QModelIndex, sourceRight: QModelIndex) -> bool:
|
||||
if sourceLeft.column() != sourceRight.column():
|
||||
return
|
||||
|
||||
column = source_left.column()
|
||||
column = sourceLeft.column()
|
||||
if column == 0:
|
||||
return source_left.data(DbB30TableModel.IdRole) < source_right.data(
|
||||
return sourceLeft.data(DbB30TableModel.IdRole) < sourceRight.data(
|
||||
DbB30TableModel.IdRole
|
||||
)
|
||||
elif column == 2:
|
||||
score_left = source_left.data(DbB30TableModel.ScoreRole)
|
||||
score_right = source_right.data(DbB30TableModel.ScoreRole)
|
||||
if isinstance(score_left, Score) and isinstance(score_right, Score):
|
||||
scoreLeft = sourceLeft.data(DbB30TableModel.ScoreRole)
|
||||
scoreRight = sourceRight.data(DbB30TableModel.ScoreRole)
|
||||
if isinstance(scoreLeft, Score) and isinstance(scoreRight, Score):
|
||||
if self.sortRole() == self.Sort_C2_ScoreRole:
|
||||
return score_left.score < score_right.score
|
||||
return scoreLeft.score < scoreRight.score
|
||||
elif self.sortRole() == self.Sort_C2_TimeRole:
|
||||
if score_left.date and score_right.date:
|
||||
return score_left.date < score_right.date
|
||||
elif score_left.date:
|
||||
if scoreLeft.date and scoreRight.date:
|
||||
return scoreLeft.date < scoreRight.date
|
||||
elif scoreLeft.date:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
elif column == 3:
|
||||
return source_left.data(DbB30TableModel.PttRole) < source_right.data(
|
||||
DbB30TableModel.PttRole
|
||||
)
|
||||
return super().lessThan(source_left, source_right)
|
||||
pttLeft = sourceLeft.data(DbB30TableModel.PttRole)
|
||||
pttRight = sourceRight.data(DbB30TableModel.PttRole)
|
||||
if pttLeft and pttRight:
|
||||
return pttLeft < pttRight
|
||||
elif pttLeft:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
return super().lessThan(sourceLeft, sourceRight)
|
||||
|
@ -1,15 +1,21 @@
|
||||
from arcaea_offline.calculate import calculate_play_rating
|
||||
from arcaea_offline.models import Chart, Score
|
||||
import logging
|
||||
|
||||
from arcaea_offline.models import Chart, Difficulty, Score, ScoreCalculated, Song
|
||||
from PySide6.QtCore import QCoreApplication, QModelIndex, QSortFilterProxyModel, Qt
|
||||
from sqlalchemy import select
|
||||
|
||||
from .base import DbTableModel
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DbScoreTableModel(DbTableModel):
|
||||
IdRole = Qt.ItemDataRole.UserRole + 10
|
||||
ChartRole = Qt.ItemDataRole.UserRole + 11
|
||||
ScoreRole = Qt.ItemDataRole.UserRole + 12
|
||||
PttRole = Qt.ItemDataRole.UserRole + 13
|
||||
SongRole = Qt.ItemDataRole.UserRole + 14
|
||||
DifficultyRole = Qt.ItemDataRole.UserRole + 15
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
@ -27,81 +33,73 @@ class DbScoreTableModel(DbTableModel):
|
||||
]
|
||||
|
||||
def syncDb(self):
|
||||
newScores = self._db.get_scores()
|
||||
newScores = sorted(newScores, key=lambda x: x.id)
|
||||
newCharts = []
|
||||
for score in newScores:
|
||||
dbChart = self._db.get_chart(score.song_id, score.rating_class)
|
||||
newCharts.append(
|
||||
dbChart
|
||||
if isinstance(dbChart, Chart)
|
||||
else Chart(
|
||||
song_id=score.song_id,
|
||||
rating_class=score.rating_class,
|
||||
title=score.song_id,
|
||||
set="unknown",
|
||||
self.beginResetModel()
|
||||
self.beginRemoveRows(QModelIndex(), 0, self.rowCount())
|
||||
self.__items.clear()
|
||||
self.endRemoveRows()
|
||||
self.endResetModel()
|
||||
|
||||
with self._db.sessionmaker() as session:
|
||||
stmt = (
|
||||
select(Score, Chart, Song, Difficulty, ScoreCalculated.potential)
|
||||
.join(
|
||||
ScoreCalculated,
|
||||
(Score.id == ScoreCalculated.id),
|
||||
isouter=True,
|
||||
)
|
||||
.join(
|
||||
Chart,
|
||||
(Score.song_id == Chart.song_id)
|
||||
& (Score.rating_class == Chart.rating_class),
|
||||
isouter=True,
|
||||
)
|
||||
.join(
|
||||
Song,
|
||||
(Score.song_id == Song.id),
|
||||
isouter=True,
|
||||
)
|
||||
.join(
|
||||
Difficulty,
|
||||
(Score.song_id == Difficulty.song_id)
|
||||
& (Score.rating_class == Difficulty.rating_class),
|
||||
isouter=True,
|
||||
)
|
||||
)
|
||||
newPtts = []
|
||||
for chart, score in zip(newCharts, newScores):
|
||||
if (
|
||||
isinstance(chart, Chart)
|
||||
and chart.constant is not None
|
||||
and isinstance(score, Score)
|
||||
):
|
||||
newPtts.append(calculate_play_rating(chart.constant, score.score))
|
||||
else:
|
||||
newPtts.append(None)
|
||||
results = session.execute(stmt).all()
|
||||
|
||||
newScoreIds = [score.id for score in newScores]
|
||||
oldScoreIds = [item[self.ScoreRole].id for item in self.__items]
|
||||
self.beginInsertRows(QModelIndex(), 0, len(results) - 1)
|
||||
for result in results:
|
||||
score, chart, song, difficulty, potential = result
|
||||
|
||||
deleteIds = list(set(oldScoreIds) - set(newScoreIds))
|
||||
newIds = list(set(newScoreIds) - set(oldScoreIds))
|
||||
deleteRowIndexes = [oldScoreIds.index(deleteId) for deleteId in deleteIds]
|
||||
if chart:
|
||||
chartInModel = chart
|
||||
elif song and difficulty:
|
||||
chartInModel = Chart(
|
||||
song_id=song.id,
|
||||
rating_class=difficulty.rating_class,
|
||||
title=difficulty.title or song.title,
|
||||
set=song.set,
|
||||
)
|
||||
else:
|
||||
chartInModel = Chart(
|
||||
song_id=score.song_id,
|
||||
rating_class=score.rating_class,
|
||||
title=score.song_id,
|
||||
set="unknown",
|
||||
)
|
||||
|
||||
# first delete rows
|
||||
for deleteRowIndex in sorted(deleteRowIndexes, reverse=True):
|
||||
self.beginRemoveRows(QModelIndex(), deleteRowIndex, deleteRowIndex)
|
||||
self.__items.pop(deleteRowIndex)
|
||||
self.endRemoveRows()
|
||||
|
||||
# now update existing datas
|
||||
for oldItem, newChart, newScore, newPtt in zip(
|
||||
self.__items, newCharts, newScores, newPtts
|
||||
):
|
||||
oldItem[self.IdRole] = newScore.id
|
||||
oldItem[self.ChartRole] = newChart
|
||||
oldItem[self.ScoreRole] = newScore
|
||||
oldItem[self.PttRole] = newPtt
|
||||
|
||||
# finally insert new rows
|
||||
for newId in newIds:
|
||||
insertRowIndex = self.rowCount()
|
||||
itemListIndex = newScoreIds.index(newId)
|
||||
score = newScores[itemListIndex]
|
||||
chart = newCharts[itemListIndex]
|
||||
ptt = newPtts[itemListIndex]
|
||||
self.beginInsertRows(QModelIndex(), insertRowIndex, insertRowIndex)
|
||||
self.__items.append(
|
||||
{
|
||||
self.IdRole: score.id,
|
||||
self.ChartRole: chart,
|
||||
self.ScoreRole: score,
|
||||
self.PttRole: ptt,
|
||||
}
|
||||
)
|
||||
self.__items.append(
|
||||
{
|
||||
self.IdRole: score.id,
|
||||
self.ScoreRole: score,
|
||||
self.ChartRole: chartInModel,
|
||||
self.SongRole: song,
|
||||
self.DifficultyRole: difficulty,
|
||||
self.PttRole: potential,
|
||||
}
|
||||
)
|
||||
self.endInsertRows()
|
||||
|
||||
# trigger view update
|
||||
topLeft = self.index(0, 0)
|
||||
bottomRight = self.index(self.rowCount() - 1, self.columnCount() - 1)
|
||||
self.dataChanged.emit(
|
||||
topLeft,
|
||||
bottomRight,
|
||||
[Qt.ItemDataRole.DisplayRole, self.IdRole, self.ChartRole, self.ScoreRole],
|
||||
)
|
||||
|
||||
def rowCount(self, *args):
|
||||
return len(self.__items)
|
||||
|
||||
@ -112,8 +110,12 @@ class DbScoreTableModel(DbTableModel):
|
||||
self.IdRole,
|
||||
]:
|
||||
return self.__items[index.row()][self.IdRole]
|
||||
elif index.column() == 1 and role == self.ChartRole:
|
||||
return self.__items[index.row()][self.ChartRole]
|
||||
elif index.column() == 1 and role in [
|
||||
self.ChartRole,
|
||||
self.SongRole,
|
||||
self.DifficultyRole,
|
||||
]:
|
||||
return self.__items[index.row()][role]
|
||||
elif index.column() == 2 and role in [self.ChartRole, self.ScoreRole]:
|
||||
return self.__items[index.row()][role]
|
||||
elif index.column() == 3:
|
||||
@ -129,7 +131,7 @@ class DbScoreTableModel(DbTableModel):
|
||||
return False
|
||||
|
||||
if index.column() == 2 and isinstance(value, Score) and role == self.ScoreRole:
|
||||
self._db.update_score(self.__items[index.row()][self.IdRole], value)
|
||||
self._db.update_score(value)
|
||||
self.syncDb()
|
||||
return True
|
||||
|
||||
@ -147,11 +149,12 @@ class DbScoreTableModel(DbTableModel):
|
||||
return False
|
||||
|
||||
try:
|
||||
self._db.delete_score(self.__items[row][self.IdRole])
|
||||
self._db.delete_score(self.__items[row][self.ScoreRole])
|
||||
if syncDb:
|
||||
self.syncDb()
|
||||
return True
|
||||
except Exception:
|
||||
logger.exception(f"Table[Score]: Cannot remove row {row}")
|
||||
return False
|
||||
|
||||
def removeRow(self, row: int, parent=...):
|
||||
@ -180,7 +183,7 @@ class DbScoreTableSortFilterProxyModel(QSortFilterProxyModel):
|
||||
Sort_C2_ScoreRole = Qt.ItemDataRole.UserRole + 75
|
||||
Sort_C2_TimeRole = Qt.ItemDataRole.UserRole + 76
|
||||
|
||||
def lessThan(self, sourceLeft, sourceRight) -> bool:
|
||||
def lessThan(self, sourceLeft: QModelIndex, sourceRight: QModelIndex) -> bool:
|
||||
if sourceLeft.column() != sourceRight.column():
|
||||
return
|
||||
|
||||
|
32
ui/extends/tabs/tabDb/tabDb_ChartInfoEditor.py
Normal file
32
ui/extends/tabs/tabDb/tabDb_ChartInfoEditor.py
Normal file
@ -0,0 +1,32 @@
|
||||
from arcaea_offline.models import Difficulty, Song
|
||||
from PySide6.QtCore import QModelIndex, Qt
|
||||
from PySide6.QtGui import QStandardItem, QStandardItemModel
|
||||
|
||||
from ui.extends.shared.delegates.chartDelegate import ChartDelegate
|
||||
|
||||
|
||||
class ChartInfoAbsentModel(QStandardItemModel):
|
||||
SongRole = Qt.ItemDataRole.UserRole
|
||||
DifficultyRole = Qt.ItemDataRole.UserRole + 1
|
||||
|
||||
def setCustomData(self, songs: list[Song], difficulties: list[Difficulty]):
|
||||
self.clear()
|
||||
|
||||
for song, difficulty in zip(songs, difficulties):
|
||||
item = QStandardItem()
|
||||
item.setData(song, self.SongRole)
|
||||
item.setData(difficulty, self.DifficultyRole)
|
||||
self.appendRow(item)
|
||||
|
||||
def setLoading(self):
|
||||
self.clear()
|
||||
|
||||
self.appendRow(QStandardItem("Loading..."))
|
||||
|
||||
|
||||
class ListViewDelegate(ChartDelegate):
|
||||
def getSong(self, index: QModelIndex):
|
||||
return index.data(ChartInfoAbsentModel.SongRole)
|
||||
|
||||
def getDifficulty(self, index: QModelIndex):
|
||||
return index.data(ChartInfoAbsentModel.DifficultyRole)
|
@ -7,6 +7,7 @@ import exif
|
||||
from arcaea_offline.database import Database
|
||||
from arcaea_offline.models import Chart, Score
|
||||
from arcaea_offline.utils.partner import KanaeDayNight, kanae_day_night
|
||||
from arcaea_offline_ocr.crop import CropBlackEdges
|
||||
from arcaea_offline_ocr.device import DeviceOcr, DeviceOcrResult
|
||||
from arcaea_offline_ocr.device.rois import (
|
||||
DeviceRois,
|
||||
@ -43,6 +44,7 @@ class TabDeviceOcrRunnable(OcrRunnable):
|
||||
def run(self):
|
||||
try:
|
||||
img = imread_unicode(self.imagePath, cv2.IMREAD_COLOR)
|
||||
img = CropBlackEdges.crop(img, cv2.COLOR_BGR2GRAY)
|
||||
if isinstance(self.rois, type) and issubclass(self.rois, DeviceRoisAuto):
|
||||
rois = self.rois(img.shape[1], img.shape[0])
|
||||
else:
|
||||
|
@ -31,6 +31,9 @@ class AndrealExecuteRunnable(QRunnable):
|
||||
encoding="utf-8",
|
||||
)
|
||||
result = subp.stdout
|
||||
if subp.returncode != 0:
|
||||
logger.error("AndrealImageGenerator Error: ")
|
||||
logger.error(result)
|
||||
b64Result = [s for s in result.split("\n") if s]
|
||||
imageBytes = base64.b64decode(
|
||||
re.sub(r"data:image/.*;base64,", "", b64Result[-1])
|
||||
|
120
ui/extends/tabs/tabTools/tabTools_ChartRecommend.py
Normal file
120
ui/extends/tabs/tabTools/tabTools_ChartRecommend.py
Normal file
@ -0,0 +1,120 @@
|
||||
import re
|
||||
from typing import Any
|
||||
|
||||
from arcaea_offline.database import Database
|
||||
from arcaea_offline.models import Chart, ScoreBest
|
||||
from arcaea_offline.utils.rating import rating_class_to_text
|
||||
from PySide6.QtCore import QAbstractListModel, QModelIndex, Qt
|
||||
from PySide6.QtGui import QStandardItem, QStandardItemModel
|
||||
|
||||
from ui.extends.shared.delegates.chartDelegate import ChartDelegate
|
||||
from ui.extends.shared.delegates.scoreDelegate import ScoreDelegate
|
||||
|
||||
|
||||
class ChartsModel(QAbstractListModel):
|
||||
ChartRole = Qt.ItemDataRole.UserRole
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
|
||||
self.__data: list[dict[int, Any]] = []
|
||||
|
||||
def rowCount(self, *args) -> int:
|
||||
return len(self.__data)
|
||||
|
||||
def columnCount(self, *args) -> int:
|
||||
return 1
|
||||
|
||||
def headerData(self, *args):
|
||||
return None
|
||||
|
||||
def data(self, index: QModelIndex, role: int):
|
||||
if not self.checkIndex(index):
|
||||
return None
|
||||
|
||||
return self.__data[index.row()].get(role, None)
|
||||
|
||||
def clear(self):
|
||||
self.beginResetModel()
|
||||
self.beginRemoveRows(QModelIndex(), 0, self.rowCount())
|
||||
self.__data.clear()
|
||||
self.endRemoveRows()
|
||||
self.endResetModel()
|
||||
|
||||
def setCharts(self, charts: list[Chart]):
|
||||
self.clear()
|
||||
|
||||
db = Database()
|
||||
self.beginInsertRows(QModelIndex(), 0, len(charts))
|
||||
for chart in charts:
|
||||
pack = db.get_pack(chart.set)
|
||||
if re.search(r"_append_.*$", pack.id):
|
||||
basePackId = re.sub(r"_append_.*$", "", pack.id)
|
||||
basePackName = db.get_pack(basePackId).name
|
||||
packName = f"{basePackName} - {pack.name}"
|
||||
else:
|
||||
packName = pack.name
|
||||
|
||||
tooltip = (
|
||||
f"{chart.title}@{packName} [{rating_class_to_text(chart.rating_class)}]"
|
||||
)
|
||||
self.__data.append(
|
||||
{
|
||||
Qt.ItemDataRole.ToolTipRole: tooltip,
|
||||
self.ChartRole: chart,
|
||||
}
|
||||
)
|
||||
self.endInsertRows()
|
||||
|
||||
|
||||
class CustomChartDelegate(ChartDelegate):
|
||||
def getChart(self, index: QModelIndex) -> Chart | None:
|
||||
return index.data(ChartsModel.ChartRole)
|
||||
|
||||
|
||||
class ChartsWithScoreBestModel(QStandardItemModel):
|
||||
ChartRole = Qt.ItemDataRole.UserRole
|
||||
ScoreBestRole = Qt.ItemDataRole.UserRole + 10
|
||||
|
||||
def columnCount(self, *args) -> int:
|
||||
return 3
|
||||
|
||||
def headerData(self, *args):
|
||||
return None
|
||||
|
||||
def setChartAndScore(self, charts: list[Chart], scoreBests: list[ScoreBest]):
|
||||
self.clear()
|
||||
|
||||
db = Database()
|
||||
self.beginInsertRows(QModelIndex(), 0, len(charts))
|
||||
for chart, scoreBest in zip(charts, scoreBests):
|
||||
pack = db.get_pack(chart.set)
|
||||
if re.search(r"_append_.*$", pack.id):
|
||||
basePackId = re.sub(r"_append_.*$", "", pack.id)
|
||||
basePackName = db.get_pack(basePackId).name
|
||||
packName = f"{basePackName} - {pack.name}"
|
||||
else:
|
||||
packName = pack.name
|
||||
|
||||
tooltip = (
|
||||
f"{chart.title}@{packName} [{rating_class_to_text(chart.rating_class)}]\n"
|
||||
f"{scoreBest.score} > {scoreBest.potential}"
|
||||
)
|
||||
|
||||
chartItem = QStandardItem()
|
||||
chartItem.setData(tooltip, Qt.ItemDataRole.ToolTipRole)
|
||||
chartItem.setData(chart, self.ChartRole)
|
||||
|
||||
scoreBestItem = QStandardItem()
|
||||
scoreBestItem.setData(tooltip, Qt.ItemDataRole.ToolTipRole)
|
||||
scoreBestItem.setData(scoreBest, self.ScoreBestRole)
|
||||
|
||||
potentialTextItem = QStandardItem()
|
||||
potentialTextItem.setText(f"{scoreBest.potential}")
|
||||
|
||||
self.appendRow([chartItem, scoreBestItem, potentialTextItem])
|
||||
|
||||
|
||||
class CustomScoreBestDelegate(ScoreDelegate):
|
||||
def getScore(self, index: QModelIndex):
|
||||
return index.data(ChartsWithScoreBestModel.ScoreBestRole)
|
23
ui/implements/components/arcaeaScoreLineEdit.py
Normal file
23
ui/implements/components/arcaeaScoreLineEdit.py
Normal file
@ -0,0 +1,23 @@
|
||||
from PySide6.QtGui import QFont
|
||||
|
||||
from .focusSelectAllLineEdit import FocusSelectAllLineEdit
|
||||
|
||||
|
||||
class ArcaeaScoreLineEdit(FocusSelectAllLineEdit):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
|
||||
font = QFont("GeosansLight")
|
||||
font.setPointSize(14)
|
||||
font.setBold(True)
|
||||
font.setStyleStrategy(
|
||||
QFont.StyleStrategy.NoSubpixelAntialias
|
||||
| QFont.StyleStrategy.PreferAntialias
|
||||
)
|
||||
self.setFont(font)
|
||||
|
||||
self.setInputMask("B9'999'999;_")
|
||||
|
||||
def score(self) -> int | None:
|
||||
textWithoutMask = self.text().replace("'", "")
|
||||
return int(textWithoutMask) if textWithoutMask else None
|
@ -27,15 +27,19 @@ class ChartSelector(Ui_ChartSelector, QWidget):
|
||||
|
||||
self.valueChanged.connect(self.updateResultLabel)
|
||||
self.songIdSelector.valueChanged.connect(self.updateRatingClassEnabled)
|
||||
self.songIdSelector.quickSearchActivated.connect(
|
||||
self.__songIdSelectedQuickSearchActivated
|
||||
)
|
||||
|
||||
self.songIdSelector.valueChanged.connect(self.valueChanged)
|
||||
self.ratingClassSelector.valueChanged.connect(self.valueChanged)
|
||||
|
||||
# handle `songIdSelector.updateDatabase` by this component
|
||||
databaseUpdateSignals.songDataUpdated.disconnect(
|
||||
databaseUpdateSignals.songAddOrDelete.disconnect(
|
||||
self.songIdSelector.updateDatabase
|
||||
)
|
||||
databaseUpdateSignals.songDataUpdated.connect(self.updateDatabase)
|
||||
databaseUpdateSignals.songAddOrDelete.connect(self.updateDatabase)
|
||||
databaseUpdateSignals.chartInfoUpdated.connect(self.updateResultLabel)
|
||||
|
||||
def setSongIdSelectorMode(self, mode: SongIdSelectorMode):
|
||||
self.songIdSelector.setMode(mode)
|
||||
@ -85,15 +89,17 @@ class ChartSelector(Ui_ChartSelector, QWidget):
|
||||
texts = [" | ".join(t) for t in texts]
|
||||
text = f'{texts[0]}<br><font color="gray">{texts[1]}</font>'
|
||||
else:
|
||||
text = f'No chart data<br><font color="gray">{chart.set} | {chart.song_id} | {chart.rating_class}</font>'
|
||||
text = (
|
||||
"No chart data<br>"
|
||||
f'<font color="gray">{chart.set} | {chart.song_id} | {chart.rating_class}</font>'
|
||||
)
|
||||
self.resultLabel.setText(text)
|
||||
else:
|
||||
self.resultLabel.setText("...")
|
||||
|
||||
def updateRatingClassEnabled(self):
|
||||
ratingClasses = []
|
||||
songId = self.songIdSelector.songId()
|
||||
if songId:
|
||||
if songId := self.songIdSelector.songId():
|
||||
if self.songIdSelector.mode == SongIdSelectorMode.Chart:
|
||||
items = self.db.get_charts_by_song_id(songId)
|
||||
else:
|
||||
@ -106,9 +112,8 @@ class ChartSelector(Ui_ChartSelector, QWidget):
|
||||
self.songIdSelector.reset()
|
||||
|
||||
def selectChart(self, chart: Chart):
|
||||
if not self.songIdSelector.selectPack(chart.set):
|
||||
return False
|
||||
if not self.songIdSelector.selectSongId(chart.song_id):
|
||||
return False
|
||||
self.songIdSelector.selectChart(chart)
|
||||
self.ratingClassSelector.select(chart.rating_class)
|
||||
|
||||
def __songIdSelectedQuickSearchActivated(self, chart: Chart):
|
||||
self.ratingClassSelector.select(chart.rating_class)
|
||||
return True
|
||||
|
85
ui/implements/components/playRatingCalculator.py
Normal file
85
ui/implements/components/playRatingCalculator.py
Normal file
@ -0,0 +1,85 @@
|
||||
from arcaea_offline.calculate import calculate_play_rating
|
||||
from PySide6.QtCore import QCoreApplication
|
||||
from PySide6.QtGui import QGuiApplication
|
||||
from PySide6.QtWidgets import (
|
||||
QHBoxLayout,
|
||||
QLabel,
|
||||
QPushButton,
|
||||
QSizePolicy,
|
||||
QSpacerItem,
|
||||
QWidget,
|
||||
)
|
||||
|
||||
from ui.extends.shared.language import LanguageChangeEventFilter
|
||||
|
||||
from .arcaeaScoreLineEdit import ArcaeaScoreLineEdit
|
||||
|
||||
|
||||
class PlayRatingCalculator(QWidget):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
|
||||
self.languageChangeEventFilter = LanguageChangeEventFilter(self)
|
||||
self.installEventFilter(self.languageChangeEventFilter)
|
||||
|
||||
self.setupUi()
|
||||
|
||||
self.arcaeaScoreLineEdit.textChanged.connect(self.updateResultLabel)
|
||||
self.copyButton.clicked.connect(self.on_copyButton_clicked)
|
||||
|
||||
self.constant: int | None = None
|
||||
|
||||
def setConstant(self, constant: int | None):
|
||||
self.constant = constant
|
||||
self.updateResultLabel()
|
||||
|
||||
@property
|
||||
def result(self):
|
||||
if self.constant is None:
|
||||
return None
|
||||
|
||||
score = self.arcaeaScoreLineEdit.score()
|
||||
return None if score is None else calculate_play_rating(self.constant, score)
|
||||
|
||||
def updateResultLabel(self):
|
||||
result = self.result
|
||||
self.resultLabel.setText(str(round(result, 3)) if result is not None else "...")
|
||||
self.resultLabel.setToolTip(str(result))
|
||||
|
||||
def on_copyButton_clicked(self):
|
||||
result = self.result
|
||||
if result is not None:
|
||||
QGuiApplication.clipboard().setText(str(result))
|
||||
|
||||
def setupUi(self, *args):
|
||||
self.horizontalLayout = QHBoxLayout(self)
|
||||
|
||||
self.arcaeaScoreLineEdit = ArcaeaScoreLineEdit(self)
|
||||
self.horizontalLayout.addWidget(self.arcaeaScoreLineEdit)
|
||||
|
||||
self.label = QLabel(self)
|
||||
self.label.setText(" > ")
|
||||
self.horizontalLayout.addWidget(self.label)
|
||||
|
||||
self.resultLabel = QLabel(self)
|
||||
self.resultLabel.setText("...")
|
||||
self.resultLabel.setSizePolicy(
|
||||
QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Preferred
|
||||
)
|
||||
self.resultLabel.setMinimumWidth(100)
|
||||
self.horizontalLayout.addWidget(self.resultLabel)
|
||||
|
||||
self.horizontalSpacer = QSpacerItem(
|
||||
20, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Preferred
|
||||
)
|
||||
self.horizontalLayout.addSpacerItem(self.horizontalSpacer)
|
||||
|
||||
self.copyButton = QPushButton(self)
|
||||
self.horizontalLayout.addWidget(self.copyButton)
|
||||
|
||||
self.retranslateUi()
|
||||
|
||||
def retranslateUi(self, *args):
|
||||
self.copyButton.setText(
|
||||
QCoreApplication.translate("PotentialCalculator", "copyButton")
|
||||
)
|
@ -1,3 +1,4 @@
|
||||
import logging
|
||||
from typing import Type
|
||||
|
||||
from PySide6.QtCore import Signal
|
||||
@ -6,6 +7,8 @@ from PySide6.QtWidgets import QHBoxLayout, QSizePolicy, QVBoxLayout, QWidget
|
||||
|
||||
from ui.implements.components.ratingClassRadioButton import RatingClassRadioButton
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class RatingClassSelector(QWidget):
|
||||
valueChanged = Signal()
|
||||
@ -41,16 +44,30 @@ class RatingClassSelector(QWidget):
|
||||
self.bydButton.setAutoExclusive(False)
|
||||
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.prsButton.setColors(QColor("#809955"), QColor("#f7f9f4"))
|
||||
self.ftrButton.setColors(QColor("#702d60"), QColor("#f7ebf4"))
|
||||
self.bydButton.setColors(QColor("#710f25"), QColor("#f9ced8"))
|
||||
self.etrButton.setColors(QColor("#4f2c7a"), QColor("#e4daf1"))
|
||||
|
||||
self.pstButton.clicked.connect(self.select)
|
||||
self.prsButton.clicked.connect(self.select)
|
||||
self.ftrButton.clicked.connect(self.select)
|
||||
self.bydButton.clicked.connect(self.select)
|
||||
self.etrButton.clicked.connect(self.select)
|
||||
self.reset()
|
||||
self.setButtonsEnabled([])
|
||||
|
||||
@ -106,9 +123,10 @@ class RatingClassSelector(QWidget):
|
||||
|
||||
if ratingClass is None or isinstance(ratingClass, bool):
|
||||
button = self.sender()
|
||||
elif ratingClass in range(4):
|
||||
elif ratingClass in range(len(self.buttons)):
|
||||
button = self.buttons[ratingClass]
|
||||
else:
|
||||
logger.debug(f"Cannot select {ratingClass=}, condition check failed")
|
||||
return
|
||||
|
||||
if not button.isEnabled():
|
||||
|
@ -302,7 +302,7 @@ class ScoreEditor(Ui_ScoreEditor, QWidget):
|
||||
|
||||
if score.score is None:
|
||||
flags |= ScoreValidateResult.ScoreIncomplete
|
||||
elif score.pure is None or score.far is None:
|
||||
elif score.pure is None or score.far is None or score.lost is None:
|
||||
flags |= ScoreValidateResult.ScoreIncompleteForValidate
|
||||
elif self.__chart.notes is not None:
|
||||
score_range = calculate_score_range(
|
||||
|
@ -23,6 +23,7 @@ class SongIdSelectorMode(IntEnum):
|
||||
|
||||
class SongIdSelector(Ui_SongIdSelector, QWidget):
|
||||
valueChanged = Signal()
|
||||
quickSearchActivated = Signal(Chart)
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
@ -71,7 +72,7 @@ class SongIdSelector(Ui_SongIdSelector, QWidget):
|
||||
self.songIdComboBox.currentIndexChanged.connect(self.valueChanged)
|
||||
|
||||
self.updateDatabase()
|
||||
databaseUpdateSignals.songDataUpdated.connect(self.updateDatabase)
|
||||
databaseUpdateSignals.songAddOrDelete.connect(self.updateDatabase)
|
||||
|
||||
def setMode(self, mode: SongIdSelectorMode):
|
||||
self.mode = mode
|
||||
@ -126,8 +127,7 @@ class SongIdSelector(Ui_SongIdSelector, QWidget):
|
||||
self.packComboBox.clear()
|
||||
packs = self.db.get_packs()
|
||||
for pack in packs:
|
||||
isAppendPack = re.search(r"_append_.*$", pack.id)
|
||||
if isAppendPack:
|
||||
if isAppendPack := re.search(r"_append_.*$", pack.id):
|
||||
basePackId = re.sub(r"_append_.*$", "", pack.id)
|
||||
basePackName = self.db.get_pack(basePackId).name
|
||||
packName = f"{basePackName} - {pack.name}"
|
||||
@ -146,8 +146,7 @@ class SongIdSelector(Ui_SongIdSelector, QWidget):
|
||||
|
||||
def fillSongIdComboBox(self):
|
||||
self.songIdComboBox.clear()
|
||||
packId = self.packComboBox.currentData()
|
||||
if packId:
|
||||
if packId := self.packComboBox.currentData():
|
||||
if self.mode == SongIdSelectorMode.SongId:
|
||||
items = self.db.get_songs_by_pack_id(packId)
|
||||
elif self.mode == SongIdSelectorMode.Chart:
|
||||
@ -208,14 +207,15 @@ class SongIdSelector(Ui_SongIdSelector, QWidget):
|
||||
return False
|
||||
|
||||
def selectChart(self, chart: Chart):
|
||||
if not self.selectPack(chart.set):
|
||||
return False
|
||||
return self.selectSongId(chart.song_id)
|
||||
packSelected = self.selectPack(chart.set)
|
||||
songIdSelected = self.selectSongId(chart.song_id)
|
||||
return packSelected and songIdSelected
|
||||
|
||||
@Slot(QModelIndex)
|
||||
def searchCompleterSetSelection(self, index: QModelIndex):
|
||||
chart = index.data(Qt.ItemDataRole.UserRole + 10) # type: Chart
|
||||
chart: Chart = index.data(Qt.ItemDataRole.UserRole + 10)
|
||||
self.selectChart(chart)
|
||||
self.quickSearchActivated.emit(chart)
|
||||
|
||||
self.searchLineEdit.clear()
|
||||
self.searchLineEdit.clearFocus()
|
||||
|
226
ui/implements/tabs/tabDb/tabDb_ChartInfoEditor.py
Normal file
226
ui/implements/tabs/tabDb/tabDb_ChartInfoEditor.py
Normal file
@ -0,0 +1,226 @@
|
||||
import logging
|
||||
|
||||
from arcaea_offline.database import Database
|
||||
from arcaea_offline.models import Chart, ChartInfo, Difficulty, Song
|
||||
from arcaea_offline.utils.rating import rating_class_to_text
|
||||
from PySide6.QtCore import QCoreApplication, QModelIndex, Qt, Slot
|
||||
from PySide6.QtGui import QPixmap, QRegularExpressionValidator, QStandardItem
|
||||
from PySide6.QtWidgets import QApplication, QMessageBox, QStyledItemDelegate, QWidget
|
||||
from sqlalchemy import select
|
||||
|
||||
from ui.designer.tabs.tabDb.tabDb_ChartInfoEditor_ui import Ui_TabDb_ChartInfoEditor
|
||||
from ui.extends.shared.data import Data
|
||||
from ui.extends.shared.database import databaseUpdateSignals
|
||||
from ui.extends.shared.language import LanguageChangeEventFilter
|
||||
from ui.extends.tabs.tabDb.tabDb_ChartInfoEditor import (
|
||||
ChartInfoAbsentModel,
|
||||
ListViewDelegate,
|
||||
)
|
||||
from ui.implements.components.songIdSelector import SongIdSelectorMode
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TabDb_ChartInfoEditor(Ui_TabDb_ChartInfoEditor, QWidget):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.setupUi(self)
|
||||
|
||||
self.languageChangeEventFilter = LanguageChangeEventFilter(self)
|
||||
self.installEventFilter(self.languageChangeEventFilter)
|
||||
|
||||
self.db = Database()
|
||||
|
||||
self.numberRegexValidator = QRegularExpressionValidator(r"^\d+$", self)
|
||||
self.constantLineEdit.setValidator(self.numberRegexValidator)
|
||||
self.notesLineEdit.setValidator(self.numberRegexValidator)
|
||||
|
||||
self.constantLineEdit.textChanged.connect(self.updateConstantPreviewLabel)
|
||||
|
||||
self.chartInfoAbsentModel = ChartInfoAbsentModel(self)
|
||||
self.listView.setModel(self.chartInfoAbsentModel)
|
||||
self.listViewDelegate = ListViewDelegate(self)
|
||||
|
||||
self.listView.selectionModel().currentChanged.connect(
|
||||
self.listViewSelectionChanged
|
||||
)
|
||||
|
||||
self.chartSelector.setSongIdSelectorMode(SongIdSelectorMode.SongId)
|
||||
self.chartSelector.valueChanged.connect(self.chartSelectorValueChanged)
|
||||
|
||||
databaseUpdateSignals.chartInfoUpdated.connect(self.updateChartInfoAbsentModel)
|
||||
self.updateChartInfoAbsentModel()
|
||||
|
||||
self.commitButton.clicked.connect(self.commitChartInfo)
|
||||
self.deleteButton.clicked.connect(self.deleteChartInfo)
|
||||
|
||||
def updateConstantPreviewLabel(self):
|
||||
text = self.constantLineEdit.text()
|
||||
if self.constantLineEdit.hasAcceptableInput():
|
||||
self.constantPreviewLabel.setText(f"> {int(text) / 10:.1f}")
|
||||
else:
|
||||
self.constantPreviewLabel.setText("> ...")
|
||||
|
||||
def reset(self):
|
||||
self.jacketLabel.clear()
|
||||
self.titleLabel.setText("...")
|
||||
self.ratingLabel.setText("...")
|
||||
self.constantLineEdit.setText("")
|
||||
self.notesLineEdit.setText("")
|
||||
|
||||
def updateChartInfoAbsentModel(self):
|
||||
self.listView.setItemDelegate(QStyledItemDelegate())
|
||||
self.chartInfoAbsentModel.clear()
|
||||
self.chartInfoAbsentModel.appendRow(QStandardItem("Loading..."))
|
||||
QApplication.processEvents()
|
||||
|
||||
with self.db.sessionmaker() as session:
|
||||
stmt = (
|
||||
select(Difficulty)
|
||||
.join(
|
||||
ChartInfo,
|
||||
(Difficulty.song_id == ChartInfo.song_id)
|
||||
& (Difficulty.rating_class == ChartInfo.rating_class),
|
||||
isouter=True,
|
||||
)
|
||||
.where(ChartInfo.notes.is_(None))
|
||||
)
|
||||
absentInfoDifficulties = sorted(
|
||||
list(session.scalars(stmt)),
|
||||
key=lambda d: f"{d.song_id},{d.rating_class}",
|
||||
)
|
||||
songIds = sorted(list(set(d.song_id for d in absentInfoDifficulties)))
|
||||
songsStmt = select(Song).where(Song.id.in_(songIds))
|
||||
songs = sorted(list(session.scalars(songsStmt)), key=lambda s: s.id)
|
||||
|
||||
modelSongs = []
|
||||
for difficulty in absentInfoDifficulties:
|
||||
songIndex = songIds.index(difficulty.song_id)
|
||||
modelSongs.append(songs[songIndex])
|
||||
self.chartInfoAbsentModel.setCustomData(modelSongs, absentInfoDifficulties)
|
||||
self.listView.setItemDelegate(self.listViewDelegate)
|
||||
|
||||
@Slot(QModelIndex)
|
||||
def listViewSelectionChanged(self, current: QModelIndex):
|
||||
if current.row() < 0 or current.column() < 0:
|
||||
return
|
||||
|
||||
song: Song = current.data(ChartInfoAbsentModel.SongRole)
|
||||
difficulty: Difficulty = current.data(ChartInfoAbsentModel.DifficultyRole)
|
||||
self.chartSelector.selectChart(
|
||||
Chart(
|
||||
song_id=difficulty.song_id,
|
||||
rating_class=difficulty.rating_class,
|
||||
set=song.set,
|
||||
)
|
||||
)
|
||||
|
||||
def chartSelectorValueChanged(self):
|
||||
if chart := self.chartSelector.value():
|
||||
self.fillChartInfo(chart.song_id, chart.rating_class)
|
||||
else:
|
||||
self.reset()
|
||||
|
||||
def fillChartInfo(self, songId: str, ratingClass: int):
|
||||
song = self.db.get_song(songId)
|
||||
difficulty = self.db.get_difficulty(songId, ratingClass)
|
||||
|
||||
self.titleLabel.setText(difficulty.title or song.title)
|
||||
self.ratingLabel.setText(
|
||||
rating_class_to_text(difficulty.rating_class)
|
||||
+ " "
|
||||
+ str(difficulty.rating)
|
||||
+ ("+" if difficulty.rating_plus else "")
|
||||
)
|
||||
|
||||
jacketPath = Data().getJacketPath(song, difficulty)
|
||||
if not jacketPath:
|
||||
pixmap = QPixmap(":/images/jacket-placeholder.png")
|
||||
else:
|
||||
pixmap = QPixmap(str(jacketPath.resolve()))
|
||||
self.jacketLabel.setPixmap(
|
||||
pixmap.scaled(
|
||||
self.jacketLabel.size(),
|
||||
Qt.AspectRatioMode.KeepAspectRatio,
|
||||
Qt.TransformationMode.SmoothTransformation,
|
||||
)
|
||||
)
|
||||
|
||||
chartInfo = self.db.get_chart_info(songId, ratingClass)
|
||||
if chartInfo is not None:
|
||||
if chartInfo.constant is not None:
|
||||
self.constantLineEdit.setText(str(chartInfo.constant))
|
||||
if chartInfo.notes is not None:
|
||||
self.notesLineEdit.setText(str(chartInfo.notes))
|
||||
else:
|
||||
self.constantLineEdit.setText("")
|
||||
self.notesLineEdit.setText("")
|
||||
|
||||
def commitChartInfo(self):
|
||||
chart = self.chartSelector.value()
|
||||
|
||||
if not chart:
|
||||
QMessageBox.critical(
|
||||
self,
|
||||
None,
|
||||
# fmt: off
|
||||
QCoreApplication.translate("TabDb_ChartInfoEditor", "commit.chartNotSelected"),
|
||||
# fmt: on
|
||||
)
|
||||
return
|
||||
if not self.constantLineEdit.hasAcceptableInput():
|
||||
QMessageBox.critical(
|
||||
self,
|
||||
None,
|
||||
# fmt: off
|
||||
QCoreApplication.translate("TabDb_ChartInfoEditor", "commit.constantRequired"),
|
||||
# fmt: on
|
||||
)
|
||||
return
|
||||
|
||||
constant = int(self.constantLineEdit.text())
|
||||
notes = (
|
||||
int(self.notesLineEdit.text())
|
||||
if self.notesLineEdit.hasAcceptableInput()
|
||||
else None
|
||||
)
|
||||
chartInfo = ChartInfo(
|
||||
song_id=chart.song_id,
|
||||
rating_class=chart.rating_class,
|
||||
constant=constant,
|
||||
notes=notes,
|
||||
)
|
||||
with self.db.sessionmaker() as session:
|
||||
session.merge(chartInfo)
|
||||
session.commit()
|
||||
databaseUpdateSignals.chartInfoUpdated.emit()
|
||||
|
||||
def deleteChartInfo(self):
|
||||
chart = self.chartSelector.value()
|
||||
|
||||
if not chart:
|
||||
QMessageBox.critical(
|
||||
self,
|
||||
None,
|
||||
# fmt: off
|
||||
QCoreApplication.translate("TabDb_ChartInfoEditor", "commit.chartNotSelected"),
|
||||
# fmt: on
|
||||
)
|
||||
return
|
||||
|
||||
chartInfo = self.db.get_chart_info(chart.song_id, chart.rating_class)
|
||||
if chartInfo:
|
||||
result = QMessageBox.warning(
|
||||
self,
|
||||
None,
|
||||
# fmt: off
|
||||
QCoreApplication.translate("TabDb_ChartInfoEditor", "deleteConfirm"),
|
||||
# fmt: on
|
||||
QMessageBox.StandardButton.Yes,
|
||||
QMessageBox.StandardButton.No,
|
||||
)
|
||||
if result == QMessageBox.StandardButton.Yes:
|
||||
with self.db.sessionmaker() as session:
|
||||
session.delete(chartInfo)
|
||||
session.commit()
|
||||
databaseUpdateSignals.chartInfoUpdated.emit()
|
@ -1,3 +1,4 @@
|
||||
import csv
|
||||
import json
|
||||
import logging
|
||||
import traceback
|
||||
@ -5,6 +6,7 @@ import zipfile
|
||||
|
||||
from arcaea_offline.database import Database
|
||||
from arcaea_offline.external.arcaea import (
|
||||
ArcaeaOnlineParser,
|
||||
PacklistParser,
|
||||
SonglistDifficultiesParser,
|
||||
SonglistParser,
|
||||
@ -12,8 +14,10 @@ from arcaea_offline.external.arcaea import (
|
||||
)
|
||||
from arcaea_offline.external.arcaea.common import ArcaeaParser
|
||||
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.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 ui.designer.tabs.tabDb.tabDb_Manage_ui import Ui_TabDb_Manage
|
||||
@ -46,7 +50,7 @@ class TabDb_Manage(Ui_TabDb_Manage, QWidget):
|
||||
with db.sessionmaker() as session:
|
||||
parser.write_database(session)
|
||||
session.commit()
|
||||
databaseUpdateSignals.songDataUpdated.emit()
|
||||
databaseUpdateSignals.chartInfoUpdated.emit()
|
||||
QMessageBox.information(self, None, "OK")
|
||||
except Exception as e:
|
||||
logging.exception("Sync arcsong.db error")
|
||||
@ -54,6 +58,29 @@ class TabDb_Manage(Ui_TabDb_Manage, QWidget):
|
||||
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(
|
||||
self, parser: ArcaeaParser, instance, logName, path
|
||||
) -> int:
|
||||
@ -62,7 +89,7 @@ class TabDb_Manage(Ui_TabDb_Manage, QWidget):
|
||||
with db.sessionmaker() as session:
|
||||
parser.write_database(session)
|
||||
session.commit()
|
||||
databaseUpdateSignals.songDataUpdated.emit()
|
||||
databaseUpdateSignals.songAddOrDelete.emit()
|
||||
itemNum = len([item for item in parser.parse() if isinstance(item, instance)])
|
||||
logger.info(f"updated {itemNum} {logName} from {path}")
|
||||
return itemNum
|
||||
@ -178,16 +205,41 @@ class TabDb_Manage(Ui_TabDb_Manage, QWidget):
|
||||
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()
|
||||
def on_exportScoresButton_clicked(self):
|
||||
scores = Database().export_scores()
|
||||
version = Database().version()
|
||||
scores = Database().export_scores_def_v2()
|
||||
timestamp = QDateTime.currentMSecsSinceEpoch()
|
||||
content = json.dumps(scores, ensure_ascii=False)
|
||||
|
||||
exportLocation, _filter = QFileDialog.getSaveFileName(
|
||||
self,
|
||||
"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);;*",
|
||||
)
|
||||
with open(exportLocation, "w", encoding="utf-8") as f:
|
||||
@ -206,3 +258,27 @@ class TabDb_Manage(Ui_TabDb_Manage, QWidget):
|
||||
)
|
||||
with open(exportLocation, "w", encoding="utf-8") as f:
|
||||
f.write(content)
|
||||
|
||||
@Slot()
|
||||
def on_exportSmartRteB30Button_clicked(self):
|
||||
try:
|
||||
with Database().sessionmaker() as session:
|
||||
converter = SmartRteB30CsvConverter(session)
|
||||
csvRows = converter.rows()
|
||||
|
||||
exportLocation, _filter = QFileDialog.getSaveFileName(
|
||||
self,
|
||||
"Export CSV file",
|
||||
QDir.current().filePath("smartrte_scores.csv"),
|
||||
"CSV (*.csv);;*",
|
||||
)
|
||||
with open(exportLocation, "w", encoding="utf-8", newline="") as f:
|
||||
csvWriter = csv.writer(f)
|
||||
csvWriter.writerows(csvRows)
|
||||
|
||||
QMessageBox.information(self, None, "OK")
|
||||
except Exception as e:
|
||||
logging.exception("Export SmartRTE csv error:")
|
||||
QMessageBox.critical(
|
||||
self, "Export Error", "\n".join(traceback.format_exception(e))
|
||||
)
|
||||
|
353
ui/implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py
Normal file
353
ui/implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py
Normal file
@ -0,0 +1,353 @@
|
||||
from enum import IntEnum
|
||||
|
||||
from arcaea_offline.database import Database
|
||||
from arcaea_offline.models import Chart, Difficulty, Score, Song
|
||||
from PySide6.QtCore import QCoreApplication, QModelIndex, Qt, Slot
|
||||
from PySide6.QtGui import QStandardItem, QStandardItemModel
|
||||
from PySide6.QtWidgets import QMessageBox, QStyledItemDelegate, QWidget
|
||||
from sqlalchemy import delete, func, select
|
||||
from sqlalchemy.orm import InstrumentedAttribute, Session
|
||||
|
||||
from ui.designer.tabs.tabDb.tabDb_RemoveDuplicateScores_ui import (
|
||||
Ui_TabDb_RemoveDuplicateScores,
|
||||
)
|
||||
from ui.extends.shared.delegates.chartDelegate import ChartDelegate
|
||||
from ui.extends.shared.delegates.scoreDelegate import ScoreDelegate
|
||||
from ui.extends.shared.language import LanguageChangeEventFilter
|
||||
|
||||
|
||||
class RemoveDuplicateScoresModel(QStandardItemModel):
|
||||
ScoreRole = Qt.ItemDataRole.UserRole
|
||||
ChartRole = Qt.ItemDataRole.UserRole + 10
|
||||
SongRole = Qt.ItemDataRole.UserRole + 11
|
||||
DifficultyRole = Qt.ItemDataRole.UserRole + 12
|
||||
|
||||
def setChartDelegateDatas(
|
||||
self, item: QStandardItem, songId: str, ratingClass: int, session: Session
|
||||
):
|
||||
chart = (
|
||||
session.query(Chart)
|
||||
.where((Chart.song_id == songId) & (Chart.rating_class == ratingClass))
|
||||
.first()
|
||||
)
|
||||
song = session.query(Song).where(Song.id == songId).first()
|
||||
difficulty = (
|
||||
session.query(Difficulty)
|
||||
.where(
|
||||
(Difficulty.song_id == songId)
|
||||
& (Difficulty.rating_class == ratingClass)
|
||||
)
|
||||
.first()
|
||||
)
|
||||
|
||||
if chart is None and song is None and difficulty is None:
|
||||
chart = Chart(song_id=songId, rating_class=ratingClass, set="unknown")
|
||||
|
||||
item.setData(chart, self.ChartRole)
|
||||
item.setData(song, self.SongRole)
|
||||
item.setData(difficulty, self.DifficultyRole)
|
||||
|
||||
def getGroupKey(self, score: Score, columns: list[InstrumentedAttribute]) -> str:
|
||||
baseKeys = [score.song_id, str(score.rating_class)]
|
||||
for column in columns:
|
||||
key = f"{column.key}{getattr(score,column.key)}"
|
||||
baseKeys.append(key)
|
||||
return "||".join(baseKeys)
|
||||
|
||||
def setScores(self, scores: list[Score], columns: list[InstrumentedAttribute]):
|
||||
self.clear()
|
||||
|
||||
scoreKeyMap: dict[str, list[Score]] = {}
|
||||
for score in scores:
|
||||
key = self.getGroupKey(score, columns)
|
||||
if scoreKeyMap.get(key) is None:
|
||||
scoreKeyMap[key] = [score]
|
||||
else:
|
||||
scoreKeyMap[key].append(score)
|
||||
|
||||
db = Database()
|
||||
with db.sessionmaker() as session:
|
||||
for key, scores in scoreKeyMap.items():
|
||||
songId, ratingClass = key.split("||")[:2]
|
||||
ratingClass = int(ratingClass)
|
||||
|
||||
parentCheckBoxItem = QStandardItem(f"{len(scores)} items")
|
||||
parentChartItem = QStandardItem()
|
||||
self.setChartDelegateDatas(
|
||||
parentChartItem, songId, ratingClass, session
|
||||
)
|
||||
|
||||
for i, score in enumerate(scores):
|
||||
scoreCheckBoxItem = QStandardItem()
|
||||
scoreCheckBoxItem.setEditable(False)
|
||||
scoreCheckBoxItem.setCheckable(True)
|
||||
scoreCheckBoxItem.setEnabled(True)
|
||||
scoreItem = QStandardItem()
|
||||
scoreItem.setData(score, self.ScoreRole)
|
||||
scoreItem.setEditable(False)
|
||||
scoreItem.setEnabled(True)
|
||||
parentCheckBoxItem.setChild(i, 0, scoreCheckBoxItem)
|
||||
parentCheckBoxItem.setChild(i, 1, scoreItem)
|
||||
|
||||
self.appendRow([parentCheckBoxItem, parentChartItem])
|
||||
|
||||
|
||||
class TreeViewChartDelegate(ChartDelegate):
|
||||
def getChart(self, index: QModelIndex):
|
||||
return index.data(RemoveDuplicateScoresModel.ChartRole)
|
||||
|
||||
def getSong(self, index: QModelIndex):
|
||||
return index.data(RemoveDuplicateScoresModel.SongRole)
|
||||
|
||||
def getDifficulty(self, index: QModelIndex):
|
||||
return index.data(RemoveDuplicateScoresModel.DifficultyRole)
|
||||
|
||||
|
||||
class TreeViewScoreDelegate(ScoreDelegate):
|
||||
def getScore(self, index: QModelIndex):
|
||||
return index.data(RemoveDuplicateScoresModel.ScoreRole)
|
||||
|
||||
|
||||
class TreeViewProxyDelegate(QStyledItemDelegate):
|
||||
def __init__(
|
||||
self, chartDelegate: ChartDelegate, scoreDelegate: ScoreDelegate, parent=None
|
||||
):
|
||||
super().__init__(parent)
|
||||
self.chartDelegate = chartDelegate
|
||||
self.scoreDelegate = scoreDelegate
|
||||
|
||||
def delegateForIndex(self, index: QModelIndex) -> QStyledItemDelegate:
|
||||
return self.scoreDelegate if index.parent().isValid() else self.chartDelegate
|
||||
|
||||
def sizeHint(self, option, index: QModelIndex):
|
||||
return self.delegateForIndex(index).sizeHint(option, index)
|
||||
|
||||
def paint(self, painter, option, index: QModelIndex):
|
||||
self.delegateForIndex(index).paint(painter, option, index)
|
||||
QStyledItemDelegate.paint(self, painter, option, index)
|
||||
|
||||
|
||||
class QuickSelectComboBoxValues(IntEnum):
|
||||
ID_EARLIER = 0
|
||||
DATE_EARLIER = 1
|
||||
COLUMNS_INTEGRAL = 2
|
||||
|
||||
|
||||
class TabDb_RemoveDuplicateScores(Ui_TabDb_RemoveDuplicateScores, QWidget):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.setupUi(self)
|
||||
|
||||
self.languageChangeEventFilter = LanguageChangeEventFilter(self)
|
||||
self.installEventFilter(self.languageChangeEventFilter)
|
||||
|
||||
self.db = Database()
|
||||
|
||||
self.removeDuplicateScoresModel = RemoveDuplicateScoresModel(self)
|
||||
self.treeView.setModel(self.removeDuplicateScoresModel)
|
||||
|
||||
self.treeViewChartDelegate = TreeViewChartDelegate(self.treeView)
|
||||
self.treeViewScoreDelegate = TreeViewScoreDelegate(self.treeView)
|
||||
self.treeViewProxyDelegate = TreeViewProxyDelegate(
|
||||
self.treeViewChartDelegate, self.treeViewScoreDelegate, self.treeView
|
||||
)
|
||||
self.treeView.setItemDelegateForColumn(1, self.treeViewProxyDelegate)
|
||||
|
||||
self.quickSelect_comboBox.addItem(
|
||||
# fmt: off
|
||||
QCoreApplication.translate("TabDb_RemoveDuplicateScores", "quickSelectComboBox.idEarlier"),
|
||||
# fmt: on
|
||||
QuickSelectComboBoxValues.ID_EARLIER
|
||||
)
|
||||
self.quickSelect_comboBox.addItem(
|
||||
# fmt: off
|
||||
QCoreApplication.translate("TabDb_RemoveDuplicateScores", "quickSelectComboBox.dateEarlier"),
|
||||
# fmt: on
|
||||
QuickSelectComboBoxValues.DATE_EARLIER
|
||||
)
|
||||
self.quickSelect_comboBox.addItem(
|
||||
# fmt: off
|
||||
QCoreApplication.translate("TabDb_RemoveDuplicateScores", "quickSelectComboBox.columnsIntegral"),
|
||||
# fmt: on
|
||||
QuickSelectComboBoxValues.COLUMNS_INTEGRAL
|
||||
)
|
||||
|
||||
def getQueryColumns(self):
|
||||
columns: list[InstrumentedAttribute] = [Score.song_id, Score.rating_class]
|
||||
|
||||
if self.scan_option_scoreCheckBox.isChecked():
|
||||
columns.append(Score.score)
|
||||
if self.scan_option_pureCheckBox.isChecked():
|
||||
columns.append(Score.pure)
|
||||
if self.scan_option_farCheckBox.isChecked():
|
||||
columns.append(Score.far)
|
||||
if self.scan_option_lostCheckBox.isChecked():
|
||||
columns.append(Score.lost)
|
||||
if self.scan_option_maxRecallCheckBox.isChecked():
|
||||
columns.append(Score.max_recall)
|
||||
if self.scan_option_dateCheckBox.isChecked():
|
||||
columns.append(Score.date)
|
||||
if self.scan_option_modifierCheckBox.isChecked():
|
||||
columns.append(Score.modifier)
|
||||
if self.scan_option_clearTypeCheckBox.isChecked():
|
||||
columns.append(Score.clear_type)
|
||||
|
||||
return columns
|
||||
|
||||
def getQueryScores(self):
|
||||
columns = self.getQueryColumns()
|
||||
with self.db.sessionmaker() as session:
|
||||
groupBySubquery = (
|
||||
select(*columns).group_by(*columns).having(func.count() > 1).subquery()
|
||||
)
|
||||
selectInClause = [
|
||||
col == getattr(groupBySubquery.c, col.key) for col in columns
|
||||
]
|
||||
return session.query(Score).where(*selectInClause).all()
|
||||
|
||||
def scan(self):
|
||||
scores = self.getQueryScores()
|
||||
self.removeDuplicateScoresModel.setScores(scores, self.getQueryColumns())
|
||||
self.treeView.expandAll()
|
||||
|
||||
def deselectAll(self):
|
||||
for row in range(self.removeDuplicateScoresModel.rowCount()):
|
||||
parentItem = self.removeDuplicateScoresModel.item(row, 0)
|
||||
for childRow in range(parentItem.rowCount()):
|
||||
childCheckBoxItem = parentItem.child(childRow, 0)
|
||||
childCheckBoxItem.setCheckState(Qt.CheckState.Unchecked)
|
||||
|
||||
def quickSelect(self):
|
||||
mode = self.quickSelect_comboBox.currentData()
|
||||
|
||||
if mode is None:
|
||||
return
|
||||
|
||||
for row in range(self.removeDuplicateScoresModel.rowCount()):
|
||||
parentItem = self.removeDuplicateScoresModel.item(row, 0)
|
||||
|
||||
scores: list[Score] = []
|
||||
|
||||
for childRow in range(parentItem.rowCount()):
|
||||
childScoreItem = parentItem.child(childRow, 1)
|
||||
scores.append(childScoreItem.data(RemoveDuplicateScoresModel.ScoreRole))
|
||||
|
||||
if mode == QuickSelectComboBoxValues.ID_EARLIER:
|
||||
chosenRow = min(enumerate(scores), key=lambda i: i[1].id)[0]
|
||||
elif mode == QuickSelectComboBoxValues.DATE_EARLIER:
|
||||
chosenRow = min(
|
||||
enumerate(scores),
|
||||
key=lambda i: float("inf") if i[1].date is None else i[1].date,
|
||||
)[0]
|
||||
elif mode == QuickSelectComboBoxValues.COLUMNS_INTEGRAL:
|
||||
chosenRow = max(
|
||||
enumerate(scores),
|
||||
key=lambda i: sum(
|
||||
getattr(i[1], col.key) is not None
|
||||
for col in i[1].__table__.columns
|
||||
),
|
||||
)[0]
|
||||
|
||||
for childRow in range(parentItem.rowCount()):
|
||||
childCheckBoxItem = parentItem.child(childRow, 0)
|
||||
if childRow != chosenRow:
|
||||
childCheckBoxItem.setCheckState(Qt.CheckState.Checked)
|
||||
else:
|
||||
childCheckBoxItem.setCheckState(Qt.CheckState.Unchecked)
|
||||
|
||||
def reverseSelection(self):
|
||||
for row in range(self.removeDuplicateScoresModel.rowCount()):
|
||||
parentItem = self.removeDuplicateScoresModel.item(row, 0)
|
||||
# only when there's a checked item in this group, we perform a reversed selection
|
||||
# otherwise we ignore this group
|
||||
performReverse = any(
|
||||
parentItem.child(childRow, 0).checkState() == Qt.CheckState.Checked
|
||||
for childRow in range(parentItem.rowCount())
|
||||
)
|
||||
if not performReverse:
|
||||
continue
|
||||
|
||||
for childRow in range(parentItem.rowCount()):
|
||||
childCheckBoxItem = parentItem.child(childRow, 0)
|
||||
newCheckState = (
|
||||
Qt.CheckState.Unchecked
|
||||
if childCheckBoxItem.checkState() != Qt.CheckState.Unchecked
|
||||
else Qt.CheckState.Checked
|
||||
)
|
||||
childCheckBoxItem.setCheckState(newCheckState)
|
||||
|
||||
def deleteSelection(self):
|
||||
selectedScores: list[Score] = []
|
||||
for row in range(self.removeDuplicateScoresModel.rowCount()):
|
||||
parentItem = self.removeDuplicateScoresModel.item(row, 0)
|
||||
for childRow in range(parentItem.rowCount()):
|
||||
childCheckBoxItem = parentItem.child(childRow, 0)
|
||||
if childCheckBoxItem.checkState() == Qt.CheckState.Checked:
|
||||
childScoreItem = parentItem.child(childRow, 1)
|
||||
selectedScores.append(
|
||||
childScoreItem.data(RemoveDuplicateScoresModel.ScoreRole)
|
||||
)
|
||||
|
||||
confirm = QMessageBox.warning(
|
||||
self,
|
||||
None,
|
||||
# fmt: off
|
||||
QCoreApplication.translate("TabDb_RemoveDuplicateScores", "deleteSelectionDialog.content {}").format(len(selectedScores)),
|
||||
# fmt: on
|
||||
QMessageBox.StandardButton.Yes,
|
||||
QMessageBox.StandardButton.No,
|
||||
)
|
||||
if confirm != QMessageBox.StandardButton.Yes:
|
||||
return
|
||||
|
||||
with self.db.sessionmaker() as session:
|
||||
ids = [s.id for s in selectedScores]
|
||||
session.execute(delete(Score).where(Score.id.in_(ids)))
|
||||
session.commit()
|
||||
|
||||
self.scan()
|
||||
|
||||
@Slot()
|
||||
def on_scan_scanButton_clicked(self):
|
||||
if len(self.getQueryColumns()) <= 2:
|
||||
result = QMessageBox.warning(
|
||||
self,
|
||||
None,
|
||||
# fmt: off
|
||||
QCoreApplication.translate("TabDb_RemoveDuplicateScores", "scan_noColumnsDialog.content"),
|
||||
# fmt: on
|
||||
QMessageBox.StandardButton.Yes,
|
||||
QMessageBox.StandardButton.No,
|
||||
)
|
||||
if result != QMessageBox.StandardButton.Yes:
|
||||
return
|
||||
|
||||
self.scan()
|
||||
|
||||
@Slot()
|
||||
def on_quickSelect_selectButton_clicked(self):
|
||||
self.quickSelect()
|
||||
|
||||
@Slot()
|
||||
def on_deselectAllButton_clicked(self):
|
||||
self.deselectAll()
|
||||
|
||||
@Slot()
|
||||
def on_reverseSelectionButton_clicked(self):
|
||||
self.reverseSelection()
|
||||
|
||||
@Slot()
|
||||
def on_expandAllButton_clicked(self):
|
||||
self.treeView.expandAll()
|
||||
|
||||
@Slot()
|
||||
def on_collapseAllButton_clicked(self):
|
||||
self.treeView.collapseAll()
|
||||
|
||||
@Slot()
|
||||
def on_resetModelButton_clicked(self):
|
||||
self.removeDuplicateScoresModel.clear()
|
||||
|
||||
@Slot()
|
||||
def on_deleteSelectionButton_clicked(self):
|
||||
self.deleteSelection()
|
@ -1,5 +1,4 @@
|
||||
from arcaea_offline.models import Score
|
||||
from PySide6.QtCore import QModelIndex, Qt, Slot
|
||||
from PySide6.QtCore import Qt, Slot
|
||||
from PySide6.QtGui import QColor, QPalette
|
||||
from PySide6.QtWidgets import QMessageBox
|
||||
|
||||
@ -17,6 +16,12 @@ class TableChartDelegate(ChartDelegate):
|
||||
def getChart(self, index):
|
||||
return index.data(DbScoreTableModel.ChartRole)
|
||||
|
||||
def getSong(self, index):
|
||||
return index.data(DbScoreTableModel.SongRole)
|
||||
|
||||
def getDifficulty(self, index):
|
||||
return index.data(DbScoreTableModel.DifficultyRole)
|
||||
|
||||
|
||||
class TableScoreDelegate(ScoreDelegate):
|
||||
def getChart(self, index):
|
||||
@ -49,6 +54,7 @@ class DbScoreTableViewer(DbTableViewer):
|
||||
highlightColor.setAlpha(25)
|
||||
tableViewPalette.setColor(QPalette.ColorRole.Highlight, highlightColor)
|
||||
self.tableView.setPalette(tableViewPalette)
|
||||
self.tableModel.rowsInserted.connect(self.resizeTableView)
|
||||
self.tableModel.dataChanged.connect(self.resizeTableView)
|
||||
|
||||
self.fillSortComboBox()
|
||||
|
@ -1,3 +1,5 @@
|
||||
import logging
|
||||
|
||||
from arcaea_offline.database import Database
|
||||
from PySide6.QtCore import QCoreApplication
|
||||
from PySide6.QtGui import QShowEvent
|
||||
@ -6,6 +8,8 @@ from PySide6.QtWidgets import QWidget
|
||||
from ui.designer.tabs.tabOverview_ui import Ui_TabOverview
|
||||
from ui.extends.shared.language import LanguageChangeEventFilter
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TabOverview(Ui_TabOverview, QWidget):
|
||||
def __init__(self, parent=None):
|
||||
@ -22,18 +26,27 @@ class TabOverview(Ui_TabOverview, QWidget):
|
||||
return super().showEvent(event)
|
||||
|
||||
def updateOverview(self):
|
||||
b30 = self.db.get_b30() or 0.00
|
||||
self.b30Label.setText(str(f"{b30:.3f}"))
|
||||
self.databaseDescribeLabel.setText(
|
||||
self.describeFormatString.format(
|
||||
self.db.count_packs(),
|
||||
self.db.count_songs(),
|
||||
self.db.count_difficulties(),
|
||||
self.db.count_chart_infos(),
|
||||
self.db.count_complete_chart_infos(),
|
||||
self.db.count_scores(),
|
||||
try:
|
||||
b30 = self.db.get_b30() or 0.00
|
||||
self.b30Label.setText(str(f"{b30:.3f}"))
|
||||
except Exception:
|
||||
logger.exception("Cannot get b30:")
|
||||
self.b30Label.setText("ERR")
|
||||
|
||||
try:
|
||||
self.databaseDescribeLabel.setText(
|
||||
self.describeFormatString.format(
|
||||
self.db.count_packs(),
|
||||
self.db.count_songs(),
|
||||
self.db.count_difficulties(),
|
||||
self.db.count_chart_infos(),
|
||||
self.db.count_complete_chart_infos(),
|
||||
self.db.count_scores(),
|
||||
)
|
||||
)
|
||||
)
|
||||
except Exception:
|
||||
logger.exception("Cannot update overview:")
|
||||
self.databaseDescribeLabel.setText("ERR")
|
||||
|
||||
def retranslateUi(self, *args):
|
||||
super().retranslateUi(self)
|
||||
|
@ -1,27 +1,53 @@
|
||||
import logging
|
||||
import random
|
||||
|
||||
from arcaea_offline.calculate import calculate_constants_from_play_rating
|
||||
from arcaea_offline.database import Database
|
||||
from arcaea_offline.models import Chart, ScoreBest
|
||||
from arcaea_offline.models import Chart, Score
|
||||
from arcaea_offline.utils.rating import rating_class_to_text
|
||||
from arcaea_offline.utils.score import score_to_grade_text
|
||||
from PySide6.QtCore import Slot
|
||||
from PySide6.QtWidgets import QLabel, QWidget
|
||||
from PySide6.QtCore import QModelIndex, Qt, Slot
|
||||
from PySide6.QtWidgets import QDialog, QLabel, QVBoxLayout, QWidget
|
||||
|
||||
from ui.designer.tabs.tabTools.tabTools_ChartRecommend_ui import (
|
||||
Ui_TabTools_ChartRecommend,
|
||||
)
|
||||
from ui.extends.shared.language import LanguageChangeEventFilter
|
||||
from ui.extends.tabs.tabTools.tabTools_ChartRecommend import (
|
||||
ChartsModel,
|
||||
ChartsWithScoreBestModel,
|
||||
CustomChartDelegate,
|
||||
CustomScoreBestDelegate,
|
||||
)
|
||||
from ui.implements.components.playRatingCalculator import PlayRatingCalculator
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def chartToText(chart: Chart):
|
||||
return f"{chart.artist} - {chart.title}<br>({chart.song_id}) {rating_class_to_text(chart.rating_class)}"
|
||||
class QuickPlayRatingCalculatorDialog(QDialog):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
|
||||
self.verticalLayout = QVBoxLayout(self)
|
||||
|
||||
def scoreBestToText(score: ScoreBest):
|
||||
return f"{score_to_grade_text(score.score)} {score.score} > {score.potential:.4f}"
|
||||
self.chartLabel = QLabel(self)
|
||||
self.verticalLayout.addWidget(self.chartLabel)
|
||||
|
||||
self.playRatingCalculator = PlayRatingCalculator(self)
|
||||
self.verticalLayout.addWidget(self.playRatingCalculator)
|
||||
|
||||
self.setMinimumWidth(400)
|
||||
|
||||
self.playRatingCalculator.arcaeaScoreLineEdit.setFocus(
|
||||
Qt.FocusReason.PopupFocusReason
|
||||
)
|
||||
|
||||
def setChart(self, chart: Chart):
|
||||
self.chartLabel.setText(
|
||||
f"{chart.title} {rating_class_to_text(chart.rating_class)} {chart.constant / 10}"
|
||||
)
|
||||
self.playRatingCalculator.setConstant(chart.constant)
|
||||
|
||||
def setScore(self, score: Score):
|
||||
self.playRatingCalculator.arcaeaScoreLineEdit.setText(str(score))
|
||||
|
||||
|
||||
class TabTools_ChartRecommend(Ui_TabTools_ChartRecommend, QWidget):
|
||||
@ -29,13 +55,30 @@ class TabTools_ChartRecommend(Ui_TabTools_ChartRecommend, QWidget):
|
||||
super().__init__(parent)
|
||||
self.setupUi(self)
|
||||
|
||||
self.languageChangeEventFilter = LanguageChangeEventFilter(self)
|
||||
self.installEventFilter(self.languageChangeEventFilter)
|
||||
|
||||
self.db = Database()
|
||||
|
||||
self.chartsByConstant = []
|
||||
self.chartsRecommendFromPlayRating = []
|
||||
self.chartsByConstantModel = ChartsModel(self)
|
||||
self.chartsRecommendFromPlayRatingModel = ChartsWithScoreBestModel(self)
|
||||
|
||||
self.numLabelFormatString = "{} charts"
|
||||
|
||||
self.chartDelegate = CustomChartDelegate(self)
|
||||
self.scoreBestDelegate = CustomScoreBestDelegate(self)
|
||||
self.chartsByConstant_modelView.setModel(self.chartsByConstantModel)
|
||||
self.chartsByConstant_modelView.setItemDelegate(self.chartDelegate)
|
||||
self.chartsRecommendFromPlayRating_modelView.setModel(
|
||||
self.chartsRecommendFromPlayRatingModel
|
||||
)
|
||||
self.chartsRecommendFromPlayRating_modelView.setItemDelegateForColumn(
|
||||
0, self.chartDelegate
|
||||
)
|
||||
self.chartsRecommendFromPlayRating_modelView.setItemDelegateForColumn(
|
||||
1, self.scoreBestDelegate
|
||||
)
|
||||
|
||||
self.chartsRecommendFromPlayRating_playRatingSpinBox.valueChanged.connect(
|
||||
self.updateChartsRecommendFromPlayRating
|
||||
)
|
||||
@ -43,81 +86,91 @@ class TabTools_ChartRecommend(Ui_TabTools_ChartRecommend, QWidget):
|
||||
self.updateChartsRecommendFromPlayRating
|
||||
)
|
||||
|
||||
self.chartsByConstant_refreshButton.clicked.connect(self.fillChartsByConstant)
|
||||
self.chartsRecommendFromPlayRating_refreshButton.clicked.connect(
|
||||
self.fillChartsRecommendFromPlayRating
|
||||
self.chartsByConstant_modelView.doubleClicked.connect(
|
||||
self.openQuickPlayRatingCalculator_chartsByConstant
|
||||
)
|
||||
self.chartsRecommendFromPlayRating_modelView.doubleClicked.connect(
|
||||
self.openQuickPlayRatingCalculator_chartsRecommendFromPlayRating
|
||||
)
|
||||
|
||||
@Slot(float)
|
||||
def on_rangeFromPlayRating_playRatingSpinBox_valueChanged(self, value: float):
|
||||
try:
|
||||
result = calculate_constants_from_play_rating(value)
|
||||
exPlusLower, exPlusUpper = result.EXPlus
|
||||
exLower, exUpper = result.EX
|
||||
aaLower, aaUpper = result.AA
|
||||
|
||||
self.rangeFromPlayRating_ExPlusLabel.setText(
|
||||
f"{exPlusLower:.3f}~{exPlusUpper:.3f}"
|
||||
constant = round(
|
||||
value, self.rangeFromPlayRating_playRatingSpinBox.decimals()
|
||||
)
|
||||
self.rangeFromPlayRating_ExLabel.setText(f"{exLower:.3f}~{exUpper:.3f}")
|
||||
self.rangeFromPlayRating_AaLabel.setText(f"{aaLower:.3f}~{aaUpper:.3f}")
|
||||
result = calculate_constants_from_play_rating(constant)
|
||||
labels = [
|
||||
self.rangeFromPlayRating_ExPlusLabel,
|
||||
self.rangeFromPlayRating_ExLabel,
|
||||
self.rangeFromPlayRating_AaLabel,
|
||||
self.rangeFromPlayRating_ALabel,
|
||||
self.rangeFromPlayRating_BLabel,
|
||||
self.rangeFromPlayRating_CLabel,
|
||||
]
|
||||
|
||||
for label, constantRange in zip(
|
||||
labels,
|
||||
[result.EXPlus, result.EX, result.AA, result.A, result.B, result.C],
|
||||
):
|
||||
label.setText(f"{constantRange[0]:.3f}~{constantRange[1]:.3f}")
|
||||
except Exception:
|
||||
logging.exception("cannot calculate constant from play rating")
|
||||
logging.exception("Cannot calculate constant from play rating:")
|
||||
self.rangeFromPlayRating_ExPlusLabel.setText("...")
|
||||
self.rangeFromPlayRating_ExLabel.setText("...")
|
||||
self.rangeFromPlayRating_AaLabel.setText("...")
|
||||
|
||||
def fillChartsByConstant(self):
|
||||
while item := self.chartsByConstant_gridLayout.takeAt(0):
|
||||
item.widget().deleteLater()
|
||||
|
||||
charts = random.sample(
|
||||
self.chartsByConstant, k=min(len(self.chartsByConstant), 6)
|
||||
)
|
||||
row = 0
|
||||
for i, chart in enumerate(charts):
|
||||
if i % 3 == 0:
|
||||
row += 1
|
||||
label = QLabel(self)
|
||||
label.setText(chartToText(chart))
|
||||
self.chartsByConstant_gridLayout.addWidget(label, row, i % 3)
|
||||
|
||||
@Slot(float)
|
||||
def on_chartsByConstant_constantSpinBox_valueChanged(self, value: float):
|
||||
self.chartsByConstant = self.db.get_charts_by_constant(int(value * 10))
|
||||
chartsNum = len(self.chartsByConstant)
|
||||
self.chartsByConstant_refreshButton.setEnabled(chartsNum > 6)
|
||||
constant = round(value, self.chartsByConstant_constantSpinBox.decimals())
|
||||
charts = self.db.get_charts_by_constant(int(constant * 10))
|
||||
chartsNum = len(charts)
|
||||
self.chartsByConstant_numLabel.setText(
|
||||
self.numLabelFormatString.format(chartsNum)
|
||||
)
|
||||
self.fillChartsByConstant()
|
||||
|
||||
def fillChartsRecommendFromPlayRating(self):
|
||||
while item := self.chartsRecommendFromPlayRating_gridLayout.takeAt(0):
|
||||
item.widget().deleteLater()
|
||||
|
||||
charts = random.sample(
|
||||
self.chartsRecommendFromPlayRating,
|
||||
k=min(len(self.chartsRecommendFromPlayRating), 6),
|
||||
)
|
||||
row = 0
|
||||
for i, chart in enumerate(charts):
|
||||
if i % 3 == 0:
|
||||
row += 1
|
||||
scoreBest = self.db.get_score_best(chart.song_id, chart.rating_class)
|
||||
label = QLabel(self)
|
||||
label.setText(f"{chartToText(chart)}<br>-<br>{scoreBestToText(scoreBest)}")
|
||||
self.chartsRecommendFromPlayRating_gridLayout.addWidget(label, row, i % 3)
|
||||
self.chartsByConstantModel.setCharts(charts)
|
||||
|
||||
def updateChartsRecommendFromPlayRating(self):
|
||||
playRating = self.chartsRecommendFromPlayRating_playRatingSpinBox.value()
|
||||
bounds = self.chartsRecommendFromPlayRating_boundsSpinBox.value()
|
||||
self.chartsRecommendFromPlayRating = self.db.recommend_charts(
|
||||
playRating, bounds
|
||||
charts = self.db.recommend_charts(
|
||||
round(
|
||||
playRating,
|
||||
self.chartsRecommendFromPlayRating_playRatingSpinBox.decimals(),
|
||||
),
|
||||
round(
|
||||
bounds,
|
||||
self.chartsRecommendFromPlayRating_boundsSpinBox.decimals(),
|
||||
),
|
||||
)
|
||||
chartsNum = len(self.chartsRecommendFromPlayRating)
|
||||
self.chartsRecommendFromPlayRating_refreshButton.setEnabled(chartsNum > 6)
|
||||
chartsNum = len(charts)
|
||||
self.chartsRecommendFromPlayRating_numLabel.setText(
|
||||
self.numLabelFormatString.format(chartsNum)
|
||||
)
|
||||
self.fillChartsRecommendFromPlayRating()
|
||||
scores = [self.db.get_score_best(c.song_id, c.rating_class) for c in charts]
|
||||
self.chartsRecommendFromPlayRatingModel.setChartAndScore(charts, scores)
|
||||
self.chartsRecommendFromPlayRating_modelView.resizeRowsToContents()
|
||||
self.chartsRecommendFromPlayRating_modelView.resizeColumnsToContents()
|
||||
|
||||
@Slot(QModelIndex)
|
||||
def openQuickPlayRatingCalculator_chartsByConstant(self, index: QModelIndex):
|
||||
dialog = QuickPlayRatingCalculatorDialog(self)
|
||||
chart = index.data(ChartsModel.ChartRole)
|
||||
dialog.setChart(chart)
|
||||
dialog.show()
|
||||
|
||||
@Slot(QModelIndex)
|
||||
def openQuickPlayRatingCalculator_chartsRecommendFromPlayRating(
|
||||
self, index: QModelIndex
|
||||
):
|
||||
dialog = QuickPlayRatingCalculatorDialog(self)
|
||||
|
||||
row = index.row()
|
||||
chartIndex = self.chartsRecommendFromPlayRatingModel.item(row, 0)
|
||||
scoreIndex = self.chartsRecommendFromPlayRatingModel.item(row, 1)
|
||||
|
||||
chart = chartIndex.data(ChartsWithScoreBestModel.ChartRole)
|
||||
score: Score = scoreIndex.data(ChartsWithScoreBestModel.ScoreBestRole)
|
||||
dialog.setChart(chart)
|
||||
dialog.setScore(score.score)
|
||||
dialog.show()
|
||||
|
@ -1,6 +1,5 @@
|
||||
import re
|
||||
|
||||
from arcaea_offline.calculate import calculate_play_rating
|
||||
from arcaea_offline.database import Database
|
||||
from PySide6.QtCore import QDateTime
|
||||
from PySide6.QtWidgets import QVBoxLayout, QWidget
|
||||
@ -27,15 +26,8 @@ class TabTools_InfoLookup(Ui_TabTools_InfoLookup, QWidget):
|
||||
self.ratingClassSelector.valueChanged.connect(self.updateDifficultyLabels)
|
||||
self.ratingClassSelector.valueChanged.connect(self.updateChartInfoLabels)
|
||||
|
||||
self.songIdSelector.valueChanged.connect(
|
||||
self.updatePlayRatingCalculateResultLabel
|
||||
)
|
||||
self.ratingClassSelector.valueChanged.connect(
|
||||
self.updatePlayRatingCalculateResultLabel
|
||||
)
|
||||
self.playRatingCalculateScoreLineEdit.textChanged.connect(
|
||||
self.updatePlayRatingCalculateResultLabel
|
||||
)
|
||||
self.songIdSelector.valueChanged.connect(self.updatePlayRatingCalculator)
|
||||
self.ratingClassSelector.valueChanged.connect(self.updatePlayRatingCalculator)
|
||||
|
||||
self.langSelectComboBox.addItem("En - English [en]", "en")
|
||||
self.langSelectComboBox.addItem("あ - Japanese [ja]", "ja")
|
||||
@ -213,29 +205,12 @@ class TabTools_InfoLookup(Ui_TabTools_InfoLookup, QWidget):
|
||||
str(chartInfo.notes) if chartInfo.notes is not None else "-"
|
||||
)
|
||||
|
||||
def resetPlayRatingCalculateResultLabel(self):
|
||||
self.playRatingCalculateResultLabel.setText("...")
|
||||
|
||||
def updatePlayRatingCalculateResultLabel(self):
|
||||
def updatePlayRatingCalculator(self):
|
||||
songId = self.songIdSelector.songId()
|
||||
ratingClass = self.ratingClassSelector.value()
|
||||
|
||||
if not songId or ratingClass is None:
|
||||
self.resetPlayRatingCalculateResultLabel()
|
||||
return
|
||||
|
||||
chartInfo = self.db.get_chart_info(songId, ratingClass)
|
||||
|
||||
if not chartInfo or not chartInfo.constant:
|
||||
self.resetPlayRatingCalculateResultLabel()
|
||||
return
|
||||
|
||||
if scoreText := self.playRatingCalculateScoreLineEdit.text().replace("'", ""):
|
||||
score = int(scoreText)
|
||||
|
||||
self.playRatingCalculateResultLabel.setText(
|
||||
f"{calculate_play_rating(chartInfo.constant, score):.3f}"
|
||||
)
|
||||
if not chartInfo:
|
||||
self.playRatingCalculator.setConstant(None)
|
||||
else:
|
||||
self.resetPlayRatingCalculateResultLabel()
|
||||
return
|
||||
self.playRatingCalculator.setConstant(chartInfo.constant)
|
||||
|
@ -1,6 +1,5 @@
|
||||
import logging
|
||||
|
||||
from arcaea_offline.calculate import calculate_play_rating
|
||||
from arcaea_offline.calculate.world_step import (
|
||||
AmaneBelowExPartnerBonus,
|
||||
AwakenedEtoPartnerBonus,
|
||||
@ -15,14 +14,22 @@ from arcaea_offline.calculate.world_step import (
|
||||
calculate_step,
|
||||
calculate_step_original,
|
||||
)
|
||||
from arcaea_offline.models import Chart, Score
|
||||
from PySide6.QtCore import QEasingCurve, QObject, QSize, Qt, QTimeLine
|
||||
from PySide6.QtGui import QIcon, QPainter, QPaintEvent, QPixmap
|
||||
from PySide6.QtCore import (
|
||||
QCoreApplication,
|
||||
QEasingCurve,
|
||||
QObject,
|
||||
QSize,
|
||||
QTimeLine,
|
||||
Signal,
|
||||
)
|
||||
from PySide6.QtGui import QIcon, QPixmap
|
||||
from PySide6.QtWidgets import (
|
||||
QAbstractButton,
|
||||
QButtonGroup,
|
||||
QDialog,
|
||||
QGraphicsColorizeEffect,
|
||||
QLabel,
|
||||
QPushButton,
|
||||
QVBoxLayout,
|
||||
QWidget,
|
||||
)
|
||||
|
||||
@ -30,26 +37,13 @@ from ui.designer.tabs.tabTools.tabTools_StepCalculator_ui import (
|
||||
Ui_TabTools_StepCalculator,
|
||||
)
|
||||
from ui.extends.shared.language import LanguageChangeEventFilter
|
||||
from ui.implements.components.chartAndScoreInput import ChartAndScoreInput
|
||||
from ui.implements.components.chartSelector import ChartSelector
|
||||
from ui.implements.components.playRatingCalculator import PlayRatingCalculator
|
||||
from ui.implements.components.songIdSelector import SongIdSelectorMode
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class MapTypeListWidgetWidget(QLabel):
|
||||
def paintEvent(self, e: QPaintEvent) -> None:
|
||||
size = self.size()
|
||||
painter = QPainter(self)
|
||||
scaledPixmap = self.pixmap().scaled(
|
||||
size,
|
||||
Qt.AspectRatioMode.KeepAspectRatio,
|
||||
Qt.TransformationMode.SmoothTransformation,
|
||||
)
|
||||
x = (size.width() - scaledPixmap.width()) / 2
|
||||
y = (size.height() - scaledPixmap.height()) / 2
|
||||
painter.drawPixmap(x, y, scaledPixmap)
|
||||
|
||||
|
||||
class ButtonGrayscaleEffectApplier(QObject):
|
||||
def __init__(self, parent: QAbstractButton):
|
||||
super().__init__(parent)
|
||||
@ -79,11 +73,56 @@ class ButtonGrayscaleEffectApplier(QObject):
|
||||
target.setGraphicsEffect(effect)
|
||||
|
||||
|
||||
class ChartAndScoreInputDialog(ChartAndScoreInput):
|
||||
class PlayRatingCalculatorDialog(QDialog):
|
||||
accepted = Signal()
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.setWindowFlag(Qt.WindowType.Dialog, True)
|
||||
self.setSongIdSelectorMode(SongIdSelectorMode.Chart)
|
||||
|
||||
self.verticalLayout = QVBoxLayout(self)
|
||||
|
||||
self.chartSelector = ChartSelector(self)
|
||||
self.chartSelector.setSongIdSelectorMode(SongIdSelectorMode.Chart)
|
||||
self.verticalLayout.addWidget(self.chartSelector)
|
||||
|
||||
self.playRatingCalculator = PlayRatingCalculator(self)
|
||||
self.verticalLayout.addWidget(self.playRatingCalculator)
|
||||
|
||||
self.acceptButton = QPushButton(self)
|
||||
self.acceptButton.setText(
|
||||
# fmt: off
|
||||
QCoreApplication.translate("StepCalculator", "playRatingCalculatorDialog.acceptButton")
|
||||
# fmt: on
|
||||
)
|
||||
self.acceptButton.setEnabled(False)
|
||||
self.verticalLayout.addWidget(self.acceptButton)
|
||||
|
||||
self.chartSelector.valueChanged.connect(self.updatePlayRatingCalculator)
|
||||
self.playRatingCalculator.arcaeaScoreLineEdit.textChanged.connect(
|
||||
self.updateAcceptButton
|
||||
)
|
||||
self.acceptButton.clicked.connect(self.accepted)
|
||||
|
||||
def updatePlayRatingCalculator(self):
|
||||
chart = self.chartSelector.value()
|
||||
if chart is None:
|
||||
self.playRatingCalculator.setConstant(None)
|
||||
else:
|
||||
self.playRatingCalculator.setConstant(chart.constant)
|
||||
self.updateAcceptButton()
|
||||
|
||||
def updateAcceptButton(self):
|
||||
if self.playRatingCalculator.result is None:
|
||||
self.acceptButton.setEnabled(False)
|
||||
else:
|
||||
self.acceptButton.setEnabled(True)
|
||||
|
||||
def reset(self):
|
||||
self.chartSelector.resetButton.click()
|
||||
self.playRatingCalculator.arcaeaScoreLineEdit.clear()
|
||||
|
||||
def value(self):
|
||||
return self.playRatingCalculator.result
|
||||
|
||||
|
||||
class TabTools_StepCalculator(Ui_TabTools_StepCalculator, QWidget):
|
||||
@ -203,23 +242,18 @@ class TabTools_StepCalculator(Ui_TabTools_StepCalculator, QWidget):
|
||||
)
|
||||
self.partnerSkillPresetButton_maya.clicked.connect(self.applyPartnerPreset)
|
||||
|
||||
def openChartAndScoreInputDialog(self):
|
||||
dialog = ChartAndScoreInputDialog(self)
|
||||
dialog.scoreCommited.connect(
|
||||
lambda: self.setPlayResultFromChartAndScoreInput(dialog)
|
||||
)
|
||||
dialog.show()
|
||||
self.playRatingCalculatorDialog = PlayRatingCalculatorDialog(self)
|
||||
self.playRatingCalculatorDialog.accepted.connect(self.set_toStep_PlayRating)
|
||||
|
||||
def setPlayResultFromChartAndScoreInput(self, dialog: ChartAndScoreInputDialog):
|
||||
if score := dialog.score():
|
||||
chart = dialog.chart()
|
||||
self.calculate_toStep_playResultSpinBox.setValue(
|
||||
float(calculate_play_rating(chart.constant, score.score))
|
||||
)
|
||||
dialog.close()
|
||||
dialog.deleteLater()
|
||||
else:
|
||||
return
|
||||
def openChartAndScoreInputDialog(self):
|
||||
self.playRatingCalculatorDialog.reset()
|
||||
self.playRatingCalculatorDialog.show()
|
||||
|
||||
def set_toStep_PlayRating(self):
|
||||
result = self.playRatingCalculatorDialog.value()
|
||||
if result is not None:
|
||||
self.calculate_toStep_playResultSpinBox.setValue(result)
|
||||
self.playRatingCalculatorDialog.close()
|
||||
|
||||
def applyPartnerPreset(self):
|
||||
if not self.sender():
|
||||
@ -307,7 +341,8 @@ class TabTools_StepCalculator(Ui_TabTools_StepCalculator, QWidget):
|
||||
step = calculate_step(
|
||||
playResult, partner_bonus=partnerBonus, step_booster=stepBooster
|
||||
)
|
||||
self.calculate_toStep_resultLabel.setText(f"{step}<br>({stepOriginal})")
|
||||
self.calculate_toStep_resultLabel.setText(str(step))
|
||||
self.calculate_toStep_detailedResultLabel.setText(str(stepOriginal))
|
||||
except Exception:
|
||||
if self.detailedLogOutputCheckBox.isChecked():
|
||||
logger.exception("Cannot calculate toStep")
|
||||
@ -315,16 +350,14 @@ class TabTools_StepCalculator(Ui_TabTools_StepCalculator, QWidget):
|
||||
|
||||
# fromStep
|
||||
try:
|
||||
self.calculate_fromStep_resultLabel.setText(
|
||||
str(
|
||||
calculate_play_rating_from_step(
|
||||
self.calculate_fromStep_targetStepSpinBox.value(),
|
||||
self.partnerStepValueSpinBox.value(),
|
||||
partner_bonus=partnerBonus,
|
||||
step_booster=stepBooster,
|
||||
)
|
||||
)
|
||||
fromStepResult = calculate_play_rating_from_step(
|
||||
self.calculate_fromStep_targetStepSpinBox.value(),
|
||||
self.partnerStepValueSpinBox.value(),
|
||||
partner_bonus=partnerBonus,
|
||||
step_booster=stepBooster,
|
||||
)
|
||||
self.calculate_fromStep_resultLabel.setText(str(round(fromStepResult, 2)))
|
||||
self.calculate_fromStep_detailedResultLabel.setText(str(fromStepResult))
|
||||
except Exception:
|
||||
if self.detailedLogOutputCheckBox.isChecked():
|
||||
logger.exception("Cannot calculate fromStep")
|
||||
|
BIN
ui/resources/fonts/GeosansLight.ttf
Normal file
BIN
ui/resources/fonts/GeosansLight.ttf
Normal file
Binary file not shown.
@ -17,74 +17,55 @@
|
||||
<context>
|
||||
<name>ChartSelector</name>
|
||||
<message>
|
||||
<location filename="../../designer/components/chartSelector.ui" line="26"/>
|
||||
<location filename="../../designer/components/chartSelector.ui" line="20"/>
|
||||
<source>songIdSelector.title</source>
|
||||
<translation>Select a Song</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/components/chartSelector.ui" line="71"/>
|
||||
<location filename="../../designer/components/chartSelector.ui" line="65"/>
|
||||
<source>resetButton</source>
|
||||
<translation>Reset</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>DB30TableModel</name>
|
||||
<message>
|
||||
<location filename="../../extends/shared/models/tables/b30.py" line="21"/>
|
||||
<source>horizontalHeader.id</source>
|
||||
<translation>ID</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../extends/shared/models/tables/b30.py" line="22"/>
|
||||
<source>horizontalHeader.chart</source>
|
||||
<translation>Chart</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../extends/shared/models/tables/b30.py" line="23"/>
|
||||
<source>horizontalHeader.score</source>
|
||||
<translation>Score</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../extends/shared/models/tables/b30.py" line="24"/>
|
||||
<source>horizontalHeader.potential</source>
|
||||
<translation>Potential</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>DatabaseChecker</name>
|
||||
<message>
|
||||
<location filename="../../startup/databaseChecker.ui" line="23"/>
|
||||
<location filename="../../startup/databaseChecker_ui.py" line="162"/>
|
||||
<source>dbPathLabel</source>
|
||||
<translation>Database path</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../startup/databaseChecker.ui" line="33"/>
|
||||
<location filename="../../startup/databaseChecker_ui.py" line="165"/>
|
||||
<source>dbFilenameLabel</source>
|
||||
<translation>Database filename</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../startup/databaseChecker.ui" line="64"/>
|
||||
<location filename="../../startup/databaseChecker_ui.py" line="168"/>
|
||||
<source>confirmDbPathButton</source>
|
||||
<translation>Confirm</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../startup/databaseChecker.ui" line="117"/>
|
||||
<location filename="../../startup/databaseChecker_ui.py" line="177"/>
|
||||
<source>dbVersionLabel</source>
|
||||
<translation>Database version</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../startup/databaseChecker.ui" line="131"/>
|
||||
<source>dbReInitLabel</source>
|
||||
<translation>Re-initialize database</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../startup/databaseChecker.ui" line="138"/>
|
||||
<source>dbReInitButton</source>
|
||||
<translation>Re-initialize</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../startup/databaseChecker.ui" line="93"/>
|
||||
<location filename="../../startup/databaseChecker_ui.py" line="171"/>
|
||||
<source>dbCheckConnLabel</source>
|
||||
<translation>Database connection</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../startup/databaseChecker.ui" line="110"/>
|
||||
<location filename="../../startup/databaseChecker_ui.py" line="174"/>
|
||||
<source>continueButton</source>
|
||||
<translation>Continue</translation>
|
||||
</message>
|
||||
@ -100,24 +81,47 @@
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>DbScoreTableModel</name>
|
||||
<name>DbB30TableModel</name>
|
||||
<message>
|
||||
<location filename="../../extends/shared/models/tables/score.py" line="22"/>
|
||||
<location filename="../../extends/shared/models/tables/b30.py" line="20"/>
|
||||
<source>horizontalHeader.id</source>
|
||||
<translation>ID</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../extends/shared/models/tables/score.py" line="23"/>
|
||||
<location filename="../../extends/shared/models/tables/b30.py" line="21"/>
|
||||
<source>horizontalHeader.chart</source>
|
||||
<translation>Chart</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../extends/shared/models/tables/score.py" line="24"/>
|
||||
<location filename="../../extends/shared/models/tables/b30.py" line="22"/>
|
||||
<source>horizontalHeader.score</source>
|
||||
<translation>Score</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../extends/shared/models/tables/score.py" line="25"/>
|
||||
<location filename="../../extends/shared/models/tables/b30.py" line="23"/>
|
||||
<source>horizontalHeader.potential</source>
|
||||
<translation>Potential</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>DbScoreTableModel</name>
|
||||
<message>
|
||||
<location filename="../../extends/shared/models/tables/score.py" line="28"/>
|
||||
<source>horizontalHeader.id</source>
|
||||
<translation>ID</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../extends/shared/models/tables/score.py" line="29"/>
|
||||
<source>horizontalHeader.chart</source>
|
||||
<translation>Chart</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../extends/shared/models/tables/score.py" line="30"/>
|
||||
<source>horizontalHeader.score</source>
|
||||
<translation>Score</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../extends/shared/models/tables/score.py" line="31"/>
|
||||
<source>horizontalHeader.potential</source>
|
||||
<translation>Potential</translation>
|
||||
</message>
|
||||
@ -303,6 +307,14 @@ validation</translation>
|
||||
<translation>Score</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PotentialCalculator</name>
|
||||
<message>
|
||||
<location filename="../../implements/components/playRatingCalculator.py" line="85"/>
|
||||
<source>copyButton</source>
|
||||
<translation>Copy</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>ResettableItem</name>
|
||||
<message>
|
||||
@ -542,18 +554,26 @@ validation</translation>
|
||||
<translation>Search...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/components/songIdSelector.ui" line="54"/>
|
||||
<location filename="../../designer/components/songIdSelector.ui" line="94"/>
|
||||
<location filename="../../designer/components/songIdSelector.ui" line="41"/>
|
||||
<location filename="../../designer/components/songIdSelector.ui" line="81"/>
|
||||
<source>previous</source>
|
||||
<translation>Previous</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/components/songIdSelector.ui" line="77"/>
|
||||
<location filename="../../designer/components/songIdSelector.ui" line="117"/>
|
||||
<location filename="../../designer/components/songIdSelector.ui" line="64"/>
|
||||
<location filename="../../designer/components/songIdSelector.ui" line="104"/>
|
||||
<source>next</source>
|
||||
<translation>Next</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>StepCalculator</name>
|
||||
<message>
|
||||
<location filename="../../implements/tabs/tabTools/tabTools_StepCalculator.py" line="96"/>
|
||||
<source>playRatingCalculatorDialog.acceptButton</source>
|
||||
<translation>Accept</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>TabAbout</name>
|
||||
<message>
|
||||
@ -574,6 +594,16 @@ validation</translation>
|
||||
<source>tab.manage</source>
|
||||
<translation>Manage</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDbEntry.ui" line="29"/>
|
||||
<source>tab.chartInfoEditor</source>
|
||||
<translation>Chart Info Editor</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDbEntry.ui" line="34"/>
|
||||
<source>tab.removeDuplicateScores</source>
|
||||
<translation>Remove Duplicate Scores</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../implements/tabs/tabDbEntry.py" line="20"/>
|
||||
<source>tab.scoreTableViewer</source>
|
||||
@ -585,78 +615,290 @@ validation</translation>
|
||||
<translation>Table [B30]</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>TabDb_ChartInfoEditor</name>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_ChartInfoEditor.ui" line="20"/>
|
||||
<source>editor.title</source>
|
||||
<translation>Editor</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_ChartInfoEditor.ui" line="32"/>
|
||||
<source>editor.constant</source>
|
||||
<translation>Constant</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_ChartInfoEditor.ui" line="39"/>
|
||||
<source>editor.notes</source>
|
||||
<translation>Notes</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_ChartInfoEditor.ui" line="168"/>
|
||||
<source>editor.tip</source>
|
||||
<translation>Tip</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_ChartInfoEditor.ui" line="175"/>
|
||||
<source>editor.tip.content</source>
|
||||
<translation>Due to the special data structure,<br>please fill in 10 times of the constant value.<br>For example, Testify [BYD] is a 12.0,<br>then fill "120" instead of "12.0".</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_ChartInfoEditor.ui" line="213"/>
|
||||
<source>editor.delete</source>
|
||||
<translation>Delete</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_ChartInfoEditor.ui" line="220"/>
|
||||
<source>editor.commit</source>
|
||||
<translation>Commit</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../implements/tabs/tabDb/tabDb_ChartInfoEditor.py" line="167"/>
|
||||
<location filename="../../implements/tabs/tabDb/tabDb_ChartInfoEditor.py" line="206"/>
|
||||
<source>commit.chartNotSelected</source>
|
||||
<translation>Please select a chart first.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../implements/tabs/tabDb/tabDb_ChartInfoEditor.py" line="176"/>
|
||||
<source>commit.constantRequired</source>
|
||||
<translation>Constant field is required.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../implements/tabs/tabDb/tabDb_ChartInfoEditor.py" line="217"/>
|
||||
<source>deleteConfirm</source>
|
||||
<translation>Are you sure to delete this chart data?</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>TabDb_Manage</name>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="23"/>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="78"/>
|
||||
<source>syncArcSongDbButton</source>
|
||||
<translation>Sync arcsong.db</translation>
|
||||
</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>
|
||||
<translation>Update chart info</translation>
|
||||
</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>
|
||||
<translation>Import Score Database</translation>
|
||||
<translation>Game Save Database</translation>
|
||||
</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>
|
||||
<translation>Import your local score database</translation>
|
||||
<translation>Import scores from your game save database</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="58"/>
|
||||
<source>exportScoresButton</source>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="139"/>
|
||||
<source>exportScoreGroup</source>
|
||||
<translation>Export Scores</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="65"/>
|
||||
<source>exportScores.description</source>
|
||||
<translation>Export all your scores to a JSON file</translation>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="146"/>
|
||||
<source>exportScoresButton</source>
|
||||
<translation>D.E.F. V2</translation>
|
||||
</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 <i>Arcaea Offline Data Exchange Format V2</i> 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>
|
||||
<translation>Import packlist</translation>
|
||||
</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>
|
||||
<translation>Import songlist</translation>
|
||||
</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>
|
||||
<translation>Import packlist file</translation>
|
||||
</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>
|
||||
<translation>Import songlist file</translation>
|
||||
</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>
|
||||
<translation>Export arcsong.json</translation>
|
||||
</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>
|
||||
<translation>Export arcsong.json file</translation>
|
||||
<translation>Export arcsong.json file based on the information in database</translation>
|
||||
</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>
|
||||
<translation>Import APK</translation>
|
||||
<translation>Import from APK</translation>
|
||||
</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>
|
||||
<translation>Import packlist and songlist from .apk file</translation>
|
||||
</message>
|
||||
<message>
|
||||
<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>
|
||||
<translation>Arcaea Online</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="126"/>
|
||||
<source>importOnline.description</source>
|
||||
<translation>Import scores from the Arcaea Online API result</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="160"/>
|
||||
<source>exportSmartRteB30Button</source>
|
||||
<translation>SmartRTE B30</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="167"/>
|
||||
<source>exportSmartRteB30.description</source>
|
||||
<translation>Export all your scores to <a href="https://smartrte.github.io/b30gen.html">smartrte.github.io</a> compatible CSV file</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>TabDb_RemoveDuplicateScores</name>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="20"/>
|
||||
<source>scan.title</source>
|
||||
<translation>Scan Options</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="30"/>
|
||||
<source>scan.option.score</source>
|
||||
<translation>Score</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="71"/>
|
||||
<source>scan.option.date</source>
|
||||
<translation>Date</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="78"/>
|
||||
<source>scan.option.modifier</source>
|
||||
<translation>Modifier</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="85"/>
|
||||
<source>scan.option.clearType</source>
|
||||
<translation>Clear Type</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="94"/>
|
||||
<source>scan.scanButton</source>
|
||||
<translation>Scan</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="124"/>
|
||||
<source>quickSelect.title</source>
|
||||
<translation>Quick Select</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="130"/>
|
||||
<source>quickSelect.description</source>
|
||||
<translation>Keep the first score item<br>that matches:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="166"/>
|
||||
<source>quickSelect.selectButton</source>
|
||||
<translation>Select</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="182"/>
|
||||
<source>deselectAllButton</source>
|
||||
<translation>Clear Selection</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="189"/>
|
||||
<source>reverseSelectionButton</source>
|
||||
<translation>Reverse Selection</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="209"/>
|
||||
<source>collapseAllButton</source>
|
||||
<translation>Collapse All Groups</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="216"/>
|
||||
<source>expandAllButton</source>
|
||||
<translation>Expand All Groups</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="223"/>
|
||||
<source>resetModelButton</source>
|
||||
<translation>Reset Model</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="251"/>
|
||||
<source>deleteSelectionButton</source>
|
||||
<translation>Delete Selected Scores</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="158"/>
|
||||
<source>quickSelectComboBox.idEarlier</source>
|
||||
<translation>Earlier ID</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="164"/>
|
||||
<source>quickSelectComboBox.dateEarlier</source>
|
||||
<translation>Earlier date</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="170"/>
|
||||
<source>quickSelectComboBox.columnsIntegral</source>
|
||||
<translation>More complete data</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="295"/>
|
||||
<source>deleteSelectionDialog.content {}</source>
|
||||
<translation>Deleting {} scores from database, this cannot be undone!<br>Confirm?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="317"/>
|
||||
<source>scan_noColumnsDialog.content</source>
|
||||
<translation>You haven't selected any column! Are you sure to continue?</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>TabOcrDisabled</name>
|
||||
@ -783,28 +1025,28 @@ validation</translation>
|
||||
<translation>Rois</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="128"/>
|
||||
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="134"/>
|
||||
<source>options.masker</source>
|
||||
<translation>Masker</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="138"/>
|
||||
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="145"/>
|
||||
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="144"/>
|
||||
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="151"/>
|
||||
<source>options.useCustom</source>
|
||||
<translation>Use custom options</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="203"/>
|
||||
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="215"/>
|
||||
<source>dependencies.title</source>
|
||||
<translation>OCR Dependencies</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="209"/>
|
||||
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="221"/>
|
||||
<source>dependencies.knnModel</source>
|
||||
<translation>KNearest model</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="246"/>
|
||||
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="258"/>
|
||||
<source>dependencies.phashDatabase</source>
|
||||
<translation>Image pHash database</translation>
|
||||
</message>
|
||||
@ -812,7 +1054,7 @@ validation</translation>
|
||||
<context>
|
||||
<name>TabOverview</name>
|
||||
<message>
|
||||
<location filename="../../implements/tabs/tabOverview.py" line="43"/>
|
||||
<location filename="../../implements/tabs/tabOverview.py" line="56"/>
|
||||
<source>databaseDescribeLabel {} {} {} {} {} {}</source>
|
||||
<translation>There are {} packs, {} songs, {} difficulties, {} chart info ({} complete) and {} scores in database.</translation>
|
||||
</message>
|
||||
@ -902,6 +1144,11 @@ validation</translation>
|
||||
<source>generateImageButton</source>
|
||||
<translation>Generate</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabTools/tabTools_Andreal.ui" line="335"/>
|
||||
<source>sourceCode</source>
|
||||
<translation>Source code</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../implements/tabs/tabTools/tabTools_Andreal.py" line="138"/>
|
||||
<source>imageWhatIsThisDialog.description</source>
|
||||
@ -911,23 +1158,17 @@ validation</translation>
|
||||
<context>
|
||||
<name>TabTools_ChartRecommend</name>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabTools/tabTools_ChartRecommend.ui" line="20"/>
|
||||
<location filename="../../designer/tabs/tabTools/tabTools_ChartRecommend.ui" line="102"/>
|
||||
<source>constantRangeFromPlayRating</source>
|
||||
<translation>Chart Constant Range from Play Rating</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabTools/tabTools_ChartRecommend.ui" line="118"/>
|
||||
<location filename="../../designer/tabs/tabTools/tabTools_ChartRecommend.ui" line="20"/>
|
||||
<source>chartsByConstant</source>
|
||||
<translation>Charts by Constant</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabTools/tabTools_ChartRecommend.ui" line="174"/>
|
||||
<location filename="../../designer/tabs/tabTools/tabTools_ChartRecommend.ui" line="273"/>
|
||||
<source>refreshButton</source>
|
||||
<translation>Roll</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabTools/tabTools_ChartRecommend.ui" line="197"/>
|
||||
<location filename="../../designer/tabs/tabTools/tabTools_ChartRecommend.ui" line="248"/>
|
||||
<source>chartsRecommendFromPlayRating</source>
|
||||
<translation>Chart from Play Rating Based on Best Score</translation>
|
||||
</message>
|
||||
|
@ -1,5 +1,5 @@
|
||||
import argparse
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
@ -32,23 +32,31 @@ assert startup.exists()
|
||||
no_obsolete = args.no_obsolete
|
||||
|
||||
commands = [
|
||||
(
|
||||
"pyside6-lupdate"
|
||||
" -extensions py,ui"
|
||||
f" {designer.absolute()} {extends.absolute()} {implements.absolute()} {startup.absolute()}"
|
||||
f" -ts {str((output_dir_path / 'zh_CN.ts').absolute())}"
|
||||
), # zh_CN
|
||||
(
|
||||
"pyside6-lupdate"
|
||||
" -extensions py,ui"
|
||||
f" {designer.absolute()} {extends.absolute()} {implements.absolute()} {startup.absolute()}"
|
||||
f" -ts {str((output_dir_path / 'en_US.ts').absolute())}"
|
||||
), # en_US
|
||||
[
|
||||
"pyside6-lupdate",
|
||||
"-extensions",
|
||||
"py,ui",
|
||||
str(designer.absolute()),
|
||||
str(extends.absolute()),
|
||||
str(implements.absolute()),
|
||||
str(startup.absolute()),
|
||||
"-ts",
|
||||
str((output_dir_path / "zh_CN.ts").absolute()),
|
||||
], # zh_CN
|
||||
[
|
||||
"pyside6-lupdate",
|
||||
"-extensions",
|
||||
"py,ui",
|
||||
str(designer.absolute()),
|
||||
str(extends.absolute()),
|
||||
str(implements.absolute()),
|
||||
str(startup.absolute()),
|
||||
"-ts",
|
||||
str((output_dir_path / "en_US.ts").absolute()),
|
||||
], # en_US
|
||||
]
|
||||
if no_obsolete:
|
||||
commands = [f"{command} -no-obsolete" for command in commands]
|
||||
commands = [command + ["-no-obsolete"] for command in commands]
|
||||
|
||||
for command in commands:
|
||||
print(f"Executing '{command}'")
|
||||
output = os.popen(command).read()
|
||||
print(output)
|
||||
subprocess.run(command)
|
||||
|
@ -17,74 +17,55 @@
|
||||
<context>
|
||||
<name>ChartSelector</name>
|
||||
<message>
|
||||
<location filename="../../designer/components/chartSelector.ui" line="26"/>
|
||||
<location filename="../../designer/components/chartSelector.ui" line="20"/>
|
||||
<source>songIdSelector.title</source>
|
||||
<translation>选择一首歌曲</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/components/chartSelector.ui" line="71"/>
|
||||
<location filename="../../designer/components/chartSelector.ui" line="65"/>
|
||||
<source>resetButton</source>
|
||||
<translation>重置</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>DB30TableModel</name>
|
||||
<message>
|
||||
<location filename="../../extends/shared/models/tables/b30.py" line="21"/>
|
||||
<source>horizontalHeader.id</source>
|
||||
<translation>ID</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../extends/shared/models/tables/b30.py" line="22"/>
|
||||
<source>horizontalHeader.chart</source>
|
||||
<translation>谱面</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../extends/shared/models/tables/b30.py" line="23"/>
|
||||
<source>horizontalHeader.score</source>
|
||||
<translation>分数</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../extends/shared/models/tables/b30.py" line="24"/>
|
||||
<source>horizontalHeader.potential</source>
|
||||
<translation>单曲 PTT</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>DatabaseChecker</name>
|
||||
<message>
|
||||
<location filename="../../startup/databaseChecker.ui" line="23"/>
|
||||
<location filename="../../startup/databaseChecker_ui.py" line="162"/>
|
||||
<source>dbPathLabel</source>
|
||||
<translation>数据库路径</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../startup/databaseChecker.ui" line="33"/>
|
||||
<location filename="../../startup/databaseChecker_ui.py" line="165"/>
|
||||
<source>dbFilenameLabel</source>
|
||||
<translation>数据库文件名</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../startup/databaseChecker.ui" line="64"/>
|
||||
<location filename="../../startup/databaseChecker_ui.py" line="168"/>
|
||||
<source>confirmDbPathButton</source>
|
||||
<translation>确认</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../startup/databaseChecker.ui" line="117"/>
|
||||
<location filename="../../startup/databaseChecker_ui.py" line="177"/>
|
||||
<source>dbVersionLabel</source>
|
||||
<translation>数据库版本</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../startup/databaseChecker.ui" line="131"/>
|
||||
<source>dbReInitLabel</source>
|
||||
<translation>重新初始化数据库</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../startup/databaseChecker.ui" line="138"/>
|
||||
<source>dbReInitButton</source>
|
||||
<translation>重新初始化</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../startup/databaseChecker.ui" line="93"/>
|
||||
<location filename="../../startup/databaseChecker_ui.py" line="171"/>
|
||||
<source>dbCheckConnLabel</source>
|
||||
<translation>数据库连接</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../startup/databaseChecker.ui" line="110"/>
|
||||
<location filename="../../startup/databaseChecker_ui.py" line="174"/>
|
||||
<source>continueButton</source>
|
||||
<translation>继续</translation>
|
||||
</message>
|
||||
@ -100,24 +81,47 @@
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>DbScoreTableModel</name>
|
||||
<name>DbB30TableModel</name>
|
||||
<message>
|
||||
<location filename="../../extends/shared/models/tables/score.py" line="22"/>
|
||||
<location filename="../../extends/shared/models/tables/b30.py" line="20"/>
|
||||
<source>horizontalHeader.id</source>
|
||||
<translation>ID</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../extends/shared/models/tables/score.py" line="23"/>
|
||||
<location filename="../../extends/shared/models/tables/b30.py" line="21"/>
|
||||
<source>horizontalHeader.chart</source>
|
||||
<translation>谱面</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../extends/shared/models/tables/score.py" line="24"/>
|
||||
<location filename="../../extends/shared/models/tables/b30.py" line="22"/>
|
||||
<source>horizontalHeader.score</source>
|
||||
<translation>分数</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../extends/shared/models/tables/score.py" line="25"/>
|
||||
<location filename="../../extends/shared/models/tables/b30.py" line="23"/>
|
||||
<source>horizontalHeader.potential</source>
|
||||
<translation>单曲 PTT</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>DbScoreTableModel</name>
|
||||
<message>
|
||||
<location filename="../../extends/shared/models/tables/score.py" line="28"/>
|
||||
<source>horizontalHeader.id</source>
|
||||
<translation>ID</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../extends/shared/models/tables/score.py" line="29"/>
|
||||
<source>horizontalHeader.chart</source>
|
||||
<translation>谱面</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../extends/shared/models/tables/score.py" line="30"/>
|
||||
<source>horizontalHeader.score</source>
|
||||
<translation>分数</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../extends/shared/models/tables/score.py" line="31"/>
|
||||
<source>horizontalHeader.potential</source>
|
||||
<translation>单曲 PTT</translation>
|
||||
</message>
|
||||
@ -302,6 +306,14 @@
|
||||
<translation>分数</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PotentialCalculator</name>
|
||||
<message>
|
||||
<location filename="../../implements/components/playRatingCalculator.py" line="85"/>
|
||||
<source>copyButton</source>
|
||||
<translation>复制</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>ResettableItem</name>
|
||||
<message>
|
||||
@ -541,18 +553,26 @@
|
||||
<translation>搜索……</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/components/songIdSelector.ui" line="54"/>
|
||||
<location filename="../../designer/components/songIdSelector.ui" line="94"/>
|
||||
<location filename="../../designer/components/songIdSelector.ui" line="41"/>
|
||||
<location filename="../../designer/components/songIdSelector.ui" line="81"/>
|
||||
<source>previous</source>
|
||||
<translation>上一个</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/components/songIdSelector.ui" line="77"/>
|
||||
<location filename="../../designer/components/songIdSelector.ui" line="117"/>
|
||||
<location filename="../../designer/components/songIdSelector.ui" line="64"/>
|
||||
<location filename="../../designer/components/songIdSelector.ui" line="104"/>
|
||||
<source>next</source>
|
||||
<translation>下一个</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>StepCalculator</name>
|
||||
<message>
|
||||
<location filename="../../implements/tabs/tabTools/tabTools_StepCalculator.py" line="96"/>
|
||||
<source>playRatingCalculatorDialog.acceptButton</source>
|
||||
<translation>确定</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>TabAbout</name>
|
||||
<message>
|
||||
@ -573,6 +593,16 @@
|
||||
<source>tab.manage</source>
|
||||
<translation>管理</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDbEntry.ui" line="29"/>
|
||||
<source>tab.chartInfoEditor</source>
|
||||
<translation>谱面信息编辑器</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDbEntry.ui" line="34"/>
|
||||
<source>tab.removeDuplicateScores</source>
|
||||
<translation>移除重复分数</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../implements/tabs/tabDbEntry.py" line="20"/>
|
||||
<source>tab.scoreTableViewer</source>
|
||||
@ -584,78 +614,290 @@
|
||||
<translation>表 [B30]</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>TabDb_ChartInfoEditor</name>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_ChartInfoEditor.ui" line="20"/>
|
||||
<source>editor.title</source>
|
||||
<translation>编辑器</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_ChartInfoEditor.ui" line="32"/>
|
||||
<source>editor.constant</source>
|
||||
<translation>定数</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_ChartInfoEditor.ui" line="39"/>
|
||||
<source>editor.notes</source>
|
||||
<translation>note 数</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_ChartInfoEditor.ui" line="168"/>
|
||||
<source>editor.tip</source>
|
||||
<translation>提示</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_ChartInfoEditor.ui" line="175"/>
|
||||
<source>editor.tip.content</source>
|
||||
<translation>由于特殊的数据结构,请在编辑<br>定数时填入原数值的 10 倍。<br>举例:Testify [BYD] 的定数是 12.0,<br>则填入 120,而非 12.0。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_ChartInfoEditor.ui" line="213"/>
|
||||
<source>editor.delete</source>
|
||||
<translation>删除</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_ChartInfoEditor.ui" line="220"/>
|
||||
<source>editor.commit</source>
|
||||
<translation>提交</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../implements/tabs/tabDb/tabDb_ChartInfoEditor.py" line="167"/>
|
||||
<location filename="../../implements/tabs/tabDb/tabDb_ChartInfoEditor.py" line="206"/>
|
||||
<source>commit.chartNotSelected</source>
|
||||
<translation>请先选择一个谱面</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../implements/tabs/tabDb/tabDb_ChartInfoEditor.py" line="176"/>
|
||||
<source>commit.constantRequired</source>
|
||||
<translation>定数字段为必填项</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../implements/tabs/tabDb/tabDb_ChartInfoEditor.py" line="217"/>
|
||||
<source>deleteConfirm</source>
|
||||
<translation>确定删除该谱面数据吗?</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>TabDb_Manage</name>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="23"/>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="78"/>
|
||||
<source>syncArcSongDbButton</source>
|
||||
<translation>同步 arcsong.db</translation>
|
||||
</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>
|
||||
<translation>更新谱面信息</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="37"/>
|
||||
<source>importSt3Button</source>
|
||||
<translation>导入本地存档数据库</translation>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="98"/>
|
||||
<source>importScoreGroup</source>
|
||||
<translation>导入分数</translation>
|
||||
</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>
|
||||
<translation>遏卡抑五年,天降飞龙,姿容极度美艳。白衣仙女以妙法擒之,与之相恋。<br>来年,恶人携联结万邦之力来袭,仙女龙妃以根源之术,呼唤神通叁式之威,退敌千里,永护宝库安宁。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="58"/>
|
||||
<source>exportScoresButton</source>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="139"/>
|
||||
<source>exportScoreGroup</source>
|
||||
<translation>导出分数</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="65"/>
|
||||
<source>exportScores.description</source>
|
||||
<translation>将所有分数导出为 JSON 文件</translation>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="146"/>
|
||||
<source>exportScoresButton</source>
|
||||
<translation>数据交换格式 V2</translation>
|
||||
</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>将所有分数导出为 <i>Arcaea Offline 数据交换格式 V2</i> 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>
|
||||
<translation>导入 packlist</translation>
|
||||
</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>
|
||||
<translation>导入 songlist</translation>
|
||||
</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>
|
||||
<translation>导入 packlist 文件</translation>
|
||||
</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>
|
||||
<translation>导入 songlist 文件</translation>
|
||||
</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>
|
||||
<translation>导出 arcsong.json</translation>
|
||||
</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>
|
||||
<translation>导出 arcsong.json 文件</translation>
|
||||
<translation>基于数据库信息导出 arcsong.json 文件</translation>
|
||||
</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>
|
||||
<translation>导入 APK</translation>
|
||||
<translation>从 APK 导入</translation>
|
||||
</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>
|
||||
<translation>从 .apk 文件导入 packlist 和 songlist</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="71"/>
|
||||
<source>chartInfoGroup</source>
|
||||
<translation>谱面信息</translation>
|
||||
</message>
|
||||
<message>
|
||||
<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>
|
||||
<translation>从 Arcaea Online 的 API 结果导入分数</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="160"/>
|
||||
<source>exportSmartRteB30Button</source>
|
||||
<translation>SmartRTE B30</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_Manage.ui" line="167"/>
|
||||
<source>exportSmartRteB30.description</source>
|
||||
<translation>将所有分数导出为兼容 <a href="https://smartrte.github.io/b30gen.html">smartrte.github.io</a> 的 CSV 文件</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>TabDb_RemoveDuplicateScores</name>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="20"/>
|
||||
<source>scan.title</source>
|
||||
<translation>扫描选项</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="30"/>
|
||||
<source>scan.option.score</source>
|
||||
<translation>分数</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="71"/>
|
||||
<source>scan.option.date</source>
|
||||
<translation>时间</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="78"/>
|
||||
<source>scan.option.modifier</source>
|
||||
<translation>Modifier</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="85"/>
|
||||
<source>scan.option.clearType</source>
|
||||
<translation>Clear Type</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="94"/>
|
||||
<source>scan.scanButton</source>
|
||||
<translation>扫描</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="124"/>
|
||||
<source>quickSelect.title</source>
|
||||
<translation>快速选择</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="130"/>
|
||||
<source>quickSelect.description</source>
|
||||
<translation>仅保留第一个<br>符合以下条件的分数:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="166"/>
|
||||
<source>quickSelect.selectButton</source>
|
||||
<translation>选择</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="182"/>
|
||||
<source>deselectAllButton</source>
|
||||
<translation>清空选择</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="189"/>
|
||||
<source>reverseSelectionButton</source>
|
||||
<translation>反选</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="209"/>
|
||||
<source>collapseAllButton</source>
|
||||
<translation>折叠所有</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="216"/>
|
||||
<source>expandAllButton</source>
|
||||
<translation>展开所有</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="223"/>
|
||||
<source>resetModelButton</source>
|
||||
<translation>重置模型</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabDb/tabDb_RemoveDuplicateScores.ui" line="251"/>
|
||||
<source>deleteSelectionButton</source>
|
||||
<translation>删除已选分数</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="158"/>
|
||||
<source>quickSelectComboBox.idEarlier</source>
|
||||
<translation>ID 更早</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="164"/>
|
||||
<source>quickSelectComboBox.dateEarlier</source>
|
||||
<translation>时间更早</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="170"/>
|
||||
<source>quickSelectComboBox.columnsIntegral</source>
|
||||
<translation>数据更完整</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="295"/>
|
||||
<source>deleteSelectionDialog.content {}</source>
|
||||
<translation>将从数据库中删除 {} 个分数。此操作无法撤销!<br>确认吗?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../implements/tabs/tabDb/tabDb_RemoveDuplicateScores.py" line="317"/>
|
||||
<source>scan_noColumnsDialog.content</source>
|
||||
<translation>还未选择任何字段!确定继续吗?</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>TabOcrDisabled</name>
|
||||
@ -782,28 +1024,28 @@
|
||||
<translation>定位器</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="128"/>
|
||||
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="134"/>
|
||||
<source>options.masker</source>
|
||||
<translation>遮罩器</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="138"/>
|
||||
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="145"/>
|
||||
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="144"/>
|
||||
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="151"/>
|
||||
<source>options.useCustom</source>
|
||||
<translation>使用自定义设置</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="203"/>
|
||||
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="215"/>
|
||||
<source>dependencies.title</source>
|
||||
<translation>OCR 依赖</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="209"/>
|
||||
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="221"/>
|
||||
<source>dependencies.knnModel</source>
|
||||
<translation>KNearest 模型</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="246"/>
|
||||
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="258"/>
|
||||
<source>dependencies.phashDatabase</source>
|
||||
<translation>图像 pHash 数据库</translation>
|
||||
</message>
|
||||
@ -811,7 +1053,7 @@
|
||||
<context>
|
||||
<name>TabOverview</name>
|
||||
<message>
|
||||
<location filename="../../implements/tabs/tabOverview.py" line="43"/>
|
||||
<location filename="../../implements/tabs/tabOverview.py" line="56"/>
|
||||
<source>databaseDescribeLabel {} {} {} {} {} {}</source>
|
||||
<translation>数据库中有 {} 个曲包,{} 首歌曲,{} 个难度,{} 个谱面信息({} 个完整),{} 个分数记录。</translation>
|
||||
</message>
|
||||
@ -901,6 +1143,11 @@
|
||||
<source>generateImageButton</source>
|
||||
<translation>生成</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabTools/tabTools_Andreal.ui" line="335"/>
|
||||
<source>sourceCode</source>
|
||||
<translation>源代码</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../implements/tabs/tabTools/tabTools_Andreal.py" line="138"/>
|
||||
<source>imageWhatIsThisDialog.description</source>
|
||||
@ -910,23 +1157,17 @@
|
||||
<context>
|
||||
<name>TabTools_ChartRecommend</name>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabTools/tabTools_ChartRecommend.ui" line="20"/>
|
||||
<location filename="../../designer/tabs/tabTools/tabTools_ChartRecommend.ui" line="102"/>
|
||||
<source>constantRangeFromPlayRating</source>
|
||||
<translation>由单曲 PTT 逆算谱面定数范围</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabTools/tabTools_ChartRecommend.ui" line="118"/>
|
||||
<location filename="../../designer/tabs/tabTools/tabTools_ChartRecommend.ui" line="20"/>
|
||||
<source>chartsByConstant</source>
|
||||
<translation>按定数查谱</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabTools/tabTools_ChartRecommend.ui" line="174"/>
|
||||
<location filename="../../designer/tabs/tabTools/tabTools_ChartRecommend.ui" line="273"/>
|
||||
<source>refreshButton</source>
|
||||
<translation>换一批</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../designer/tabs/tabTools/tabTools_ChartRecommend.ui" line="197"/>
|
||||
<location filename="../../designer/tabs/tabTools/tabTools_ChartRecommend.ui" line="248"/>
|
||||
<source>chartsRecommendFromPlayRating</source>
|
||||
<translation>由单曲 PTT 结合最好成绩推荐谱面</translation>
|
||||
</message>
|
||||
|
@ -6,6 +6,8 @@
|
||||
|
||||
<file>partnerModifiers.json</file>
|
||||
|
||||
<file>fonts/GeosansLight.ttf</file>
|
||||
|
||||
<file>images/icon.png</file>
|
||||
<file>images/logo.png</file>
|
||||
<file>images/jacket-placeholder.png</file>
|
||||
|
@ -3,7 +3,7 @@ import traceback
|
||||
from enum import IntEnum
|
||||
|
||||
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 ui.extends.shared.database import create_engine
|
||||
@ -59,8 +59,13 @@ class DatabaseChecker(Ui_DatabaseChecker, QDialog):
|
||||
return QUrl.fromLocalFile(self.dbFileInfo().filePath())
|
||||
|
||||
def dbSqliteUrl(self):
|
||||
# dbSqliteUrl.setScheme("sqlite")
|
||||
return QUrl(self.dbFileUrl().toString().replace("file://", "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://"))
|
||||
else:
|
||||
return QUrl(self.dbFileUrl().toString().replace("file://", "sqlite:///"))
|
||||
|
||||
def confirmDb(self) -> DatabaseCheckerResult:
|
||||
flags = 0x000
|
||||
@ -138,6 +143,11 @@ class DatabaseChecker(Ui_DatabaseChecker, QDialog):
|
||||
db.init()
|
||||
self.updateLabels()
|
||||
|
||||
@Slot()
|
||||
def on_dbReInitButton_clicked(self):
|
||||
Database().init(checkfirst=True)
|
||||
QMessageBox.information(self, None, "OK")
|
||||
|
||||
@Slot()
|
||||
def on_continueButton_clicked(self):
|
||||
self.accept()
|
||||
|
@ -125,6 +125,20 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>dbReInitLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QPushButton" name="dbReInitButton">
|
||||
<property name="text">
|
||||
<string>dbReInitButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
|
@ -8,173 +8,131 @@
|
||||
## 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,
|
||||
Qt,
|
||||
QTime,
|
||||
QUrl,
|
||||
)
|
||||
from PySide6.QtGui import (
|
||||
QBrush,
|
||||
QColor,
|
||||
QConicalGradient,
|
||||
QCursor,
|
||||
QFont,
|
||||
QFontDatabase,
|
||||
QGradient,
|
||||
QIcon,
|
||||
QImage,
|
||||
QKeySequence,
|
||||
QLinearGradient,
|
||||
QPainter,
|
||||
QPalette,
|
||||
QPixmap,
|
||||
QRadialGradient,
|
||||
QTransform,
|
||||
)
|
||||
from PySide6.QtWidgets import (
|
||||
QApplication,
|
||||
QFormLayout,
|
||||
QFrame,
|
||||
QHBoxLayout,
|
||||
QLabel,
|
||||
QLineEdit,
|
||||
QPushButton,
|
||||
QSizePolicy,
|
||||
QSpacerItem,
|
||||
QWidget,
|
||||
)
|
||||
from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
|
||||
QMetaObject, QObject, QPoint, QRect,
|
||||
QSize, QTime, QUrl, Qt)
|
||||
from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
|
||||
QFont, QFontDatabase, QGradient, QIcon,
|
||||
QImage, QKeySequence, QLinearGradient, QPainter,
|
||||
QPalette, QPixmap, QRadialGradient, QTransform)
|
||||
from PySide6.QtWidgets import (QApplication, QFormLayout, QFrame, QHBoxLayout,
|
||||
QLabel, QLineEdit, QPushButton, QSizePolicy,
|
||||
QSpacerItem, QWidget)
|
||||
|
||||
from ui.implements.components.fileSelector import FileSelector
|
||||
|
||||
|
||||
class Ui_DatabaseChecker(object):
|
||||
def setupUi(self, DatabaseChecker):
|
||||
if not DatabaseChecker.objectName():
|
||||
DatabaseChecker.setObjectName("DatabaseChecker")
|
||||
DatabaseChecker.setObjectName(u"DatabaseChecker")
|
||||
DatabaseChecker.resize(350, 250)
|
||||
DatabaseChecker.setWindowTitle("DatabaseChecker")
|
||||
DatabaseChecker.setWindowTitle(u"DatabaseChecker")
|
||||
self.formLayout = QFormLayout(DatabaseChecker)
|
||||
self.formLayout.setObjectName("formLayout")
|
||||
self.formLayout.setLabelAlignment(
|
||||
Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter
|
||||
)
|
||||
self.formLayout.setObjectName(u"formLayout")
|
||||
self.formLayout.setLabelAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
|
||||
self.label = QLabel(DatabaseChecker)
|
||||
self.label.setObjectName("label")
|
||||
self.label.setObjectName(u"label")
|
||||
|
||||
self.formLayout.setWidget(0, QFormLayout.LabelRole, self.label)
|
||||
|
||||
self.dbDirSelector = FileSelector(DatabaseChecker)
|
||||
self.dbDirSelector.setObjectName("dbDirSelector")
|
||||
self.dbDirSelector.setObjectName(u"dbDirSelector")
|
||||
|
||||
self.formLayout.setWidget(0, QFormLayout.FieldRole, self.dbDirSelector)
|
||||
|
||||
self.label_3 = QLabel(DatabaseChecker)
|
||||
self.label_3.setObjectName("label_3")
|
||||
self.label_3.setObjectName(u"label_3")
|
||||
|
||||
self.formLayout.setWidget(1, QFormLayout.LabelRole, self.label_3)
|
||||
|
||||
self.dbFilenameLineEdit = QLineEdit(DatabaseChecker)
|
||||
self.dbFilenameLineEdit.setObjectName("dbFilenameLineEdit")
|
||||
self.dbFilenameLineEdit.setObjectName(u"dbFilenameLineEdit")
|
||||
|
||||
self.formLayout.setWidget(1, QFormLayout.FieldRole, self.dbFilenameLineEdit)
|
||||
|
||||
self.horizontalLayout = QHBoxLayout()
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
self.horizontalSpacer = QSpacerItem(
|
||||
40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum
|
||||
)
|
||||
self.horizontalLayout.setObjectName(u"horizontalLayout")
|
||||
self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
|
||||
|
||||
self.horizontalLayout.addItem(self.horizontalSpacer)
|
||||
|
||||
self.confirmDbPathButton = QPushButton(DatabaseChecker)
|
||||
self.confirmDbPathButton.setObjectName("confirmDbPathButton")
|
||||
self.confirmDbPathButton.setObjectName(u"confirmDbPathButton")
|
||||
sizePolicy = QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(
|
||||
self.confirmDbPathButton.sizePolicy().hasHeightForWidth()
|
||||
)
|
||||
sizePolicy.setHeightForWidth(self.confirmDbPathButton.sizePolicy().hasHeightForWidth())
|
||||
self.confirmDbPathButton.setSizePolicy(sizePolicy)
|
||||
|
||||
self.horizontalLayout.addWidget(self.confirmDbPathButton)
|
||||
|
||||
|
||||
self.formLayout.setLayout(2, QFormLayout.FieldRole, self.horizontalLayout)
|
||||
|
||||
self.dbVersionLabel = QLabel(DatabaseChecker)
|
||||
self.dbVersionLabel.setObjectName("dbVersionLabel")
|
||||
self.dbVersionLabel.setText("-")
|
||||
self.dbVersionLabel.setObjectName(u"dbVersionLabel")
|
||||
self.dbVersionLabel.setText(u"-")
|
||||
|
||||
self.formLayout.setWidget(4, QFormLayout.FieldRole, self.dbVersionLabel)
|
||||
|
||||
self.verticalSpacer = QSpacerItem(
|
||||
20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding
|
||||
)
|
||||
self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
|
||||
|
||||
self.formLayout.setItem(6, QFormLayout.FieldRole, self.verticalSpacer)
|
||||
|
||||
self.label_5 = QLabel(DatabaseChecker)
|
||||
self.label_5.setObjectName("label_5")
|
||||
self.label_5.setObjectName(u"label_5")
|
||||
|
||||
self.formLayout.setWidget(7, QFormLayout.LabelRole, self.label_5)
|
||||
|
||||
self.dbCheckConnLabel = QLabel(DatabaseChecker)
|
||||
self.dbCheckConnLabel.setObjectName("dbCheckConnLabel")
|
||||
self.dbCheckConnLabel.setText("...")
|
||||
self.dbCheckConnLabel.setObjectName(u"dbCheckConnLabel")
|
||||
self.dbCheckConnLabel.setText(u"...")
|
||||
|
||||
self.formLayout.setWidget(7, QFormLayout.FieldRole, self.dbCheckConnLabel)
|
||||
|
||||
self.continueButton = QPushButton(DatabaseChecker)
|
||||
self.continueButton.setObjectName("continueButton")
|
||||
self.continueButton.setObjectName(u"continueButton")
|
||||
self.continueButton.setEnabled(False)
|
||||
|
||||
self.formLayout.setWidget(8, QFormLayout.SpanningRole, self.continueButton)
|
||||
|
||||
self.label_2 = QLabel(DatabaseChecker)
|
||||
self.label_2.setObjectName("label_2")
|
||||
self.label_2.setObjectName(u"label_2")
|
||||
|
||||
self.formLayout.setWidget(4, QFormLayout.LabelRole, self.label_2)
|
||||
|
||||
self.line = QFrame(DatabaseChecker)
|
||||
self.line.setObjectName("line")
|
||||
self.line.setObjectName(u"line")
|
||||
self.line.setFrameShape(QFrame.HLine)
|
||||
self.line.setFrameShadow(QFrame.Sunken)
|
||||
|
||||
self.formLayout.setWidget(3, QFormLayout.SpanningRole, self.line)
|
||||
|
||||
self.label_4 = QLabel(DatabaseChecker)
|
||||
self.label_4.setObjectName(u"label_4")
|
||||
|
||||
self.formLayout.setWidget(5, QFormLayout.LabelRole, self.label_4)
|
||||
|
||||
self.dbReInitButton = QPushButton(DatabaseChecker)
|
||||
self.dbReInitButton.setObjectName(u"dbReInitButton")
|
||||
|
||||
self.formLayout.setWidget(5, QFormLayout.FieldRole, self.dbReInitButton)
|
||||
|
||||
|
||||
self.retranslateUi(DatabaseChecker)
|
||||
|
||||
QMetaObject.connectSlotsByName(DatabaseChecker)
|
||||
|
||||
# setupUi
|
||||
|
||||
def retranslateUi(self, DatabaseChecker):
|
||||
self.label.setText(
|
||||
QCoreApplication.translate("DatabaseChecker", "dbPathLabel", None)
|
||||
)
|
||||
self.label_3.setText(
|
||||
QCoreApplication.translate("DatabaseChecker", "dbFilenameLabel", None)
|
||||
)
|
||||
self.confirmDbPathButton.setText(
|
||||
QCoreApplication.translate("DatabaseChecker", "confirmDbPathButton", None)
|
||||
)
|
||||
self.label_5.setText(
|
||||
QCoreApplication.translate("DatabaseChecker", "dbCheckConnLabel", None)
|
||||
)
|
||||
self.continueButton.setText(
|
||||
QCoreApplication.translate("DatabaseChecker", "continueButton", None)
|
||||
)
|
||||
self.label_2.setText(
|
||||
QCoreApplication.translate("DatabaseChecker", "dbVersionLabel", None)
|
||||
)
|
||||
self.label.setText(QCoreApplication.translate("DatabaseChecker", u"dbPathLabel", None))
|
||||
self.label_3.setText(QCoreApplication.translate("DatabaseChecker", u"dbFilenameLabel", None))
|
||||
self.confirmDbPathButton.setText(QCoreApplication.translate("DatabaseChecker", u"confirmDbPathButton", None))
|
||||
self.label_5.setText(QCoreApplication.translate("DatabaseChecker", u"dbCheckConnLabel", None))
|
||||
self.continueButton.setText(QCoreApplication.translate("DatabaseChecker", u"continueButton", None))
|
||||
self.label_2.setText(QCoreApplication.translate("DatabaseChecker", u"dbVersionLabel", None))
|
||||
self.label_4.setText(QCoreApplication.translate("DatabaseChecker", u"dbReInitLabel", None))
|
||||
self.dbReInitButton.setText(QCoreApplication.translate("DatabaseChecker", u"dbReInitButton", None))
|
||||
pass
|
||||
|
||||
# retranslateUi
|
||||
|
||||
|
Reference in New Issue
Block a user