Exemple #1
0
 def draw_icon(self, painter):
     path = QPainterPath(QPointF(0, 0.3))
     path.lineTo(0, 0.9)
     path.lineTo(1, 0.3)
     path.lineTo(1, 0.9)
     path.closeSubpath()
     painter.drawPath(path)
Exemple #2
0
    def draw_icon(self, painter):
        path = QPainterPath(QPointF(0, 0.3))
        path.lineTo(0, 0.9)
        path.lineTo(1, 0.3)
        path.lineTo(1, 0.9)
        path.closeSubpath()
        painter.drawPath(path)

        prev_brush = painter.brush()
        prev_pen = painter.pen()

        painter.setPen(Qt.NoPen)
        painter.setBrush(self._arrow_brush)
        arrow = QPolygonF([
            QPointF(0.2, 0),
            QPointF(0.2, 0.20),
            QPointF(0.5, 0.40),
            QPointF(0.8, 0.20),
            QPointF(0.8, 0)
        ])
        painter.drawPolygon(arrow)

        painter.setPen(prev_pen)
        painter.setBrush(prev_brush)
        painter.drawLine(QPointF(0.2, 0), QPointF(0.5, 0.20))
        painter.drawLine(QPointF(0.2, 0.20), QPointF(0.5, 0.40))
        painter.drawLine(QPointF(0.5, 0.20), QPointF(0.8, 0))
        painter.drawLine(QPointF(0.5, 0.40), QPointF(0.8, 0.20))

        painter.drawLine(QPointF(0.5, 0.6), QPointF(0.5, 0.0))
Exemple #3
0
    def draw_icon(self, painter):
        path = QPainterPath(QPointF(0, 0.3))
        path.lineTo(0, 0.9)
        path.lineTo(1, 0.3)
        path.lineTo(1, 0.9)
        path.closeSubpath()
        painter.drawPath(path)
        painter.drawLine(QPointF(0.5, 0.6), QPointF(0.5, 0.15))

        # Draw the arrow end-caps
        painter.setBrush(QBrush(QColor(0, 0, 0)))

        top_arrow_point = QPointF(0.65, 0.36)
        arrow = QPolygonF([
            QPointF(-0.09, 0.0),
            QPointF(-0.005, 0.0),
            QPointF(-0.005, 0.8),
            QPointF(0.005, 0.8),
            QPointF(0.005, 0.0),
            QPointF(0.09, 0.0),
            QPointF(0.00, -0.25)
        ])

        t = QTransform()
        t.rotate(35)
        top_arrow_r = t.map(arrow)
        arrow_l = top_arrow_r.translated(top_arrow_point)
        painter.drawPolygon(arrow_l)

        painter.setBrush(self._interlock_brush)
        painter.drawRect(QRectF(0.3, 0, 0.4, 0.15))
Exemple #4
0
 def draw_icon(self, painter):
     path = QPainterPath(QPointF(0, 0))
     path.lineTo(1, 1)
     path.lineTo(0.005, 1)
     path.lineTo(0.5, 0.5)
     path.lineTo(0, 0.9)
     path.closeSubpath()
     painter.drawPath(path)
     painter.drawEllipse(QPointF(0.5, 0.5), 0.05, 0.05)
Exemple #5
0
def painterPathForTriangle():
    bottomLeft = QPointF(-1.0, -1.0)
    top = QPointF(0.0, 1.0)
    bottomRight = QPointF(1.0, -1.0)

    path = QPainterPath(bottomLeft)
    path.lineTo(top)
    path.lineTo(bottomRight)
    path.closeSubpath()
    return path
Exemple #6
0
 def draw_icon(self, painter):
     path = QPainterPath(QPointF(0, 0.3))
     path.lineTo(0, 0.9)
     path.lineTo(1, 0.3)
     path.lineTo(1, 0.9)
     path.closeSubpath()
     painter.drawPath(path)
     painter.drawLine(QPointF(0.5, 0.6), QPointF(0.5, 0.3))
     painter.setBrush(self._interlock_brush)
     painter.drawRect(QRectF(0.2, 0, 0.6, 0.3))
Exemple #7
0
    def draw_icon(self, painter):
        path = QPainterPath(QPointF(0, 0.3))
        path.lineTo(0, 0.9)
        path.lineTo(1, 0.3)
        path.lineTo(1, 0.9)
        path.closeSubpath()
        painter.drawPath(path)

        painter.drawLine(QPointF(0.4, 0), QPointF(0.5, 0.15))
        painter.drawLine(QPointF(0.4, 0.10), QPointF(0.5, 0.25))
        painter.drawLine(QPointF(0.5, 0.15), QPointF(0.6, 0))
        painter.drawLine(QPointF(0.5, 0.25), QPointF(0.6, 0.10))

        painter.drawLine(QPointF(0.5, 0.6), QPointF(0.5, 0.0))
Exemple #8
0
def qwtCombinePathList(rect, pathList):
    if not pathList:
        return QPainterPath()

    ordered = [None] * 8
    for subPath in pathList:
        index = -1
        br = subPath.controlPointRect()
        if br.center().x() < rect.center().x():
            if br.center().y() < rect.center().y():
                if abs(br.top() - rect.top()) < abs(br.left() - rect.left()):
                    index = 1
                else:
                    index = 0
            else:
                if abs(br.bottom() - rect.bottom) < abs(br.left() -
                                                        rect.left()):
                    index = 6
                else:
                    index = 7
            if subPath.currentPosition().y() > br.center().y():
                qwtRevertPath(subPath)
        else:
            if br.center().y() < rect.center().y():
                if abs(br.top() - rect.top()) < abs(br.right() - rect.right()):
                    index = 2
                else:
                    index = 3
            else:
                if abs(br.bottom() - rect.bottom()) < abs(br.right() -
                                                          rect.right()):
                    index = 5
                else:
                    index = 4
            if subPath.currentPosition().y() < br.center().y():
                qwtRevertPath(subPath)
        ordered[index] = subPath
    for i in range(4):
        if ordered[2 * i].isEmpty() != ordered[2 * i + 1].isEmpty():
            return QPainterPath()
    corners = QPolygonF(rect)
    path = QPainterPath()
    for i in range(4):
        if ordered[2 * i].isEmpty():
            path.lineTo(corners[i])
        else:
            path.connectPath(ordered[2 * i])
            path.connectPath(ordered[2 * i + 1])
    path.closeSubpath()
    return path
Exemple #9
0
    def draw_icon(self, painter):
        path = QPainterPath(QPointF(0, 0.3))
        path.lineTo(0, 0.9)
        path.lineTo(1, 0.3)
        path.lineTo(1, 0.9)
        path.closeSubpath()
        painter.drawPath(path)
        painter.drawLine(QPointF(0.5, 0.6), QPointF(0.5, 0.3))
        painter.setBrush(self._interlock_brush)
        painter.drawRect(QRectF(0.2, 0, 0.6, 0.3))
        # Draw the N
        n_path = QPainterPath(QPointF(0.25, 0.25))
        n_path.lineTo(0.25, 0.05)
        n_path.lineTo(0.45, 0.25)
        n_path.lineTo(0.45, 0.05)
        painter.drawPath(n_path)

        # Draw the O
        painter.drawEllipse(QPointF(0.65, 0.15), 0.1, 0.1)
Exemple #10
0
    def drawLine(self, qp, value: int):
        """Draw line on triangle indicating value.

        Parameters
        ----------
        qp: QPainter object
        value: int
            Value of highlight thickness.
        """
        col = QColor('white')
        qp.setPen(QPen(col, 2))
        qp.setBrush(col)
        path = QPainterPath()
        path.moveTo(value, 15)

        path.lineTo(value, 0)
        path.closeSubpath()

        qp.drawPath(path)
        self.valueChanged.emit(self._value)
Exemple #11
0
 def drawPolygon(self, *args):
     if len(args) == 3:
         points, pointCount, mode = args
     elif len(args) == 2:
         points, mode = args
         pointCount = len(points)
     else:
         raise TypeError("Unexpected arguments")
     device = self.nullDevice()
     if device is None:
         return
     if device.mode() == QwtNullPaintDevice.PathMode:
         path = QPainterPath()
         if pointCount > 0:
             path.moveTo(points[0])
             for i in range(1, pointCount):
                 path.lineTo(points[i])
             if mode != QPaintEngine.PolylineMode:
                 path.closeSubpath()
         device.drawPath(path)
         return
     device.drawPolygon(points, pointCount, mode)
Exemple #12
0
    def drawTriangle(self, qp):
        """Draw triangle.

        Parameters
        ----------
        qp: QPainter object
        """
        width = self.rect().width()
        height = self.rect().height()

        col = QColor(135, 206, 235)
        qp.setPen(QPen(col, 1))
        qp.setBrush(col)
        path = QPainterPath()

        height = 10
        path.moveTo(0, height)

        path.lineTo(width, height)

        path.lineTo(width, 0)
        path.closeSubpath()

        qp.drawPath(path)
Exemple #13
0
    def _paintBackgroundCross(cls, painter):
        grey = QColor(220, 220, 220)
        greyAccent = QColor(180, 180, 180)

        painter.setBrush(QBrush(grey))
        painter.setPen(QPen(greyAccent, 1))

        path = QPainterPath()
        h0 = -86
        h1 = -18
        h2 = 18
        h3 = 86
        v0 = -86
        v1 = -18
        v2 = 18
        v3 = 86
        c = 7

        path.moveTo(v0, h1)
        path.lineTo(v1 - c, h1)
        path.lineTo(v1, h1 - c)
        path.lineTo(v1, h0)
        path.lineTo(v2, h0)
        path.lineTo(v2, h1 - c)
        path.lineTo(v2 + c, h1)
        path.lineTo(v3, h1)
        path.lineTo(v3, h2)
        path.lineTo(v2 + c, h2)
        path.lineTo(v2, h2 + c)
        path.lineTo(v2, h3)
        path.lineTo(v1, h3)
        path.lineTo(v1, h2 + c)
        path.lineTo(v1 - c, h2)
        path.lineTo(v0, h2)
        path.closeSubpath()
        painter.drawPath(path)
Exemple #14
0
    def _paintAbsDropIcon(self, painter, placement):
        self._configureBrushAndPen(painter, Qt.white, Qt.white)
        r = QRectF(-14, -14, 28, 28)
        painter.drawRoundedRect(r, 2, 2)

        self._configureBrushAndPen(painter, self.Blue, self.BlueAccent)

        title = {
            Placement.LEFT: QRectF(-10, -10, 10, 4),
            Placement.RIGHT: QRectF(0, -10, 10, 4),
            Placement.TOP: QRectF(-10, -10, 20, 4),
            Placement.BOTTOM: QRectF(-10, -2, 20, 4),
            Placement.TAB: None,
        }
        if title[placement] is not None:
            painter.drawRect(title[placement])

        if placement == self._activeAbsoluteRegion:
            self._configureBrushAndPen(painter, self.Yellow, self.BlueAccent)
        else:
            self._configureBrushAndPen(painter, self.BlueDim,
                                       self.BlueAccentDim)

        bg = {
            Placement.LEFT: QRectF(-10, -5, 10, 14),
            Placement.RIGHT: QRectF(0, -5, 10, 14),
            Placement.TOP: QRectF(-10, -5, 20, 7),
            Placement.BOTTOM: QRectF(-10, 2, 20, 7),
            Placement.TAB: None,
        }
        if bg[placement] is not None:
            painter.drawRect(bg[placement])

        if placement == Placement.LEFT:
            painter.setBrush(QBrush(self.Blue))
            painter.setPen(QPen(self.BlueAccent, 1))

            path = QPainterPath()
            path.moveTo(6, 0)
            path.lineTo(10, -4)
            path.lineTo(10, 4)
            path.closeSubpath()
            painter.drawPath(path)

        elif placement == Placement.TOP:
            painter.setBrush(QBrush(self.Blue))
            painter.setPen(QPen(self.BlueAccent, 1))

            path = QPainterPath()
            path.moveTo(0, 6)
            path.lineTo(-4, 10)
            path.lineTo(4, 10)
            path.closeSubpath()
            painter.drawPath(path)

        elif placement == Placement.RIGHT:
            painter.setBrush(QBrush(self.Blue))
            painter.setPen(QPen(self.BlueAccent, 1))

            path = QPainterPath()
            path.moveTo(-6, 0)
            path.lineTo(-10, -4)
            path.lineTo(-10, 4)
            path.closeSubpath()
            painter.drawPath(path)

        elif placement == Placement.BOTTOM:
            painter.setBrush(QBrush(self.Blue))
            painter.setPen(QPen(self.BlueAccent, 1))

            path = QPainterPath()
            path.moveTo(0, -6)
            path.lineTo(-4, -10)
            path.lineTo(4, -10)
            path.closeSubpath()
            painter.drawPath(path)
Exemple #15
0
class FadingTipBox(FadingDialog):
    """ """
    def __init__(self, parent, opacity, duration, easing_curve, tour=None):
        super(FadingTipBox, self).__init__(parent, opacity, duration,
                                           easing_curve)
        self.holder = self.anim  # needed for qt to work
        self.parent = parent
        self.tour = tour

        self.frames = None
        self.color_top = QColor.fromRgb(230, 230, 230)
        self.color_back = QColor.fromRgb(255, 255, 255)
        self.offset_shadow = 0
        self.fixed_width = 300

        self.key_pressed = None

        self.setAttribute(Qt.WA_TranslucentBackground)
        self.setWindowFlags(Qt.Dialog | Qt.FramelessWindowHint |
                            Qt.WindowStaysOnTopHint)
        self.setModal(False)

        # Widgets
        def toolbutton(icon):
            bt = QToolButton()
            bt.setAutoRaise(True)
            bt.setIcon(icon)
            return bt

        self.button_close = toolbutton(ima.icon("tour.close"))
        self.button_home = toolbutton(ima.icon("tour.home"))
        self.button_previous = toolbutton(ima.icon("tour.previous"))
        self.button_end = toolbutton(ima.icon("tour.end"))
        self.button_next = toolbutton(ima.icon("tour.next"))
        self.button_run = QPushButton(_('Run code'))
        self.button_disable = None
        self.button_current = QToolButton()
        self.label_image = QLabel()

        self.label_title = QLabel()
        self.combo_title = QComboBox()
        self.label_current = QLabel()
        self.label_content = QLabel()

        self.label_content.setMinimumWidth(self.fixed_width)
        self.label_content.setMaximumWidth(self.fixed_width)

        self.label_current.setAlignment(Qt.AlignCenter)

        self.label_content.setWordWrap(True)

        self.widgets = [self.label_content, self.label_title,
                        self.label_current, self.combo_title,
                        self.button_close, self.button_run, self.button_next,
                        self.button_previous, self.button_end,
                        self.button_home, self.button_current]

        arrow = get_image_path('hide.png')

        self.stylesheet = '''QComboBox {
                             padding-left: 5px;
                             background-color: rgbs(230,230,230,100%);
                             border-width: 0px;
                             border-radius: 0px;
                             min-height:20px;
                             max-height:20px;
                             }

                             QComboBox::drop-down  {
                             subcontrol-origin: padding;
                             subcontrol-position: top left;
                             border-width: 0px;
                             }
                             
                             QComboBox::down-arrow {
                             image: url(''' + arrow + ''');
                             }
                             
                             '''
        # Windows fix, slashes should be always in unix-style
        self.stylesheet = self.stylesheet.replace('\\', '/')

        self.setFocusPolicy(Qt.StrongFocus)
        for widget in self.widgets:
            widget.setFocusPolicy(Qt.NoFocus)
            widget.setStyleSheet(self.stylesheet)

        layout_top = QHBoxLayout()
        layout_top.addWidget(self.combo_title)
        layout_top.addStretch()
        layout_top.addWidget(self.button_close)
        layout_top.addSpacerItem(QSpacerItem(self.offset_shadow,
                                             self.offset_shadow))

        layout_content = QHBoxLayout()
        layout_content.addWidget(self.label_content)
        layout_content.addWidget(self.label_image)
        layout_content.addSpacerItem(QSpacerItem(5, 5))

        layout_run = QHBoxLayout()
        layout_run.addStretch()
        layout_run.addWidget(self.button_run)
        layout_run.addStretch()
        layout_run.addSpacerItem(QSpacerItem(self.offset_shadow,
                                             self.offset_shadow))

        layout_navigation = QHBoxLayout()
        layout_navigation.addWidget(self.button_home)
        layout_navigation.addWidget(self.button_previous)
        layout_navigation.addStretch()
        layout_navigation.addWidget(self.label_current)
        layout_navigation.addStretch()
        layout_navigation.addWidget(self.button_next)
        layout_navigation.addWidget(self.button_end)
        layout_navigation.addSpacerItem(QSpacerItem(self.offset_shadow,
                                                    self.offset_shadow))

        layout = QVBoxLayout()
        layout.addLayout(layout_top)
        layout.addStretch()
        layout.addSpacerItem(QSpacerItem(15, 15))
        layout.addLayout(layout_content)
        layout.addLayout(layout_run)
        layout.addStretch()
        layout.addSpacerItem(QSpacerItem(15, 15))
        layout.addLayout(layout_navigation)
        layout.addSpacerItem(QSpacerItem(self.offset_shadow,
                                         self.offset_shadow))

        layout.setSizeConstraint(QLayout.SetFixedSize)

        self.setLayout(layout)

        self.set_funcs_before_fade_in([self._disable_widgets])
        self.set_funcs_after_fade_in([self._enable_widgets, self.setFocus])
        self.set_funcs_before_fade_out([self._disable_widgets])

        self.setContextMenuPolicy(Qt.CustomContextMenu)

        # signals and slots
        # These are defined every time by the AnimatedTour Class

    def _disable_widgets(self):
        """ """
        for widget in self.widgets:
            widget.setDisabled(True)

    def _enable_widgets(self):
        """ """
        self.setWindowFlags(Qt.Dialog | Qt.FramelessWindowHint |
                            Qt.WindowStaysOnTopHint)
        for widget in self.widgets:
            widget.setDisabled(False)

        if self.button_disable == 'previous':
            self.button_previous.setDisabled(True)
            self.button_home.setDisabled(True)
        elif self.button_disable == 'next':
            self.button_next.setDisabled(True)
            self.button_end.setDisabled(True)

    def set_data(self, title, content, current, image, run, frames=None,
                 step=None):
        """ """
        self.label_title.setText(title)
        self.combo_title.clear()
        self.combo_title.addItems(frames)
        self.combo_title.setCurrentIndex(step)
#        min_content_len = max([len(f) for f in frames])
#        self.combo_title.setMinimumContentsLength(min_content_len)

        # Fix and try to see how it looks with a combo box
        self.label_current.setText(current)
        self.button_current.setText(current)
        self.label_content.setText(content)
        self.image = image

        if image is None:
            self.label_image.setFixedHeight(1)
            self.label_image.setFixedWidth(1)
        else:
            extension = image.split('.')[-1]
            self.image = QPixmap(get_image_path(image), extension)
            self.label_image.setPixmap(self.image)
            self.label_image.setFixedSize(self.image.size())

        if run is None:
            self.button_run.setVisible(False)
        else:
            self.button_run.setDisabled(False)
            self.button_run.setVisible(True)

        # Refresh layout
        self.layout().activate()

    def set_pos(self, x, y):
        """ """
        self.x = x
        self.y = y
        self.move(QPoint(x, y))

    def build_paths(self):
        """ """
        geo = self.geometry()
        radius = 0
        shadow = self.offset_shadow
        x0, y0 = geo.x(), geo.y()
        width, height = geo.width() - shadow, geo.height() - shadow

        left, top = 0, 0
        right, bottom = width, height

        self.round_rect_path = QPainterPath()
        self.round_rect_path.moveTo(right, top + radius)
        self.round_rect_path.arcTo(right-radius, top, radius, radius, 0.0,
                                   90.0)
        self.round_rect_path.lineTo(left+radius, top)
        self.round_rect_path.arcTo(left, top, radius, radius, 90.0, 90.0)
        self.round_rect_path.lineTo(left, bottom-radius)
        self.round_rect_path.arcTo(left, bottom-radius, radius, radius, 180.0,
                                   90.0)
        self.round_rect_path.lineTo(right-radius, bottom)
        self.round_rect_path.arcTo(right-radius, bottom-radius, radius, radius,
                                   270.0, 90.0)
        self.round_rect_path.closeSubpath()

        # Top path
        header = 36
        offset = 2
        left, top = offset, offset
        right = width - (offset)
        self.top_rect_path = QPainterPath()
        self.top_rect_path.lineTo(right, top + radius)
        self.top_rect_path.moveTo(right, top + radius)
        self.top_rect_path.arcTo(right-radius, top, radius, radius, 0.0, 90.0)
        self.top_rect_path.lineTo(left+radius, top)
        self.top_rect_path.arcTo(left, top, radius, radius, 90.0, 90.0)
        self.top_rect_path.lineTo(left, top + header)
        self.top_rect_path.lineTo(right, top + header)

    def paintEvent(self, event):
        """ """
        self.build_paths()

        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)

        painter.fillPath(self.round_rect_path, self.color_back)
        painter.fillPath(self.top_rect_path, self.color_top)
        painter.strokePath(self.round_rect_path, QPen(Qt.gray, 1))

        # TODO: Build the pointing arrow?

    def keyReleaseEvent(self, event):
        """ """
        key = event.key()
        self.key_pressed = key

        keys = [Qt.Key_Right, Qt.Key_Left, Qt.Key_Down, Qt.Key_Up,
                Qt.Key_Escape, Qt.Key_PageUp, Qt.Key_PageDown,
                Qt.Key_Home, Qt.Key_End, Qt.Key_Menu]

        if key in keys:
            if not self.is_fade_running():
                self.sig_key_pressed.emit()

    def mousePressEvent(self, event):
        """override Qt method"""
        # Raise the main application window on click
        self.parent.raise_()
        self.raise_()

        if event.button() == Qt.RightButton:
            pass
#            clicked_widget = self.childAt(event.x(), event.y())
#            if clicked_widget == self.label_current:
#            self.context_menu_requested(event)

    def focusOutEvent(self, event):
        """Override Qt method."""
        # To be used so tips do not appear outside spyder
        self.tour.lost_focus()

    def context_menu_requested(self, event):
        """ """
        pos = QPoint(event.x(), event.y())
        menu = QMenu(self)

        actions = []
        action_title = create_action(self, _('Go to step: '), icon=QIcon())
        action_title.setDisabled(True)
        actions.append(action_title)
#        actions.append(create_action(self, _(': '), icon=QIcon()))

        add_actions(menu, actions)

        menu.popup(self.mapToGlobal(pos))

    def reject(self):
        """Qt method to handle escape key event"""
        if not self.is_fade_running():
            key = Qt.Key_Escape
            self.key_pressed = key
            self.sig_key_pressed.emit()
Exemple #16
0
class FadingTipBox(FadingDialog):
    """ """
    def __init__(self,
                 parent,
                 opacity,
                 duration,
                 easing_curve,
                 tour=None,
                 color_top=None,
                 color_back=None,
                 combobox_background=None):
        super(FadingTipBox, self).__init__(parent, opacity, duration,
                                           easing_curve)
        self.holder = self.anim  # needed for qt to work
        self.parent = parent
        self.tour = tour

        self.frames = None
        self.offset_shadow = 0
        self.fixed_width = 300

        self.key_pressed = None

        self.setAttribute(Qt.WA_TranslucentBackground)
        self.setWindowFlags(Qt.Dialog | Qt.FramelessWindowHint
                            | Qt.WindowStaysOnTopHint)
        self.setModal(False)

        # Widgets
        def toolbutton(icon):
            bt = QToolButton()
            bt.setAutoRaise(True)
            bt.setIcon(icon)
            return bt

        self.button_close = toolbutton(ima.icon("tour.close"))
        self.button_home = toolbutton(ima.icon("tour.home"))
        self.button_previous = toolbutton(ima.icon("tour.previous"))
        self.button_end = toolbutton(ima.icon("tour.end"))
        self.button_next = toolbutton(ima.icon("tour.next"))
        self.button_run = QPushButton(_('Run code'))
        self.button_disable = None
        self.button_current = QToolButton()
        self.label_image = QLabel()

        self.label_title = QLabel()
        self.combo_title = QComboBox()
        self.label_current = QLabel()
        self.label_content = QLabel()

        self.label_content.setMinimumWidth(self.fixed_width)
        self.label_content.setMaximumWidth(self.fixed_width)

        self.label_current.setAlignment(Qt.AlignCenter)

        self.label_content.setWordWrap(True)

        self.widgets = [
            self.label_content, self.label_title, self.label_current,
            self.combo_title, self.button_close, self.button_run,
            self.button_next, self.button_previous, self.button_end,
            self.button_home, self.button_current
        ]

        arrow = get_image_path('hide.png')

        self.color_top = color_top
        self.color_back = color_back
        self.combobox_background = combobox_background
        self.stylesheet = '''QComboBox {{
                             padding-left: 5px;
                             background-color: {}
                             border-width: 0px;
                             border-radius: 0px;
                             min-height:20px;
                             max-height:20px;
                             }}

                             QComboBox::drop-down  {{
                             subcontrol-origin: padding;
                             subcontrol-position: top left;
                             border-width: 0px;
                             }}

                             QComboBox::down-arrow {{
                             image: url({});
                             }}

                             '''.format(self.combobox_background.name(), arrow)
        # Windows fix, slashes should be always in unix-style
        self.stylesheet = self.stylesheet.replace('\\', '/')

        self.setFocusPolicy(Qt.StrongFocus)
        for widget in self.widgets:
            widget.setFocusPolicy(Qt.NoFocus)
            widget.setStyleSheet(self.stylesheet)

        layout_top = QHBoxLayout()
        layout_top.addWidget(self.combo_title)
        layout_top.addStretch()
        layout_top.addWidget(self.button_close)
        layout_top.addSpacerItem(
            QSpacerItem(self.offset_shadow, self.offset_shadow))

        layout_content = QHBoxLayout()
        layout_content.addWidget(self.label_content)
        layout_content.addWidget(self.label_image)
        layout_content.addSpacerItem(QSpacerItem(5, 5))

        layout_run = QHBoxLayout()
        layout_run.addStretch()
        layout_run.addWidget(self.button_run)
        layout_run.addStretch()
        layout_run.addSpacerItem(
            QSpacerItem(self.offset_shadow, self.offset_shadow))

        layout_navigation = QHBoxLayout()
        layout_navigation.addWidget(self.button_home)
        layout_navigation.addWidget(self.button_previous)
        layout_navigation.addStretch()
        layout_navigation.addWidget(self.label_current)
        layout_navigation.addStretch()
        layout_navigation.addWidget(self.button_next)
        layout_navigation.addWidget(self.button_end)
        layout_navigation.addSpacerItem(
            QSpacerItem(self.offset_shadow, self.offset_shadow))

        layout = QVBoxLayout()
        layout.addLayout(layout_top)
        layout.addStretch()
        layout.addSpacerItem(QSpacerItem(15, 15))
        layout.addLayout(layout_content)
        layout.addLayout(layout_run)
        layout.addStretch()
        layout.addSpacerItem(QSpacerItem(15, 15))
        layout.addLayout(layout_navigation)
        layout.addSpacerItem(
            QSpacerItem(self.offset_shadow, self.offset_shadow))

        layout.setSizeConstraint(QLayout.SetFixedSize)

        self.setLayout(layout)

        self.set_funcs_before_fade_in([self._disable_widgets])
        self.set_funcs_after_fade_in([self._enable_widgets, self.setFocus])
        self.set_funcs_before_fade_out([self._disable_widgets])

        self.setContextMenuPolicy(Qt.CustomContextMenu)

        # signals and slots
        # These are defined every time by the AnimatedTour Class

    def _disable_widgets(self):
        """ """
        for widget in self.widgets:
            widget.setDisabled(True)

    def _enable_widgets(self):
        """ """
        self.setWindowFlags(Qt.Dialog | Qt.FramelessWindowHint
                            | Qt.WindowStaysOnTopHint)
        for widget in self.widgets:
            widget.setDisabled(False)

        if self.button_disable == 'previous':
            self.button_previous.setDisabled(True)
            self.button_home.setDisabled(True)
        elif self.button_disable == 'next':
            self.button_next.setDisabled(True)
            self.button_end.setDisabled(True)

    def set_data(self,
                 title,
                 content,
                 current,
                 image,
                 run,
                 frames=None,
                 step=None):
        """ """
        self.label_title.setText(title)
        self.combo_title.clear()
        self.combo_title.addItems(frames)
        self.combo_title.setCurrentIndex(step)
        #        min_content_len = max([len(f) for f in frames])
        #        self.combo_title.setMinimumContentsLength(min_content_len)

        # Fix and try to see how it looks with a combo box
        self.label_current.setText(current)
        self.button_current.setText(current)
        self.label_content.setText(content)
        self.image = image

        if image is None:
            self.label_image.setFixedHeight(1)
            self.label_image.setFixedWidth(1)
        else:
            extension = image.split('.')[-1]
            self.image = QPixmap(get_image_path(image), extension)
            self.label_image.setPixmap(self.image)
            self.label_image.setFixedSize(self.image.size())

        if run is None:
            self.button_run.setVisible(False)
        else:
            self.button_run.setDisabled(False)
            self.button_run.setVisible(True)

        # Refresh layout
        self.layout().activate()

    def set_pos(self, x, y):
        """ """
        self.x = ceil(x)
        self.y = ceil(y)
        self.move(QPoint(self.x, self.y))

    def build_paths(self):
        """ """
        geo = self.geometry()
        radius = 0
        shadow = self.offset_shadow
        x0, y0 = geo.x(), geo.y()
        width, height = geo.width() - shadow, geo.height() - shadow

        left, top = 0, 0
        right, bottom = width, height

        self.round_rect_path = QPainterPath()
        self.round_rect_path.moveTo(right, top + radius)
        self.round_rect_path.arcTo(right - radius, top, radius, radius, 0.0,
                                   90.0)
        self.round_rect_path.lineTo(left + radius, top)
        self.round_rect_path.arcTo(left, top, radius, radius, 90.0, 90.0)
        self.round_rect_path.lineTo(left, bottom - radius)
        self.round_rect_path.arcTo(left, bottom - radius, radius, radius,
                                   180.0, 90.0)
        self.round_rect_path.lineTo(right - radius, bottom)
        self.round_rect_path.arcTo(right - radius, bottom - radius, radius,
                                   radius, 270.0, 90.0)
        self.round_rect_path.closeSubpath()

        # Top path
        header = 36
        offset = 2
        left, top = offset, offset
        right = width - (offset)
        self.top_rect_path = QPainterPath()
        self.top_rect_path.lineTo(right, top + radius)
        self.top_rect_path.moveTo(right, top + radius)
        self.top_rect_path.arcTo(right - radius, top, radius, radius, 0.0,
                                 90.0)
        self.top_rect_path.lineTo(left + radius, top)
        self.top_rect_path.arcTo(left, top, radius, radius, 90.0, 90.0)
        self.top_rect_path.lineTo(left, top + header)
        self.top_rect_path.lineTo(right, top + header)

    def paintEvent(self, event):
        """ """
        self.build_paths()

        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)

        painter.fillPath(self.round_rect_path, self.color_back)
        painter.fillPath(self.top_rect_path, self.color_top)
        painter.strokePath(self.round_rect_path, QPen(Qt.gray, 1))

        # TODO: Build the pointing arrow?

    def keyReleaseEvent(self, event):
        """ """
        key = event.key()
        self.key_pressed = key

        keys = [
            Qt.Key_Right, Qt.Key_Left, Qt.Key_Down, Qt.Key_Up, Qt.Key_Escape,
            Qt.Key_PageUp, Qt.Key_PageDown, Qt.Key_Home, Qt.Key_End,
            Qt.Key_Menu
        ]

        if key in keys:
            if not self.is_fade_running():
                self.sig_key_pressed.emit()

    def mousePressEvent(self, event):
        """override Qt method"""
        # Raise the main application window on click
        self.parent.raise_()
        self.raise_()

        if event.button() == Qt.RightButton:
            pass


#            clicked_widget = self.childAt(event.x(), event.y())
#            if clicked_widget == self.label_current:
#            self.context_menu_requested(event)

    def focusOutEvent(self, event):
        """Override Qt method."""
        # To be used so tips do not appear outside spyder
        self.tour.lost_focus()

    def context_menu_requested(self, event):
        """ """
        pos = QPoint(event.x(), event.y())
        menu = QMenu(self)

        actions = []
        action_title = create_action(self, _('Go to step: '), icon=QIcon())
        action_title.setDisabled(True)
        actions.append(action_title)
        #        actions.append(create_action(self, _(': '), icon=QIcon()))

        add_actions(menu, actions)

        menu.popup(self.mapToGlobal(pos))

    def reject(self):
        """Qt method to handle escape key event"""
        if not self.is_fade_running():
            key = Qt.Key_Escape
            self.key_pressed = key
            self.sig_key_pressed.emit()
Exemple #17
0
class RectangularRegion(ChartItem):
    """ Rectangular overlay, that (optionally) can be resized by handles.

    TODO:
      * Notification framework
      * Modifiers to allow for more flexible mouse interactions
    """
    def __init__(self, x, y, width=1, height=1, rotation=0, parent=None):
        """ Constructor.

        :param x: Initial x position of ROIs center.
        :param y: Initial y position of ROIs center.
        :param width: Initial width
        :param height: Initial height
        :param rotation: Initial rotation in radians
        :param parent: Optional parent item.
        """
        super(RectangularRegion, self).__init__(parent)

        self.setFlags(QGraphicsItem.ItemIsMovable
                      | QGraphicsItem.ItemIsFocusable
                      | QGraphicsItem.ItemSendsGeometryChanges)

        # self.setHandlesChildEvents(False)
        # self.setFiltersChildEvents(True)
        self.__in_move = False

        self._path = QPainterPath()
        self.pen = QPen(QBrush(QColor(161, 0, 161, 255)), 1.0, Qt.SolidLine)
        self.pen.setCosmetic(True)
        self.brush = QBrush(QColor(255, 255, 255, 40))

        self.state = RoiState()
        self.state.pos = QPointF(x, y)
        self.state.w0 = width
        self.state.w1 = width
        self.state.h0 = height
        self.state.h1 = height

        self.state.rotation = rotation

        self.setPos(self.state.pos)
        self.updatePath()

        self._handles = []

    @property
    def handles(self):
        """ Returns all handles which are attached to the ROI.

        :return: list
        """
        return self._handles

    def addHandle(self, handle):
        """ Adds a handle to the ROI.

        :param handle: Resize or rotate handle
        """
        handle.setParentItem(self)
        # self.addToGroup(handle)
        self.handles.append(handle)
        handle.updatePosition()

    def removeHandle(self, handle):
        """ Removes the given handle from the ROI.

        :param handle: Handle
        :return:
        """
        if handle not in self.handles:
            _log.warning("Handle not part of ROI.")
            return

        self.handles.remove(handle)
        # self.removeFromGroup(handle)
        self.scene().removeItem(handle)

    def boundingRect(self):
        return self._path.boundingRect()

    def updatePath(self):
        p0 = Vec2(self.state.w0, self.state.h0)
        p1 = Vec2(-self.state.w1, self.state.h0)
        p2 = Vec2(-self.state.w1, -self.state.h1)
        p3 = Vec2(self.state.w0, -self.state.h1)

        p0t = p0.rotate(self.state.rotation)
        p1t = p1.rotate(self.state.rotation)
        p2t = p2.rotate(self.state.rotation)
        p3t = p3.rotate(self.state.rotation)

        self._path = QPainterPath()
        self._path.moveTo(p0t.x, p0t.y)
        self._path.lineTo(p1t.x, p1t.y)
        self._path.lineTo(p2t.x, p2t.y)
        self._path.lineTo(p3t.x, p3t.y)
        self._path.closeSubpath()

        self.prepareGeometryChange()

    def paint(self, p=QPainter(), o=QStyleOptionGraphicsItem(), widget=None):
        p.setRenderHint(QPainter.Antialiasing)
        p.setPen(self.pen)
        p.setBrush(self.brush)
        p.drawPath(self._path)

        p.setBrush(Qt.transparent)
        p.drawLine(QLineF(-0.5, 0, 0.5, 0))
        p.drawLine(QLineF(0, -0.5, 0, 0.5))
        p.drawEllipse(QPointF(0, 0), 0.25, 0.25)

    def mousePressEvent(self, e):
        # !!!F*****g leason learned, call super to avoid weird jumps in position!!!
        super(RectangularRegion, self).mousePressEvent(e)
        self.__in_move = True

    def mouseReleaseEvent(self, e):
        super(RectangularRegion, self).mouseReleaseEvent(e)
        self.__in_move = False

    def itemChange(self, change, value):
        if change == QGraphicsItem.ItemPositionChange and self.__in_move:
            old_pos = self.pos()
            new_pos = value  # .toPointF()

            delta = old_pos - new_pos
            _log.debug("Delta: {}".format(delta))

            self.state.pos = new_pos
            value = new_pos

            for handle in self.handles:
                handle.updatePosition()

        return super(RectangularRegion, self).itemChange(change, value)

    def rotation(self):
        """ Override takes rotation from the state instead of items transformation.

        :return: rotation in degrees
        """
        return self.state.rotation * 180 / np.pi

    def setRotation(self, degree):
        """ Override to propagate rotation to state instead of applying it to the items transform

        :param degree: Rotation in degrees
        """
        self.state.rotation = (degree % 360) * np.pi / 180.0

        for h in self.handles:
            h.updatePosition()

        self.updatePath()