[Pymoul-svn] SF.net SVN: pymoul: [116] pymoul/trunk/src/moul
Status: Alpha
Brought to you by:
tiran
|
From: <ti...@us...> - 2007-02-02 03:32:29
|
Revision: 116
http://pymoul.svn.sourceforge.net/pymoul/?rev=116&view=rev
Author: tiran
Date: 2007-02-01 19:32:28 -0800 (Thu, 01 Feb 2007)
Log Message:
-----------
Added error handling and threadlet
Modified Paths:
--------------
pymoul/trunk/src/moul/file/directory.py
pymoul/trunk/src/moul/osdependent/linux/__init__.py
pymoul/trunk/src/moul/qt/localization.py
pymoul/trunk/src/moul/qt/mainwindow.py
pymoul/trunk/src/moul/qt/moulqt.py
Added Paths:
-----------
pymoul/trunk/src/moul/qt/errorhandler.py
pymoul/trunk/src/moul/qt/threadlet.py
Modified: pymoul/trunk/src/moul/file/directory.py
===================================================================
--- pymoul/trunk/src/moul/file/directory.py 2007-02-02 00:49:08 UTC (rev 115)
+++ pymoul/trunk/src/moul/file/directory.py 2007-02-02 03:32:28 UTC (rev 116)
@@ -145,7 +145,7 @@
'soundwav' : 'sfx' + os.sep + 'streamingCache',
'video' : 'avi',
}
- _factory = {
+ _factories = {
'loc' : (parseLocDirectory, ('loc',)),
}
Modified: pymoul/trunk/src/moul/osdependent/linux/__init__.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/linux/__init__.py 2007-02-02 00:49:08 UTC (rev 115)
+++ pymoul/trunk/src/moul/osdependent/linux/__init__.py 2007-02-02 03:32:28 UTC (rev 116)
@@ -93,7 +93,7 @@
finally:
if fd:
fd.close()
- except IoError:
+ except IOError:
continue
details = {}
for line in status:
Added: pymoul/trunk/src/moul/qt/errorhandler.py
===================================================================
--- pymoul/trunk/src/moul/qt/errorhandler.py (rev 0)
+++ pymoul/trunk/src/moul/qt/errorhandler.py 2007-02-02 03:32:28 UTC (rev 116)
@@ -0,0 +1,118 @@
+#!/usr/bin/env python2.5
+# pyMoul - Python interface to Myst Online URU Live
+# Copyright (C) 2007 Christian Heimes <christian (at) cheimes (dot) de>
+
+# 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 2 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, write to the Free Software Foundation, Inc., 59
+# Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+"""Error handling for moul qt
+
+The module installs a custom exception hook that shows unhandled traceback in
+the ui. It also contains several functions to create message boxes.
+"""
+__author__ = "Christian Heimes"
+__version__ = "$Id"
+__revision__ = "$Revision$"
+
+import sys
+import os
+from traceback import format_exception
+
+from PyQt4 import QtGui
+from PyQt4 import QtCore
+from PyQt4.QtCore import Qt
+
+from moul.log import getLogger
+
+LOG = getLogger('moul.qt.error')
+
+def trUtf8(s):
+ return s
+
+def qtexcepthook(typ, value, traceback):
+ """
+ Custom exception hood to announce error inside the UI
+ """
+ # TODO: translation aware
+ LOG.critical("UNHANDLED ERROR", exc_info=(typ, value, traceback))
+ return # XXX: remove
+ try:
+ title = trUtf8("An unhandled error has occured")
+ msg = (trUtf8("Please report the error:\n\n") +
+ '\n'.join([line.strip() for line in
+ format_exception(typ, value, traceback)])
+ )
+ mb = criticalMB(None, title, msg)
+ mb.exec_()
+ except Exception, msg:
+ print msg
+ #sys.exit(100)
+
+def setupQtExceptHook():
+ """
+ Install Qt exception hook
+ """
+ LOG.info("Qt exception hook installed")
+ sys.excepthook = qtexcepthook
+
+def removeQtExceptHook():
+ """
+ Remove Qt exception hook
+ """
+ LOG.info("Qt exception hook removed")
+ sys.excepthook = sys.__excepthook__
+
+def _mkMessageBox(context, icon='Information'):
+ """
+ Create a message box
+ """
+ assert icon in ('Question', 'Information', 'Warning', 'Critical')
+ if context:
+ mb = QtGui.QMessageBox(context)
+ else:
+ mb = QtGui.QMessageBox()
+ mb.setWindowIcon(QtGui.QIcon(":/resources/uru_icon_32x32.png"))
+ mb.setIcon(getattr(QtGui.QMessageBox, icon))
+ mb.setStandardButtons(QtGui.QMessageBox.Close)
+ return mb
+
+
+def criticalMB(context, title, text):
+ """
+ Critical message box
+ """
+ mb = _mkMessageBox(context, icon='Critical')
+ mb.setWindowTitle(title)
+ mb.setText(text)
+ return mb
+
+def warningMB(context, title, text):
+ """
+ warning message box
+ """
+ mb = _mkMessageBox(context, icon='Warning')
+ mb.setWindowTitle(title)
+ mb.setText(text)
+ return mb
+
+def infoMB(context, title, text):
+ """
+ Info message box
+ """
+ mb = _mkMessageBox(context, icon='Info')
+ mb.setStandardButtons(QtGui.QMessageBox.Ok)
+ mb.setWindowTitle(title)
+ mb.setText(text)
+ return mb
Modified: pymoul/trunk/src/moul/qt/localization.py
===================================================================
--- pymoul/trunk/src/moul/qt/localization.py 2007-02-02 00:49:08 UTC (rev 115)
+++ pymoul/trunk/src/moul/qt/localization.py 2007-02-02 03:32:28 UTC (rev 116)
@@ -33,7 +33,7 @@
from moul.config import lookupDir
from moul.file.localization import translationRegistry as tr
-from moul.file.localization import parseLocDirectory
+from moul.file.directory import UruGameDataDirectory
from moul.log import getLogger
from moul.log import signalLogDecorator
@@ -48,17 +48,16 @@
Mixin for documentation tab
"""
def _documents_init(self):
- return
- locDir = lookupDir('loc')
- if not os.path.isdir(locDir):
+ installDir = lookupDir('install')
+ self._gamedir = UruGameDataDirectory(installDir)
+ if not self._gamedir.exists('loc'):
return
- self.tab_documents.setEnabled(True)
-
- parseLocDirectory(locDir)
-
+ self._gamedir.factory('loc')
+ self.tab_sub_journals.setEnabled(True)
+
self._documents_state = {}
-
+
self.connect(self.cb_doc_language, SIGNAL("currentIndexChanged(int)"),
self.on_cb_doc_language_currentIndexChanged)
self.connect(self.cb_doc_age, SIGNAL("currentIndexChanged(int)"),
Modified: pymoul/trunk/src/moul/qt/mainwindow.py
===================================================================
--- pymoul/trunk/src/moul/qt/mainwindow.py 2007-02-02 00:49:08 UTC (rev 115)
+++ pymoul/trunk/src/moul/qt/mainwindow.py 2007-02-02 03:32:28 UTC (rev 116)
@@ -48,18 +48,6 @@
LOG = getLogger('moul.qt')
-def criticalMessageBox(self, title, text):
- """
- Critical warning!
- """
- mb = QtGui.QMessageBox()
- mb.setWindowIcon(QtGui.QIcon(":/resources/uru_icon_32x32.png"))
- mb.setIcon(QtGui.QMessageBox.Critical)
- mb.setWindowTitle(self.trUtf8(title))
- mb.setText(self.trUtf8(text))
- mb.setStandardButtons(QtGui.QMessageBox.Close)
- return mb
-
class MainWindow(QtGui.QMainWindow, Ui_MainWindow, LocalizationMixin):
def __init__(self):
QtGui.QMainWindow.__init__(self)
@@ -75,7 +63,8 @@
# dirty flag: unsaved changes
self._dirty = False
self.setDirty(False)
-
+ self.tab_sub_journals.setEnabled(False)
+
# init handlers
self._timezone_init()
self._graphics_init()
@@ -84,8 +73,7 @@
self._systray_init()
self._about_init()
self._documents_init()
- self.tab_sub_journals.setEnabled(False)
-
+
# run checker
self._moulrunning = None
self._moulrunning_thread = MoulRunningThread()
@@ -498,9 +486,9 @@
"""
self._ping_thread = thread = PingServerThread()
- self.connect(thread, SIGNAL("started"),
+ self.connect(thread, SIGNAL("started()"),
self.on_pingthread_started)
- self.connect(thread, SIGNAL("done()"),
+ self.connect(thread, SIGNAL("finished()"),
self.on_pingthread_done)
self.connect(thread, SIGNAL("server(const QString&)"),
self.on_pingthread_server)
@@ -563,7 +551,6 @@
def run(self):
# TODO: thread safety!
- self.emit(SIGNAL("started"))
# emit a list of names first
for server in self.servers:
self.emit(SIGNAL("server(const QString&)"), server.name)
@@ -583,8 +570,6 @@
name, ping[0], ping[1])
continue
self.emit(SIGNAL("ping(const QString&, float)"), name, ping)
-
- self.emit(SIGNAL("done()"))
class MoulRunningThread(QtCore.QThread):
def __init__(self, parent=None):
Modified: pymoul/trunk/src/moul/qt/moulqt.py
===================================================================
--- pymoul/trunk/src/moul/qt/moulqt.py 2007-02-02 00:49:08 UTC (rev 115)
+++ pymoul/trunk/src/moul/qt/moulqt.py 2007-02-02 03:32:28 UTC (rev 116)
@@ -28,7 +28,9 @@
from PyQt4 import QtGui
from moul.qt.mainwindow import MainWindow
-from moul.qt.mainwindow import criticalMessageBox
+from moul.qt.errorhandler import criticalMB
+from moul.qt.errorhandler import setupQtExceptHook
+from moul.qt.errorhandler import removeQtExceptHook
from moul.osdependent.singleapp import SimpleSingleApp
from moul.config import getPyMoulDataDir
from moul.osdependent import isMoulRunning
@@ -55,28 +57,24 @@
try:
singleapp.acquire()
except OSError:
- mb = criticalMessageBox(app,
- "pyMoul QT already running",
- """An instance of pyMoul QT is already running!""")
+ mb = criticalMB(app,
+ app.trUtf8("pyMoul QT already running"),
+ app.trUtf8("""An instance of pyMoul QT is already running!""")
+ )
mb.exec_()
sys.exit(1)
-
+
createLogfile()
-
-# if isMoulRunning():
-# mb = criticalMessageBox(app,
-# "URU is running",
-# """URU is running! Please close Uru or Uru Launcher first.""")
-# mb.exec_()
-# sys.exit(2)
+ setupQtExceptHook()
LOG.info("Invoking PyMoul QT MainWindow")
mainWindow = MainWindow()
mainWindow.show()
err = app.exec_()
LOG.info("Exiting PyMoul QT UI with status %i" % err)
+ removeQtExceptHook()
return err
-
+
if __name__ == '__main__':
err = main(sys.argv)
sys.exit(err)
Added: pymoul/trunk/src/moul/qt/threadlet.py
===================================================================
--- pymoul/trunk/src/moul/qt/threadlet.py (rev 0)
+++ pymoul/trunk/src/moul/qt/threadlet.py 2007-02-02 03:32:28 UTC (rev 116)
@@ -0,0 +1,68 @@
+#!/usr/bin/env python2.5
+# pyMoul - Python interface to Myst Online URU Live
+# Copyright (C) 2007 Christian Heimes <christian (at) cheimes (dot) de>
+
+# 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 2 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, write to the Free Software Foundation, Inc., 59
+# Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+"""Threadlet - execute a function in a seperate thread
+"""
+__author__ = "Christian Heimes"
+__version__ = "$Id: moulqt.py 110 2007-01-31 15:40:51Z tiran $"
+__revision__ = "$Revision: 110 $"
+
+import sys
+
+from PyQt4 import QtCore
+
+LOG = getLogger('moul.tasklket')
+
+class Threadlet(QtCore.QThread):
+ """Threadlet - execute a function in a seperate thread
+
+ @signal started(): Signal is emitted when the thread starts executing.
+ @signal finished(): Signal is emitted when the thread has finished.
+ @signal terminated(): Signal is emitted when the thread is terminated.
+ @signal done(result): Signal is emitted when the function has returned.
+ The result argument contains the return value of the function.
+
+ >>> def pow(x, y): return x**y
+ >>> def printer(r): print r
+ >>> example =Threadlet(pow, parent=None, 2, 6)
+ >>> connect(example, SIGNAL('done(result)'), printer)
+ >>> example.start()
+
+ started()
+ done(result)
+ finished()
+
+ @warning: The function and all applied arguments must be reentrant or
+ thread safe!
+ """
+ def __init__(self, func, parent=None, *args, **kwargs):
+ """
+ @param func: a callable
+ @param parent: Qt parent
+ @param *args: additional arguments for the function
+ @param **kwargs: additional keyword arguments for the function
+ """
+ QtCore.QThread.__init__(self, parent)
+ self._func = func
+ self._args = args
+ self._kwargs = kwargs
+
+ def run(self):
+ result = self._func(*self._args, **self._kwargs)
+ self.emit(SIGNAL("done(result)"), result)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|