summaryrefslogtreecommitdiff
path: root/silx/gui/widgets/ThreadPoolPushButton.py
diff options
context:
space:
mode:
Diffstat (limited to 'silx/gui/widgets/ThreadPoolPushButton.py')
-rw-r--r--silx/gui/widgets/ThreadPoolPushButton.py238
1 files changed, 0 insertions, 238 deletions
diff --git a/silx/gui/widgets/ThreadPoolPushButton.py b/silx/gui/widgets/ThreadPoolPushButton.py
deleted file mode 100644
index 949b6ef..0000000
--- a/silx/gui/widgets/ThreadPoolPushButton.py
+++ /dev/null
@@ -1,238 +0,0 @@
-# coding: utf-8
-# /*##########################################################################
-#
-# Copyright (c) 2016-2018 European Synchrotron Radiation Facility
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-# THE SOFTWARE.
-#
-# ###########################################################################*/
-"""ThreadPoolPushButton module
-"""
-
-__authors__ = ["V. Valls"]
-__license__ = "MIT"
-__date__ = "13/10/2016"
-
-import logging
-from .. import qt
-from .WaitingPushButton import WaitingPushButton
-
-
-_logger = logging.getLogger(__name__)
-
-
-class _Wrapper(qt.QRunnable):
- """Wrapper to allow to call a function into a `QThreadPool` and
- sending signals during the life cycle of the object"""
-
- def __init__(self, signalHolder, function, args, kwargs):
- """Constructor"""
- super(_Wrapper, self).__init__()
- self.__signalHolder = signalHolder
- self.__callable = function
- self.__args = args
- self.__kwargs = kwargs
-
- def run(self):
- holder = self.__signalHolder
- holder.started.emit()
- try:
- result = self.__callable(*self.__args, **self.__kwargs)
- holder.succeeded.emit(result)
- except Exception as e:
- module = self.__callable.__module__
- name = self.__callable.__name__
- _logger.error("Error while executing callable %s.%s.", module, name, exc_info=True)
- holder.failed.emit(e)
- finally:
- holder.finished.emit()
- holder._sigReleaseRunner.emit(self)
-
- def autoDelete(self):
- """Returns true to ask the QThreadPool to manage the life cycle of
- this QRunner."""
- return True
-
-
-class ThreadPoolPushButton(WaitingPushButton):
- """
- ThreadPoolPushButton provides a simple push button to execute
- a threaded task with user feedback when the task is running.
-
- The task can be defined with the method `setCallable`. It takes a python
- function and arguments as parameters.
-
- WARNING: This task is run in a separate thread.
-
- Everytime the button is pushed a new runner is created to execute the
- function with defined arguments. An animated waiting icon is displayed
- to show the activity. By default the button is disabled when an execution
- is requested. This behaviour can be disabled by using
- `setDisabledWhenWaiting`.
-
- When the button is clicked a `beforeExecuting` signal is sent from the
- Qt main thread. Then the task is started in a thread pool and the following
- signals are emitted from the thread pool. Right before calling the
- registered callable, the widget emits a `started` signal.
- When the task ends, its result is emitted by the `succeeded` signal, but
- if it fails the signal `failed` is emitted with the resulting exception.
- At the end, the `finished` signal is emitted.
-
- The task can be programatically executed by using `executeCallable`.
-
- >>> # Compute a value
- >>> import math
- >>> button = ThreadPoolPushButton(text="Compute 2^16")
- >>> button.setCallable(math.pow, 2, 16)
- >>> button.succeeded.connect(print) # python3
-
- .. image:: img/ThreadPoolPushButton.png
-
- >>> # Compute a wrong value
- >>> import math
- >>> button = ThreadPoolPushButton(text="Compute sqrt(-1)")
- >>> button.setCallable(math.sqrt, -1)
- >>> button.failed.connect(print) # python3
- """
-
- def __init__(self, parent=None, text=None, icon=None):
- """Constructor
-
- :param str text: Text displayed on the button
- :param qt.QIcon icon: Icon displayed on the button
- :param qt.QWidget parent: Parent of the widget
- """
- WaitingPushButton.__init__(self, parent=parent, text=text, icon=icon)
- self.__callable = None
- self.__args = None
- self.__kwargs = None
- self.__runnerCount = 0
- self.__runnerSet = set([])
- self.clicked.connect(self.executeCallable)
- self.finished.connect(self.__runnerFinished)
- self._sigReleaseRunner.connect(self.__releaseRunner)
-
- beforeExecuting = qt.Signal()
- """Signal emitted just before execution of the callable by the main Qt
- thread. In synchronous mode (direct mode), it can be used to define
- dynamically `setCallable`, or to execute something in the Qt thread before
- the execution, or both."""
-
- started = qt.Signal()
- """Signal emitted from the thread pool when the defined callable is
- started.
-
- WARNING: This signal is emitted from the thread performing the task, and
- might be received after the registered callable has been called. If you
- want to perform some initialisation or set the callable to run, use the
- `beforeExecuting` signal instead.
- """
-
- finished = qt.Signal()
- """Signal emitted from the thread pool when the defined callable is
- finished"""
-
- succeeded = qt.Signal(object)
- """Signal emitted from the thread pool when the callable exit with a
- success.
-
- The parameter of the signal is the result returned by the callable.
- """
-
- failed = qt.Signal(object)
- """Signal emitted emitted from the thread pool when the callable raises an
- exception.
-
- The parameter of the signal is the raised exception.
- """
-
- _sigReleaseRunner = qt.Signal(object)
- """Callback to release runners"""
-
- def __runnerStarted(self):
- """Called when a runner is started.
-
- Count the number of executed tasks to change the state of the widget.
- """
- self.__runnerCount += 1
- if self.__runnerCount > 0:
- self.wait()
-
- def __runnerFinished(self):
- """Called when a runner is finished.
-
- Count the number of executed tasks to change the state of the widget.
- """
- self.__runnerCount -= 1
- if self.__runnerCount <= 0:
- self.stopWaiting()
-
- @qt.Slot()
- def executeCallable(self):
- """Execute the defined callable in QThreadPool.
-
- First emit a `beforeExecuting` signal.
- If callable is not defined, nothing append.
- If a callable is defined, it will be started
- as a new thread using the `QThreadPool` system. At start of the thread
- the `started` will be emitted. When the callable returns a result it
- is emitted by the `succeeded` signal. If the callable fail, the signal
- `failed` is emitted with the resulting exception. Then the `finished`
- signal is emitted.
- """
- self.beforeExecuting.emit()
- if self.__callable is None:
- return
- self.__runnerStarted()
- runner = self._createRunner(self.__callable, self.__args, self.__kwargs)
- qt.silxGlobalThreadPool().start(runner)
- self.__runnerSet.add(runner)
-
- def __releaseRunner(self, runner):
- self.__runnerSet.remove(runner)
-
- def hasPendingOperations(self):
- return len(self.__runnerSet) > 0
-
- def _createRunner(self, function, args, kwargs):
- """Create a QRunnable from a callable object.
-
- :param callable function: A callable Python object.
- :param List args: List of arguments to call the function.
- :param dict kwargs: Dictionary of arguments used to call the function.
- :rtpye: qt.QRunnable
- """
- runnable = _Wrapper(self, function, args, kwargs)
- return runnable
-
- def setCallable(self, function, *args, **kwargs):
- """Define a callable which will be executed on QThreadPool everytime
- the button is clicked.
-
- To retrieve the results, connect to the `succeeded` signal.
-
- WARNING: The callable will be called in a separate thread.
-
- :param callable function: A callable Python object
- :param List args: List of arguments to call the function.
- :param dict kwargs: Dictionary of arguments used to call the function.
- """
- self.__callable = function
- self.__args = args
- self.__kwargs = kwargs