Package Camelot :: Package camelot :: Package view :: Package model_thread
[frames] | no frames]

Source Code for Package Camelot.camelot.view.model_thread

  1  #  ============================================================================ 
  2  # 
  3  #  Copyright (C) 2007-2008 Conceptive Engineering bvba. All rights reserved. 
  4  #  www.conceptive.be / project-camelot@conceptive.be 
  5  # 
  6  #  This file is part of the Camelot Library. 
  7  # 
  8  #  This file may be used under the terms of the GNU General Public 
  9  #  License version 2.0 as published by the Free Software Foundation 
 10  #  and appearing in the file LICENSE.GPL included in the packaging of 
 11  #  this file.  Please review the following information to ensure GNU 
 12  #  General Public Licensing requirements will be met: 
 13  #  http://www.trolltech.com/products/qt/opensource.html 
 14  # 
 15  #  If you are unsure which license is appropriate for your use, please 
 16  #  review the following information: 
 17  #  http://www.trolltech.com/products/qt/licensing.html or contact 
 18  #  project-camelot@conceptive.be. 
 19  # 
 20  #  This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 
 21  #  WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 
 22  # 
 23  #  For use of this library in commercial applications, please contact 
 24  #  project-camelot@conceptive.be 
 25  # 
 26  #  ============================================================================ 
 27   
 28  import logging 
 29  from functools import wraps 
 30   
 31  from PyQt4 import QtCore, QtGui 
 32   
 33  logger = logging.getLogger( 'camelot.view.model_thread' ) 
 34   
 35  _model_thread_ = [] 
36 37 -class ModelThreadException( Exception ):
38 pass
39
40 -def model_function( original_function ):
41 """Decorator to ensure a function is only called from within the model 42 thread. If this function is called in another thread, an exception will be 43 thrown 44 """ 45 46 def in_model_thread(): 47 """return wether current thread is model thread""" 48 from no_thread_model_thread import NoThreadModelThread 49 current_thread = QtCore.QThread.currentThread() 50 model_thread = get_model_thread() 51 return (current_thread==model_thread) or isinstance(model_thread, (NoThreadModelThread,))
52 53 @wraps(original_function) 54 def wrapper( *args, **kwargs ): 55 assert in_model_thread() 56 return original_function( *args, **kwargs ) 57 58 return wrapper 59
60 -def gui_function( original_function ):
61 """Decorator to ensure a function is only called from within the gui thread. 62 If this function is called in another thread, an exception will be thrown 63 """ 64 65 def in_gui_thread(): 66 """return wether current thread is gui thread""" 67 gui_thread = QtGui.QApplication.instance().thread() 68 current_thread = QtCore.QThread.currentThread() 69 return gui_thread == current_thread
70 71 @wraps( original_function ) 72 def wrapper( *args, **kwargs ): 73 assert in_gui_thread() 74 return original_function( *args, **kwargs ) 75 76 return wrapper 77
78 -def setup_model():
79 """Call the setup_model function in the settings""" 80 from settings import setup_model 81 setup_model()
82
83 -class AbstractModelThread(object):
84 """Abstract implementation of a model thread class 85 Thread in which the model runs, all requests to the model should be 86 posted to the the model thread. 87 88 This class ensures the gui thread doesn't block when the model needs 89 time to complete tasks by providing asynchronous communication between 90 the model thread and the gui thread 91 """ 92 93 thread_busy_signal = QtCore.SIGNAL('thread_busy') 94
95 - def __init__(self, setup_thread = setup_model ):
96 """ 97 @param setup_thread: function to be called at startup of the thread to initialize 98 everything, by default this will setup the model. set to None if nothing should 99 be done. 100 """ 101 self.logger = logging.getLogger( logger.name + '.%s' % id( self ) ) 102 self._setup_thread = setup_thread 103 self._exit = False 104 self._traceback = '' 105 self.logger.debug( 'model thread constructed' )
106
107 - def run(self):
108 pass
109
110 - def traceback( self ):
111 """The formatted traceback of the last exception in the model thread""" 112 return self._traceback
113
114 - def wait_on_work(self):
115 """Wait for all work to be finished, this function should only be used 116 to do unit testing and such, since it will block the calling thread until 117 all work is done""" 118 pass
119
120 - def post( self, request, response = None, exception = None ):
121 """Post a request to the model thread, request should be 122 a function that takes no arguments. The request function 123 will be called within the model thread. When the request 124 is finished, on first occasion, the response function will be 125 called within the gui thread. The response function takes as 126 arguments, the results of the request function. 127 @param request: function to be called within the model thread 128 @param response: a slot that will be called with the result of the 129 request function 130 @param exception: a slot that will be called in case request throws 131 an exception 132 """ 133 raise NotImplemented
134
135 - def busy( self ):
136 """Return True or False indicating wether either the model or the 137 gui thread is doing something""" 138 return False
139
140 -def construct_model_thread( *args, **kwargs ):
141 import settings 142 if hasattr(settings, 'THREADING') and settings.THREADING==False: 143 logger.info('running without threads') 144 from no_thread_model_thread import NoThreadModelThread 145 _model_thread_.insert( 0, NoThreadModelThread( *args, **kwargs ) ) 146 else: 147 from signal_slot_model_thread import SignalSlotModelThread 148 _model_thread_.insert( 0, SignalSlotModelThread( *args, **kwargs ) )
149
150 -def has_model_thread():
151 return len( _model_thread_ ) > 0
152
153 -def get_model_thread():
154 return _model_thread_[0]
155
156 -def post(request, response = None, exception = None):
157 """Post a request and a response to the default model thread""" 158 mt = get_model_thread() 159 mt.post(request, response, exception)
160