impr: ScoreEditor validation

This commit is contained in:
2023-09-17 03:36:00 +08:00
parent 4a8bae414b
commit 0d80fb6f46
3 changed files with 389 additions and 190 deletions

View File

@ -1,3 +1,4 @@
from dataclasses import dataclass
from enum import IntEnum from enum import IntEnum
from typing import Any, Optional from typing import Any, Optional
@ -17,20 +18,74 @@ from PySide6.QtWidgets import (
from ui.designer.components.scoreEditor_ui import Ui_ScoreEditor from ui.designer.components.scoreEditor_ui import Ui_ScoreEditor
from ui.extends.shared.language import LanguageChangeEventFilter from ui.extends.shared.language import LanguageChangeEventFilter
# TODO: use bit flags
class ScoreValidateResult(IntEnum): class ScoreValidateResult(IntEnum):
Ok = 0 Ok = 0x001
ScoreMismatch = 1
ScoreEmpty = 2 ScoreMismatch = 0x010
ChartInvalid = 50 ScoreEmpty = 0x020
ChartIncomplete = 51 ScoreIncomplete = 0x040
ScoreIncomplete = 100 ScoreIncompleteForValidate = 0x080
ChartNotSet = 0x100
ChartIncomplete = 0x200
@dataclass
class ScoreEditorValidationItem:
flag: int
title: str = ""
text: str = ""
warnIfIncomplete: bool = False
class ScoreEditor(Ui_ScoreEditor, QWidget): class ScoreEditor(Ui_ScoreEditor, QWidget):
valueChanged = Signal() valueChanged = Signal()
accepted = Signal() accepted = Signal()
VALIDATION_ITEMS = [
ScoreEditorValidationItem(
ScoreValidateResult.ChartIncomplete,
warnIfIncomplete=True,
),
ScoreEditorValidationItem(
ScoreValidateResult.ScoreMismatch,
),
ScoreEditorValidationItem(
ScoreValidateResult.ScoreEmpty,
),
ScoreEditorValidationItem(
ScoreValidateResult.ScoreIncompleteForValidate, warnIfIncomplete=True
),
]
VALIDATION_ITEMS_TEXT = [
[
# fmt: off
lambda: QCoreApplication.translate("ScoreEditor", "confirmDialog.chartIncomplete.title"),
lambda: QCoreApplication.translate("ScoreEditor", "confirmDialog.chartIncomplete.text"),
# fmt: on
],
[
# fmt: off
lambda: QCoreApplication.translate("ScoreEditor", "confirmDialog.scoreMismatch.title"),
lambda: QCoreApplication.translate("ScoreEditor", "confirmDialog.scoreMismatch.text"),
# fmt: on
],
[
# fmt: off
lambda: QCoreApplication.translate("ScoreEditor", "confirmDialog.emptyScore.title"),
lambda: QCoreApplication.translate("ScoreEditor", "confirmDialog.emptyScore.text"),
# fmt: on
],
[
# fmt: off
lambda: QCoreApplication.translate("ScoreEditor", "confirmDialog.scoreIncompleteForValidate.title"),
lambda: QCoreApplication.translate("ScoreEditor", "confirmDialog.scoreIncompleteForValidate.text"),
# fmt: on,
],
]
def __init__(self, parent=None): def __init__(self, parent=None):
super().__init__(parent) super().__init__(parent)
self.setupUi(self) self.setupUi(self)
@ -80,6 +135,16 @@ class ScoreEditor(Ui_ScoreEditor, QWidget):
self.dateTimeEdit.setDateTime(QDateTime.currentDateTime()) self.dateTimeEdit.setDateTime(QDateTime.currentDateTime())
def retranslateUi(self, *args):
super().retranslateUi(self)
for item, itemTextCallables in zip(
self.VALIDATION_ITEMS, self.VALIDATION_ITEMS_TEXT
):
titleCallable, textCallable = itemTextCallables
item.title = titleCallable()
item.text = textCallable()
def validateBeforeAccept(self): def validateBeforeAccept(self):
return self.__validateBeforeAccept return self.__validateBeforeAccept
@ -94,71 +159,78 @@ class ScoreEditor(Ui_ScoreEditor, QWidget):
self.warnIfIncompleteCheckBox.setChecked(__bool) self.warnIfIncompleteCheckBox.setChecked(__bool)
self.__warnIfIncomplete = __bool self.__warnIfIncomplete = __bool
def __triggerMessageBox(
self, methodStr: str, title: str, text: str, userConfirmButton: bool = False
) -> QMessageBox.StandardButton:
if methodStr == "critical":
method = QMessageBox.critical
elif methodStr == "warning":
method = QMessageBox.warning
else:
method = QMessageBox.information
if userConfirmButton:
return method(
self,
title,
text,
QMessageBox.StandardButton.Yes,
QMessageBox.StandardButton.No,
)
else:
return method(self, title, text)
def triggerValidateMessageBox(self): def triggerValidateMessageBox(self):
validate = self.validateScore() validate = self.validateScore()
if validate == ScoreValidateResult.Ok: if validate & ScoreValidateResult.Ok:
return True return True
if validate == ScoreValidateResult.ChartInvalid: if validate & ScoreValidateResult.ChartNotSet:
QMessageBox.critical( self.__triggerMessageBox(
self, "critical",
# fmt: off # fmt: off
QCoreApplication.translate("ScoreEditor", "chartInvalidDialog.title"), QCoreApplication.translate("ScoreEditor", "confirmDialog.chartNotSet.title"),
QCoreApplication.translate("ScoreEditor", "chartInvalidDialog.title"), QCoreApplication.translate("ScoreEditor", "confirmDialog.chartNotSet.text"),
# fmt: on # fmt: on
) )
return False return False
if validate == ScoreValidateResult.ChartIncomplete: if validate & ScoreValidateResult.ScoreIncomplete:
if not self.__warnIfIncomplete: self.__triggerMessageBox(
return True "critical",
result = QMessageBox.warning(
self,
# fmt: off # fmt: off
QCoreApplication.translate("ScoreEditor", "chartIncompleteDialog.title"), QCoreApplication.translate("ScoreEditor", "confirmDialog.scoreIncomplete.title"),
QCoreApplication.translate("ScoreEditor", "chartIncompleteDialog.content"), QCoreApplication.translate("ScoreEditor", "confirmDialog.scoreIncomplete.text"),
# fmt: on # fmt: on
QMessageBox.StandardButton.Yes,
QMessageBox.StandardButton.No,
) )
return result == QMessageBox.StandardButton.Yes
if validate == ScoreValidateResult.ScoreMismatch:
result = QMessageBox.warning(
self,
# fmt: off
QCoreApplication.translate("ScoreEditor", "scoreMismatchDialog.title"),
QCoreApplication.translate("ScoreEditor", "scoreMismatchDialog.content"),
# fmt: on
QMessageBox.StandardButton.Yes,
QMessageBox.StandardButton.No,
)
return result == QMessageBox.StandardButton.Yes
elif validate == ScoreValidateResult.ScoreEmpty:
result = QMessageBox.warning(
self,
# fmt: off
QCoreApplication.translate("ScoreEditor", "emptyScoreDialog.title"),
QCoreApplication.translate("ScoreEditor", "emptyScoreDialog.content"),
# fmt: on
QMessageBox.StandardButton.Yes,
QMessageBox.StandardButton.No,
)
return result == QMessageBox.StandardButton.Yes
elif validate == ScoreValidateResult.ScoreIncomplete:
if not self.__warnIfIncomplete:
return True
result = QMessageBox.warning(
self,
# fmt: off
QCoreApplication.translate("ScoreEditor", "scoreIncompleteDialog.title"),
QCoreApplication.translate("ScoreEditor", "scoreIncompleteDialog.content"),
# fmt: on
QMessageBox.StandardButton.Yes,
QMessageBox.StandardButton.No,
)
return result == QMessageBox.StandardButton.Yes
else:
return False return False
# since validate may have multiple results
# ask user step by step, then return the final result
finalResult = True
for item in self.VALIDATION_ITEMS:
if not finalResult:
# user canceled commit, break then return
break
if not validate & item.flag:
continue
if item.warnIfIncomplete and not self.warnIfIncomplete():
# if the item requires `warnIfIncomplete`
# and the user set the `warnIfIncomplete` option to `False`
# skip this validation
continue
finalResult = (
self.__triggerMessageBox(
"warning", item.title, item.text, userConfirmButton=True
)
== QMessageBox.StandardButton.Yes
)
return finalResult
@Slot() @Slot()
def on_commitButton_clicked(self): def on_commitButton_clicked(self):
userAccept = ( userAccept = (
@ -170,7 +242,7 @@ class ScoreEditor(Ui_ScoreEditor, QWidget):
def score(self): def score(self):
score_text = self.scoreLineEdit.text().replace("'", "") score_text = self.scoreLineEdit.text().replace("'", "")
return int(score_text) if score_text else 0 return int(score_text) if score_text else None
def setComboBoxMaximums(self, max: int): def setComboBoxMaximums(self, max: int):
self.pureSpinBox.setMaximum(max) self.pureSpinBox.setMaximum(max)
@ -198,44 +270,73 @@ class ScoreEditor(Ui_ScoreEditor, QWidget):
def validateScore(self) -> ScoreValidateResult: def validateScore(self) -> ScoreValidateResult:
if not isinstance(self.__chart, Chart): if not isinstance(self.__chart, Chart):
return ScoreValidateResult.ChartInvalid return ScoreValidateResult.ChartNotSet
flags = 0x000
if self.__chart.notes is None: if self.__chart.notes is None:
return ScoreValidateResult.ChartIncomplete flags |= ScoreValidateResult.ChartIncomplete
score = self.value() score = self.value()
if score.pure is None or score.far is None: if score.score is None:
return ScoreValidateResult.ScoreIncomplete flags |= ScoreValidateResult.ScoreIncomplete
elif score.pure is None or score.far is None:
score_range = calculate_score_range(self.__chart.notes, score.pure, score.far) flags |= ScoreValidateResult.ScoreIncompleteForValidate
elif self.__chart.notes is not None:
score_range = calculate_score_range(
self.__chart.notes, score.pure, score.far
)
note_in_range = score.pure + score.far + score.lost <= self.__chart.notes note_in_range = score.pure + score.far + score.lost <= self.__chart.notes
score_in_range = score_range[0] <= score.score <= score_range[1] score_in_range = score_range[0] <= score.score <= score_range[1]
if not score_in_range or not note_in_range: if not score_in_range or not note_in_range:
return ScoreValidateResult.ScoreMismatch flags |= ScoreValidateResult.ScoreMismatch
if score.score == 0: if score.score == 0:
return ScoreValidateResult.ScoreEmpty flags |= ScoreValidateResult.ScoreEmpty
return ScoreValidateResult.Ok
return ScoreValidateResult.Ok if flags == 0x000 else flags
def updateValidateLabel(self): def updateValidateLabel(self):
validate = self.validateScore() validate = self.validateScore()
if validate == ScoreValidateResult.Ok: texts = []
text = QCoreApplication.translate("ScoreEditor", "validate.ok")
elif validate == ScoreValidateResult.ChartInvalid:
text = QCoreApplication.translate("ScoreEditor", "validate.chartInvalid")
elif validate == ScoreValidateResult.ChartIncomplete:
text = QCoreApplication.translate("ScoreEditor", "validate.chartIncomple")
elif validate == ScoreValidateResult.ScoreMismatch:
text = QCoreApplication.translate("ScoreEditor", "validate.scoreMismatch")
elif validate == ScoreValidateResult.ScoreEmpty:
text = QCoreApplication.translate("ScoreEditor", "validate.scoreEmpty")
elif validate == ScoreValidateResult.ScoreIncomplete:
text = QCoreApplication.translate("ScoreEditor", "validate.scoreIncomplete")
else:
text = QCoreApplication.translate("ScoreEditor", "validate.unknownState")
self.validateLabel.setText(text) if validate & ScoreValidateResult.Ok:
texts.append(QCoreApplication.translate("ScoreEditor", "validate.ok"))
if validate & ScoreValidateResult.ChartNotSet:
texts.append(
QCoreApplication.translate("ScoreEditor", "validate.chartNotSet")
)
if validate & ScoreValidateResult.ChartIncomplete:
texts.append(
QCoreApplication.translate("ScoreEditor", "validate.chartIncomple")
)
if validate & ScoreValidateResult.ScoreMismatch:
texts.append(
QCoreApplication.translate("ScoreEditor", "validate.scoreMismatch")
)
if validate & ScoreValidateResult.ScoreEmpty:
texts.append(
QCoreApplication.translate("ScoreEditor", "validate.scoreEmpty")
)
if validate & ScoreValidateResult.ScoreIncomplete:
texts.append(
QCoreApplication.translate("ScoreEditor", "validate.scoreIncomplete")
)
if validate & ScoreValidateResult.ScoreIncompleteForValidate:
texts.append(
# fmt: off
QCoreApplication.translate("ScoreEditor", "validate.scoreIncompleteForValidate")
# fmt: on
)
if not texts:
texts.append(
QCoreApplication.translate("ScoreEditor", "validate.unknownState")
)
self.validateLabel.setText(" | ".join(texts))
def __getItemBaseName(self, item: QLineEdit | QSpinBox | QDateTimeEdit | QComboBox): def __getItemBaseName(self, item: QLineEdit | QSpinBox | QDateTimeEdit | QComboBox):
if isinstance(item, QSpinBox): if isinstance(item, QSpinBox):

View File

@ -315,94 +315,143 @@ validation</translation>
<name>ScoreEditor</name> <name>ScoreEditor</name>
<message> <message>
<location filename="../../designer/components/scoreEditor.ui" line="20"/> <location filename="../../designer/components/scoreEditor.ui" line="20"/>
<location filename="../../designer/components/scoreEditor.ui" line="50"/> <location filename="../../designer/components/scoreEditor.ui" line="53"/>
<location filename="../../designer/components/scoreEditor.ui" line="80"/> <location filename="../../designer/components/scoreEditor.ui" line="83"/>
<location filename="../../designer/components/scoreEditor.ui" line="217"/> <location filename="../../designer/components/scoreEditor.ui" line="223"/>
<location filename="../../designer/components/scoreEditor.ui" line="231"/> <location filename="../../designer/components/scoreEditor.ui" line="237"/>
<location filename="../../designer/components/scoreEditor.ui" line="241"/> <location filename="../../designer/components/scoreEditor.ui" line="247"/>
<location filename="../../designer/components/scoreEditor.ui" line="275"/> <location filename="../../designer/components/scoreEditor.ui" line="281"/>
<location filename="../../designer/components/scoreEditor.ui" line="318"/> <location filename="../../designer/components/scoreEditor.ui" line="327"/>
<source>setNone</source> <source>setNone</source>
<translation>None</translation> <translation>None</translation>
</message> </message>
<message> <message>
<location filename="../../designer/components/scoreEditor.ui" line="251"/> <location filename="../../designer/components/scoreEditor.ui" line="257"/>
<source>formLabel.date</source> <source>formLabel.date</source>
<translation>Time</translation> <translation>Time</translation>
</message> </message>
<message> <message>
<location filename="../../designer/components/scoreEditor.ui" line="298"/> <location filename="../../designer/components/scoreEditor.ui" line="307"/>
<source>formLabel.comment</source> <source>formLabel.comment</source>
<translation>Comment</translation> <translation>Comment</translation>
</message> </message>
<message> <message>
<location filename="../../designer/components/scoreEditor.ui" line="308"/> <location filename="../../designer/components/scoreEditor.ui" line="317"/>
<source>formLabel.score</source> <source>formLabel.score</source>
<translation>Score</translation> <translation>Score</translation>
</message> </message>
<message> <message>
<location filename="../../designer/components/scoreEditor.ui" line="335"/> <location filename="../../designer/components/scoreEditor.ui" line="344"/>
<source>idAutoInsert</source> <source>idAutoInsert</source>
<translation>(Auto Insert)</translation> <translation>(Auto Insert)</translation>
</message> </message>
<message> <message>
<location filename="../../designer/components/scoreEditor.ui" line="261"/> <location filename="../../designer/components/scoreEditor.ui" line="351"/>
<source>warnIfIncomplete</source>
<translation>Warn if incomplete</translation>
</message>
<message>
<location filename="../../designer/components/scoreEditor.ui" line="267"/>
<source>commitButton</source> <source>commitButton</source>
<translation>Commit</translation> <translation>Commit</translation>
</message> </message>
<message> <message>
<location filename="../../implements/components/scoreEditor.py" line="110"/> <location filename="../../implements/components/scoreEditor.py" line="306"/>
<source>emptyScoreDialog.title</source>
<translation>Empty Score</translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="111"/>
<source>emptyScoreDialog.content</source>
<translation>Are you sure to commit an empty score?</translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="90"/>
<location filename="../../implements/components/scoreEditor.py" line="91"/>
<source>chartInvalidDialog.title</source>
<translation>Chart Invalid</translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="99"/>
<source>scoreMismatchDialog.title</source>
<translation>Possible Invalid Score</translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="100"/>
<source>scoreMismatchDialog.content</source>
<translation>The entered score may not match the selected chart. Commit this score anyway?</translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="185"/>
<source>validate.ok</source> <source>validate.ok</source>
<translation>OK</translation> <translation>OK</translation>
</message> </message>
<message> <message>
<location filename="../../implements/components/scoreEditor.py" line="187"/> <location filename="../../implements/components/scoreEditor.py" line="65"/>
<source>validate.chartInvalid</source> <source>confirmDialog.chartIncomplete.title</source>
<translation>Chart invalid</translation> <translation>No chart data</translation>
</message> </message>
<message> <message>
<location filename="../../implements/components/scoreEditor.py" line="189"/> <location filename="../../implements/components/scoreEditor.py" line="66"/>
<source>confirmDialog.chartIncomplete.text</source>
<translation>Chart data incomplete, cannot verify score. Commit anyway?</translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="71"/>
<source>confirmDialog.scoreMismatch.title</source>
<translation>Score mismatch</translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="72"/>
<source>confirmDialog.scoreMismatch.text</source>
<translation>The entered score may not match the selected chart. Commit anyway?</translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="77"/>
<source>confirmDialog.emptyScore.title</source>
<translation>Empty score</translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="78"/>
<source>confirmDialog.emptyScore.text</source>
<translation>Score empty. Commit anyway?</translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="83"/>
<source>confirmDialog.scoreIncompleteForValidate.title</source>
<translation>Score incomplete</translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="84"/>
<source>confirmDialog.scoreIncompleteForValidate.text</source>
<translation>Cannot verify an incomplete score. Commit anyway?</translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="192"/>
<source>confirmDialog.chartNotSet.title</source>
<translation>Chart not set</translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="193"/>
<source>confirmDialog.chartNotSet.text</source>
<translation>Chart not set, cannot commit.</translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="201"/>
<source>confirmDialog.scoreIncomplete.title</source>
<translation>Score incomplete</translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="202"/>
<source>confirmDialog.scoreIncomplete.text</source>
<translation>Necessary score field missing, cannot commit.</translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="310"/>
<source>validate.chartNotSet</source>
<translation>Chart not set</translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="314"/>
<source>validate.chartIncomple</source>
<translation>No chart data, cannot verify</translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="318"/>
<source>validate.scoreMismatch</source> <source>validate.scoreMismatch</source>
<translation>Possible invalid score</translation> <translation>Possible invalid score</translation>
</message> </message>
<message> <message>
<location filename="../../implements/components/scoreEditor.py" line="191"/> <location filename="../../implements/components/scoreEditor.py" line="322"/>
<source>validate.scoreEmpty</source> <source>validate.scoreEmpty</source>
<translation>Empty score</translation> <translation>Empty score</translation>
</message> </message>
<message> <message>
<location filename="../../implements/components/scoreEditor.py" line="193"/> <location filename="../../implements/components/scoreEditor.py" line="326"/>
<source>validate.scoreIncomplete</source> <source>validate.scoreIncomplete</source>
<translation>Missing necessary score field</translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="332"/>
<source>validate.scoreIncompleteForValidate</source>
<translation>Score incomplete, cannot verify</translation> <translation>Score incomplete, cannot verify</translation>
</message> </message>
<message> <message>
<location filename="../../implements/components/scoreEditor.py" line="196"/> <location filename="../../implements/components/scoreEditor.py" line="337"/>
<source>validate.unknownState</source> <source>validate.unknownState</source>
<translation>Unknown</translation> <translation>Unknown</translation>
</message> </message>
@ -422,7 +471,7 @@ validation</translation>
<message> <message>
<location filename="../../implements/settings/settingsAndreal.py" line="79"/> <location filename="../../implements/settings/settingsAndreal.py" line="79"/>
<location filename="../../implements/settings/settingsAndreal.py" line="82"/> <location filename="../../implements/settings/settingsAndreal.py" line="82"/>
<location filename="../../implements/settings/settingsGeneral.py" line="105"/> <location filename="../../implements/settings/settingsGeneral.py" line="107"/>
<location filename="../../implements/settings/settingsOcr.py" line="137"/> <location filename="../../implements/settings/settingsOcr.py" line="137"/>
<location filename="../../implements/settings/settingsOcr.py" line="140"/> <location filename="../../implements/settings/settingsOcr.py" line="140"/>
<location filename="../../implements/settings/settingsOcr.py" line="143"/> <location filename="../../implements/settings/settingsOcr.py" line="143"/>
@ -436,27 +485,27 @@ validation</translation>
<translation>Andreal Executable</translation> <translation>Andreal Executable</translation>
</message> </message>
<message> <message>
<location filename="../../implements/settings/settingsGeneral.py" line="76"/> <location filename="../../implements/settings/settingsGeneral.py" line="78"/>
<source>general.dbUrlResetWarning</source> <source>general.dbUrlResetWarning</source>
<translation>Application will now delete this setting and exit. Reboot application manually to specify a new database file. Continue?</translation> <translation>Application will now delete this setting and exit. Reboot application manually to specify a new database file. Continue?</translation>
</message> </message>
<message> <message>
<location filename="../../implements/settings/settingsGeneral.py" line="99"/> <location filename="../../implements/settings/settingsGeneral.py" line="101"/>
<source>general.title</source> <source>general.title</source>
<translation>General</translation> <translation>General</translation>
</message> </message>
<message> <message>
<location filename="../../implements/settings/settingsGeneral.py" line="101"/> <location filename="../../implements/settings/settingsGeneral.py" line="103"/>
<source>general.language.label</source> <source>general.language.label</source>
<translation>Language</translation> <translation>Language</translation>
</message> </message>
<message> <message>
<location filename="../../implements/settings/settingsGeneral.py" line="102"/> <location filename="../../implements/settings/settingsGeneral.py" line="104"/>
<source>general.language.followSystem</source> <source>general.language.followSystem</source>
<translation>Follow system</translation> <translation>Follow system</translation>
</message> </message>
<message> <message>
<location filename="../../implements/settings/settingsGeneral.py" line="104"/> <location filename="../../implements/settings/settingsGeneral.py" line="106"/>
<source>general.dbUrl.label</source> <source>general.dbUrl.label</source>
<translation>Database URL</translation> <translation>Database URL</translation>
</message> </message>

View File

@ -314,94 +314,143 @@
<name>ScoreEditor</name> <name>ScoreEditor</name>
<message> <message>
<location filename="../../designer/components/scoreEditor.ui" line="20"/> <location filename="../../designer/components/scoreEditor.ui" line="20"/>
<location filename="../../designer/components/scoreEditor.ui" line="50"/> <location filename="../../designer/components/scoreEditor.ui" line="53"/>
<location filename="../../designer/components/scoreEditor.ui" line="80"/> <location filename="../../designer/components/scoreEditor.ui" line="83"/>
<location filename="../../designer/components/scoreEditor.ui" line="217"/> <location filename="../../designer/components/scoreEditor.ui" line="223"/>
<location filename="../../designer/components/scoreEditor.ui" line="231"/> <location filename="../../designer/components/scoreEditor.ui" line="237"/>
<location filename="../../designer/components/scoreEditor.ui" line="241"/> <location filename="../../designer/components/scoreEditor.ui" line="247"/>
<location filename="../../designer/components/scoreEditor.ui" line="275"/> <location filename="../../designer/components/scoreEditor.ui" line="281"/>
<location filename="../../designer/components/scoreEditor.ui" line="318"/> <location filename="../../designer/components/scoreEditor.ui" line="327"/>
<source>setNone</source> <source>setNone</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../../designer/components/scoreEditor.ui" line="251"/> <location filename="../../designer/components/scoreEditor.ui" line="257"/>
<source>formLabel.date</source> <source>formLabel.date</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../../designer/components/scoreEditor.ui" line="298"/> <location filename="../../designer/components/scoreEditor.ui" line="307"/>
<source>formLabel.comment</source> <source>formLabel.comment</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../../designer/components/scoreEditor.ui" line="308"/> <location filename="../../designer/components/scoreEditor.ui" line="317"/>
<source>formLabel.score</source> <source>formLabel.score</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../../designer/components/scoreEditor.ui" line="335"/> <location filename="../../designer/components/scoreEditor.ui" line="344"/>
<source>idAutoInsert</source> <source>idAutoInsert</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../../designer/components/scoreEditor.ui" line="261"/> <location filename="../../designer/components/scoreEditor.ui" line="351"/>
<source>warnIfIncomplete</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/components/scoreEditor.ui" line="267"/>
<source>commitButton</source> <source>commitButton</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../../implements/components/scoreEditor.py" line="110"/> <location filename="../../implements/components/scoreEditor.py" line="306"/>
<source>emptyScoreDialog.title</source>
<translation></translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="111"/>
<source>emptyScoreDialog.content</source>
<translation></translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="90"/>
<location filename="../../implements/components/scoreEditor.py" line="91"/>
<source>chartInvalidDialog.title</source>
<translation></translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="99"/>
<source>scoreMismatchDialog.title</source>
<translation></translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="100"/>
<source>scoreMismatchDialog.content</source>
<translation></translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="185"/>
<source>validate.ok</source> <source>validate.ok</source>
<translation>OK</translation> <translation>OK</translation>
</message> </message>
<message> <message>
<location filename="../../implements/components/scoreEditor.py" line="187"/> <location filename="../../implements/components/scoreEditor.py" line="65"/>
<source>validate.chartInvalid</source> <source>confirmDialog.chartIncomplete.title</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../../implements/components/scoreEditor.py" line="189"/> <location filename="../../implements/components/scoreEditor.py" line="66"/>
<source>confirmDialog.chartIncomplete.text</source>
<translation></translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="71"/>
<source>confirmDialog.scoreMismatch.title</source>
<translation></translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="72"/>
<source>confirmDialog.scoreMismatch.text</source>
<translation></translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="77"/>
<source>confirmDialog.emptyScore.title</source>
<translation></translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="78"/>
<source>confirmDialog.emptyScore.text</source>
<translation></translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="83"/>
<source>confirmDialog.scoreIncompleteForValidate.title</source>
<translation></translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="84"/>
<source>confirmDialog.scoreIncompleteForValidate.text</source>
<translation></translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="192"/>
<source>confirmDialog.chartNotSet.title</source>
<translation></translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="193"/>
<source>confirmDialog.chartNotSet.text</source>
<translation></translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="201"/>
<source>confirmDialog.scoreIncomplete.title</source>
<translation></translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="202"/>
<source>confirmDialog.scoreIncomplete.text</source>
<translation></translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="310"/>
<source>validate.chartNotSet</source>
<translation></translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="314"/>
<source>validate.chartIncomple</source>
<translation></translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="318"/>
<source>validate.scoreMismatch</source> <source>validate.scoreMismatch</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../../implements/components/scoreEditor.py" line="191"/> <location filename="../../implements/components/scoreEditor.py" line="322"/>
<source>validate.scoreEmpty</source> <source>validate.scoreEmpty</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../../implements/components/scoreEditor.py" line="193"/> <location filename="../../implements/components/scoreEditor.py" line="326"/>
<source>validate.scoreIncomplete</source> <source>validate.scoreIncomplete</source>
<translation></translation>
</message>
<message>
<location filename="../../implements/components/scoreEditor.py" line="332"/>
<source>validate.scoreIncompleteForValidate</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../../implements/components/scoreEditor.py" line="196"/> <location filename="../../implements/components/scoreEditor.py" line="337"/>
<source>validate.unknownState</source> <source>validate.unknownState</source>
<translation></translation> <translation></translation>
</message> </message>
@ -421,7 +470,7 @@
<message> <message>
<location filename="../../implements/settings/settingsAndreal.py" line="79"/> <location filename="../../implements/settings/settingsAndreal.py" line="79"/>
<location filename="../../implements/settings/settingsAndreal.py" line="82"/> <location filename="../../implements/settings/settingsAndreal.py" line="82"/>
<location filename="../../implements/settings/settingsGeneral.py" line="105"/> <location filename="../../implements/settings/settingsGeneral.py" line="107"/>
<location filename="../../implements/settings/settingsOcr.py" line="137"/> <location filename="../../implements/settings/settingsOcr.py" line="137"/>
<location filename="../../implements/settings/settingsOcr.py" line="140"/> <location filename="../../implements/settings/settingsOcr.py" line="140"/>
<location filename="../../implements/settings/settingsOcr.py" line="143"/> <location filename="../../implements/settings/settingsOcr.py" line="143"/>
@ -435,27 +484,27 @@
<translation>Andreal </translation> <translation>Andreal </translation>
</message> </message>
<message> <message>
<location filename="../../implements/settings/settingsGeneral.py" line="76"/> <location filename="../../implements/settings/settingsGeneral.py" line="78"/>
<source>general.dbUrlResetWarning</source> <source>general.dbUrlResetWarning</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../../implements/settings/settingsGeneral.py" line="99"/> <location filename="../../implements/settings/settingsGeneral.py" line="101"/>
<source>general.title</source> <source>general.title</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../../implements/settings/settingsGeneral.py" line="101"/> <location filename="../../implements/settings/settingsGeneral.py" line="103"/>
<source>general.language.label</source> <source>general.language.label</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../../implements/settings/settingsGeneral.py" line="102"/> <location filename="../../implements/settings/settingsGeneral.py" line="104"/>
<source>general.language.followSystem</source> <source>general.language.followSystem</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../../implements/settings/settingsGeneral.py" line="104"/> <location filename="../../implements/settings/settingsGeneral.py" line="106"/>
<source>general.dbUrl.label</source> <source>general.dbUrl.label</source>
<translation> URL</translation> <translation> URL</translation>
</message> </message>