From b5aefb5f28d6f4c12601b11eec1efff6a7ce7dae Mon Sep 17 00:00:00 2001 From: 283375 Date: Sun, 17 Sep 2023 00:40:08 +0800 Subject: [PATCH] impr: update when database changed, instead of `showEvent` --- ui/extends/shared/database.py | 9 ++++++++- ui/implements/components/chartSelector.py | 14 +++++++++++--- ui/implements/components/songIdSelector.py | 8 ++++---- ui/implements/tabs/tabDb/tabDb_Manage.py | 18 ++++++++++++------ 4 files changed, 35 insertions(+), 14 deletions(-) diff --git a/ui/extends/shared/database.py b/ui/extends/shared/database.py index e6a623c..50e07f3 100644 --- a/ui/extends/shared/database.py +++ b/ui/extends/shared/database.py @@ -1,6 +1,6 @@ from typing import Type -from PySide6.QtCore import QUrl +from PySide6.QtCore import QObject, QUrl, Signal from sqlalchemy import Engine from sqlalchemy import create_engine as sa_create_engine from sqlalchemy.pool import NullPool, Pool @@ -9,3 +9,10 @@ from sqlalchemy.pool import NullPool, Pool def create_engine(_url: str | QUrl, pool: Type[Pool] = NullPool) -> Engine: url = _url.toString() if isinstance(_url, QUrl) else _url return sa_create_engine(url, poolclass=pool) + + +class DatabaseUpdateSignals(QObject): + songDataUpdated = Signal() + + +databaseUpdateSignals = DatabaseUpdateSignals() diff --git a/ui/implements/components/chartSelector.py b/ui/implements/components/chartSelector.py index 347f50d..b4f7c89 100644 --- a/ui/implements/components/chartSelector.py +++ b/ui/implements/components/chartSelector.py @@ -4,10 +4,10 @@ from arcaea_offline.database import Database from arcaea_offline.models import Chart from arcaea_offline.utils.rating import rating_class_to_text from PySide6.QtCore import Signal, Slot -from PySide6.QtGui import QShowEvent from PySide6.QtWidgets import QWidget from ui.designer.components.chartSelector_ui import Ui_ChartSelector +from ui.extends.shared.database import databaseUpdateSignals from ui.extends.shared.language import LanguageChangeEventFilter logger = logging.getLogger(__name__) @@ -30,6 +30,12 @@ class ChartSelector(Ui_ChartSelector, QWidget): self.songIdSelector.valueChanged.connect(self.valueChanged) self.ratingClassSelector.valueChanged.connect(self.valueChanged) + # handle `songIdSelector.updateDatabase` by this component + databaseUpdateSignals.songDataUpdated.disconnect( + self.songIdSelector.updateDatabase + ) + databaseUpdateSignals.songDataUpdated.connect(self.updateDatabase) + def value(self): songId = self.songIdSelector.songId() ratingClass = self.ratingClassSelector.value() @@ -38,13 +44,15 @@ class ChartSelector(Ui_ChartSelector, QWidget): return self.db.get_chart(songId, ratingClass) return None - def showEvent(self, event: QShowEvent): + def updateDatabase(self): # remember selection and restore later ratingClass = self.ratingClassSelector.value() + # wait `songIdSelector` finish + self.songIdSelector.updateDatabase() + if ratingClass is not None: self.ratingClassSelector.select(ratingClass) - return super().showEvent(event) @Slot() def updateResultLabel(self): diff --git a/ui/implements/components/songIdSelector.py b/ui/implements/components/songIdSelector.py index a5a4d9e..1a229b0 100644 --- a/ui/implements/components/songIdSelector.py +++ b/ui/implements/components/songIdSelector.py @@ -5,11 +5,11 @@ from typing import Literal from arcaea_offline.database import Database from arcaea_offline.models import Chart from PySide6.QtCore import QModelIndex, Qt, Signal, Slot -from PySide6.QtGui import QShowEvent from PySide6.QtWidgets import QCompleter, QWidget from ui.designer.components.songIdSelector_ui import Ui_SongIdSelector from ui.extends.components.songIdSelector import SearchCompleterModel +from ui.extends.shared.database import databaseUpdateSignals from ui.extends.shared.delegates.descriptionDelegate import DescriptionDelegate from ui.extends.shared.language import LanguageChangeEventFilter @@ -40,6 +40,8 @@ class SongIdSelector(Ui_SongIdSelector, QWidget): lambda: self.quickSwitchSelection("next", "package") ) + databaseUpdateSignals.songDataUpdated.connect(self.updateDatabase) + self.fillPackComboBox() self.packComboBox.setCurrentIndex(-1) self.songIdComboBox.setCurrentIndex(-1) @@ -93,8 +95,7 @@ class SongIdSelector(Ui_SongIdSelector, QWidget): self.packComboBox.setCurrentIndex(-1) self.songIdComboBox.setCurrentIndex(-1) - def showEvent(self, event: QShowEvent): - # update database results when widget visible + def updateDatabase(self): self.searchCompleterModel.updateSearcherSongs() # remember selection and restore later @@ -107,7 +108,6 @@ class SongIdSelector(Ui_SongIdSelector, QWidget): self.selectPack(pack) if songId: self.selectSongId(songId) - return super().showEvent(event) def fillPackComboBox(self): self.packComboBox.clear() diff --git a/ui/implements/tabs/tabDb/tabDb_Manage.py b/ui/implements/tabs/tabDb/tabDb_Manage.py index 600ae6f..3c9fa1e 100644 --- a/ui/implements/tabs/tabDb/tabDb_Manage.py +++ b/ui/implements/tabs/tabDb/tabDb_Manage.py @@ -12,10 +12,12 @@ from arcaea_offline.external.arcaea import ( ) from arcaea_offline.external.arcaea.common import ArcaeaParser from arcaea_offline.external.arcsong import ArcsongDbParser +from arcaea_offline.models import Difficulty, Pack, Song from PySide6.QtCore import QDir, Slot from PySide6.QtWidgets import QFileDialog, QMessageBox, QWidget from ui.designer.tabs.tabDb.tabDb_Manage_ui import Ui_TabDb_Manage +from ui.extends.shared.database import databaseUpdateSignals logger = logging.getLogger(__name__) @@ -40,6 +42,7 @@ class TabDb_Manage(Ui_TabDb_Manage, QWidget): with db.sessionmaker() as session: parser.write_database(session) session.commit() + databaseUpdateSignals.songDataUpdated.emit() QMessageBox.information(self, None, "OK") except Exception as e: logging.exception("Sync arcsong.db error") @@ -47,28 +50,31 @@ class TabDb_Manage(Ui_TabDb_Manage, QWidget): self, "Sync Error", "\n".join(traceback.format_exception(e)) ) - def importFromArcaeaParser(self, parser: ArcaeaParser, logName, path) -> int: + def importFromArcaeaParser( + self, parser: ArcaeaParser, instance, logName, path + ) -> int: # extracted by sourcery db = Database() with db.sessionmaker() as session: parser.write_database(session) session.commit() - itemNum = len(parser.parse()) + databaseUpdateSignals.songDataUpdated.emit() + itemNum = len([item for item in parser.parse() if isinstance(item, instance)]) logger.info(f"updated {itemNum} {logName} from {path}") return itemNum def importPacklist(self, packlistPath): packlistParser = PacklistParser(packlistPath) - return self.importFromArcaeaParser(packlistParser, "packs", packlistPath) + return self.importFromArcaeaParser(packlistParser, Pack, "packs", packlistPath) def importSonglist(self, songlistPath): songlistParser = SonglistParser(songlistPath) - return self.importFromArcaeaParser(songlistParser, "songs", songlistPath) + return self.importFromArcaeaParser(songlistParser, Song, "songs", songlistPath) def importSonglistDifficulties(self, songlistPath): songlistDifficultiesParser = SonglistDifficultiesParser(songlistPath) return self.importFromArcaeaParser( - songlistDifficultiesParser, "difficulties", songlistPath + songlistDifficultiesParser, Difficulty, "difficulties", songlistPath ) @Slot() @@ -190,7 +196,7 @@ class TabDb_Manage(Ui_TabDb_Manage, QWidget): exportLocation, _filter = QFileDialog.getSaveFileName( self, - "Save your scores to...", + "Export arcsong.json", QDir.current().filePath("arcsong.json"), "JSON (*.json);;*", )