+35
-23
@@ -34,6 +34,7 @@ from os import path, remove, rename
|
|||||||
from PyQt5.QtGui import QIcon
|
from PyQt5.QtGui import QIcon
|
||||||
from PyQt5.QtWidgets import QApplication, QErrorMessage
|
from PyQt5.QtWidgets import QApplication, QErrorMessage
|
||||||
|
|
||||||
|
from nw.error import exceptionHandler
|
||||||
from nw.config import Config
|
from nw.config import Config
|
||||||
|
|
||||||
__package__ = "nw"
|
__package__ = "nw"
|
||||||
@@ -249,11 +250,12 @@ def main(sysArgs=None):
|
|||||||
if errorData:
|
if errorData:
|
||||||
errApp = QApplication([])
|
errApp = QApplication([])
|
||||||
errMsg = QErrorMessage()
|
errMsg = QErrorMessage()
|
||||||
errMsg.setMinimumWidth(500)
|
errMsg.resize(500, 300)
|
||||||
errMsg.setMinimumHeight(300)
|
|
||||||
errMsg.showMessage((
|
errMsg.showMessage((
|
||||||
"ERROR: novelWriter cannot start due to the following issues:<br><br>"
|
"<h3>A critical error has been encountered</h3>"
|
||||||
" - %s<br><br>Exiting."
|
"<p>novelWriter cannot start due to the following issues:<p>"
|
||||||
|
"<p> - %s</p>"
|
||||||
|
"<p>Shutting down ...</p>"
|
||||||
) % (
|
) % (
|
||||||
"<br> - ".join(errorData)
|
"<br> - ".join(errorData)
|
||||||
))
|
))
|
||||||
@@ -276,34 +278,44 @@ def main(sysArgs=None):
|
|||||||
nwApp.setWindowIcon(QIcon(CONFIG.appIcon))
|
nwApp.setWindowIcon(QIcon(CONFIG.appIcon))
|
||||||
nwApp.setOrganizationDomain(__domain__)
|
nwApp.setOrganizationDomain(__domain__)
|
||||||
|
|
||||||
|
# We try to catch critical errors while setting up the main GUI
|
||||||
|
# by wrapping the main GUI in a try/except structure. This will
|
||||||
|
# not catch all exceptions for other parts of the application.
|
||||||
|
# For all other unhandled exceptions, we use a custom exception
|
||||||
|
# handler that pops a dialog box with the error message.
|
||||||
|
sys.excepthook = exceptionHandler
|
||||||
|
|
||||||
try:
|
try:
|
||||||
nwGUI = GuiMain()
|
nwGUI = GuiMain()
|
||||||
sys.exit(nwApp.exec_())
|
sys.exit(nwApp.exec_())
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
# novelWriter has crashed!
|
|
||||||
from traceback import print_tb, format_tb
|
|
||||||
|
|
||||||
eInfo = sys.exc_info()
|
from traceback import print_tb
|
||||||
logger.critical("%s: %s" % (eInfo[0].__name__, eInfo[1]))
|
from nw.error import formatHtmlErrMsg
|
||||||
print_tb(eInfo[2])
|
|
||||||
|
|
||||||
del nwApp
|
exType, exValue, exTrace = sys.exc_info()
|
||||||
|
|
||||||
errApp = QApplication([])
|
logger.critical("%s: %s" % (exType.__name__, str(exValue)))
|
||||||
errMsg = QErrorMessage()
|
print_tb(exTrace)
|
||||||
errMsg.setWindowTitle("Critical Error")
|
|
||||||
errMsg.setMinimumWidth(500)
|
|
||||||
errMsg.setMinimumHeight(300)
|
|
||||||
errMsg.showMessage((
|
|
||||||
"<h3>novelWriter has encountered a critical error!</h3>"
|
|
||||||
"<p><b>%s:</b><br>%s</p>"
|
|
||||||
"<p><b>Traceback:</b><br>%s</p>"
|
|
||||||
"<p>Shutting down ...</p>"
|
|
||||||
) % (eInfo[0].__name__, eInfo[1], "<br>".join(format_tb(eInfo[2]))))
|
|
||||||
errApp.exec_()
|
|
||||||
|
|
||||||
del eInfo
|
try:
|
||||||
|
del nwApp
|
||||||
|
|
||||||
|
errApp = QApplication([])
|
||||||
|
errMsg = QErrorMessage()
|
||||||
|
errMsg.setWindowTitle("Critical Error")
|
||||||
|
errMsg.resize(800, 400)
|
||||||
|
errMsg.showMessage((
|
||||||
|
"<h3>A critical error has been encountered</h3>"
|
||||||
|
"%s"
|
||||||
|
"<p>Shutting down ...</p>"
|
||||||
|
) % formatHtmlErrMsg(exType, exValue, exTrace))
|
||||||
|
errApp.exec_()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.critical("Could not create error message dialog.")
|
||||||
|
logger.critical(str(e))
|
||||||
|
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|||||||
+111
@@ -0,0 +1,111 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""novelWriter Init
|
||||||
|
|
||||||
|
novelWriter – Exception Handling
|
||||||
|
==================================
|
||||||
|
Error handling functions
|
||||||
|
|
||||||
|
File History:
|
||||||
|
Created: 2020-08-02 [0.10.2]
|
||||||
|
|
||||||
|
This file is a part of novelWriter
|
||||||
|
Copyright 2020, 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/>.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def formatHtmlErrMsg(exType, exValue, exTrace):
|
||||||
|
"""Generates a HTML version of an exception.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
import sys
|
||||||
|
from traceback import format_tb
|
||||||
|
from nw import __issuesurl__, __version__
|
||||||
|
from PyQt5.Qt import PYQT_VERSION_STR
|
||||||
|
from PyQt5.QtCore import QT_VERSION_STR, QSysInfo
|
||||||
|
|
||||||
|
fmtTrace = ""
|
||||||
|
for trEntry in format_tb(exTrace):
|
||||||
|
for trLine in trEntry.split("\n"):
|
||||||
|
stripLine = trLine.lstrip(" ")
|
||||||
|
nIndent = len(trLine) - len(stripLine)
|
||||||
|
fmtTrace += " "*nIndent + stripLine + "<br>"
|
||||||
|
|
||||||
|
theMessage = (
|
||||||
|
"<p>Please report this error by submitting an issue report on "
|
||||||
|
"GitHub, providing a description and this error message. "
|
||||||
|
"URL: <{issueUrl}>.</p>"
|
||||||
|
"<p><b>Environment</b><br>Version: {nwVersion}, OS: {osType} ({osKernel}),"
|
||||||
|
"Python: {pyVersion} ({pyHexVer:#x}), Qt: {qtVers}, PyQt: {pyqtVers}</p>"
|
||||||
|
"<p><b>Error Type</b><br>{exType}: {exMessage}</p>"
|
||||||
|
"<p><b>Traceback</b><br>{exTrace}</p>"
|
||||||
|
).format(
|
||||||
|
nwVersion = __version__,
|
||||||
|
osType = sys.platform,
|
||||||
|
osKernel = QSysInfo.kernelVersion(),
|
||||||
|
pyVersion = sys.version.split()[0],
|
||||||
|
pyHexVer = sys.hexversion,
|
||||||
|
qtVers = QT_VERSION_STR,
|
||||||
|
pyqtVers = PYQT_VERSION_STR,
|
||||||
|
issueUrl = __issuesurl__,
|
||||||
|
exType = exType.__name__,
|
||||||
|
exMessage = str(exValue),
|
||||||
|
exTrace = fmtTrace
|
||||||
|
)
|
||||||
|
|
||||||
|
return theMessage
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
return "Could not generate error message.<br>%s" % str(e)
|
||||||
|
|
||||||
|
return "Could not generate error message."
|
||||||
|
|
||||||
|
|
||||||
|
def exceptionHandler(exType, exValue, exTrace):
|
||||||
|
"""Function to catch unhandled global exceptions.
|
||||||
|
"""
|
||||||
|
import logging
|
||||||
|
from traceback import print_tb, format_tb
|
||||||
|
from nw import CONFIG
|
||||||
|
from PyQt5.QtWidgets import qApp, QApplication, QErrorMessage, QMessageBox
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
logger.error("%s: %s" % (exType.__name__, str(exValue)))
|
||||||
|
print_tb(exTrace)
|
||||||
|
|
||||||
|
if not CONFIG.showGUI:
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
nwGUI = None
|
||||||
|
for qWin in qApp.topLevelWidgets():
|
||||||
|
if qWin.objectName() == "GuiMain":
|
||||||
|
nwGUI = qWin
|
||||||
|
break
|
||||||
|
|
||||||
|
if nwGUI is None:
|
||||||
|
logger.warning("Could not find main GUI window so cannot open error dialog")
|
||||||
|
return
|
||||||
|
|
||||||
|
errMsg = QErrorMessage(nwGUI)
|
||||||
|
errMsg.setWindowTitle("Unhandled Error")
|
||||||
|
errMsg.resize(800, 400)
|
||||||
|
errMsg.showMessage((
|
||||||
|
"<h3>An unhandled error has been encountered</h3>%s"
|
||||||
|
) % formatHtmlErrMsg(exType, exValue, exTrace))
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(str(e))
|
||||||
|
|
||||||
|
return
|
||||||
@@ -432,7 +432,6 @@ class GuiBuildNovel(QDialog):
|
|||||||
def _buildPreview(self):
|
def _buildPreview(self):
|
||||||
"""Build a preview of the project in the document viewer.
|
"""Build a preview of the project in the document viewer.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Get Settings
|
# Get Settings
|
||||||
fmtTitle = self.fmtTitle.text().strip()
|
fmtTitle = self.fmtTitle.text().strip()
|
||||||
fmtChapter = self.fmtChapter.text().strip()
|
fmtChapter = self.fmtChapter.text().strip()
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ class GuiMain(QMainWindow):
|
|||||||
QMainWindow.__init__(self)
|
QMainWindow.__init__(self)
|
||||||
|
|
||||||
logger.debug("Initialising GUI ...")
|
logger.debug("Initialising GUI ...")
|
||||||
|
self.setObjectName("GuiMain")
|
||||||
self.mainConf = nw.CONFIG
|
self.mainConf = nw.CONFIG
|
||||||
|
|
||||||
# Some runtime info useful for debugging
|
# Some runtime info useful for debugging
|
||||||
|
|||||||
Reference in New Issue
Block a user