Commit 2e3865b5 authored by Dan Pascu's avatar Dan Pascu

Allow run_in_gui_thread to wait for the function to finish

parent 07fca1ea
...@@ -3,6 +3,9 @@ from PyQt4.QtCore import QObject, QThread, QTimer ...@@ -3,6 +3,9 @@ from PyQt4.QtCore import QObject, QThread, QTimer
from PyQt4.QtGui import QApplication from PyQt4.QtGui import QApplication
from application.python.decorator import decorator, preserve_signature from application.python.decorator import decorator, preserve_signature
from application.python.types import Singleton from application.python.types import Singleton
from functools import partial
from threading import Event
from sys import exc_info
from blink.event import CallFunctionEvent from blink.event import CallFunctionEvent
...@@ -17,7 +20,7 @@ class QSingleton(Singleton, type(QObject)): ...@@ -17,7 +20,7 @@ class QSingleton(Singleton, type(QObject)):
def call_in_gui_thread(function, *args, **kw): def call_in_gui_thread(function, *args, **kw):
application = QApplication.instance() application = QApplication.instance()
if application.thread() is QThread.currentThread(): if application.thread() is QThread.currentThread():
function(*args, **kw) return function(*args, **kw)
else: else:
application.postEvent(application, CallFunctionEvent(function, args, kw)) application.postEvent(application, CallFunctionEvent(function, args, kw))
...@@ -26,15 +29,49 @@ def call_later(interval, function, *args, **kw): ...@@ -26,15 +29,49 @@ def call_later(interval, function, *args, **kw):
QTimer.singleShot(int(interval*1000), lambda: function(*args, **kw)) QTimer.singleShot(int(interval*1000), lambda: function(*args, **kw))
@decorator class FunctionExecutor(object):
def run_in_gui_thread(function): __slots__ = 'function', 'event', 'result', 'exception', 'traceback'
@preserve_signature(function)
def wrapper(*args, **kw): def __init__(self, function):
application = QApplication.instance() self.function = function
if application.thread() is QThread.currentThread(): self.event = Event()
function(*args, **kw) self.result = None
self.exception = None
self.traceback = None
def __call__(self, *args, **kw):
try:
self.result = self.function(*args, **kw)
except BaseException as exception:
self.exception = exception
self.traceback = exc_info()[2]
finally:
self.event.set()
def wait(self):
self.event.wait()
if self.exception is not None:
raise type(self.exception), self.exception, self.traceback
else: else:
application.postEvent(application, CallFunctionEvent(function, args, kw)) return self.result
return wrapper
@decorator
def run_in_gui_thread(function=None, wait=False):
if function is not None:
@preserve_signature(function)
def function_wrapper(*args, **kw):
application = QApplication.instance()
if application.thread() is QThread.currentThread():
return function(*args, **kw)
else:
if wait:
executor = FunctionExecutor(function)
application.postEvent(application, CallFunctionEvent(executor, args, kw))
return executor.wait()
else:
application.postEvent(application, CallFunctionEvent(function, args, kw))
return function_wrapper
else:
return partial(run_in_gui_thread, wait=wait)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment