def __init__(self, qbaseobject, callback, signals=None, connections=None, mutex_expiry=5000): """ Args: qbaseobject (QBaseObject): The QBaseObject instance this is attached to. Whenever the task is started, it will be checked for a parent window/progressbar. """ self._qbaseobject = qbaseobject SoloThreadedTask.__init__(self, callback = callback, signals = signals, connections = connections, mutex_expiry = mutex_expiry, )
def __init__(self, progressbar, callback, signals=None, connections=None, mutex_expiry=5000): self._progressbar = progressbar SoloThreadedTask.__init__( self, callback=callback, signals=signals, connections=connections, mutex_expiry=mutex_expiry, )
def __init__(self): QtWidgets.QListWidget.__init__(self) self._sem_rendering = QtCore.QSemaphore(1) self._thread_loading = SoloThreadedTask( callback=self._find_list_items, signals={ 'add_item': str, 'clear': None, }, connections={ 'add_item': [self.addItem], 'clear': [self.clear], }, )
def start(self, expiryTimeout=-1, threadpool=None, wait=False, *args, **kwds ): """ Looks for/connects the progressbar. """ with threading.Lock(): jobid = uuid.uuid4().hex # check if this QBaseObject has a parent window, # and if that window has a method called `progressbar` # (presumably yielding a progressbar) progressbar = None if hasattr( self._qbaseobject, 'window' ): if hasattr( self._qbaseobject.window(), 'progressbar' ): progressbar = self._qbaseobject.window().progressbar() # default arguments connections = self._connections.copy() if not connections: connections = {} if progressbar: progbar_connections = { 'incr_progress' : functools.partial( progressbar.incr_progress, jobid=jobid ), 'add_progress' : functools.partial( progressbar.add_progress, jobid=jobid ), 'returned' : functools.partial( progressbar._handle_return_or_abort, jobid=jobid ), 'exception' : functools.partial( progressbar._handle_return_or_abort, jobid=jobid ), } else: progbar_connections = {} for signal in progbar_connections: if signal in connections: connections[ signal ].append( progbar_connections[signal] ) else: connections[ signal ] = [ progbar_connections[signal] ] SoloThreadedTask.start(self, expiryTimeout = expiryTimeout, threadpool = threadpool, wait = wait, _connections = connections, *args,**kwds )
def start(self, expiryTimeout=-1, threadpool=None, wait=False, *args, **kwds): """ Wraps :py:meth:`qconcurrency.threading_.SoloThreadedTask.start` , adding signal-connections so that they update a progressbar. See Also: * :py:meth:`qconcurrency.threading_.SoloThreadedTask.start` """ jobid = uuid.uuid4().hex connections = self._connections.copy() if not connections: connections = {} progbar_connections = { 'incr_progress': functools.partial(self._progressbar.incr_progress, jobid=jobid), 'add_progress': functools.partial(self._progressbar.add_progress, jobid=jobid), 'returned': functools.partial(self._progressbar._handle_return_or_abort, jobid=jobid), 'exception': functools.partial(self._progressbar._handle_return_or_abort, jobid=jobid), } for signal in progbar_connections: if signal in connections: connections[signal].append(progbar_connections[signal]) else: connections[signal] = [progbar_connections[signal]] SoloThreadedTask.start(self, expiryTimeout=expiryTimeout, threadpool=threadpool, wait=wait, _connections=connections, *args, **kwds)
class MyThreadedList(QtWidgets.QListWidget): def __init__(self): QtWidgets.QListWidget.__init__(self) self._sem_rendering = QtCore.QSemaphore(1) self._thread_loading = SoloThreadedTask( callback=self._find_list_items, signals={ 'add_item': str, 'clear': None, }, connections={ 'add_item': [self.addItem], 'clear': [self.clear], }, ) def load(self): """ Loads list with items from a separate thread. If load is already in progress, it will be cancelled before the new load request starts. """ self._thread_loading.start() def _find_list_items(self, signalmgr=None): """ Adds 100 items to the list-widget, """ signalmgr.clear.emit() for i in range(100): signalmgr.handle_if_abort( ) # check for a request-abort, and exit early # slow signals down, emitting one object at a time # so that job can be cancelled. # ( signals have no priority, once emitted, ) # ( you must wait for them all to be handled ) self._sem_rendering.tryAcquire(1, 5000) signalmgr.add_item.emit(str(i)) # add an item to the list def addItem(self, item): """ Unecessarily waits .01 seconds (so you can see widget updating live), then adds the item to the list. """ time.sleep(0.01) try: QtWidgets.QListWidget.addItem(self, item) except: self._mutex_rendering.unlock() six.reraise(*sys.exc_info()) if not self._sem_rendering.available(): self._sem_rendering.release(1) # in this example, the wait is performed # in the UI thread - it never has a chance to process # QApp events (causing item to be rendered) until it runs # out of signals to fire. It is unlikely you will # need the following line in your production code. # QtCore.QCoreApplication.instance().processEvents()
from qconcurrency import QApplication from qconcurrency.threading_ import SoloThreadedTask from Qt import QtWidgets, QtCore import six import supercli.logging import time supercli.logging.SetLog(lv=10) with QApplication(): wid = QtWidgets.QPushButton('close me') wid.show() queue_finished = six.moves.queue.Queue() threadpool = QtCore.QThreadPool() def _callback(queue_finished, signalmgr=None): for i in range(3): signalmgr.handle_if_abort() time.sleep(0.05) queue_finished.put(True) task = SoloThreadedTask(callback=_callback, ) task.start( queue_finished=queue_finished, threadpool=threadpool, wait=True, )