Add an error dialog and use it to show plugin load/unload errors.
Will be used later for errors in plugin execution and general errors from signal handlers and etc. "Copy to PasteBin" still not implemented.
This commit is contained in:
parent
0584827087
commit
5c4ab7a592
54
src/mcedit2/dialogs/error_dialog.py
Normal file
54
src/mcedit2/dialogs/error_dialog.py
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
"""
|
||||||
|
error_dialog
|
||||||
|
"""
|
||||||
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
|
import logging
|
||||||
|
import traceback
|
||||||
|
import sys
|
||||||
|
import platform
|
||||||
|
|
||||||
|
from PySide import QtGui
|
||||||
|
from mcedit2.util import qglcontext
|
||||||
|
|
||||||
|
from mcedit2.util.load_ui import load_ui
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
def showErrorDialog(text, tb, fatal):
|
||||||
|
dialog = ErrorDialog(text, tb, fatal)
|
||||||
|
dialog.exec_()
|
||||||
|
|
||||||
|
class ErrorDialog(QtGui.QDialog):
|
||||||
|
"""
|
||||||
|
A dialog for displaying an error traceback when something goes wrong.
|
||||||
|
|
||||||
|
Used to report compile and run errors for plugin modules and classes, and might be
|
||||||
|
used to report errors in MCEdit itself during signal or event handlers.
|
||||||
|
"""
|
||||||
|
def __init__(self, text, exc_info, fatal):
|
||||||
|
super(ErrorDialog, self).__init__()
|
||||||
|
load_ui("error_dialog.ui", baseinstance=self)
|
||||||
|
|
||||||
|
exc_type, exc_value, exc_tb = exc_info
|
||||||
|
|
||||||
|
self.errorDescriptionLabel.setText(text)
|
||||||
|
tbText = "".join(traceback.format_exception(exc_type, exc_value, exc_tb))
|
||||||
|
|
||||||
|
contextInfo = qglcontext.getContextInfo() or ""
|
||||||
|
|
||||||
|
from mcedit2 import __version__
|
||||||
|
tbText = "MCEdit version: %s\n" \
|
||||||
|
"Python version: %s\n" \
|
||||||
|
"Platform: %s\n" \
|
||||||
|
"System version: %s\n" \
|
||||||
|
"Processor: %s\n" \
|
||||||
|
"\n" \
|
||||||
|
"%s\n" \
|
||||||
|
"------\n\n" \
|
||||||
|
"%s" % (__version__, sys.version, sys.platform,
|
||||||
|
platform.platform(), platform.processor(),
|
||||||
|
contextInfo, tbText)
|
||||||
|
self.tracebackView.setText(tbText)
|
||||||
|
|
||||||
|
self.restartMCEditLabel.setVisible(fatal)
|
||||||
|
|
@ -6,6 +6,7 @@ import logging
|
|||||||
from PySide import QtGui, QtCore
|
from PySide import QtGui, QtCore
|
||||||
from PySide.QtCore import Qt
|
from PySide.QtCore import Qt
|
||||||
from mcedit2 import plugins
|
from mcedit2 import plugins
|
||||||
|
from mcedit2.dialogs.error_dialog import showErrorDialog
|
||||||
from mcedit2.util.load_ui import load_ui
|
from mcedit2.util.load_ui import load_ui
|
||||||
from mcedit2.util.resources import resourcePath
|
from mcedit2.util.resources import resourcePath
|
||||||
|
|
||||||
@ -77,9 +78,13 @@ class PluginsTableModel(QtCore.QAbstractTableModel):
|
|||||||
pluginRef.enabled = value
|
pluginRef.enabled = value
|
||||||
|
|
||||||
if value:
|
if value:
|
||||||
pluginRef.load()
|
if not pluginRef.load():
|
||||||
|
showErrorDialog("%s while loading plugin \"%s\"" % (pluginRef.loadError[0].__name__, pluginRef.displayName), pluginRef.loadError, False)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
pluginRef.unload()
|
if not pluginRef.unload():
|
||||||
|
showErrorDialog("%s while unloading plugin \"%s\"" % (pluginRef.unloadError[0].__name__, pluginRef.displayName), pluginRef.unloadError, False)
|
||||||
|
|
||||||
|
|
||||||
self.dataChanged.emit(index, index)
|
self.dataChanged.emit(index, index)
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ import numpy
|
|||||||
import sys
|
import sys
|
||||||
from mcedit2 import plugins
|
from mcedit2 import plugins
|
||||||
from mcedit2.appsettings import RecentFilesSetting, EnableLightingSetting, DevModeSetting
|
from mcedit2.appsettings import RecentFilesSetting, EnableLightingSetting, DevModeSetting
|
||||||
|
from mcedit2.dialogs.error_dialog import showErrorDialog
|
||||||
from mcedit2.dialogs.plugins_dialog import PluginsDialog
|
from mcedit2.dialogs.plugins_dialog import PluginsDialog
|
||||||
from mcedit2.library import LibraryWidget
|
from mcedit2.library import LibraryWidget
|
||||||
|
|
||||||
@ -339,7 +340,8 @@ class MCEditApp(QtGui.QApplication):
|
|||||||
|
|
||||||
for pluginRef in plugins.getAllPlugins():
|
for pluginRef in plugins.getAllPlugins():
|
||||||
if pluginRef.enabled:
|
if pluginRef.enabled:
|
||||||
pluginRef.load()
|
if not pluginRef.load():
|
||||||
|
showErrorDialog("%s while loading plugin \"%s\"" % (pluginRef.loadError[0].__name__, pluginRef.displayName), pluginRef.loadError, False)
|
||||||
|
|
||||||
log.info("Opening worlds from command line.")
|
log.info("Opening worlds from command line.")
|
||||||
|
|
||||||
@ -956,5 +958,7 @@ class MCEditApp(QtGui.QApplication):
|
|||||||
for pluginRef in plugins.getAllPlugins():
|
for pluginRef in plugins.getAllPlugins():
|
||||||
if pluginRef.checkTimestamps():
|
if pluginRef.checkTimestamps():
|
||||||
log.info("Plugin %s changed. Reloading plugin module...", pluginRef.displayName)
|
log.info("Plugin %s changed. Reloading plugin module...", pluginRef.displayName)
|
||||||
pluginRef.unload()
|
if not pluginRef.unload():
|
||||||
pluginRef.load()
|
showErrorDialog("%s while unloading plugin \"%s\"" % (pluginRef.unloadError[0].__name__, pluginRef.displayName), pluginRef.unloadError, False)
|
||||||
|
if not pluginRef.load():
|
||||||
|
showErrorDialog("%s while loading plugin \"%s\"" % (pluginRef.loadError[0].__name__, pluginRef.displayName), pluginRef.loadError, False)
|
||||||
|
@ -121,14 +121,17 @@ class PluginRef(object):
|
|||||||
|
|
||||||
log.info("Loaded %s (%s)", self.filename, self.displayName)
|
log.info("Loaded %s (%s)", self.filename, self.displayName)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.loadError = traceback.format_exc()
|
self.loadError = sys.exc_info()
|
||||||
log.exception("Error while loading plugin from %s: %r", self.filename, e)
|
log.exception("Error while loading plugin from %s: %r", self.filename, e)
|
||||||
|
return False
|
||||||
else:
|
else:
|
||||||
self.loadError = None
|
self.loadError = None
|
||||||
finally:
|
finally:
|
||||||
if io:
|
if io:
|
||||||
io.close()
|
io.close()
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
def unload(self):
|
def unload(self):
|
||||||
if self.pluginModule is None:
|
if self.pluginModule is None:
|
||||||
return
|
return
|
||||||
@ -139,12 +142,14 @@ class PluginRef(object):
|
|||||||
sys.modules.pop(k)
|
sys.modules.pop(k)
|
||||||
break
|
break
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.unloadError = traceback.format_exc()
|
self.loadError = sys.exc_info()
|
||||||
log.exception("Error while unloading plugin from %s: %r", self.filename, e)
|
log.exception("Error while unloading plugin from %s: %r", self.filename, e)
|
||||||
|
return False
|
||||||
else:
|
else:
|
||||||
self.unloadError = None
|
self.unloadError = None
|
||||||
|
|
||||||
self.pluginModule = None
|
self.pluginModule = None
|
||||||
|
return True
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def isLoaded(self):
|
def isLoaded(self):
|
||||||
|
136
src/mcedit2/ui/error_dialog.ui
Normal file
136
src/mcedit2/ui/error_dialog.ui
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>Dialog</class>
|
||||||
|
<widget class="QDialog" name="Dialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>690</width>
|
||||||
|
<height>550</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>MCEdit Error</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string><html><head/><body><p><span style=" font-size:12pt;">An Error Has Occurred:</span></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="textFormat">
|
||||||
|
<enum>Qt::RichText</enum>
|
||||||
|
</property>
|
||||||
|
<property name="scaledContents">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="errorDescriptionLabel">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>1</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>(no error yet!)</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="restartMCEditLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>It is recommended to undo the last command, save your work, and restart MCEdit.</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>Error Details:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QTextBrowser" name="tracebackView"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="text">
|
||||||
|
<string>Send this error report to the plugin or application developer to help get it fixed. </string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="text">
|
||||||
|
<string>Clicking "Copy to PasteBin" will copy a Pastebin URL to your clipboard.</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="copyToPastebinButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Copy to PasteBin</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="continueButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Continue</string>
|
||||||
|
</property>
|
||||||
|
<property name="default">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>continueButton</sender>
|
||||||
|
<signal>clicked()</signal>
|
||||||
|
<receiver>Dialog</receiver>
|
||||||
|
<slot>accept()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>650</x>
|
||||||
|
<y>523</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>505</x>
|
||||||
|
<y>5</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
@ -9,6 +9,11 @@ import re
|
|||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
_lastAcquiredContextInfo = None
|
||||||
|
|
||||||
|
def getContextInfo():
|
||||||
|
return _lastAcquiredContextInfo
|
||||||
|
|
||||||
def setDefaultFormat():
|
def setDefaultFormat():
|
||||||
oglFormat = QtOpenGL.QGLFormat()
|
oglFormat = QtOpenGL.QGLFormat()
|
||||||
oglFormat.setVersion(1, 3)
|
oglFormat.setVersion(1, 3)
|
||||||
@ -17,6 +22,7 @@ def setDefaultFormat():
|
|||||||
|
|
||||||
def validateQGLContext(context):
|
def validateQGLContext(context):
|
||||||
context.makeCurrent()
|
context.makeCurrent()
|
||||||
|
|
||||||
versionFlags = QtOpenGL.QGLFormat.openGLVersionFlags()
|
versionFlags = QtOpenGL.QGLFormat.openGLVersionFlags()
|
||||||
log.info("OpenGL Version Info:")
|
log.info("OpenGL Version Info:")
|
||||||
for flag in (
|
for flag in (
|
||||||
@ -61,6 +67,8 @@ def validateQGLContext(context):
|
|||||||
detailedText += "GL_RENDERER: %s\n" % GL.glGetString(GL.GL_RENDERER)
|
detailedText += "GL_RENDERER: %s\n" % GL.glGetString(GL.GL_RENDERER)
|
||||||
|
|
||||||
log.info("%s", detailedText)
|
log.info("%s", detailedText)
|
||||||
|
global _lastAcquiredContextInfo
|
||||||
|
_lastAcquiredContextInfo = detailedText
|
||||||
|
|
||||||
if (not context.isValid() or not actualFormat.directRendering()
|
if (not context.isValid() or not actualFormat.directRendering()
|
||||||
or not versionFlags & QtOpenGL.QGLFormat.OpenGL_Version_1_3
|
or not versionFlags & QtOpenGL.QGLFormat.OpenGL_Version_1_3
|
||||||
|
Reference in New Issue
Block a user