13 Commits

Author SHA1 Message Date
0c6f4f4961 chore: v0.3.9 2024-06-20 00:04:46 +08:00
10fb98d530 chore: upgrade dependencies 2024-06-20 00:03:19 +08:00
bf034d1397 ci: update build actions
* Switch to official Nuitka GitHub Actions

* Adding Linux build support

* Upgrade deprecated actions
2024-06-20 00:00:28 +08:00
4f864611ee fix: B30 table order (#11) 2024-06-19 22:20:31 +08:00
d9c163431c feat: OCR score date source (#9)
* New settings entries

* Choose `birthTime`/`lastModified` for OCR score date source if the image EXIF fails
2024-06-19 22:18:25 +08:00
d5895fe230 chore: v0.3.8 2024-04-01 01:00:46 +08:00
cd2e3f51ca ci: update build actions 2024-04-01 01:00:27 +08:00
4a09dc210a Merge pull request #7 from ArcaeaOffline/fix-issue-6
fix: rating class selection logic
2024-03-24 16:40:24 +08:00
cc8ab11b78 fix: rating class selection logic 2024-03-24 16:17:48 +08:00
48c5682e55 Merge pull request #5 from ArcaeaOffline/fix-issue-4
fix: linux dbUrl issue
2024-03-23 19:08:23 +08:00
ee03770764 chore: update README 2024-03-23 18:21:48 +08:00
b45c7f7de5 chore: dependencies 2024-03-23 18:18:53 +08:00
15bc56e6f9 fix: linux dbUrl issue 2024-03-23 17:41:36 +08:00
19 changed files with 635 additions and 198 deletions

View File

@ -1,37 +1,65 @@
name: Build UI from latest `arcaea-offline-*` dependencies name: Build Executable from latest `arcaea-offline-*` dependencies
run-name: ${{ github.actor }} started a build request. run-name: ${{ github.actor }} started a build request.
on: [workflow_dispatch]
on:
workflow_dispatch:
permissions:
contents: write
discussions: write
jobs: jobs:
build-windows: build:
runs-on: windows-2022 strategy:
matrix:
os: [ubuntu-latest, windows-latest]
fail-fast: false
runs-on: ${{ matrix.os }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-python@v4
- uses: actions/setup-python@v5
with: with:
python-version: '3.11' python-version: "3.11"
cache: "pip"
# install dependencies # install dependencies
- run: 'pip install -r requirements.txt' - run: "pip install -r requirements.txt"
- run: 'pip uninstall arcaea-offline arcaea-offline-ocr -y' - 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"
- run: 'pip install git+https://github.com/283375/arcaea-offline-ocr' - run: "pip install git+https://github.com/283375/arcaea-offline-ocr"
- run: 'pip install nuitka imageio' - run: "pip install imageio"
- name: Install UPX - name: Install UPX
uses: crazy-max/ghaction-upx@v3 uses: crazy-max/ghaction-upx@v3
with: with:
install-only: true install-only: true
# release builtin files - name: Release builtin files
- run: 'pyside6-lrelease.exe .\ui\resources\lang\en_US.ts .\ui\resources\lang\zh_CN.ts' run: |
- run: 'python prebuild.py' pyside6-lrelease ui/resources/lang/en_US.ts ui/resources/lang/zh_CN.ts
- run: 'pyside6-rcc.exe .\ui\resources\resources.qrc -o .\ui\resources\resources_rc.py' python prebuild.py
pyside6-rcc ui/resources/resources.qrc -o ui/resources/resources_rc.py
# build - name: Build Executable
- 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: Nuitka/Nuitka-Action@main
- uses: actions/upload-artifact@v3
with: with:
name: build-windows nuitka-version: main
path: index.exe script-name: index.py
standalone: true
onefile: true
enable-plugins: pyside6,upx
windows-icon-from-ico: ui/resources/images/icon.png
linux-icon: ui/resources/images/icon.png
- name: Upload Artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ runner.os }} Build
path: |
build/*.exe
build/*.bin
build/*.app/**/*

View File

@ -1,35 +1,78 @@
name: Build UI name: Build Executable
run-name: ${{ github.actor }} started a build request. run-name: ${{ github.actor }} started a build request.
on: [workflow_dispatch]
on:
workflow_dispatch:
push:
tags:
- "v[0-9]+.[0-9]+.[0-9]+"
permissions:
contents: write
discussions: write
jobs: jobs:
build-windows: build:
runs-on: windows-2022 strategy:
matrix:
os: [ubuntu-latest, windows-latest]
fail-fast: false
runs-on: ${{ matrix.os }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-python@v4
with:
python-version: '3.11'
cache: 'pip'
# install dependencies - uses: actions/setup-python@v5
- run: 'pip install -r requirements.txt' with:
- run: 'pip install nuitka imageio' python-version: "3.11"
cache: "pip"
- name: Install dependencies
run: |
pip install -r requirements.txt
pip install imageio
- name: Install UPX - name: Install UPX
uses: crazy-max/ghaction-upx@v3 uses: crazy-max/ghaction-upx@v3
with: with:
install-only: true install-only: true
# release builtin files - name: Release builtin files
- run: 'pyside6-lrelease.exe .\ui\resources\lang\en_US.ts .\ui\resources\lang\zh_CN.ts' run: |
- run: 'python prebuild.py' pyside6-lrelease ui/resources/lang/en_US.ts ui/resources/lang/zh_CN.ts
- run: 'pyside6-rcc.exe .\ui\resources\resources.qrc -o .\ui\resources\resources_rc.py' python prebuild.py
pyside6-rcc ui/resources/resources.qrc -o ui/resources/resources_rc.py
# build - name: Build Executable
- 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: Nuitka/Nuitka-Action@main
- uses: actions/upload-artifact@v3
with: with:
name: build-windows nuitka-version: main
path: index.exe script-name: index.py
standalone: true
onefile: true
enable-plugins: pyside6,upx
windows-icon-from-ico: ui/resources/images/icon.png
linux-icon: ui/resources/images/icon.png
- name: Upload Artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ runner.os }} Build
path: |
build/*.exe
build/*.bin
build/*.app/**/*
- name: Draft a release
uses: softprops/action-gh-release@v2
with:
discussion_category_name: New releases
draft: true
generate_release_notes: true
files: |
build/*.exe
build/*.bin
build/*.app/**/*

View File

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

View File

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

View File

@ -1,4 +1,5 @@
arcaea-offline==0.2.1 arcaea-offline==0.2.2
arcaea-offline-ocr==0.0.97 arcaea-offline-ocr==0.0.99
exif==1.6.0 exif==1.6.0
Pillow==10.1.0
PySide6==6.5.2 PySide6==6.5.2

View File

@ -22,39 +22,6 @@
<string>queue.title</string> <string>queue.title</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>iccOptionsGroupBox</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QRadioButton" name="iccUseQtRadioButton">
<property name="text">
<string>icc.useQt</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="iccUsePILRadioButton">
<property name="text">
<string>icc.usePIL</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="iccTryFixRadioButton">
<property name="text">
<string>icc.tryFix</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item> <item>
<widget class="QPushButton" name="ocr_addImageButton"> <widget class="QPushButton" name="ocr_addImageButton">
<property name="text"> <property name="text">
@ -95,6 +62,13 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item>
<widget class="QPushButton" name="optionsDialogButton">
<property name="text">
<string>queue.optionsButton</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QPushButton" name="ocr_startButton"> <widget class="QPushButton" name="ocr_startButton">
<property name="text"> <property name="text">

View File

@ -0,0 +1,140 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>OcrQueueOptionsDialog</class>
<widget class="QDialog" name="OcrQueueOptionsDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>331</width>
<height>157</height>
</rect>
</property>
<property name="windowTitle">
<string>OCR Options</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>iccOptionsGroupBox</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QRadioButton" name="iccUseQtRadioButton">
<property name="text">
<string>icc.useQt</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="iccUsePILRadioButton">
<property name="text">
<string>icc.usePIL</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="iccTryFixRadioButton">
<property name="text">
<string>icc.tryFix</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>dateOptionsGroupBox</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QCheckBox" name="dateReadFromExifCheckbox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>date.readFromExif</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="dateUseCreationDateRadioButton">
<property name="text">
<string>date.useCreationDate</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="dateUseModifyDateRadioButton">
<property name="text">
<string>date.useModifyDate</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>OcrQueueOptionsDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>OcrQueueOptionsDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -0,0 +1,107 @@
# -*- coding: utf-8 -*-
################################################################################
## Form generated from reading UI file 'ocrQueueOptionsDialog.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 (QAbstractButton, QApplication, QCheckBox, QDialog,
QDialogButtonBox, QGroupBox, QHBoxLayout, QRadioButton,
QSizePolicy, QVBoxLayout, QWidget)
class Ui_OcrQueueOptionsDialog(object):
def setupUi(self, OcrQueueOptionsDialog):
if not OcrQueueOptionsDialog.objectName():
OcrQueueOptionsDialog.setObjectName(u"OcrQueueOptionsDialog")
OcrQueueOptionsDialog.resize(331, 157)
self.verticalLayout = QVBoxLayout(OcrQueueOptionsDialog)
self.verticalLayout.setObjectName(u"verticalLayout")
self.horizontalLayout = QHBoxLayout()
self.horizontalLayout.setObjectName(u"horizontalLayout")
self.groupBox = QGroupBox(OcrQueueOptionsDialog)
self.groupBox.setObjectName(u"groupBox")
self.verticalLayout_2 = QVBoxLayout(self.groupBox)
self.verticalLayout_2.setObjectName(u"verticalLayout_2")
self.iccUseQtRadioButton = QRadioButton(self.groupBox)
self.iccUseQtRadioButton.setObjectName(u"iccUseQtRadioButton")
self.verticalLayout_2.addWidget(self.iccUseQtRadioButton)
self.iccUsePILRadioButton = QRadioButton(self.groupBox)
self.iccUsePILRadioButton.setObjectName(u"iccUsePILRadioButton")
self.iccUsePILRadioButton.setChecked(True)
self.verticalLayout_2.addWidget(self.iccUsePILRadioButton)
self.iccTryFixRadioButton = QRadioButton(self.groupBox)
self.iccTryFixRadioButton.setObjectName(u"iccTryFixRadioButton")
self.verticalLayout_2.addWidget(self.iccTryFixRadioButton)
self.horizontalLayout.addWidget(self.groupBox)
self.groupBox_2 = QGroupBox(OcrQueueOptionsDialog)
self.groupBox_2.setObjectName(u"groupBox_2")
self.verticalLayout_3 = QVBoxLayout(self.groupBox_2)
self.verticalLayout_3.setObjectName(u"verticalLayout_3")
self.dateReadFromExifCheckbox = QCheckBox(self.groupBox_2)
self.dateReadFromExifCheckbox.setObjectName(u"dateReadFromExifCheckbox")
self.dateReadFromExifCheckbox.setEnabled(False)
self.dateReadFromExifCheckbox.setChecked(True)
self.verticalLayout_3.addWidget(self.dateReadFromExifCheckbox)
self.dateUseCreationDateRadioButton = QRadioButton(self.groupBox_2)
self.dateUseCreationDateRadioButton.setObjectName(u"dateUseCreationDateRadioButton")
self.dateUseCreationDateRadioButton.setChecked(True)
self.verticalLayout_3.addWidget(self.dateUseCreationDateRadioButton)
self.dateUseModifyDateRadioButton = QRadioButton(self.groupBox_2)
self.dateUseModifyDateRadioButton.setObjectName(u"dateUseModifyDateRadioButton")
self.verticalLayout_3.addWidget(self.dateUseModifyDateRadioButton)
self.horizontalLayout.addWidget(self.groupBox_2)
self.verticalLayout.addLayout(self.horizontalLayout)
self.buttonBox = QDialogButtonBox(OcrQueueOptionsDialog)
self.buttonBox.setObjectName(u"buttonBox")
self.buttonBox.setOrientation(Qt.Horizontal)
self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel|QDialogButtonBox.Ok)
self.verticalLayout.addWidget(self.buttonBox)
self.retranslateUi(OcrQueueOptionsDialog)
self.buttonBox.accepted.connect(OcrQueueOptionsDialog.accept)
self.buttonBox.rejected.connect(OcrQueueOptionsDialog.reject)
QMetaObject.connectSlotsByName(OcrQueueOptionsDialog)
# setupUi
def retranslateUi(self, OcrQueueOptionsDialog):
OcrQueueOptionsDialog.setWindowTitle(QCoreApplication.translate("OcrQueueOptionsDialog", u"OCR Options", None))
self.groupBox.setTitle(QCoreApplication.translate("OcrQueueOptionsDialog", u"iccOptionsGroupBox", None))
self.iccUseQtRadioButton.setText(QCoreApplication.translate("OcrQueueOptionsDialog", u"icc.useQt", None))
self.iccUsePILRadioButton.setText(QCoreApplication.translate("OcrQueueOptionsDialog", u"icc.usePIL", None))
self.iccTryFixRadioButton.setText(QCoreApplication.translate("OcrQueueOptionsDialog", u"icc.tryFix", None))
self.groupBox_2.setTitle(QCoreApplication.translate("OcrQueueOptionsDialog", u"dateOptionsGroupBox", None))
self.dateReadFromExifCheckbox.setText(QCoreApplication.translate("OcrQueueOptionsDialog", u"date.readFromExif", None))
self.dateUseCreationDateRadioButton.setText(QCoreApplication.translate("OcrQueueOptionsDialog", u"date.useCreationDate", None))
self.dateUseModifyDateRadioButton.setText(QCoreApplication.translate("OcrQueueOptionsDialog", u"date.useModifyDate", None))
# retranslateUi

View File

@ -17,8 +17,8 @@ from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
QPalette, QPixmap, QRadialGradient, QTransform) QPalette, QPixmap, QRadialGradient, QTransform)
from PySide6.QtWidgets import (QAbstractItemView, QApplication, QCheckBox, QGroupBox, from PySide6.QtWidgets import (QAbstractItemView, QApplication, QCheckBox, QGroupBox,
QHBoxLayout, QHeaderView, QLabel, QProgressBar, QHBoxLayout, QHeaderView, QLabel, QProgressBar,
QPushButton, QRadioButton, QSizePolicy, QSpacerItem, QPushButton, QSizePolicy, QSpacerItem, QTableView,
QTableView, QVBoxLayout, QWidget) QVBoxLayout, QWidget)
class Ui_OcrQueue(object): class Ui_OcrQueue(object):
def setupUi(self, OcrQueue): def setupUi(self, OcrQueue):
@ -34,29 +34,6 @@ class Ui_OcrQueue(object):
self.groupBox_3.setObjectName(u"groupBox_3") self.groupBox_3.setObjectName(u"groupBox_3")
self.verticalLayout_2 = QVBoxLayout(self.groupBox_3) self.verticalLayout_2 = QVBoxLayout(self.groupBox_3)
self.verticalLayout_2.setObjectName(u"verticalLayout_2") self.verticalLayout_2.setObjectName(u"verticalLayout_2")
self.groupBox = QGroupBox(self.groupBox_3)
self.groupBox.setObjectName(u"groupBox")
self.verticalLayout = QVBoxLayout(self.groupBox)
self.verticalLayout.setObjectName(u"verticalLayout")
self.iccUseQtRadioButton = QRadioButton(self.groupBox)
self.iccUseQtRadioButton.setObjectName(u"iccUseQtRadioButton")
self.verticalLayout.addWidget(self.iccUseQtRadioButton)
self.iccUsePILRadioButton = QRadioButton(self.groupBox)
self.iccUsePILRadioButton.setObjectName(u"iccUsePILRadioButton")
self.iccUsePILRadioButton.setChecked(True)
self.verticalLayout.addWidget(self.iccUsePILRadioButton)
self.iccTryFixRadioButton = QRadioButton(self.groupBox)
self.iccTryFixRadioButton.setObjectName(u"iccTryFixRadioButton")
self.verticalLayout.addWidget(self.iccTryFixRadioButton)
self.verticalLayout_2.addWidget(self.groupBox)
self.ocr_addImageButton = QPushButton(self.groupBox_3) self.ocr_addImageButton = QPushButton(self.groupBox_3)
self.ocr_addImageButton.setObjectName(u"ocr_addImageButton") self.ocr_addImageButton.setObjectName(u"ocr_addImageButton")
@ -78,6 +55,11 @@ class Ui_OcrQueue(object):
self.verticalLayout_2.addItem(self.verticalSpacer) self.verticalLayout_2.addItem(self.verticalSpacer)
self.optionsDialogButton = QPushButton(self.groupBox_3)
self.optionsDialogButton.setObjectName(u"optionsDialogButton")
self.verticalLayout_2.addWidget(self.optionsDialogButton)
self.ocr_startButton = QPushButton(self.groupBox_3) self.ocr_startButton = QPushButton(self.groupBox_3)
self.ocr_startButton.setObjectName(u"ocr_startButton") self.ocr_startButton.setObjectName(u"ocr_startButton")
@ -154,13 +136,10 @@ class Ui_OcrQueue(object):
def retranslateUi(self, OcrQueue): def retranslateUi(self, OcrQueue):
self.groupBox_3.setTitle(QCoreApplication.translate("OcrQueue", u"queue.title", None)) self.groupBox_3.setTitle(QCoreApplication.translate("OcrQueue", u"queue.title", None))
self.groupBox.setTitle(QCoreApplication.translate("OcrQueue", u"iccOptionsGroupBox", None))
self.iccUseQtRadioButton.setText(QCoreApplication.translate("OcrQueue", u"icc.useQt", None))
self.iccUsePILRadioButton.setText(QCoreApplication.translate("OcrQueue", u"icc.usePIL", None))
self.iccTryFixRadioButton.setText(QCoreApplication.translate("OcrQueue", u"icc.tryFix", None))
self.ocr_addImageButton.setText(QCoreApplication.translate("OcrQueue", u"queue.addImageButton", None)) self.ocr_addImageButton.setText(QCoreApplication.translate("OcrQueue", u"queue.addImageButton", None))
self.ocr_removeSelectedButton.setText(QCoreApplication.translate("OcrQueue", u"queue.removeSelected", None)) self.ocr_removeSelectedButton.setText(QCoreApplication.translate("OcrQueue", u"queue.removeSelected", None))
self.ocr_removeAllButton.setText(QCoreApplication.translate("OcrQueue", u"queue.removeAll", None)) self.ocr_removeAllButton.setText(QCoreApplication.translate("OcrQueue", u"queue.removeAll", None))
self.optionsDialogButton.setText(QCoreApplication.translate("OcrQueue", u"queue.optionsButton", None))
self.ocr_startButton.setText(QCoreApplication.translate("OcrQueue", u"queue.startOcrButton", None)) self.ocr_startButton.setText(QCoreApplication.translate("OcrQueue", u"queue.startOcrButton", None))
self.groupBox_5.setTitle(QCoreApplication.translate("OcrQueue", u"results", None)) self.groupBox_5.setTitle(QCoreApplication.translate("OcrQueue", u"results", None))
self.ocr_acceptSelectedButton.setText(QCoreApplication.translate("OcrQueue", u"results.acceptSelectedButton", None)) self.ocr_acceptSelectedButton.setText(QCoreApplication.translate("OcrQueue", u"results.acceptSelectedButton", None))
@ -169,4 +148,3 @@ class Ui_OcrQueue(object):
self.statusLabel.setText("") self.statusLabel.setText("")
pass pass
# retranslateUi # retranslateUi

View File

@ -150,6 +150,7 @@ class OcrQueueModel(QAbstractListModel):
@iccOption.setter @iccOption.setter
def iccOption(self, opt: IccOption): def iccOption(self, opt: IccOption):
logger.debug(f"ICC option changed to {opt}")
self.__iccOption = opt self.__iccOption = opt
@overload @overload
@ -344,8 +345,12 @@ class OcrQueueTableProxyModel(QAbstractTableModel):
def retranslateHeaders(self): def retranslateHeaders(self):
self.__horizontalHeaders = [ self.__horizontalHeaders = [
# fmt: off # fmt: off
QCoreApplication.translate("OcrTableModel", "horizontalHeader.title.select"), QCoreApplication.translate(
QCoreApplication.translate("OcrTableModel", "horizontalHeader.title.imagePreview"), "OcrTableModel", "horizontalHeader.title.select"
),
QCoreApplication.translate(
"OcrTableModel", "horizontalHeader.title.imagePreview"
),
QCoreApplication.translate("OcrTableModel", "horizontalHeader.title.chart"), QCoreApplication.translate("OcrTableModel", "horizontalHeader.title.chart"),
QCoreApplication.translate("OcrTableModel", "horizontalHeader.title.score"), QCoreApplication.translate("OcrTableModel", "horizontalHeader.title.score"),
# fmt: on # fmt: on

View File

@ -39,7 +39,7 @@ class DbB30TableModel(DbTableModel):
(ScoreBest.song_id == Chart.song_id) (ScoreBest.song_id == Chart.song_id)
& (ScoreBest.rating_class == Chart.rating_class), & (ScoreBest.rating_class == Chart.rating_class),
) )
.order_by(ScoreBest.potential) .order_by(ScoreBest.potential.desc())
.limit(50) .limit(50)
.all() .all()
) )

View File

@ -10,6 +10,7 @@ __all__ = [
"KNN_MODEL_FILE", "KNN_MODEL_FILE",
"B30_KNN_MODEL_FILE", "B30_KNN_MODEL_FILE",
"PHASH_DATABASE_FILE", "PHASH_DATABASE_FILE",
"SCORE_DATE_SOURCE",
"ANDREAL_FOLDER", "ANDREAL_FOLDER",
"ANDREAL_EXECUTABLE", "ANDREAL_EXECUTABLE",
"Settings", "Settings",
@ -23,6 +24,7 @@ DATABASE_URL = "DatabaseUrl"
KNN_MODEL_FILE = "Ocr/KnnModelFile" KNN_MODEL_FILE = "Ocr/KnnModelFile"
B30_KNN_MODEL_FILE = "Ocr/B30KnnModelFile" B30_KNN_MODEL_FILE = "Ocr/B30KnnModelFile"
PHASH_DATABASE_FILE = "Ocr/PHashDatabaseFile" PHASH_DATABASE_FILE = "Ocr/PHashDatabaseFile"
SCORE_DATE_SOURCE = "Ocr/DateSource"
ANDREAL_FOLDER = "Andreal/AndrealFolder" ANDREAL_FOLDER = "Andreal/AndrealFolder"
ANDREAL_EXECUTABLE = "Andreal/AndrealExecutable" ANDREAL_EXECUTABLE = "Andreal/AndrealExecutable"
@ -92,6 +94,15 @@ class Settings(QSettings, metaclass=QObjectSingleton):
def resetPHashDatabaseFile(self): def resetPHashDatabaseFile(self):
self._resetStrItem(PHASH_DATABASE_FILE) self._resetStrItem(PHASH_DATABASE_FILE)
def scoreDateSource(self):
return self._strItem(SCORE_DATE_SOURCE)
def setScoreDateSource(self, value: str):
self._setStrItem(SCORE_DATE_SOURCE, value)
def resetScoreDateSource(self):
self._resetStrItem(SCORE_DATE_SOURCE)
def andrealFolder(self): def andrealFolder(self):
return self._strItem(ANDREAL_FOLDER) return self._strItem(ANDREAL_FOLDER)

View File

@ -21,6 +21,7 @@ from PySide6.QtCore import QDateTime, QFileInfo
from ui.extends.components.ocrQueue import OcrRunnable from ui.extends.components.ocrQueue import OcrRunnable
from ui.extends.shared.data import Data from ui.extends.shared.data import Data
from ui.extends.shared.settings import Settings
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -67,8 +68,14 @@ def getImageDate(imagePath: str) -> QDateTime:
if exifImage.has_exif and exifImage.get("datetime_original"): if exifImage.has_exif and exifImage.get("datetime_original"):
datetimeStr = exifImage.get("datetime_original") datetimeStr = exifImage.get("datetime_original")
datetime = QDateTime.fromString(datetimeStr, "yyyy:MM:dd hh:mm:ss") datetime = QDateTime.fromString(datetimeStr, "yyyy:MM:dd hh:mm:ss")
if not isinstance(datetime, QDateTime): if not isinstance(datetime, QDateTime):
datetime = QFileInfo(imagePath).birthTime() dateSource = Settings().scoreDateSource()
if dateSource == "lastModified":
datetime = QFileInfo(imagePath).lastModified()
else:
datetime = QFileInfo(imagePath).birthTime()
return datetime return datetime

View File

@ -2,7 +2,7 @@ from typing import Optional
from PySide6.QtCore import Qt, QTimer, Slot from PySide6.QtCore import Qt, QTimer, Slot
from PySide6.QtGui import QColor, QPalette from PySide6.QtGui import QColor, QPalette
from PySide6.QtWidgets import QButtonGroup, QWidget from PySide6.QtWidgets import QWidget
from ui.designer.components.ocrQueue_ui import Ui_OcrQueue from ui.designer.components.ocrQueue_ui import Ui_OcrQueue
from ui.extends.components.ocrQueue import ( from ui.extends.components.ocrQueue import (
@ -13,6 +13,7 @@ from ui.extends.components.ocrQueue import (
OcrScoreDelegate, OcrScoreDelegate,
) )
from ui.extends.shared.language import LanguageChangeEventFilter from ui.extends.shared.language import LanguageChangeEventFilter
from ui.implements.components.ocrQueueOptionsDialog import OcrQueueOptionsDialog
class OcrQueue(Ui_OcrQueue, QWidget): class OcrQueue(Ui_OcrQueue, QWidget):
@ -26,6 +27,9 @@ class OcrQueue(Ui_OcrQueue, QWidget):
self.__model: Optional[OcrQueueModel] = None self.__model: Optional[OcrQueueModel] = None
self.__tableProxyModel: Optional[OcrQueueTableProxyModel] = None self.__tableProxyModel: Optional[OcrQueueTableProxyModel] = None
self.optionsDialog = OcrQueueOptionsDialog(self)
self.optionsDialog.iccOptionsChanged.connect(self.setIccOption)
self.__firstResizeDone = False self.__firstResizeDone = False
self.resizeTimer = QTimer(self) self.resizeTimer = QTimer(self)
self.resizeTimer.timeout.connect(self.tableView.resizeRowsToContents) self.resizeTimer.timeout.connect(self.tableView.resizeRowsToContents)
@ -41,13 +45,6 @@ class OcrQueue(Ui_OcrQueue, QWidget):
tableViewPalette.setColor(QPalette.ColorRole.Highlight, highlightColor) tableViewPalette.setColor(QPalette.ColorRole.Highlight, highlightColor)
self.tableView.setPalette(tableViewPalette) self.tableView.setPalette(tableViewPalette)
self.iccOptionButtonGroup = QButtonGroup(self)
self.iccOptionButtonGroup.buttonToggled.connect(self.updateIccOption)
self.iccOptionButtonGroup.addButton(self.iccUseQtRadioButton, 0)
self.iccOptionButtonGroup.addButton(self.iccUsePILRadioButton, 1)
self.iccOptionButtonGroup.addButton(self.iccTryFixRadioButton, 2)
self.updateIccOption()
self.statusLabelClearTimer = QTimer(self) self.statusLabelClearTimer = QTimer(self)
self.statusLabelClearTimer.setSingleShot(True) self.statusLabelClearTimer.setSingleShot(True)
self.statusLabelClearTimer.timeout.connect(self.clearStatusMessage) self.statusLabelClearTimer.timeout.connect(self.clearStatusMessage)
@ -93,9 +90,10 @@ class OcrQueue(Ui_OcrQueue, QWidget):
self.ocr_acceptAllButton.setEnabled(__bool) self.ocr_acceptAllButton.setEnabled(__bool)
self.ocr_ignoreValidateCheckBox.setEnabled(__bool) self.ocr_ignoreValidateCheckBox.setEnabled(__bool)
def updateIccOption(self): @Slot(int)
def setIccOption(self, option):
if self.model(): if self.model():
self.model().iccOption = self.iccOptionButtonGroup.checkedId() self.model().iccOption = option
def showStatusMessage(self, message: str): def showStatusMessage(self, message: str):
self.statusLabel.setText(message) self.statusLabel.setText(message)
@ -131,6 +129,10 @@ class OcrQueue(Ui_OcrQueue, QWidget):
def modelReseted(self): def modelReseted(self):
self.progressBar.setMaximum(0) self.progressBar.setMaximum(0)
@Slot()
def on_optionsDialogButton_clicked(self):
self.optionsDialog.exec()
@Slot() @Slot()
def on_ocr_removeSelectedButton_clicked(self): def on_ocr_removeSelectedButton_clicked(self):
if self.model(): if self.model():

View File

@ -0,0 +1,48 @@
from PySide6.QtCore import Signal
from PySide6.QtWidgets import QButtonGroup, QDialog
from ui.designer.components.ocrQueueOptionsDialog_ui import Ui_OcrQueueOptionsDialog
from ui.extends.shared.settings import Settings
class OcrQueueOptionsDialog(QDialog, Ui_OcrQueueOptionsDialog):
iccOptionsChanged = Signal(int)
def __init__(self, parent=None):
super(OcrQueueOptionsDialog, self).__init__(parent)
self.setupUi(self)
self.iccOptionButtonGroup = QButtonGroup(self)
self.iccOptionButtonGroup.buttonToggled.connect(
lambda: self.iccOptionsChanged.emit(self.iccOptionButtonGroup.checkedId())
)
self.iccOptionButtonGroup.addButton(self.iccUseQtRadioButton, 0)
self.iccOptionButtonGroup.addButton(self.iccUsePILRadioButton, 1)
self.iccOptionButtonGroup.addButton(self.iccTryFixRadioButton, 2)
self.scoreDateSourceButtonGroup = QButtonGroup(self)
self.scoreDateSourceButtonGroup.addButton(
self.dateUseCreationDateRadioButton, 0
)
self.scoreDateSourceButtonGroup.addButton(self.dateUseModifyDateRadioButton, 1)
self.scoreDateSourceButtonGroup.buttonClicked.connect(
self.on_scoreDateSourceButtonGroup_buttonClicked
)
self.settings = Settings()
self.settings.updated.connect(self.syncCheckboxesFromSettings)
self.syncCheckboxesFromSettings()
def syncCheckboxesFromSettings(self):
scoreDateSource = self.settings.scoreDateSource()
if scoreDateSource == "lastModified":
self.dateUseModifyDateRadioButton.setChecked(True)
else:
self.dateUseCreationDateRadioButton.setChecked(True)
def on_scoreDateSourceButtonGroup_buttonClicked(self, button):
buttonId = self.scoreDateSourceButtonGroup.id(button)
if buttonId == 1:
self.settings.setScoreDateSource("lastModified")
else:
self.settings.setScoreDateSource("birthTime")

View File

@ -1,3 +1,4 @@
import logging
from typing import Type from typing import Type
from PySide6.QtCore import Signal from PySide6.QtCore import Signal
@ -6,6 +7,8 @@ from PySide6.QtWidgets import QHBoxLayout, QSizePolicy, QVBoxLayout, QWidget
from ui.implements.components.ratingClassRadioButton import RatingClassRadioButton from ui.implements.components.ratingClassRadioButton import RatingClassRadioButton
logger = logging.getLogger(__name__)
class RatingClassSelector(QWidget): class RatingClassSelector(QWidget):
valueChanged = Signal() valueChanged = Signal()
@ -120,9 +123,10 @@ class RatingClassSelector(QWidget):
if ratingClass is None or isinstance(ratingClass, bool): if ratingClass is None or isinstance(ratingClass, bool):
button = self.sender() button = self.sender()
elif ratingClass in range(4): elif ratingClass in range(len(self.buttons)):
button = self.buttons[ratingClass] button = self.buttons[ratingClass]
else: else:
logger.debug(f"Cannot select {ratingClass=}, condition check failed")
return return
if not button.isEnabled(): if not button.isEnabled():

View File

@ -70,12 +70,12 @@
<translation>Continue</translation> <translation>Continue</translation>
</message> </message>
<message> <message>
<location filename="../../startup/databaseChecker.py" line="117"/> <location filename="../../startup/databaseChecker.py" line="122"/>
<source>dialog.tryInitExistingDatabase</source> <source>dialog.tryInitExistingDatabase</source>
<translation>The existing database doesn&apos;t seem to be initialized properly, try initialize again?</translation> <translation>The existing database doesn&apos;t seem to be initialized properly, try initialize again?</translation>
</message> </message>
<message> <message>
<location filename="../../startup/databaseChecker.py" line="133"/> <location filename="../../startup/databaseChecker.py" line="138"/>
<source>dialog.confirmNewDatabase</source> <source>dialog.confirmNewDatabase</source>
<translation>Database file does not exist. Create now?</translation> <translation>Database file does not exist. Create now?</translation>
</message> </message>
@ -224,85 +224,118 @@
</message> </message>
<message> <message>
<location filename="../../designer/components/ocrQueue.ui" line="28"/> <location filename="../../designer/components/ocrQueue.ui" line="28"/>
<source>iccOptionsGroupBox</source>
<translation>ICC Profile Options</translation>
</message>
<message>
<location filename="../../designer/components/ocrQueue.ui" line="34"/>
<source>icc.useQt</source>
<translation>Use Qt</translation>
</message>
<message>
<location filename="../../designer/components/ocrQueue.ui" line="41"/>
<source>icc.usePIL</source>
<translation>Use PIL</translation>
</message>
<message>
<location filename="../../designer/components/ocrQueue.ui" line="51"/>
<source>icc.tryFix</source>
<translation>Try fix</translation>
</message>
<message>
<location filename="../../designer/components/ocrQueue.ui" line="61"/>
<source>queue.addImageButton</source> <source>queue.addImageButton</source>
<translation>Add Image</translation> <translation>Add Image</translation>
</message> </message>
<message> <message>
<location filename="../../designer/components/ocrQueue.ui" line="71"/> <location filename="../../designer/components/ocrQueue.ui" line="38"/>
<source>queue.removeSelected</source> <source>queue.removeSelected</source>
<translation>Remove Selected</translation> <translation>Remove Selected</translation>
</message> </message>
<message> <message>
<location filename="../../designer/components/ocrQueue.ui" line="81"/> <location filename="../../designer/components/ocrQueue.ui" line="48"/>
<source>queue.removeAll</source> <source>queue.removeAll</source>
<translation>Remove All</translation> <translation>Remove All</translation>
</message> </message>
<message> <message>
<location filename="../../designer/components/ocrQueue.ui" line="101"/> <location filename="../../designer/components/ocrQueue.ui" line="68"/>
<source>queue.optionsButton</source>
<translation>Options</translation>
</message>
<message>
<location filename="../../designer/components/ocrQueue.ui" line="75"/>
<source>queue.startOcrButton</source> <source>queue.startOcrButton</source>
<translation>Start OCR</translation> <translation>Start OCR</translation>
</message> </message>
<message> <message>
<location filename="../../designer/components/ocrQueue.ui" line="153"/> <location filename="../../designer/components/ocrQueue.ui" line="127"/>
<source>results</source> <source>results</source>
<translation>Results</translation> <translation>Results</translation>
</message> </message>
<message> <message>
<location filename="../../designer/components/ocrQueue.ui" line="162"/> <location filename="../../designer/components/ocrQueue.ui" line="136"/>
<source>results.acceptSelectedButton</source> <source>results.acceptSelectedButton</source>
<translation>Accept Selected</translation> <translation>Accept Selected</translation>
</message> </message>
<message> <message>
<location filename="../../designer/components/ocrQueue.ui" line="169"/> <location filename="../../designer/components/ocrQueue.ui" line="143"/>
<source>results.acceptAllButton</source> <source>results.acceptAllButton</source>
<translation>Accept All</translation> <translation>Accept All</translation>
</message> </message>
<message> <message>
<location filename="../../designer/components/ocrQueue.ui" line="189"/> <location filename="../../designer/components/ocrQueue.ui" line="163"/>
<source>results.ignoreValidate</source> <source>results.ignoreValidate</source>
<translation>Ignore <translation>Ignore
validation</translation> validation</translation>
</message> </message>
</context> </context>
<context>
<name>OcrQueueOptionsDialog</name>
<message>
<location filename="../../designer/components/ocrQueueOptionsDialog.ui" line="14"/>
<source>OCR Options</source>
<translation>OCR Options</translation>
</message>
<message>
<location filename="../../designer/components/ocrQueueOptionsDialog.ui" line="22"/>
<source>iccOptionsGroupBox</source>
<translation>ICC Profile Options</translation>
</message>
<message>
<location filename="../../designer/components/ocrQueueOptionsDialog.ui" line="28"/>
<source>icc.useQt</source>
<translation>Use Qt</translation>
</message>
<message>
<location filename="../../designer/components/ocrQueueOptionsDialog.ui" line="35"/>
<source>icc.usePIL</source>
<translation>Use PIL</translation>
</message>
<message>
<location filename="../../designer/components/ocrQueueOptionsDialog.ui" line="45"/>
<source>icc.tryFix</source>
<translation>Try fix</translation>
</message>
<message>
<location filename="../../designer/components/ocrQueueOptionsDialog.ui" line="55"/>
<source>dateOptionsGroupBox</source>
<translation>Date Source</translation>
</message>
<message>
<location filename="../../designer/components/ocrQueueOptionsDialog.ui" line="64"/>
<source>date.readFromExif</source>
<translation>Read from image EXIF</translation>
</message>
<message>
<location filename="../../designer/components/ocrQueueOptionsDialog.ui" line="74"/>
<source>date.useCreationDate</source>
<translation>File creation time</translation>
</message>
<message>
<location filename="../../designer/components/ocrQueueOptionsDialog.ui" line="84"/>
<source>date.useModifyDate</source>
<translation>File last modification time</translation>
</message>
</context>
<context> <context>
<name>OcrTableModel</name> <name>OcrTableModel</name>
<message> <message>
<location filename="../../extends/components/ocrQueue.py" line="347"/> <location filename="../../extends/components/ocrQueue.py" line="348"/>
<source>horizontalHeader.title.select</source> <source>horizontalHeader.title.select</source>
<translation>Select</translation> <translation>Select</translation>
</message> </message>
<message> <message>
<location filename="../../extends/components/ocrQueue.py" line="348"/> <location filename="../../extends/components/ocrQueue.py" line="351"/>
<source>horizontalHeader.title.imagePreview</source> <source>horizontalHeader.title.imagePreview</source>
<translation>Image Preview</translation> <translation>Image Preview</translation>
</message> </message>
<message> <message>
<location filename="../../extends/components/ocrQueue.py" line="349"/> <location filename="../../extends/components/ocrQueue.py" line="352"/>
<source>horizontalHeader.title.chart</source> <source>horizontalHeader.title.chart</source>
<translation>Chart</translation> <translation>Chart</translation>
</message> </message>
<message> <message>
<location filename="../../extends/components/ocrQueue.py" line="350"/> <location filename="../../extends/components/ocrQueue.py" line="353"/>
<source>horizontalHeader.title.score</source> <source>horizontalHeader.title.score</source>
<translation>Score</translation> <translation>Score</translation>
</message> </message>

View File

@ -70,12 +70,12 @@
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../../startup/databaseChecker.py" line="117"/> <location filename="../../startup/databaseChecker.py" line="122"/>
<source>dialog.tryInitExistingDatabase</source> <source>dialog.tryInitExistingDatabase</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../../startup/databaseChecker.py" line="133"/> <location filename="../../startup/databaseChecker.py" line="138"/>
<source>dialog.confirmNewDatabase</source> <source>dialog.confirmNewDatabase</source>
<translation></translation> <translation></translation>
</message> </message>
@ -224,84 +224,117 @@
</message> </message>
<message> <message>
<location filename="../../designer/components/ocrQueue.ui" line="28"/> <location filename="../../designer/components/ocrQueue.ui" line="28"/>
<source>iccOptionsGroupBox</source>
<translation>ICC </translation>
</message>
<message>
<location filename="../../designer/components/ocrQueue.ui" line="34"/>
<source>icc.useQt</source>
<translation>使 Qt</translation>
</message>
<message>
<location filename="../../designer/components/ocrQueue.ui" line="41"/>
<source>icc.usePIL</source>
<translation>使 PIL</translation>
</message>
<message>
<location filename="../../designer/components/ocrQueue.ui" line="51"/>
<source>icc.tryFix</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/components/ocrQueue.ui" line="61"/>
<source>queue.addImageButton</source> <source>queue.addImageButton</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../../designer/components/ocrQueue.ui" line="71"/> <location filename="../../designer/components/ocrQueue.ui" line="38"/>
<source>queue.removeSelected</source> <source>queue.removeSelected</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../../designer/components/ocrQueue.ui" line="81"/> <location filename="../../designer/components/ocrQueue.ui" line="48"/>
<source>queue.removeAll</source> <source>queue.removeAll</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../../designer/components/ocrQueue.ui" line="101"/> <location filename="../../designer/components/ocrQueue.ui" line="68"/>
<source>queue.optionsButton</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/components/ocrQueue.ui" line="75"/>
<source>queue.startOcrButton</source> <source>queue.startOcrButton</source>
<translation> OCR</translation> <translation> OCR</translation>
</message> </message>
<message> <message>
<location filename="../../designer/components/ocrQueue.ui" line="153"/> <location filename="../../designer/components/ocrQueue.ui" line="127"/>
<source>results</source> <source>results</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../../designer/components/ocrQueue.ui" line="162"/> <location filename="../../designer/components/ocrQueue.ui" line="136"/>
<source>results.acceptSelectedButton</source> <source>results.acceptSelectedButton</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../../designer/components/ocrQueue.ui" line="169"/> <location filename="../../designer/components/ocrQueue.ui" line="143"/>
<source>results.acceptAllButton</source> <source>results.acceptAllButton</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../../designer/components/ocrQueue.ui" line="189"/> <location filename="../../designer/components/ocrQueue.ui" line="163"/>
<source>results.ignoreValidate</source> <source>results.ignoreValidate</source>
<translation></translation> <translation></translation>
</message> </message>
</context> </context>
<context>
<name>OcrQueueOptionsDialog</name>
<message>
<location filename="../../designer/components/ocrQueueOptionsDialog.ui" line="14"/>
<source>OCR Options</source>
<translation>OCR </translation>
</message>
<message>
<location filename="../../designer/components/ocrQueueOptionsDialog.ui" line="22"/>
<source>iccOptionsGroupBox</source>
<translation>ICC </translation>
</message>
<message>
<location filename="../../designer/components/ocrQueueOptionsDialog.ui" line="28"/>
<source>icc.useQt</source>
<translation>使 Qt</translation>
</message>
<message>
<location filename="../../designer/components/ocrQueueOptionsDialog.ui" line="35"/>
<source>icc.usePIL</source>
<translation>使 PIL</translation>
</message>
<message>
<location filename="../../designer/components/ocrQueueOptionsDialog.ui" line="45"/>
<source>icc.tryFix</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/components/ocrQueueOptionsDialog.ui" line="55"/>
<source>dateOptionsGroupBox</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/components/ocrQueueOptionsDialog.ui" line="64"/>
<source>date.readFromExif</source>
<translation> EXIF </translation>
</message>
<message>
<location filename="../../designer/components/ocrQueueOptionsDialog.ui" line="74"/>
<source>date.useCreationDate</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/components/ocrQueueOptionsDialog.ui" line="84"/>
<source>date.useModifyDate</source>
<translation></translation>
</message>
</context>
<context> <context>
<name>OcrTableModel</name> <name>OcrTableModel</name>
<message> <message>
<location filename="../../extends/components/ocrQueue.py" line="347"/> <location filename="../../extends/components/ocrQueue.py" line="348"/>
<source>horizontalHeader.title.select</source> <source>horizontalHeader.title.select</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../../extends/components/ocrQueue.py" line="348"/> <location filename="../../extends/components/ocrQueue.py" line="351"/>
<source>horizontalHeader.title.imagePreview</source> <source>horizontalHeader.title.imagePreview</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../../extends/components/ocrQueue.py" line="349"/> <location filename="../../extends/components/ocrQueue.py" line="352"/>
<source>horizontalHeader.title.chart</source> <source>horizontalHeader.title.chart</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../../extends/components/ocrQueue.py" line="350"/> <location filename="../../extends/components/ocrQueue.py" line="353"/>
<source>horizontalHeader.title.score</source> <source>horizontalHeader.title.score</source>
<translation></translation> <translation></translation>
</message> </message>

View File

@ -3,7 +3,7 @@ import traceback
from enum import IntEnum from enum import IntEnum
from arcaea_offline.database import Database from arcaea_offline.database import Database
from PySide6.QtCore import QCoreApplication, QDir, QFileInfo, Qt, QUrl, Slot from PySide6.QtCore import QCoreApplication, QDir, QFileInfo, QSysInfo, Qt, QUrl, Slot
from PySide6.QtWidgets import QDialog, QMessageBox from PySide6.QtWidgets import QDialog, QMessageBox
from ui.extends.shared.database import create_engine from ui.extends.shared.database import create_engine
@ -59,8 +59,13 @@ class DatabaseChecker(Ui_DatabaseChecker, QDialog):
return QUrl.fromLocalFile(self.dbFileInfo().filePath()) return QUrl.fromLocalFile(self.dbFileInfo().filePath())
def dbSqliteUrl(self): def dbSqliteUrl(self):
# dbSqliteUrl.setScheme("sqlite") kernelType = QSysInfo.kernelType()
return QUrl(self.dbFileUrl().toString().replace("file://", "sqlite://")) # 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: def confirmDb(self) -> DatabaseCheckerResult:
flags = 0x000 flags = 0x000