Rewrite the makeAlert and askQuestion functions to use recommended interface
This commit is contained in:
@@ -30,7 +30,7 @@ import logging
|
||||
from PyQt5.QtWidgets import QApplication, QErrorMessage
|
||||
|
||||
from novelwriter.error import exceptionHandler, logException
|
||||
from novelwriter.config import Config, Global
|
||||
from novelwriter.config import Config, NWApp
|
||||
|
||||
##
|
||||
# Version Scheme
|
||||
@@ -74,7 +74,7 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
# Create the global singleton instances
|
||||
CONFIG = Config()
|
||||
GLOBAL = Global()
|
||||
APP = NWApp()
|
||||
|
||||
|
||||
def main(sysArgs: list | None = None):
|
||||
@@ -228,7 +228,7 @@ def main(sysArgs: list | None = None):
|
||||
from novelwriter.guimain import GuiMain
|
||||
if testMode:
|
||||
nwGUI = GuiMain()
|
||||
GLOBAL.setGUI(nwGUI)
|
||||
APP.setGUI(nwGUI)
|
||||
return nwGUI
|
||||
|
||||
else:
|
||||
@@ -248,7 +248,7 @@ def main(sysArgs: list | None = None):
|
||||
|
||||
# Launch main GUI
|
||||
nwGUI = GuiMain()
|
||||
GLOBAL.setGUI(nwGUI)
|
||||
APP.setGUI(nwGUI)
|
||||
nwGUI.postLaunchTasks(cmdOpen)
|
||||
|
||||
sys.exit(nwApp.exec_())
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
"""
|
||||
novelWriter – Alert Functions
|
||||
=============================
|
||||
|
||||
File History:
|
||||
Created: 2023-08-07 [2.1b2]
|
||||
|
||||
This file is a part of novelWriter
|
||||
Copyright 2018–2023, Veronica Berglyd Olsen
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
from PyQt5.QtWidgets import QMessageBox
|
||||
|
||||
from novelwriter import GLOBAL
|
||||
from novelwriter.enum import nwAlert
|
||||
from novelwriter.constants import nwLabels
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def makeAlert(message: list[str] | str, level: nwAlert, exc: Exception | None = None) -> None:
|
||||
"""Alert both the user and the logger at the same time. The
|
||||
message can be either a string or a list of strings.
|
||||
"""
|
||||
if isinstance(message, list):
|
||||
message = list(filter(None, message)) # Strip empty strings
|
||||
popMsg = "<br>".join(message)
|
||||
logMsg = " ".join(message)
|
||||
else:
|
||||
popMsg = str(message)
|
||||
logMsg = str(message)
|
||||
|
||||
kw = {}
|
||||
if exc is not None:
|
||||
kw["exc_info"] = exc
|
||||
popMsg = f"{popMsg}<br>{type(exc).__name__}: {str(exc)}"
|
||||
|
||||
# Write to Log
|
||||
if level == nwAlert.INFO:
|
||||
logger.info(logMsg, **kw)
|
||||
elif level == nwAlert.WARN:
|
||||
logger.warning(logMsg, **kw)
|
||||
elif level == nwAlert.ERROR:
|
||||
logger.error(logMsg, **kw)
|
||||
|
||||
# Popup
|
||||
msgBox = QMessageBox()
|
||||
if level == nwAlert.INFO:
|
||||
msgBox.information(GLOBAL.gui, nwLabels.ALERT_NAME[level], popMsg)
|
||||
elif level == nwAlert.WARN:
|
||||
msgBox.warning(GLOBAL.gui, nwLabels.ALERT_NAME[level], popMsg)
|
||||
elif level == nwAlert.ERROR:
|
||||
msgBox.critical(GLOBAL.gui, nwLabels.ALERT_NAME[level], popMsg)
|
||||
|
||||
return
|
||||
|
||||
|
||||
def askQuestion(title: str, question: str) -> bool:
|
||||
"""Ask the user a Yes/No question, and return the answer."""
|
||||
msgBox = QMessageBox()
|
||||
msgRes = msgBox.question(GLOBAL.gui, title, question, QMessageBox.Yes | QMessageBox.No)
|
||||
return msgRes == QMessageBox.Yes
|
||||
@@ -17,8 +17,8 @@ licenseurl = https://creativecommons.org/licenses/by-sa/4.0/
|
||||
|
||||
[Map]
|
||||
add = typ_plus.svg
|
||||
alert_error = typ_info-large-full.svg
|
||||
alert_info = typ_delete-full.svg
|
||||
alert_error = typ_delete-full.svg
|
||||
alert_info = typ_info-large-full.svg
|
||||
alert_question = typ_lightbulb-full.svg
|
||||
alert_warn = typ_warning-full.svg
|
||||
backward = typ_chevron-left.svg
|
||||
|
||||
@@ -17,8 +17,8 @@ licenseurl = https://creativecommons.org/licenses/by-sa/4.0/
|
||||
|
||||
[Map]
|
||||
add = typ_plus.svg
|
||||
alert_error = typ_info-large-full.svg
|
||||
alert_info = typ_delete-full.svg
|
||||
alert_error = typ_delete-full.svg
|
||||
alert_info = typ_info-large-full.svg
|
||||
alert_question = typ_lightbulb-full.svg
|
||||
alert_warn = typ_warning-full.svg
|
||||
backward = typ_chevron-left.svg
|
||||
|
||||
@@ -798,7 +798,7 @@ class Config:
|
||||
# END Class Config
|
||||
|
||||
|
||||
class Global:
|
||||
class NWApp:
|
||||
"""Singleton: Global Pointers
|
||||
|
||||
This class holds pointers to the core singletons:
|
||||
@@ -852,7 +852,7 @@ class Global:
|
||||
self._project = project
|
||||
return
|
||||
|
||||
# END Class Global
|
||||
# END Class NWApp
|
||||
|
||||
|
||||
class RecentProjects:
|
||||
|
||||
@@ -167,6 +167,7 @@ class nwLabels:
|
||||
nwAlert.INFO: QT_TRANSLATE_NOOP("Constant", "Information"),
|
||||
nwAlert.WARN: QT_TRANSLATE_NOOP("Constant", "Warning"),
|
||||
nwAlert.ERROR: QT_TRANSLATE_NOOP("Constant", "Error"),
|
||||
nwAlert.ASK: QT_TRANSLATE_NOOP("Constant", "Question"),
|
||||
}
|
||||
ITEM_DESCRIPTION = {
|
||||
"none": QT_TRANSLATE_NOOP("Constant", "None"),
|
||||
|
||||
@@ -125,6 +125,7 @@ class nwAlert(Enum):
|
||||
INFO = 0
|
||||
WARN = 1
|
||||
ERROR = 2
|
||||
ASK = 3
|
||||
|
||||
# END Enum nwAlert
|
||||
|
||||
|
||||
+21
-17
@@ -1,7 +1,6 @@
|
||||
"""
|
||||
novelWriter – Exception Handling
|
||||
================================
|
||||
Error handling function and error dialog
|
||||
|
||||
File History:
|
||||
Created: 2020-08-02 [0.10.2]
|
||||
@@ -22,18 +21,24 @@ General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
import random
|
||||
import logging
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from PyQt5.QtGui import QFont, QFontDatabase
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtCore import Qt, pyqtSlot
|
||||
from PyQt5.QtWidgets import (
|
||||
qApp, QDialog, QGridLayout, QStyle, QPlainTextEdit, QLabel,
|
||||
QWidget, qApp, QDialog, QGridLayout, QStyle, QPlainTextEdit, QLabel,
|
||||
QDialogButtonBox
|
||||
)
|
||||
|
||||
if TYPE_CHECKING: # pragma: no cover
|
||||
from types import TracebackType
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -41,15 +46,15 @@ logger = logging.getLogger(__name__)
|
||||
# Utility Functions
|
||||
# =============================================================================================== #
|
||||
|
||||
def logException():
|
||||
"""Log the content of an exception message.
|
||||
"""
|
||||
def logException() -> None:
|
||||
"""Log the content of an exception message."""
|
||||
exType, exValue, _ = sys.exc_info()
|
||||
if exType is not None:
|
||||
logger.error("%s: %s", exType.__name__, str(exValue))
|
||||
return
|
||||
|
||||
|
||||
def formatException(exc):
|
||||
def formatException(exc) -> str:
|
||||
"""Format an exception as a string the same way the default
|
||||
exception handler does.
|
||||
"""
|
||||
@@ -62,7 +67,7 @@ def formatException(exc):
|
||||
|
||||
class NWErrorMessage(QDialog):
|
||||
|
||||
def __init__(self, parent):
|
||||
def __init__(self, parent: QWidget) -> None:
|
||||
super().__init__(parent=parent)
|
||||
self.setObjectName("NWErrorMessage")
|
||||
|
||||
@@ -113,7 +118,7 @@ class NWErrorMessage(QDialog):
|
||||
|
||||
return
|
||||
|
||||
def setMessage(self, exType, exValue, exTrace):
|
||||
def setMessage(self, exType: type, exValue: BaseException, exTrace: TracebackType) -> None:
|
||||
"""Generate a message and append session data, error info and
|
||||
error traceback.
|
||||
"""
|
||||
@@ -142,7 +147,7 @@ class NWErrorMessage(QDialog):
|
||||
enchantVersion = "Unknown"
|
||||
|
||||
try:
|
||||
exTrace = "\n".join(format_tb(exTrace))
|
||||
txtTrace = "\n".join(format_tb(exTrace))
|
||||
self.msgBody.setPlainText((
|
||||
"Environment:\n"
|
||||
f"novelWriter Version: {__version__}\n"
|
||||
@@ -151,7 +156,7 @@ class NWErrorMessage(QDialog):
|
||||
f"Qt: {QT_VERSION_STR}, PyQt: {PYQT_VERSION_STR}\n"
|
||||
f"enchant: {enchantVersion}\n\n"
|
||||
f"{exType.__name__}:\n{str(exValue)}\n\n"
|
||||
f"Traceback:\n{exTrace}\n"
|
||||
f"Traceback:\n{txtTrace}\n"
|
||||
))
|
||||
except Exception:
|
||||
self.msgBody.setPlainText("Failed to generate error report ...")
|
||||
@@ -162,18 +167,17 @@ class NWErrorMessage(QDialog):
|
||||
# Slots
|
||||
##
|
||||
|
||||
def _doClose(self):
|
||||
"""Close the dialog.
|
||||
"""
|
||||
@pyqtSlot()
|
||||
def _doClose(self) -> None:
|
||||
"""Close the dialog."""
|
||||
self.close()
|
||||
return
|
||||
|
||||
# END Class NWErrorMessage
|
||||
|
||||
|
||||
def exceptionHandler(exType, exValue, exTrace):
|
||||
"""Function to catch unhandled global exceptions.
|
||||
"""
|
||||
def exceptionHandler(exType: type, exValue: BaseException, exTrace: TracebackType) -> None:
|
||||
"""Function to catch unhandled global exceptions."""
|
||||
from traceback import print_tb
|
||||
from PyQt5.QtWidgets import qApp
|
||||
|
||||
|
||||
+90
-77
@@ -31,14 +31,13 @@ from pathlib import Path
|
||||
from datetime import datetime
|
||||
|
||||
from PyQt5.QtCore import Qt, QTimer, QThreadPool, pyqtSlot
|
||||
from PyQt5.QtGui import QCloseEvent, QCursor, QIcon, QKeySequence
|
||||
from PyQt5.QtGui import QCloseEvent, QCursor, QIcon, QKeySequence, QPixmap
|
||||
from PyQt5.QtWidgets import (
|
||||
qApp, QDialog, QFileDialog, QMainWindow, QMessageBox, QShortcut, QSplitter,
|
||||
QStackedWidget, QVBoxLayout, QWidget
|
||||
)
|
||||
|
||||
from novelwriter import CONFIG, GLOBAL, __hexversion__
|
||||
from novelwriter.alert import askQuestion, makeAlert
|
||||
from novelwriter import CONFIG, APP, __hexversion__
|
||||
from novelwriter.gui.theme import GuiTheme
|
||||
from novelwriter.gui.sidebar import GuiSideBar
|
||||
from novelwriter.gui.outline import GuiOutlineView
|
||||
@@ -67,7 +66,7 @@ from novelwriter.enum import (
|
||||
nwDocAction, nwDocMode, nwItemType, nwItemClass, nwAlert, nwWidget, nwView
|
||||
)
|
||||
from novelwriter.common import getGuiItem, hexToInt
|
||||
from novelwriter.constants import nwFiles
|
||||
from novelwriter.constants import nwFiles, nwLabels, trConst
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -116,8 +115,8 @@ class GuiMain(QMainWindow):
|
||||
# Core Classes
|
||||
self.mainTheme = GuiTheme()
|
||||
self.theProject = NWProject(self)
|
||||
GLOBAL.setTheme(self.mainTheme)
|
||||
GLOBAL.setProject(self.theProject)
|
||||
APP.setTheme(self.mainTheme)
|
||||
APP.setProject(self.theProject)
|
||||
|
||||
# Core Settings
|
||||
self.hasProject = False
|
||||
@@ -318,6 +317,16 @@ class GuiMain(QMainWindow):
|
||||
# Handle Windows Mode
|
||||
self.showNormal()
|
||||
|
||||
# Cache Icons
|
||||
|
||||
aPx = CONFIG.pxInt(48)
|
||||
self.alertPix: dict[nwAlert, QPixmap] = {
|
||||
nwAlert.INFO: self.mainTheme.getPixmap("alert_info", (aPx, aPx)),
|
||||
nwAlert.WARN: self.mainTheme.getPixmap("alert_warn", (aPx, aPx)),
|
||||
nwAlert.ERROR: self.mainTheme.getPixmap("alert_error", (aPx, aPx)),
|
||||
nwAlert.ASK: self.mainTheme.getPixmap("alert_question", (aPx, aPx)),
|
||||
}
|
||||
|
||||
logger.debug("Ready: GUI")
|
||||
|
||||
if __hexversion__[-2] == "a" and logger.getEffectiveLevel() > logging.DEBUG:
|
||||
@@ -325,7 +334,7 @@ class GuiMain(QMainWindow):
|
||||
"You are running an untested development version of novelWriter. "
|
||||
"Please be careful when working on a live project "
|
||||
"and make sure you take regular backups."
|
||||
), nwAlert.WARN)
|
||||
), level=nwAlert.WARN)
|
||||
|
||||
logger.info("novelWriter is ready ...")
|
||||
self.setStatus(self.tr("novelWriter is ready ..."))
|
||||
@@ -385,7 +394,7 @@ class GuiMain(QMainWindow):
|
||||
if not self.closeProject():
|
||||
self.makeAlert(self.tr(
|
||||
"Cannot create a new project when another project is open."
|
||||
), nwAlert.ERROR)
|
||||
), level=nwAlert.ERROR)
|
||||
return False
|
||||
|
||||
if projData is None:
|
||||
@@ -403,7 +412,7 @@ class GuiMain(QMainWindow):
|
||||
self.makeAlert(self.tr(
|
||||
"A project already exists in that location. "
|
||||
"Please choose another folder."
|
||||
), nwAlert.ERROR)
|
||||
), level=nwAlert.ERROR)
|
||||
return False
|
||||
|
||||
logger.info("Creating new project")
|
||||
@@ -425,13 +434,10 @@ class GuiMain(QMainWindow):
|
||||
return True
|
||||
|
||||
if not isYes:
|
||||
msgYes = self.askQuestion(
|
||||
self.tr("Close Project"),
|
||||
"%s<br>%s" % (
|
||||
self.tr("Close the current project?"),
|
||||
self.tr("Changes are saved automatically.")
|
||||
)
|
||||
)
|
||||
msgYes = self.askQuestion("%s<br>%s" % (
|
||||
self.tr("Close the current project?"),
|
||||
self.tr("Changes are saved automatically.")
|
||||
))
|
||||
if not msgYes:
|
||||
return False
|
||||
|
||||
@@ -443,10 +449,7 @@ class GuiMain(QMainWindow):
|
||||
if self.theProject.data.doBackup and CONFIG.backupOnClose:
|
||||
doBackup = True
|
||||
if CONFIG.askBeforeBackup:
|
||||
msgYes = self.askQuestion(
|
||||
self.tr("Backup Project"),
|
||||
self.tr("Backup the current project?")
|
||||
)
|
||||
msgYes = self.askQuestion(self.tr("Backup the current project?"))
|
||||
if not msgYes:
|
||||
doBackup = False
|
||||
|
||||
@@ -485,19 +488,28 @@ class GuiMain(QMainWindow):
|
||||
# Try to open the project
|
||||
if not self.theProject.openProject(projFile):
|
||||
# The project open failed.
|
||||
|
||||
lockStatus = self.theProject.getLockStatus()
|
||||
if lockStatus is None:
|
||||
# The project is not locked, so failed for some other
|
||||
# reason handled by the project class.
|
||||
return False
|
||||
|
||||
lockText = self.tr(
|
||||
"The project is already open by another instance of "
|
||||
"novelWriter, and is therefore locked. Override lock "
|
||||
"and continue anyway?"
|
||||
)
|
||||
lockInfo = self.tr(
|
||||
"Note: If the program or the computer previously "
|
||||
"crashed, the lock can safely be overridden. However, "
|
||||
"overriding it is not recommended if the project is "
|
||||
"open in another instance of novelWriter. Doing so "
|
||||
"may corrupt the project."
|
||||
)
|
||||
try:
|
||||
lockDetails = (
|
||||
"<br>%s" % self.tr(
|
||||
"The project was locked by the computer "
|
||||
"'{0}' ({1} {2}), last active on {3}."
|
||||
)
|
||||
lockDetails = self.tr(
|
||||
"The project was locked by the computer "
|
||||
"'{0}' ({1} {2}), last active on {3}."
|
||||
).format(
|
||||
lockStatus[0], lockStatus[1], lockStatus[2],
|
||||
datetime.fromtimestamp(int(lockStatus[3])).strftime("%x %X")
|
||||
@@ -505,27 +517,7 @@ class GuiMain(QMainWindow):
|
||||
except Exception:
|
||||
lockDetails = ""
|
||||
|
||||
msgBox = QMessageBox()
|
||||
msgRes = msgBox.warning(
|
||||
self, self.tr("Project Locked"),
|
||||
"%s<br><br>%s<br>%s" % (
|
||||
self.tr(
|
||||
"The project is already open by another instance of "
|
||||
"novelWriter, and is therefore locked. Override lock "
|
||||
"and continue anyway?"
|
||||
),
|
||||
self.tr(
|
||||
"Note: If the program or the computer previously "
|
||||
"crashed, the lock can safely be overridden. However, "
|
||||
"overriding it is not recommended if the project is "
|
||||
"open in another instance of novelWriter. Doing so "
|
||||
"may corrupt the project."
|
||||
),
|
||||
lockDetails
|
||||
),
|
||||
QMessageBox.Yes | QMessageBox.No, QMessageBox.No
|
||||
)
|
||||
if msgRes == QMessageBox.Yes:
|
||||
if self.askQuestion(lockText, info=lockInfo, details=lockDetails, level=nwAlert.WARN):
|
||||
if not self.theProject.openProject(projFile, overrideLock=True):
|
||||
return False
|
||||
else:
|
||||
@@ -565,9 +557,7 @@ class GuiMain(QMainWindow):
|
||||
|
||||
# Check if we need to rebuild the index
|
||||
if self.theProject.index.indexBroken:
|
||||
self.makeAlert(self.tr(
|
||||
"The project index is outdated or broken. Rebuilding index."
|
||||
), nwAlert.INFO)
|
||||
self.makeAlert(self.tr("The project index is outdated or broken. Rebuilding index."))
|
||||
self.rebuildIndex()
|
||||
|
||||
# Make sure the changed status is set to false on things opened
|
||||
@@ -756,23 +746,20 @@ class GuiMain(QMainWindow):
|
||||
except Exception as exc:
|
||||
self.makeAlert(self.tr(
|
||||
"Could not read file. The file must be an existing text file."
|
||||
), nwAlert.ERROR, exception=exc)
|
||||
), level=nwAlert.ERROR, exception=exc)
|
||||
return False
|
||||
|
||||
if self.docEditor.docHandle() is None:
|
||||
self.makeAlert(self.tr(
|
||||
"Please open a document to import the text file into."
|
||||
), nwAlert.ERROR)
|
||||
), level=nwAlert.ERROR)
|
||||
return False
|
||||
|
||||
if not self.docEditor.isEmpty():
|
||||
msgYes = self.askQuestion(
|
||||
self.tr("Import Document"),
|
||||
self.tr(
|
||||
"Importing the file will overwrite the current content of "
|
||||
"the document. Do you want to proceed?"
|
||||
)
|
||||
)
|
||||
msgYes = self.askQuestion(self.tr(
|
||||
"Importing the file will overwrite the current content of "
|
||||
"the document. Do you want to proceed?"
|
||||
))
|
||||
if not msgYes:
|
||||
return False
|
||||
|
||||
@@ -871,9 +858,7 @@ class GuiMain(QMainWindow):
|
||||
qApp.restoreOverrideCursor()
|
||||
|
||||
if not beQuiet:
|
||||
self.makeAlert(self.tr(
|
||||
"The project index has been successfully rebuilt."
|
||||
), nwAlert.INFO)
|
||||
self.makeAlert(self.tr("The project index has been successfully rebuilt."))
|
||||
|
||||
return True
|
||||
|
||||
@@ -921,7 +906,7 @@ class GuiMain(QMainWindow):
|
||||
if dlgConf.needsRestart:
|
||||
self.makeAlert(self.tr(
|
||||
"Some changes will not be applied until novelWriter has been restarted."
|
||||
), nwAlert.INFO)
|
||||
))
|
||||
|
||||
if dlgConf.refreshTree:
|
||||
self.projView.populateTree()
|
||||
@@ -1102,17 +1087,48 @@ class GuiMain(QMainWindow):
|
||||
|
||||
return
|
||||
|
||||
def makeAlert(self, message: list[str] | str, level: nwAlert = nwAlert.INFO,
|
||||
exception: Exception | None = None) -> None:
|
||||
def makeAlert(self, text: str, info: str = "", details: str = "",
|
||||
level: nwAlert = nwAlert.INFO, exception: Exception | None = None) -> None:
|
||||
"""Alert both the user and the logger at the same time. The
|
||||
message can be either a string or a list of strings.
|
||||
"""
|
||||
makeAlert(message, level, exception)
|
||||
logText = " ".join(filter(None, [text, info, details]))
|
||||
if level == nwAlert.INFO:
|
||||
logger.info(logText, stacklevel=2)
|
||||
elif level == nwAlert.WARN:
|
||||
logger.warning(logText, stacklevel=2)
|
||||
elif level == nwAlert.ERROR:
|
||||
logger.error(logText, stacklevel=2, exc_info=exception)
|
||||
|
||||
if exception is not None:
|
||||
excText = f"{type(exception).__name__}: {str(exception)}"
|
||||
info = f"{info}<br>{excText}" if info else excText
|
||||
|
||||
msgBox = QMessageBox(self)
|
||||
msgBox.setWindowTitle(trConst(nwLabels.ALERT_NAME[level]))
|
||||
msgBox.setText(text)
|
||||
msgBox.setInformativeText(info)
|
||||
msgBox.setDetailedText(details)
|
||||
msgBox.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
|
||||
msgBox.setIconPixmap(self.alertPix[level])
|
||||
msgBox.adjustSize()
|
||||
msgBox.exec_()
|
||||
|
||||
return
|
||||
|
||||
def askQuestion(self, title: str, question: str) -> bool:
|
||||
def askQuestion(self, text: str, info: str = "", details: str = "",
|
||||
level: nwAlert = nwAlert.ASK) -> bool:
|
||||
"""Ask the user a Yes/No question, and return the answer."""
|
||||
return askQuestion(title, question)
|
||||
msgBox = QMessageBox(self)
|
||||
msgBox.setWindowTitle(trConst(nwLabels.ALERT_NAME[level]))
|
||||
msgBox.setText(text)
|
||||
msgBox.setInformativeText(info)
|
||||
msgBox.setDetailedText(details)
|
||||
msgBox.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
|
||||
msgBox.setIconPixmap(self.alertPix[level])
|
||||
msgBox.adjustSize()
|
||||
msgBox.exec_()
|
||||
return msgBox.result() == QMessageBox.Yes
|
||||
|
||||
def reportConfErr(self) -> bool:
|
||||
"""Checks if the Config module has any errors to report, and let
|
||||
@@ -1120,7 +1136,7 @@ class GuiMain(QMainWindow):
|
||||
errors since it is initialised before the GUI itself.
|
||||
"""
|
||||
if CONFIG.hasError:
|
||||
self.makeAlert(CONFIG.errorText(), nwAlert.ERROR)
|
||||
self.makeAlert(CONFIG.errorText(), level=nwAlert.ERROR)
|
||||
return True
|
||||
return False
|
||||
|
||||
@@ -1131,13 +1147,10 @@ class GuiMain(QMainWindow):
|
||||
def closeMain(self) -> bool:
|
||||
"""Save everything, and close novelWriter."""
|
||||
if self.hasProject:
|
||||
msgYes = self.askQuestion(
|
||||
self.tr("Exit"),
|
||||
"%s<br>%s" % (
|
||||
self.tr("Do you want to exit novelWriter?"),
|
||||
self.tr("Changes are saved automatically.")
|
||||
)
|
||||
)
|
||||
msgYes = self.askQuestion("%s<br>%s" % (
|
||||
self.tr("Do you want to exit novelWriter?"),
|
||||
self.tr("Changes are saved automatically.")
|
||||
))
|
||||
if not msgYes:
|
||||
return False
|
||||
|
||||
@@ -1388,7 +1401,7 @@ class GuiMain(QMainWindow):
|
||||
"from the Tools menu, or by pressing {1}."
|
||||
).format(
|
||||
tag, "F9"
|
||||
), nwAlert.ERROR)
|
||||
), level=nwAlert.ERROR)
|
||||
return None, None
|
||||
return tHandle, sTitle
|
||||
|
||||
|
||||
Reference in New Issue
Block a user