-
-
Notifications
You must be signed in to change notification settings - Fork 1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactoring of Sieve, Mosaic and VizRank.
Extract OWWidget's methods for progress bars to mix-in class `Orange.widgets.utils.progressbar.ProgressBarMixin`. This simplifies `OWWidget` and also allows other dialogs (e.g. `VizRankDialog`) to use progress bars without being derived from `OWWidget`. Move `HorizontalGridDelegate` from `OWColor` to `gui` - it was also used in the `OWFile` 's domain editor and now in VizRank. Move `CanvasText`, `CanvasRectangle` and `ViewWithPress` from `OWMosaic` to `orange.widgets.visualize.utils` since they were used by Sieve and Mosaic (and may also be used elsewhere). Move the common functionality of Scatter Plot's and Sieve's VizRank to more `VizRankDialog` and `VizRankDialogAttrPair` (module `orange.widgets.visualiza.utils`. The classes are also general enough to also support ranking of other visualizations in the future. Derive `VizRankDialog` from `QDialog` (with the progress bar mix-in) instead of `OWWidget` with all its balast. Visually improve VizRankDialog. Remove the uninformative score. Remove the redundant dictionary `ScaleData.attribute_name_index` since it duplicates the functionality of `ScaleData.data_domain.index`. Fix the type of argument `buttonType` and the return type in docstring of `gui.button`. Rename `Orange.widget.utils.getHtmlCompatibleString` to `to_html`.
- Loading branch information
Showing
13 changed files
with
736 additions
and
630 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
import contextlib | ||
import time | ||
import warnings | ||
|
||
from PyQt4.QtCore import pyqtSignal as Signal, pyqtProperty, QEventLoop | ||
from PyQt4.QtGui import qApp | ||
|
||
from Orange.widgets import gui | ||
|
||
class ProgressBarMixin: | ||
# Set these here so we avoid having to call `__init__` fromm classes | ||
# that use this mix-in | ||
__progressBarValue = -1 | ||
__progressState = 0 | ||
startTime = time.time() # used in progressbar | ||
|
||
def progressBarInit(self, processEvents=QEventLoop.AllEvents): | ||
""" | ||
Initialize the widget's progress (i.e show and set progress to 0%). | ||
.. note:: | ||
This method will by default call `QApplication.processEvents` | ||
with `processEvents`. To suppress this behavior pass | ||
``processEvents=None``. | ||
:param processEvents: Process events flag | ||
:type processEvents: `QEventLoop.ProcessEventsFlags` or `None` | ||
""" | ||
self.startTime = time.time() | ||
self.setWindowTitle(self.captionTitle + " (0% complete)") | ||
|
||
if self.__progressState != 1: | ||
self.__progressState = 1 | ||
self.processingStateChanged.emit(1) | ||
|
||
self.progressBarSet(0, processEvents) | ||
|
||
def progressBarSet(self, value, processEvents=QEventLoop.AllEvents): | ||
""" | ||
Set the current progress bar to `value`. | ||
.. note:: | ||
This method will by default call `QApplication.processEvents` | ||
with `processEvents`. To suppress this behavior pass | ||
``processEvents=None``. | ||
:param float value: Progress value | ||
:param processEvents: Process events flag | ||
:type processEvents: `QEventLoop.ProcessEventsFlags` or `None` | ||
""" | ||
old = self.__progressBarValue | ||
self.__progressBarValue = value | ||
|
||
if value > 0: | ||
if self.__progressState != 1: | ||
warnings.warn("progressBarSet() called without a " | ||
"preceding progressBarInit()", | ||
stacklevel=2) | ||
self.__progressState = 1 | ||
self.processingStateChanged.emit(1) | ||
|
||
usedTime = max(1, time.time() - self.startTime) | ||
totalTime = 100.0 * usedTime / value | ||
remainingTime = max(0, int(totalTime - usedTime)) | ||
hrs = remainingTime // 3600 | ||
mins = (remainingTime % 3600) // 60 | ||
secs = remainingTime % 60 | ||
if hrs > 0: | ||
text = "{}:{:02}:{:02}".format(hrs, mins, secs) | ||
else: | ||
text = "{}:{}:{:02}".format(hrs, mins, secs) | ||
self.setWindowTitle("{} ({:.2f}% complete, remaining time: {})" | ||
.format(self.captionTitle, value, text)) | ||
else: | ||
self.setWindowTitle(self.captionTitle + " (0% complete)") | ||
|
||
if old != value: | ||
self.progressBarValueChanged.emit(value) | ||
|
||
if processEvents is not None and processEvents is not False: | ||
qApp.processEvents(processEvents) | ||
|
||
def progressBarValue(self): | ||
"""Return the state of the progress bar | ||
""" | ||
return self.__progressBarValue | ||
|
||
progressBarValue = pyqtProperty( | ||
float, fset=progressBarSet, fget=progressBarValue) | ||
processingState = pyqtProperty(int, fget=lambda self: self.__progressState) | ||
|
||
def progressBarAdvance(self, value, processEvents=QEventLoop.AllEvents): | ||
""" | ||
Advance the progress bar. | ||
.. note:: | ||
This method will by default call `QApplication.processEvents` | ||
with `processEvents`. To suppress this behavior pass | ||
``processEvents=None``. | ||
Args: | ||
value (int): progress value | ||
processEvents (`QEventLoop.ProcessEventsFlags` or `None`): | ||
process events flag | ||
""" | ||
self.progressBarSet(self.progressBarValue + value, processEvents) | ||
|
||
def progressBarFinished(self, processEvents=QEventLoop.AllEvents): | ||
""" | ||
Stop the widget's progress (i.e hide the progress bar). | ||
.. note:: | ||
This method will by default call `QApplication.processEvents` | ||
with `processEvents`. To suppress this behavior pass | ||
``processEvents=None``. | ||
:param processEvents: Process events flag | ||
:type processEvents: `QEventLoop.ProcessEventsFlags` or `None` | ||
""" | ||
self.setWindowTitle(self.captionTitle) | ||
if self.__progressState != 0: | ||
self.__progressState = 0 | ||
self.processingStateChanged.emit(0) | ||
|
||
if processEvents is not None and processEvents is not False: | ||
qApp.processEvents(processEvents) | ||
|
||
@contextlib.contextmanager | ||
def progressBar(self, iterations=0): | ||
""" | ||
Context manager for progress bar. | ||
Using it ensures that the progress bar is removed at the end without | ||
needing the `finally` blocks. | ||
Usage: | ||
with self.progressBar(20) as progress: | ||
... | ||
progress.advance() | ||
or | ||
with self.progressBar() as progress: | ||
... | ||
progress.advance(0.15) | ||
or | ||
with self.progressBar(): | ||
... | ||
self.progressBarSet(50) | ||
:param iterations: the number of iterations (optional) | ||
:type iterations: int | ||
""" | ||
progress_bar = gui.ProgressBar(self, iterations) | ||
yield progress_bar | ||
progress_bar.finish() # Let us not rely on garbage collector |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.