Move to asynchronous implementation on mbox/dialog

Signed-off-by: Loren Eteval <loren.eteval@proton.me>
This commit is contained in:
Loren Eteval
2024-04-28 22:43:09 +08:00
parent 9df8bb131c
commit ea5587bee3
10 changed files with 233 additions and 152 deletions
+24 -17
View File
@@ -98,8 +98,7 @@ class UpdatesManager(AppQNetworkAccessManager):
def __init__(self, parent=None):
super().__init__(parent)
@staticmethod
def handleFinishedByNetworkReply(networkReply):
def handleFinishedByNetworkReply(self, networkReply):
assert isinstance(networkReply, QNetworkReply)
if networkReply.error() != QNetworkReply.NetworkError.NoError:
@@ -109,8 +108,8 @@ class UpdatesManager(AppQNetworkAccessManager):
mbox.setWindowTitle(_(APPLICATION_NAME))
mbox.setText(_('Check for updates failed'))
# Show the MessageBox and wait for user to close it
mbox.exec()
# Show the MessageBox asynchronously
mbox.open()
else:
logger.info('check for updates success')
@@ -118,29 +117,37 @@ class UpdatesManager(AppQNetworkAccessManager):
info = UJSONEncoder.decode(networkReply.readAll().data())
if versionToNumber(info['tag_name']) > versionToNumber(APPLICATION_VERSION):
def handleResultCode(code):
if code == PySide6LegacyEnumValueWrapper(
AppQMessageBox.StandardButton.Yes
):
if QDesktopServices.openUrl(QtCore.QUrl(info['html_url'])):
logger.info('open download page success')
else:
logger.error('open download page failed')
else:
# Do nothing
pass
mbox = QuestionUpdateMBox(icon=AppQMessageBox.Icon.Information)
mbox.version = info['tag_name']
mbox.setText(mbox.customText())
mbox.setInformativeText(_('Go to download page?'))
mbox.finished.connect(functools.partial(handleResultCode))
# Show the MessageBox and wait for user to close it
if mbox.exec() == PySide6LegacyEnumValueWrapper(
AppQMessageBox.StandardButton.Yes
):
if QDesktopServices.openUrl(QtCore.QUrl(info['html_url'])):
logger.info('open download page success')
else:
logger.error('open download page failed')
else:
# Do nothing
pass
# dummy ref
setattr(self, '_questionUpdateMBox', mbox)
# Show the MessageBox asynchronously
mbox.open()
else:
mbox = AppQMessageBox(icon=AppQMessageBox.Icon.Information)
mbox.setWindowTitle(_(APPLICATION_NAME))
mbox.setText(_(f'{APPLICATION_NAME} is already the latest version'))
# Show the MessageBox and wait for user to close it
mbox.exec()
# Show the MessageBox asynchronously
mbox.open()
def configureHttpProxy(self, httpProxy: Union[str, None]) -> bool:
useProxy = super().configureHttpProxy(httpProxy)
+6 -6
View File
@@ -193,8 +193,8 @@ class ConnectAction(AppQAction):
_('Server configuration empty. Please configure your server first')
)
# Show the MessageBox and wait for user to close it
mbox.exec()
# Show the MessageBox asynchronously
mbox.open()
return
@@ -209,8 +209,8 @@ class ConnectAction(AppQAction):
_('Select and double click to activate configuration and connect')
)
# Show the MessageBox and wait for user to close it
mbox.exec()
# Show the MessageBox asynchronously
mbox.open()
return
@@ -242,8 +242,8 @@ class ConnectAction(AppQAction):
)
mbox.setInformativeText(_('Please complete your server configuration'))
# Show the MessageBox and wait for user to close it
mbox.exec()
# Show the MessageBox asynchronously
mbox.open()
return
+19 -8
View File
@@ -55,7 +55,8 @@ def showImportErrorMBox(clipboard: str):
mbox.setText(_('Invalid data. The content of the clipboard is:'))
mbox.setInformativeText(clipboard)
mbox.exec()
# Show the MessageBox asynchronously
mbox.open()
def importItemFromClipboard(clipboard: str):
@@ -69,7 +70,9 @@ def importItemFromClipboard(clipboard: str):
mbox = ImportSuccessMBox(icon=AppQMessageBox.Icon.Information)
mbox.remark = factory.getExtras('remark')
mbox.setText(mbox.customText())
mbox.exec()
# Show the MessageBox asynchronously
mbox.open()
needTrans('Import')
@@ -193,8 +196,8 @@ class ImportFromFileAction(AppQAction):
mbox.setText(_('Invalid configuration file'))
mbox.setInformativeText(str(ex))
# Show the MessageBox and wait for user to close it
mbox.exec()
# Show the MessageBox asynchronously
mbox.open()
else:
factory = constructFromAny(plainText, remark=os.path.basename(filename))
@@ -204,12 +207,16 @@ class ImportFromFileAction(AppQAction):
mbox = ImportSuccessMBox(icon=AppQMessageBox.Icon.Information)
mbox.remark = factory.getExtras('remark')
mbox.setText(mbox.customText())
mbox.exec()
# Show the MessageBox asynchronously
mbox.open()
else:
mbox = ImportErrorMBox(icon=AppQMessageBox.Icon.Critical)
mbox.setText(_('Invalid data'))
mbox.setInformativeText('')
mbox.show()
# Show the MessageBox asynchronously
mbox.open()
needTrans('Import Share Link From Clipboard')
@@ -248,13 +255,17 @@ class ImportURIFromClipboardAction(AppQAction):
mbox = ImportSuccessMBox(icon=AppQMessageBox.Icon.Information)
mbox.remark = imported[0]
mbox.setText(mbox.customText())
mbox.exec()
# Show the MessageBox asynchronously
mbox.open()
else:
mbox = ImportMultiSuccessMBox(icon=AppQMessageBox.Icon.Information)
mbox.imported = imported
mbox.rowCount = rowCount
mbox.setText(mbox.customText())
mbox.exec()
# Show the MessageBox asynchronously
mbox.open()
needTrans('Import JSON Configuration From Clipboard')
+3 -1
View File
@@ -63,7 +63,9 @@ class VPNModeAction(AppQAction):
try:
if APP().isSystemTrayConnected():
mbox = NewChangesNextTimeMBox()
mbox.exec()
# Show the MessageBox asynchronously
mbox.open()
except Exception:
# Any non-exit exceptions
+17 -9
View File
@@ -868,8 +868,9 @@ class UserServersQTableWidget(QTranslatable, AppQTableWidget):
# Show the MessageBox asynchronously
mbox.open()
else:
# Show the MessageBox and wait for user to close it
mbox.exec()
# Show the MessageBox asynchronously
# TODO: Verify
mbox.open()
return
@@ -939,7 +940,9 @@ class UserServersQTableWidget(QTranslatable, AppQTableWidget):
try:
if modified and APP().isSystemTrayConnected():
mbox = NewChangesNextTimeMBox()
mbox.exec()
# Show the MessageBox asynchronously
mbox.open()
except Exception:
# Any non-exit exceptions
@@ -1220,18 +1223,23 @@ class UserServersQTableWidget(QTranslatable, AppQTableWidget):
# Nothing selected. Do nothing
return
def handleResultCode(_indexes, code):
if code == PySide6LegacyEnumValueWrapper(AppQMessageBox.StandardButton.Yes):
self.deleteItemByIndex(_indexes)
else:
pass
mbox = QuestionDeleteMBox(icon=AppQMessageBox.Icon.Question)
mbox.isMulti = bool(len(indexes) > 1)
mbox.possibleRemark = f'{indexes[0] + 1} - {self.item(indexes[0], 0).text()}'
mbox.setText(mbox.customText())
mbox.finished.connect(functools.partial(handleResultCode, indexes))
if mbox.exec() == PySide6LegacyEnumValueWrapper(
AppQMessageBox.StandardButton.No
):
# Do not delete
return
# dummy ref
setattr(self, '_questionDeleteMBox', mbox)
self.deleteItemByIndex(indexes)
# Show the MessageBox asynchronously
mbox.open()
def editSelectedItemConfiguration(self):
indexes = self.selectedIndex
+21 -15
View File
@@ -151,27 +151,33 @@ class UserSubsQTableWidget(QTranslatable, AppQTableWidget):
# Nothing to do
return
def handleResultCode(_indexes, code):
if code == PySide6LegacyEnumValueWrapper(AppQMessageBox.StandardButton.Yes):
for i in range(len(_indexes)):
deleteIndex = _indexes[i] - i
deleteUnique = list(AS_UserSubscription().keys())[deleteIndex]
self.removeRow(deleteIndex)
AS_UserSubscription().pop(deleteUnique)
if callable(self.deleteUniqueCallback):
self.deleteUniqueCallback(deleteUnique)
else:
# Do not delete
pass
mbox = QuestionDeleteMBox(icon=AppQMessageBox.Icon.Question)
mbox.isMulti = bool(len(indexes) > 1)
mbox.possibleRemark = self.item(indexes[0], 0).text()
mbox.setText(mbox.customText())
mbox.finished.connect(functools.partial(handleResultCode, indexes))
if mbox.exec() == PySide6LegacyEnumValueWrapper(
AppQMessageBox.StandardButton.No
):
# Do not delete
return
# dummy ref
setattr(self, '_questionDeleteMBox', mbox)
for i in range(len(indexes)):
deleteIndex = indexes[i] - i
deleteUnique = list(AS_UserSubscription().keys())[deleteIndex]
self.removeRow(deleteIndex)
AS_UserSubscription().pop(deleteUnique)
if callable(self.deleteUniqueCallback):
self.deleteUniqueCallback(deleteUnique)
# Show the MessageBox asynchronously
mbox.open()
def flushItem(self, row, column, item):
header = self.Headers[column]
+57 -37
View File
@@ -132,44 +132,58 @@ class XrayAssetViewerQListWidget(SupportThemeChangedCallback, AppQListWidget):
self.flushItemByTheme(darkdetect.theme())
def appendNewItem(self, filename: str):
def append(_filename):
try:
shutil.copy(_filename, XRAY_ASSET_DIR)
except shutil.SameFileError:
# Same file imported. Do nothing
pass
except Exception as ex:
# Any non-exit exception
_mbox = AppQMessageBox(icon=AppQMessageBox.Icon.Critical)
_mbox.setWindowTitle(_('Import'))
_mbox.setText(_('Error import asset file'))
_mbox.setInformativeText(str(ex))
# Show the MessageBox asynchronously
_mbox.open()
else:
self.flushItem()
_mbox = AppQMessageBox(icon=AppQMessageBox.Icon.Information)
_mbox.setWindowTitle(_('Import'))
_mbox.setText(_('Import asset file success'))
# Show the MessageBox asynchronously
_mbox.open()
basename = os.path.basename(filename)
if os.path.isfile(XRAY_ASSET_DIR / basename):
def handleResultCode(_filename, code):
if code == PySide6LegacyEnumValueWrapper(
AppQMessageBox.StandardButton.Yes
):
append(_filename)
else:
# Do not overwrite
pass
mbox = AssetExistsMBox(icon=AppQMessageBox.Icon.Question)
mbox.setWindowTitle(_('Import'))
mbox.setText(_('Asset file already exists. Overwrite?'))
mbox.setInformativeText(basename)
mbox.finished.connect(functools.partial(handleResultCode, filename))
if mbox.exec() == PySide6LegacyEnumValueWrapper(
AppQMessageBox.StandardButton.No
):
# Do not overwrite
return
# dummy ref
setattr(self, '_assetExistsMBox', mbox)
try:
shutil.copy(filename, XRAY_ASSET_DIR)
except shutil.SameFileError:
# Same file imported. Do nothing
pass
except Exception as ex:
# Any non-exit exception
mbox = AppQMessageBox(icon=AppQMessageBox.Icon.Critical)
mbox.setWindowTitle(_('Import'))
mbox.setText(_('Error import asset file'))
mbox.setInformativeText(str(ex))
# Show the MessageBox and wait for user to close it
mbox.exec()
# Show the MessageBox asynchronously
mbox.open()
else:
self.flushItem()
mbox = AppQMessageBox(icon=AppQMessageBox.Icon.Information)
mbox.setWindowTitle(_('Import'))
mbox.setText(_('Import asset file success'))
# Show the MessageBox and wait for user to close it
mbox.exec()
append(filename)
def deleteSelectedItem(self):
indexes = self.selectedIndex
@@ -178,21 +192,27 @@ class XrayAssetViewerQListWidget(SupportThemeChangedCallback, AppQListWidget):
# Nothing selected
return
def handleResultCode(_indexes, code):
if code == PySide6LegacyEnumValueWrapper(AppQMessageBox.StandardButton.Yes):
for index in _indexes:
os.remove(XRAY_ASSET_DIR / self.item(index).text())
self.flushItem()
else:
# Do not delete
pass
mbox = QuestionDeleteMBox(icon=AppQMessageBox.Icon.Question)
mbox.isMulti = bool(len(indexes) > 1)
mbox.possibleRemark = f'{self.item(indexes[0]).text()}'
mbox.setText(mbox.customText())
mbox.finished.connect(functools.partial(handleResultCode, indexes))
if mbox.exec() == PySide6LegacyEnumValueWrapper(
AppQMessageBox.StandardButton.No
):
# Do not delete
return
# dummy ref
setattr(self, '_questionDeleteMBox', mbox)
for index in indexes:
os.remove(XRAY_ASSET_DIR / self.item(index).text())
self.flushItem()
# Show the MessageBox asynchronously
mbox.open()
def keyPressEvent(self, event):
if event.key() == QtCore.Qt.Key.Key_Delete:
+2 -2
View File
@@ -75,8 +75,8 @@ def saveAsFile(content: str):
mbox.setWindowTitle(_('Error saving log'))
mbox.setText(mbox.customText())
# Show the MessageBox and wait for user to close it
mbox.exec()
# Show the MessageBox asynchronously
mbox.open()
needTrans(
+59 -41
View File
@@ -118,8 +118,6 @@ class TextEditorWindow(AppQMainWindow):
self.setWindowModality(QtCore.Qt.WindowModality.WindowModal)
self.setFixedSize(520, int(520 * GOLDEN_RATIO))
self.indentSpinBox = IndentSpinBox(parent=self)
# Current editing index
self.currentIndex = -1
@@ -270,24 +268,32 @@ class TextEditorWindow(AppQMainWindow):
def questionSave(self):
if self.modified:
mbox = QuestionSaveMBox(icon=AppQMessageBox.Icon.Question)
code = mbox.exec()
if code == PySide6LegacyEnumValueWrapper(
AppQMessageBox.ButtonRole.AcceptRole
):
if self.save():
def handleResultCode(code):
if code == PySide6LegacyEnumValueWrapper(
AppQMessageBox.ButtonRole.AcceptRole
):
if self.save():
self.hide()
if code == PySide6LegacyEnumValueWrapper(
AppQMessageBox.ButtonRole.DestructiveRole
):
self.markAsSaved()
self.hide()
if code == PySide6LegacyEnumValueWrapper(
AppQMessageBox.ButtonRole.DestructiveRole
):
self.markAsSaved()
self.hide()
if code == PySide6LegacyEnumValueWrapper(
AppQMessageBox.ButtonRole.RejectRole
):
# Cancel. Do nothing
pass
if code == PySide6LegacyEnumValueWrapper(
AppQMessageBox.ButtonRole.RejectRole
):
# Cancel. Do nothing
pass
mbox = QuestionSaveMBox(icon=AppQMessageBox.Icon.Question)
mbox.finished.connect(functools.partial(handleResultCode))
# dummy ref
setattr(self, '_questionSaveMBox', mbox)
# Show the MessageBox asynchronously
mbox.open()
else:
self.hide()
@@ -319,8 +325,8 @@ class TextEditorWindow(AppQMainWindow):
mbox.setWindowTitle(_('Error saving configuration'))
mbox.setText(mbox.customText())
# Show the MessageBox and wait for user to close it
mbox.exec()
# Show the MessageBox asynchronously
mbox.open()
return False
else:
@@ -342,7 +348,9 @@ class TextEditorWindow(AppQMainWindow):
try:
if APP().isSystemTrayConnected():
mbox = NewChangesNextTimeMBox()
mbox.exec()
# Show the MessageBox asynchronously
mbox.open()
except Exception:
# Any non-exit exceptions
@@ -369,34 +377,44 @@ class TextEditorWindow(AppQMainWindow):
mbox.setText(_('Invalid server configuration'))
mbox.setInformativeText(str(ex))
# Show the MessageBox and wait for user to close it
mbox.exec()
# Show the MessageBox asynchronously
mbox.open()
def setIndent(self):
code = self.indentSpinBox.exec()
def handleResultCode(_indentSpinBox, code):
if code == PySide6LegacyEnumValueWrapper(AppQDialog.DialogCode.Accepted):
plain = self.jsonEditor.toPlainText()
if code == PySide6LegacyEnumValueWrapper(AppQDialog.DialogCode.Accepted):
plain = self.jsonEditor.toPlainText()
try:
jsonObject = JSONEncoder.decode(plain)
except Exception as ex:
# Any non-exit exceptions
try:
jsonObject = JSONEncoder.decode(plain)
except Exception as ex:
# Any non-exit exceptions
mbox = JSONDecodeErrorMBox(icon=AppQMessageBox.Icon.Critical)
mbox.error = str(ex)
mbox.setWindowTitle(_('Error setting indent'))
mbox.setText(mbox.customText())
mbox = JSONDecodeErrorMBox(icon=AppQMessageBox.Icon.Critical)
mbox.error = str(ex)
mbox.setWindowTitle(_('Error setting indent'))
mbox.setText(mbox.customText())
# Show the MessageBox asynchronously
mbox.open()
else:
text = JSONEncoder.encode(jsonObject, indent=_indentSpinBox.value())
# Show the MessageBox and wait for user to close it
mbox.exec()
self.setPlainText(text, False)
else:
text = JSONEncoder.encode(jsonObject, indent=self.indentSpinBox.value())
# Do nothing
pass
self.setPlainText(text, False)
else:
# Do nothing
pass
indentSpinBox = IndentSpinBox(parent=self)
indentSpinBox.finished.connect(
functools.partial(handleResultCode, indentSpinBox)
)
# dummy ref
setattr(self, '_IndentSpinBox', indentSpinBox)
# Show the MessageBox asynchronously
indentSpinBox.open()
def showTabAndSpaces(self):
textOption = QTextOption()
+25 -16
View File
@@ -97,9 +97,9 @@ class UserSubsWindow(AppQMainWindow):
super().__init__(*args, **kwargs)
self.setWindowModality(QtCore.Qt.WindowModality.WindowModal)
self.setWindowTitle(_('Edit Subscription'))
self.addSubsDialog = AddSubsDialog()
self.userSubsQTableWidget = UserSubsQTableWidget(deleteUniqueCallback=callback)
self.userSubsTab = AppQTabWidget(self)
@@ -135,23 +135,32 @@ class UserSubsWindow(AppQMainWindow):
self.setGeometry(100, 100, 360 * GOLDEN_RATIO, 360)
def addSubs(self):
# Show the Dialog and wait for user to close it
if self.addSubsDialog.exec() == PySide6LegacyEnumValueWrapper(
AppQDialog.DialogCode.Accepted
):
remark = self.addSubsDialog.subsRemark()
webURL = self.addSubsDialog.subsWebURL()
def handleResultCode(_addSubsDialog, code):
if code == PySide6LegacyEnumValueWrapper(AppQDialog.DialogCode.Accepted):
remark = _addSubsDialog.subsRemark()
webURL = _addSubsDialog.subsWebURL()
if remark:
# Unique id. Used by display and deletion
unique = str(uuid.uuid4())
if remark:
# Unique id. Used by display and deletion
unique = str(uuid.uuid4())
self.userSubsQTableWidget.appendNewItem(
unique=unique, remark=remark, webURL=webURL
)
else:
# Do nothing
pass
self.userSubsQTableWidget.appendNewItem(
unique=unique, remark=remark, webURL=webURL
)
else:
# Do nothing
pass
addSubsDialog = AddSubsDialog(parent=self)
addSubsDialog.finished.connect(
functools.partial(handleResultCode, addSubsDialog)
)
# dummy ref
setattr(self, '_addSubsDialog', addSubsDialog)
# Show the MessageBox asynchronously
addSubsDialog.open()
def deleteSelectedItem(self):
self.userSubsQTableWidget.deleteSelectedItem()