Commit 225dbc57 authored by Luci Stanescu's avatar Luci Stanescu

Added auxiliary thread for blocking operations

parent ab2e0f79
...@@ -10,6 +10,7 @@ __date__ = 'July 5, 2010' ...@@ -10,6 +10,7 @@ __date__ = 'July 5, 2010'
import sys import sys
from PyQt4.QtCore import QThread
from PyQt4.QtGui import QApplication from PyQt4.QtGui import QApplication
from application import log from application import log
from application.notification import IObserver, NotificationCenter from application.notification import IObserver, NotificationCenter
...@@ -31,6 +32,26 @@ from blink.update import UpdateManager ...@@ -31,6 +32,26 @@ from blink.update import UpdateManager
from blink.util import QSingleton, run_in_gui_thread from blink.util import QSingleton, run_in_gui_thread
class AuxiliaryThread(QThread):
def __init__(self, parent=None):
super(AuxiliaryThread, self).__init__(parent)
self.moveToThread(self)
def run(self):
self.exec_()
def customEvent(self, event):
handler = getattr(self, '_EH_%s' % event.name, Null)
handler(event)
def _EH_CallFunctionEvent(self, event):
try:
event.function(*event.args, **event.kw)
except:
log.error('Exception occured while calling function %s in the auxiliary thread' % event.function.__name__)
log.err()
class Blink(QApplication): class Blink(QApplication):
__metaclass__ = QSingleton __metaclass__ = QSingleton
...@@ -39,6 +60,7 @@ class Blink(QApplication): ...@@ -39,6 +60,7 @@ class Blink(QApplication):
def __init__(self): def __init__(self):
super(Blink, self).__init__(sys.argv) super(Blink, self).__init__(sys.argv)
self.application = SIPApplication() self.application = SIPApplication()
self.auxiliary_thread = AuxiliaryThread()
self.main_window = MainWindow() self.main_window = MainWindow()
self.update_manager = UpdateManager() self.update_manager = UpdateManager()
...@@ -54,6 +76,7 @@ class Blink(QApplication): ...@@ -54,6 +76,7 @@ class Blink(QApplication):
def run(self): def run(self):
from blink.util import call_in_gui_thread as call_later from blink.util import call_in_gui_thread as call_later
call_later(self._initialize_sipsimple) call_later(self._initialize_sipsimple)
self.auxiliary_thread.start()
self.exec_() self.exec_()
self.update_manager.shutdown() self.update_manager.shutdown()
self.application.stop() self.application.stop()
......
...@@ -17,7 +17,6 @@ from PyQt4.QtGui import QAction, QKeyEvent, QListView, QMenu, QMouseEvent, QReg ...@@ -17,7 +17,6 @@ from PyQt4.QtGui import QAction, QKeyEvent, QListView, QMenu, QMouseEvent, QReg
from application.notification import IObserver, NotificationCenter from application.notification import IObserver, NotificationCenter
from application.python.decorator import decorator, preserve_signature from application.python.decorator import decorator, preserve_signature
from application.python.queue import EventQueue
from application.python.util import Null from application.python.util import Null
from application.system import unlink from application.system import unlink
from functools import partial from functools import partial
...@@ -29,7 +28,7 @@ from sipsimple.util import makedirs ...@@ -29,7 +28,7 @@ from sipsimple.util import makedirs
from blink.resources import ApplicationData, Resources, IconCache from blink.resources import ApplicationData, Resources, IconCache
from blink.sessions import SessionManager from blink.sessions import SessionManager
from blink.util import run_in_gui_thread from blink.util import run_in_auxiliary_thread, run_in_gui_thread
from blink.widgets.buttons import SwitchViewButton from blink.widgets.buttons import SwitchViewButton
...@@ -502,8 +501,6 @@ class ContactModel(QAbstractListModel): ...@@ -502,8 +501,6 @@ class ContactModel(QAbstractListModel):
# emulate beginResetModel/endResetModel for QT < 4.6 # emulate beginResetModel/endResetModel for QT < 4.6
self.beginResetModel = Null # or use self.modelAboutToBeReset.emit (it'll be emited twice though in that case) self.beginResetModel = Null # or use self.modelAboutToBeReset.emit (it'll be emited twice though in that case)
self.endResetModel = self.reset self.endResetModel = self.reset
self.save_queue = EventQueue(self._store_contacts, name='ContactsSavingThread')
self.save_queue.start()
self.bonjour_group = None self.bonjour_group = None
notification_center = NotificationCenter() notification_center = NotificationCenter()
...@@ -774,6 +771,7 @@ class ContactModel(QAbstractListModel): ...@@ -774,6 +771,7 @@ class ContactModel(QAbstractListModel):
self.endRemoveRows() self.endRemoveRows()
return items return items
@run_in_auxiliary_thread
def _store_contacts(self, data): def _store_contacts(self, data):
makedirs(ApplicationData.directory) makedirs(ApplicationData.directory)
filename = ApplicationData.get('contacts') filename = ApplicationData.get('contacts')
...@@ -913,7 +911,7 @@ class ContactModel(QAbstractListModel): ...@@ -913,7 +911,7 @@ class ContactModel(QAbstractListModel):
items.remove(self.bonjour_group) items.remove(self.bonjour_group)
position = items.index(reference) if reference in contact_groups else len(self.items) position = items.index(reference) if reference in contact_groups else len(self.items)
items.insert(position, group) items.insert(position, group)
self.save_queue.put(pickle.dumps(items)) self._store_contacts(pickle.dumps(items))
class ContactSearchModel(QSortFilterProxyModel): class ContactSearchModel(QSortFilterProxyModel):
......
...@@ -24,7 +24,7 @@ from blink.accounts import AccountModel, ActiveAccountModel ...@@ -24,7 +24,7 @@ from blink.accounts import AccountModel, ActiveAccountModel
from blink.contacts import BonjourNeighbour, Contact, ContactGroup, ContactEditorDialog, ContactModel, ContactSearchModel from blink.contacts import BonjourNeighbour, Contact, ContactGroup, ContactEditorDialog, ContactModel, ContactSearchModel
from blink.sessions import SessionManager, SessionModel from blink.sessions import SessionManager, SessionModel
from blink.resources import Resources from blink.resources import Resources
from blink.util import run_in_gui_thread from blink.util import call_in_auxiliary_thread, run_in_gui_thread
from blink.widgets.buttons import SwitchViewButton from blink.widgets.buttons import SwitchViewButton
...@@ -258,22 +258,19 @@ class MainWindow(base_class, ui_class): ...@@ -258,22 +258,19 @@ class MainWindow(base_class, ui_class):
session_manager.start_call(name, address, contact=contact, account=BonjourAccount() if isinstance(contact, BonjourNeighbour) else None) session_manager.start_call(name, address, contact=contact, account=BonjourAccount() if isinstance(contact, BonjourNeighbour) else None)
def _SH_AudioAlertDeviceChanged(self, action): def _SH_AudioAlertDeviceChanged(self, action):
from twisted.internet import reactor
settings = SIPSimpleSettings() settings = SIPSimpleSettings()
settings.audio.alert_device = action.data().toPyObject() settings.audio.alert_device = action.data().toPyObject()
reactor.callInThread(settings.save) call_in_auxiliary_thread(settings.save)
def _SH_AudioInputDeviceChanged(self, action): def _SH_AudioInputDeviceChanged(self, action):
from twisted.internet import reactor
settings = SIPSimpleSettings() settings = SIPSimpleSettings()
settings.audio.input_device = action.data().toPyObject() settings.audio.input_device = action.data().toPyObject()
reactor.callInThread(settings.save) call_in_auxiliary_thread(settings.save)
def _SH_AudioOutputDeviceChanged(self, action): def _SH_AudioOutputDeviceChanged(self, action):
from twisted.internet import reactor
settings = SIPSimpleSettings() settings = SIPSimpleSettings()
settings.audio.output_device = action.data().toPyObject() settings.audio.output_device = action.data().toPyObject()
reactor.callInThread(settings.save) call_in_auxiliary_thread(settings.save)
def _SH_BreakConference(self): def _SH_BreakConference(self):
active_session = self.session_model.data(self.session_list.selectionModel().selectedIndexes()[0]) active_session = self.session_model.data(self.session_list.selectionModel().selectedIndexes()[0])
......
# Copyright (C) 2010 AG Projects. See LICENSE for details. # Copyright (C) 2010 AG Projects. See LICENSE for details.
# #
__all__ = ['QSingleton', 'call_in_gui_thread', 'call_later', 'run_in_gui_thread'] __all__ = ['QSingleton', 'call_in_gui_thread', 'call_later', 'run_in_gui_thread', 'call_in_auxiliary_thread', 'run_in_auxiliary_thread']
from PyQt4.QtCore import QObject, QTimer from PyQt4.QtCore import QObject, QTimer
from PyQt4.QtGui import QApplication
from application.python.decorator import decorator, preserve_signature from application.python.decorator import decorator, preserve_signature
from application.python.util import Singleton from application.python.util import Singleton
from blink.event import CallFunctionEvent
class QSingleton(Singleton, type(QObject)): class QSingleton(Singleton, type(QObject)):
"""A metaclass for making Qt objects singletons""" """A metaclass for making Qt objects singletons"""
...@@ -14,7 +17,6 @@ class QSingleton(Singleton, type(QObject)): ...@@ -14,7 +17,6 @@ class QSingleton(Singleton, type(QObject)):
def call_in_gui_thread(function, *args, **kw): def call_in_gui_thread(function, *args, **kw):
from blink import Blink from blink import Blink
from blink.event import CallFunctionEvent
blink = Blink() blink = Blink()
blink.postEvent(blink, CallFunctionEvent(function, args, kw)) blink.postEvent(blink, CallFunctionEvent(function, args, kw))
...@@ -29,9 +31,21 @@ def run_in_gui_thread(func): ...@@ -29,9 +31,21 @@ def run_in_gui_thread(func):
@preserve_signature(func) @preserve_signature(func)
def wrapper(*args, **kw): def wrapper(*args, **kw):
from blink import Blink from blink import Blink
from blink.event import CallFunctionEvent
blink = Blink() blink = Blink()
blink.postEvent(blink, CallFunctionEvent(func, args, kw)) blink.postEvent(blink, CallFunctionEvent(func, args, kw))
return wrapper return wrapper
def call_in_auxiliary_thread(function, *args, **kw):
application = QApplication.instance()
application.postEvent(application.auxiliary_thread, CallFunctionEvent(function, args, kw))
def run_in_auxiliary_thread(func):
@preserve_signature(func)
def wrapper(*args, **kw):
application = QApplication.instance()
application.postEvent(application.auxiliary_thread, CallFunctionEvent(func, args, kw))
return wrapper
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