Ejemplo n.º 1
0
class TextTreeNode(QGraphicsTextItem, GraphNode):
    def setBackgroundBrush(self, brush):
        if self._background_brush != brush:
            self._background_brush = QBrush(brush)
            color = brush.color()
            r, g, b, _ = color.getRgb()
            lum = 0.2126 * r + 0.7152 * g + 0.0722 * b
            if lum > 100:
                self.setDefaultTextColor(Qt.black)
            else:
                self.setDefaultTextColor(Qt.white)
            self.update()

    def backgroundBrush(self):
        brush = getattr(self, "_background_brush")
        if brush is None:
            brush = getattr(self.scene(), "defaultItemBrush", Qt.NoBrush)
        return QBrush(brush)

    backgroundBrush = pyqtProperty(
        "QBrush", fget=backgroundBrush, fset=setBackgroundBrush,
        doc="Background brush")

    def __init__(self, parent, *args, **kwargs):
        QGraphicsTextItem.__init__(self, *args)
        GraphNode.__init__(self, **kwargs)
        self._background_brush = None
        self._rect = None

        self.parent = parent
        font = self.font()
        font.setPointSize(10)
        self.setFont(font)
        self.droplet = GraphicsDroplet(-5, 0, 10, 10, self)
        self.droplet.setPos(self.rect().center().x(), self.rect().height())
        self.document().contentsChanged.connect(self.update_contents)
        self.isOpen = True
        self.setFlag(QGraphicsItem.ItemIsSelectable, True)

    def setHtml(self, html):
        return super().setHtml("<body>" + html + "</body>")

    def update_contents(self):
        self.setTextWidth(-1)
        self.setTextWidth(self.document().idealWidth())
        self.droplet.setPos(self.rect().center().x(), self.rect().height())
        self.droplet.setVisible(bool(self.branches))

    def set_rect(self, rect):
        self.prepareGeometryChange()
        rect = QRectF() if rect is None else rect
        self._rect = rect
        self.update_contents()
        self.update()

    def shape(self):
        path = QPainterPath()
        path.addRect(self.boundingRect())
        return path

    def rect(self):
        if getattr(self, "_rect", QRectF()).isValid():
            return self._rect
        else:
            return QRectF(QPointF(0, 0), self.document().size()) | \
                   getattr(self, "_rect", QRectF(0, 0, 1, 1))

    def boundingRect(self):
        return self._rect if getattr(self, "_rect", QRectF()).isValid() \
            else super().boundingRect()

    @property
    def branches(self):
        return [edge.node2 for edge in self.graph_edges() if edge.node1 is self]

    def paint(self, painter, option, widget=0):
        painter.save()
        painter.setBrush(self.backgroundBrush)
        painter.setPen(QPen(Qt.gray))
        rect = self.rect()
        painter.drawRoundedRect(rect, 4, 4)
        painter.restore()
        painter.setClipRect(rect)
        return QGraphicsTextItem.paint(self, painter, option, widget)
Ejemplo n.º 2
0
class ProgressBarMixin:
    __progressBarValue = 0
    __progressState = 0
    startTime = -1  # used in progressbar
    captionTitle = ""

    def setCaption(self, caption):
        self.captionTitle = caption
        self.setWindowTitle(caption)

    @pyqtSlot()
    def progressBarInit(self):
        """
        Initialize the widget's progress (i.e show and set progress to 0%).
        """
        self.startTime = time.time()
        self.setWindowTitle(self.captionTitle + " (0% complete)")

        if self.__progressState != 1:
            self.__progressState = 1
            self.processingStateChanged.emit(1)

        self.progressBarSet(0)

    @pyqtSlot(float)
    def progressBarSet(self, value):
        """
        Set the current progress bar to `value`.

        Parameters
        ----------
        value : float
            Progress value.
        """
        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("{} ({:d}%, ETA: {})".format(
                self.captionTitle, int(value), text))
        else:
            self.setWindowTitle(self.captionTitle + " (0% complete)")

        if old != value:
            self.progressBarValueChanged.emit(value)

    def progressBarValue(self):
        """
        Return the state (value) of the progress bar
        """
        return self.__progressBarValue

    progressBarValueChanged = pyqtSignal(float)
    progressBarValue = pyqtProperty(float,
                                    fset=progressBarSet,
                                    fget=progressBarValue,
                                    notify=progressBarValueChanged)
    processingStateChanged = pyqtSignal(int)
    processingState = pyqtProperty(int,
                                   fget=lambda self: self.__progressState,
                                   notify=processingStateChanged)

    @pyqtSlot(float)
    def progressBarAdvance(self, value):
        """
        Advance the progress bar by `value`.

        Parameters
        ----------
        value : float
            Progress value increment.
        """
        self.progressBarSet(self.__progressBarValue + value)

    @pyqtSlot()
    def progressBarFinished(self):
        """
        Stop the widget's progress (i.e hide the progress bar).

        Parameters
        ----------
        value : float
            Progress value increment.
        """
        self.setWindowTitle(self.captionTitle)
        if self.__progressState != 0:
            self.__progressState = 0
            self.processingStateChanged.emit(0)
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=None):
        """
        Initialize the widget's progress (i.e show and set progress to 0%).

        Parameters
        ----------
        processEvents : Optional[QEventLoop.ProcessEventsFlags]
            If present then `QApplication.processEvents(processEvents)`
            will be called. Passing any value here is highly discouraged.
            It is up to the client to handle the consequences of such action.

        .. versionchanged:: 3.4.2
            Deprecated and changed default `processEvents` value.

        """
        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=None):
        """
        Set the current progress bar to `value`.

        Parameters
        ----------
        value : float
            Progress value.
        processEvents : Optional[QEventLoop.ProcessEventsFlags]
            If present then `QApplication.processEvents(processEvents)`
            will be called. Passing any value here is highly discouraged.
            It is up to the client to handle the consequences of such action.

        .. versionchanged:: 3.4.2
            Deprecated and changed default `processEvents` value.
        """
        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("{} ({:d}%, ETA: {})".format(
                self.captionTitle, int(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=None):
        """
        Advance the progress bar by `value`.

        Parameters
        ----------
        value : float
            Progress value increment.
        processEvents : Optional[QEventLoop.ProcessEventsFlags]
            If present then `QApplication.processEvents(processEvents)`
            will be called. Passing any value here is highly discouraged.
            It is up to the client to handle the consequences of such action.

        .. versionchanged:: 3.4.2
            Deprecated and changed default `processEvents` value.
        """
        self.progressBarSet(self.progressBarValue + value, processEvents)

    def progressBarFinished(self, processEvents=None):
        """
        Stop the widget's progress (i.e hide the progress bar).

        Parameters
        ----------
        value : float
            Progress value increment.
        processEvents : Optional[QEventLoop.ProcessEventsFlags]
            If present then `QApplication.processEvents(processEvents)`
            will be called. Passing any value here is highly discouraged.
            It is up to the client to handle the consequences of such action.

        .. versionchanged:: 3.4.2
            Deprecated and changed default `processEvents` value.
        """
        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)
        try:
            yield progress_bar
        finally:
            progress_bar.finish()
Ejemplo n.º 4
0
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("{} ({:d}%, ETA: {})".format(
                self.captionTitle, int(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)
        try:
            yield progress_bar
        finally:
            progress_bar.finish()