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:
David Vierra 2015-07-08 13:32:36 -10:00
parent 0584827087
commit 5c4ab7a592
6 changed files with 219 additions and 7 deletions

View 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)

View File

@ -6,6 +6,7 @@ import logging
from PySide import QtGui, QtCore
from PySide.QtCore import Qt
from mcedit2 import plugins
from mcedit2.dialogs.error_dialog import showErrorDialog
from mcedit2.util.load_ui import load_ui
from mcedit2.util.resources import resourcePath
@ -77,9 +78,13 @@ class PluginsTableModel(QtCore.QAbstractTableModel):
pluginRef.enabled = 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:
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)

View File

@ -12,6 +12,7 @@ import numpy
import sys
from mcedit2 import plugins
from mcedit2.appsettings import RecentFilesSetting, EnableLightingSetting, DevModeSetting
from mcedit2.dialogs.error_dialog import showErrorDialog
from mcedit2.dialogs.plugins_dialog import PluginsDialog
from mcedit2.library import LibraryWidget
@ -339,7 +340,8 @@ class MCEditApp(QtGui.QApplication):
for pluginRef in plugins.getAllPlugins():
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.")
@ -956,5 +958,7 @@ class MCEditApp(QtGui.QApplication):
for pluginRef in plugins.getAllPlugins():
if pluginRef.checkTimestamps():
log.info("Plugin %s changed. Reloading plugin module...", pluginRef.displayName)
pluginRef.unload()
pluginRef.load()
if not pluginRef.unload():
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)

View File

@ -121,14 +121,17 @@ class PluginRef(object):
log.info("Loaded %s (%s)", self.filename, self.displayName)
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)
return False
else:
self.loadError = None
finally:
if io:
io.close()
return True
def unload(self):
if self.pluginModule is None:
return
@ -139,12 +142,14 @@ class PluginRef(object):
sys.modules.pop(k)
break
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)
return False
else:
self.unloadError = None
self.pluginModule = None
return True
@property
def isLoaded(self):

View 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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;An Error Has Occurred:&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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 &quot;Copy to PasteBin&quot; 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>

View File

@ -9,6 +9,11 @@ import re
log = logging.getLogger(__name__)
_lastAcquiredContextInfo = None
def getContextInfo():
return _lastAcquiredContextInfo
def setDefaultFormat():
oglFormat = QtOpenGL.QGLFormat()
oglFormat.setVersion(1, 3)
@ -17,6 +22,7 @@ def setDefaultFormat():
def validateQGLContext(context):
context.makeCurrent()
versionFlags = QtOpenGL.QGLFormat.openGLVersionFlags()
log.info("OpenGL Version Info:")
for flag in (
@ -61,6 +67,8 @@ def validateQGLContext(context):
detailedText += "GL_RENDERER: %s\n" % GL.glGetString(GL.GL_RENDERER)
log.info("%s", detailedText)
global _lastAcquiredContextInfo
_lastAcquiredContextInfo = detailedText
if (not context.isValid() or not actualFormat.directRendering()
or not versionFlags & QtOpenGL.QGLFormat.OpenGL_Version_1_3