From 7093f7e80fb3f8246c027e82851a4ea0a955b8d4 Mon Sep 17 00:00:00 2001
From: Kovid Goyal
Date: Sun, 5 Aug 2007 01:28:13 +0000
Subject: [PATCH] Report unhandled exceptions.
---
src/libprs500/gui2/main.py | 47 ++++++++++++++++++++++++++------------
1 file changed, 33 insertions(+), 14 deletions(-)
diff --git a/src/libprs500/gui2/main.py b/src/libprs500/gui2/main.py
index 608a0ef172..f9c880de63 100644
--- a/src/libprs500/gui2/main.py
+++ b/src/libprs500/gui2/main.py
@@ -12,12 +12,11 @@
## You should have received a copy of the GNU General Public License along
## with this program; if not, write to the Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.Warning
-import os, tempfile, sys
+import os, tempfile, sys, traceback
from PyQt4.QtCore import Qt, SIGNAL, QObject, QCoreApplication, \
- QSettings, QVariant, QSize, QThread, QModelIndex
-from PyQt4.QtGui import QPixmap, QColor, QPainter, QMenu, QIcon, QMessageBox, \
- QItemSelectionModel
+ QSettings, QVariant, QSize, QThread
+from PyQt4.QtGui import QPixmap, QColor, QPainter, QMenu, QIcon, QMessageBox
from PyQt4.QtSvg import QSvgRenderer
from libprs500 import __version__, __appname__
@@ -59,6 +58,8 @@ class Main(QObject, Ui_MainWindow):
self.upload_memory = {}
self.delete_memory = {}
self.default_thumbnail = None
+ self.device_error_dialog = error_dialog(self.window, 'Error communicating with device', ' ')
+ self.device_error_dialog.setModal(Qt.NonModal)
####################### Location View ########################
QObject.connect(self.location_view, SIGNAL('location_selected(PyQt_PyObject)'),
self.location_selected)
@@ -166,7 +167,7 @@ class Main(QObject, Ui_MainWindow):
Called once device information has been read.
'''
if exception:
- self.job_exception(id, description, exception, formatted_traceback)
+ self.device_job_exception(id, description, exception, formatted_traceback)
return
info, cp, fs = result
self.location_view.model().update_devices(cp, fs)
@@ -179,7 +180,7 @@ class Main(QObject, Ui_MainWindow):
Called once metadata has been read for all books on the device.
'''
if exception:
- self.job_exception(id, description, exception, formatted_traceback)
+ self.device_job_exception(id, description, exception, formatted_traceback)
return
mainlist, cardlist = result
self.memory_view.set_database(mainlist)
@@ -207,7 +208,7 @@ class Main(QObject, Ui_MainWindow):
Called once metadata has been uploaded.
'''
if exception:
- self.job_exception(id, description, exception, formatted_traceback)
+ self.device_job_exception(id, description, exception, formatted_traceback)
return
cp, fs = result
self.location_view.model().update_devices(cp, fs)
@@ -274,7 +275,7 @@ class Main(QObject, Ui_MainWindow):
'
\n'%(titles,))
d.exec_()
else:
- self.job_exception(id, description, exception, formatted_traceback)
+ self.device_job_exception(id, description, exception, formatted_traceback)
return
self.device_manager.add_books_to_metadata(result, metadata, self.booklists())
@@ -319,7 +320,7 @@ class Main(QObject, Ui_MainWindow):
for view in (self.memory_view, self.card_view):
view.model().deletion_done(id, bool(exception))
if exception:
- self.job_exception(id, description, exception, formatted_traceback)
+ self.device_job_exception(id, description, exception, formatted_traceback)
return
self.upload_booklists()
@@ -431,14 +432,24 @@ class Main(QObject, Ui_MainWindow):
view.resize_on_select = False
self.status_bar.reset_info()
self.current_view().clearSelection()
- self.current_view().setCurrentIndex(view.model().index(0, 0))
+ self.current_view().setCurrentIndex(self.current_view().model().index(0, 0))
- def job_exception(self, id, exception, formatted_traceback):
+ def device_job_exception(self, id, description, exception, formatted_traceback):
'''
Handle exceptions in threaded jobs.
'''
- raise JobException, str(exception) + '\n\r' + formatted_traceback
+ print >>sys.stderr, 'Error in job:', description
+ print >>sys.stderr, exception
+ print >>sys.stderr, formatted_traceback
+ if not self.device_error_dialog.isVisible():
+ msg = '%s: '%(exception.__class__.__name__,) + str(exception) + '
'
+ msg += 'Failed to perform job: '+description
+ msg += '
Further device related error messages will not be shown while this message is visible.'
+ msg += '
Detailed traceback:
'+formatted_traceback+'
'
+ self.device_error_dialog.setText(msg)
+ self.device_error_dialog.show()
+
def read_settings(self):
@@ -471,6 +482,14 @@ class Main(QObject, Ui_MainWindow):
e.accept()
else:
e.ignore()
+
+ def unhandled_exception(self, type, value, tb):
+ traceback.print_exception(type, value, tb, file=sys.stderr)
+ fe = '\n'.join(traceback.format_exception(type, value, tb))
+ msg = '' + str(value) + '
'
+ msg += 'Detailed traceback:
'+fe+'
'
+ d = error_dialog(self.window, 'ERROR: Unhandled exception', msg)
+ d.exec_()
def main():
lock = os.path.join(tempfile.gettempdir(),"libprs500_gui_lock")
@@ -497,8 +516,8 @@ def main():
import traceback
traceback.print_exception(type, value, tb, file=sys.stderr)
if type == KeyboardInterrupt:
- QCoreApplication.exit(1)
- sys.excepthook = unhandled_exception
+ main.window.close()
+ sys.excepthook = main.unhandled_exception
return app.exec_()