Ejemplo n.º 1
0
 def drawValue(self, p: QPainter, baseRect: QRectF, value: float, delta: float):
     if value == self.m_min:
         return
     if self.m_barStyle == self.BarStyle.EXPAND:
         p.setBrush(self.palette().highlight())
         p.setPen(QPen(self.palette().shadow().color(), self.m_dataPenWidth))
         radius = (baseRect.height() / 2) / delta
         p.drawEllipse(baseRect.center(), radius, radius)
         return
     if self.m_barStyle == self.BarStyle.LINE:
         p.setPen(QPen(self.palette().highlight().color(), self.m_dataPenWidth))
         p.setBrush(Qt.NoBrush)
         if value == self.m_max:
             p.drawEllipse(baseRect.adjusted(self.m_outlinePenWidth / 2, self.m_outlinePenWidth / 2,
                                             -self.m_outlinePenWidth / 2, -self.m_outlinePenWidth / 2))
         else:
             arcLength = 360 / delta
             p.drawArc(baseRect.adjusted(self.m_outlinePenWidth / 2, self.m_outlinePenWidth / 2,
                                         -self.m_outlinePenWidth / 2, -self.m_outlinePenWidth / 2),
                       int(self.m_nullPosition * 16),
                       int(-arcLength * 16))
         return
     dataPath = QPainterPath()
     dataPath.setFillRule(Qt.WindingFill)
     if value == self.m_max:
         dataPath.addEllipse(baseRect)
     else:
         arcLength = 360 / delta
         dataPath.moveTo(baseRect.center())
         dataPath.arcTo(baseRect, self.m_nullPosition, -arcLength)
         dataPath.lineTo(baseRect.center())
     p.setBrush(self.palette().highlight())
     p.setPen(QPen(self.palette().shadow().color(), self.m_dataPenWidth))
     p.drawPath(dataPath)
Ejemplo n.º 2
0
class SelectionRectangle(QGraphicsItem):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.setZValue(10000)

        self.mRectangle = QRectF()

    def setRectangle(self, rectangle):
        self.prepareGeometryChange()
        self.mRectangle = rectangle

    def boundingRect(self):
        return self.mRectangle.adjusted(-1, -1, 2, 2)

    def paint(self, painter, option, widget=None):
        if (self.mRectangle.isNull()):
            return
        # Draw a shadow
        black = QColor(Qt.black)
        black.setAlpha(128)
        pen = QPen(black, 2, Qt.DotLine)
        pen.setCosmetic(True)
        painter.setPen(pen)
        painter.drawRect(self.mRectangle.translated(1, 1))
        # Draw a rectangle in the highlight color
        highlight = QApplication.palette().highlight().color()
        pen.setColor(highlight)
        highlight.setAlpha(32)
        painter.setPen(pen)
        painter.setBrush(highlight)
        painter.drawRect(self.mRectangle)
Ejemplo n.º 3
0
class SelectionRectangle(QGraphicsItem):

    def __init__(self, parent = None):
        super().__init__(parent)

        self.setZValue(10000)

        self.mRectangle = QRectF()

    def setRectangle(self, rectangle):
        self.prepareGeometryChange()
        self.mRectangle = rectangle

    def boundingRect(self):
        return self.mRectangle.adjusted(-1, -1, 2, 2)

    def paint(self, painter, option, widget = None):
        if (self.mRectangle.isNull()):
            return
        # Draw a shadow
        black = QColor(Qt.black)
        black.setAlpha(128)
        pen = QPen(black, 2, Qt.DotLine)
        pen.setCosmetic(True)
        painter.setPen(pen)
        painter.drawRect(self.mRectangle.translated(1, 1))
        # Draw a rectangle in the highlight color
        highlight = QApplication.palette().highlight().color()
        pen.setColor(highlight)
        highlight.setAlpha(32)
        painter.setPen(pen)
        painter.setBrush(highlight)
        painter.drawRect(self.mRectangle)
Ejemplo n.º 4
0
    def _hitTest(self, rc: QRectF, mousePos: QPointF) -> Hit:
        maxdist = 4
        if not rc.adjusted(-maxdist, -maxdist, maxdist,
                           maxdist).contains(mousePos):
            return Hit.NoHit

        def dist(p1, p2):
            return (p1 - p2).manhattanLength()

        if dist(rc.topLeft(), mousePos) < maxdist:
            return Hit.TopLeft
        elif dist(rc.topRight(), mousePos) < maxdist:
            return Hit.TopRight
        elif dist(rc.bottomRight(), mousePos) < maxdist:
            return Hit.BottomRight
        elif dist(rc.bottomLeft(), mousePos) < maxdist:
            return Hit.BottomLeft
        elif abs(rc.left() - mousePos.x()) < maxdist:
            return Hit.Left
        elif abs(rc.right() - mousePos.x()) < maxdist:
            return Hit.Right
        elif abs(rc.top() - mousePos.y()) < maxdist:
            return Hit.Top
        elif abs(rc.bottom() - mousePos.y()) < maxdist:
            return Hit.Bottom
        elif rc.contains(mousePos):
            return Hit.Center
        else:
            return Hit.NoHit
Ejemplo n.º 5
0
    def paint(self, painter, styleOption, modelIndex):
        """Paint the Data Edit Cells with support for rich text.

        Other cells are painted with the base class default.
        Also paints an error rectangle if the format error flag is set.
        Arguments:
            painter -- the painter instance
            styleOption -- the data for styles and geometry
            modelIndex -- the index of the cell to be painted
        """
        cell = self.parent().item(modelIndex.row(), modelIndex.column())
        if isinstance(cell, DataEditCell):
            painter.save()
            doc = cell.doc
            doc.setTextWidth(styleOption.rect.width())
            painter.translate(styleOption.rect.topLeft())
            paintRect = QRectF(0, 0, styleOption.rect.width(),
                               styleOption.rect.height())
            painter.setClipRect(paintRect)
            painter.fillRect(paintRect, QApplication.palette().base())
            painter.setPen(QPen(QApplication.palette().text(), 1))
            painter.drawRect(paintRect.adjusted(0, 0, -1, -1))
            doc.drawContents(painter)
            if cell.errorFlag:
                path = QPainterPath(QPointF(0, 0))
                path.lineTo(0, 10)
                path.lineTo(10, 0)
                path.closeSubpath()
                painter.fillPath(path, QApplication.palette().highlight())
            painter.restore()
        else:
            super().paint(painter, styleOption, modelIndex)
Ejemplo n.º 6
0
class Indicator(QGraphicsItem):
    def __init__(self,
                 data: "InternalData",
                 scene: QGraphicsScene,
                 parent=None):
        super().__init__(parent)
        self.rect = QRectF(0, 0, 0, 0)
        self.data: "InternalData" = data

    def boundingRect(self):
        # f*****g PyQt5 binding: return value of boundingRect should be QRectF
        return QRectF(self.rect.adjusted(-2, -2, 2, 2))

    def paint(
        self,
        painter: QPainter,
        option: QStyleOptionGraphicsItem,
        widget: QWidget = None,
    ):
        painter.drawRect(self.rect)
        b = self.data.bar_data
        text = (f"open: {b.open}\n"
                f"high: {b.high}\n"
                f"low: {b.low}\n"
                f"close: {b.close}\n"
                f"date: {self.data.x}")
        rect = painter.boundingRect(0.0, 0.0, 1000.0, 1000.0, Qt.AlignLeft,
                                    text)
        painter.drawText(self.rect, Qt.AlignLeft, text)
        self.rect = rect  # fixme: scrolling will make this mismatch
Ejemplo n.º 7
0
    def paintEvent(self, event):
        painter = QPainter(self)
        if self.pixmap:
            size = self.pixmap.size()
            aspect = float(size.width()) / size.height()
            if aspect > 1:
                # Image is wider than it is tall - centre vertically
                left = 0
                width = self.width()
                height = self.height() / aspect
                top = (self.height() - height) / 2
            else:
                # Image is taller than it is wide - centre horizontally
                top = 0
                height = self.height()
                width = self.width() * aspect
                left = (self.width() - width) / 2

            painter.drawPixmap(QRect(left, top, width, height), self.pixmap)

            if self.focus:
                # self.focus contains coords between 0 and 1 - translate these
                # to pixels
                pixels = QRectF(left + self.focus.left() * width,
                                top + self.focus.top() * height,
                                self.focus.width() * width,
                                self.focus.height() * height)
                # Outer box in white
                painter.setPen(QPen(Qt.white, 1, Qt.SolidLine))
                painter.drawRect(pixels)
                # Inner box in black
                painter.setPen(QPen(Qt.black, 1, Qt.SolidLine))
                painter.drawRect(pixels.adjusted(1, 1, -1, -1))
Ejemplo n.º 8
0
class Spinner(QSvgWidget):
    icon_file = QtDynamicProperty('icon_file', type=unicode)
    icon_size = QtDynamicProperty('icon_size', type=QSize)
    icon_crop = QtDynamicProperty('icon_crop', type=int)

    def __init__(self, parent=None, icon='icons/spinner.svg'):
        super(Spinner, self).__init__(parent)
        self._original_viewbox = QRectF()
        self.icon_crop = 0
        self.icon_size = None
        self.icon_file = Resources.get(icon)

    def load(self, svg):
        super(Spinner, self).load(svg)
        self._original_viewbox = self.renderer().viewBoxF()
        self._update_viewbox(self.size())

    def event(self, event):
        if event.type() == QEvent.DynamicPropertyChange:
            if event.propertyName() == 'icon_crop':
                self._update_viewbox(self.size())
            elif event.propertyName() == 'icon_file':
                self.load(self.icon_file)
            elif event.propertyName() == 'icon_size':
                self.updateGeometry()
        return super(Spinner, self).event(event)

    def resizeEvent(self, event):
        super(Spinner, self).resizeEvent(event)
        self._update_viewbox(event.size())

    def sizeHint(self):
        return self.icon_size or super(Spinner, self).sizeHint()

    def _update_viewbox(self, size):
        if self._original_viewbox.isEmpty() or size.isEmpty():
            return
        if self.icon_crop >= 0:
            adjustment = self.icon_crop
        else:
            adjustment = self._original_viewbox.width() * self.icon_crop / (
                self._original_viewbox.width() + 2 * self.icon_crop
            )  # (w - w * w/(w+2b))/2 = wb/(w+2b)
        viewbox = self._original_viewbox.adjusted(adjustment, adjustment,
                                                  -adjustment, -adjustment)
        width = size.width()
        height = size.height()
        if height >= width:
            new_viewbox = QRectF(
                viewbox.x(),
                viewbox.y() + viewbox.height() / 2 * (1 - height / width),
                viewbox.width(),
                viewbox.height() * height / width)
        else:
            new_viewbox = QRectF(
                viewbox.x() + viewbox.width() / 2 * (1 - width / height),
                viewbox.y(),
                viewbox.width() * width / height, viewbox.height())
        self.renderer().setViewBox(new_viewbox)
Ejemplo n.º 9
0
 def addBorders(self):
     self.borders = []
     rect = QRectF(0, 0, PageSize[0], PageSize[1])
     self.borders.append(self.scene.addRect(rect, Qt.yellow))
     margin = 5.25 * PointSize
     self.borders.append(self.scene.addRect(
             rect.adjusted(margin, margin, -margin, -margin),
             Qt.yellow))
Ejemplo n.º 10
0
    def reconfigureRect(self,
                        top_left,
                        bottom_right,
                        finish=False,
                        padding=80):
        """
        Updates the bounding rect to the size of the childrenBoundingRect.
        Refreshes the outline and grab_corner locations.

        Called by partZDimensionsChangedSlot and partPropertyChangedSlot.
        """
        outline = self.outline

        hasTL = True if top_left else False
        hasBR = True if bottom_right else False

        if hasTL ^ hasBR:  # called via resizeHandle mouseMove?
            ptTL = QPointF(*top_left) if top_left else outline.rect().topLeft()
            ptBR = QPointF(*bottom_right) if bottom_right else outline.rect(
            ).bottomRight()
            o_rect = QRectF(ptTL, ptBR)
            pad_xoffset = self._BOUNDING_RECT_PADDING * 2
            new_size = int(
                (o_rect.width() - _VH_XOFFSET - pad_xoffset) / _BASE_WIDTH)
            substep = self._model_part.subStepSize()
            snap_size = new_size - new_size % substep
            snap_offset = -(new_size % substep) * _BASE_WIDTH
            self.resize_handle_group.updateText(HandleType.RIGHT, snap_size)
            if finish:
                self._model_part.setAllVirtualHelixSizes(snap_size)
                o_rect = o_rect.adjusted(0, 0, snap_offset, 0)
                # print("finish", vh_size, new_size, substep, snap_size)
            self.outline.setRect(o_rect)
        else:
            # 1. Temporarily remove children that shouldn't affect size
            outline.setParentItem(None)
            self.workplane.setParentItem(None)
            self.model_bounds_hint.setParentItem(None)
            self.resize_handle_group.setParentItemAll(None)
            self.prexover_manager.setParentItem(None)
            # 2. Get the tight bounding rect
            self.setRect(self.childrenBoundingRect())  # vh_items only
            # 3. Restore children like nothing happened
            outline.setParentItem(self)
            self.workplane.setParentItem(self)
            self.model_bounds_hint.setParentItem(self)
            self.resize_handle_group.setParentItemAll(self)
            self.prexover_manager.setParentItem(self)
            self._configureOutline(outline)

        self.resetPen(self.modelColor(), 0)  # cosmetic
        self.resetBrush(styles.DEFAULT_BRUSH_COLOR, styles.DEFAULT_ALPHA)
        self.workplane.reconfigureRect((), ())
        self.resize_handle_group.alignHandles(outline.rect())
        return outline.rect()
Ejemplo n.º 11
0
class MapObjectLabel(QGraphicsItem):
    def __init__(self, object, parent=None):
        super().__init__(parent)

        self.mBoundingRect = QRectF()
        self.mObject = object

        self.setFlags(QGraphicsItem.ItemIgnoresTransformations
                      | QGraphicsItem.ItemIgnoresParentOpacity)

    def syncWithMapObject(self, renderer):
        nameVisible = self.mObject.isVisible() and self.mObject.name() != ''
        self.setVisible(nameVisible)
        if (not nameVisible):
            return
        metrics = QFontMetricsF(QGuiApplication.font())
        boundingRect = metrics.boundingRect(self.mObject.name())
        boundingRect.translate(-boundingRect.width() / 2, -labelDistance)
        boundingRect.adjust(-labelMargin * 2, -labelMargin, labelMargin * 2,
                            labelMargin)
        pixelPos = renderer.pixelToScreenCoords_(self.mObject.position())
        bounds = objectBounds(self.mObject, renderer)
        # Adjust the bounding box for object rotation
        transform = QTransform()
        transform.translate(pixelPos.x(), pixelPos.y())
        transform.rotate(self.mObject.rotation())
        transform.translate(-pixelPos.x(), -pixelPos.y())
        bounds = transform.mapRect(bounds)
        # Center the object name on the object bounding box
        pos = QPointF((bounds.left() + bounds.right()) / 2, bounds.top())
        self.setPos(pos + self.mObject.objectGroup().offset())
        if (self.mBoundingRect != boundingRect):
            self.prepareGeometryChange()
            self.mBoundingRect = boundingRect

    def boundingRect(self):
        return self.mBoundingRect.adjusted(0, 0, 1, 1)

    def paint(self, painter, arg2, arg3):
        color = MapObjectItem.objectColor(self.mObject)
        painter.setRenderHint(QPainter.Antialiasing)
        painter.setBrush(Qt.black)
        painter.setPen(Qt.NoPen)
        painter.drawRoundedRect(self.mBoundingRect.translated(1, 1), 4, 4)
        painter.setBrush(color)
        painter.drawRoundedRect(self.mBoundingRect, 4, 4)
        textPos = QPointF(-(self.mBoundingRect.width() - labelMargin * 4) / 2,
                          -labelDistance)
        painter.drawRoundedRect(self.mBoundingRect, 4, 4)
        painter.setPen(Qt.black)
        painter.drawText(textPos + QPointF(1, 1), self.mObject.name())
        painter.setPen(Qt.white)
        painter.drawText(textPos, self.mObject.name())
Ejemplo n.º 12
0
    def addBorders(self):
        '''添加出血框和打印边界框,对scene进行操作同时添加到self.borders这一列表中'''
        self.borders = []
        rect = QRectF(0, 0, PageSize[0], PageSize[1])
        self.borders.append(self.scene.addRect(
            rect,
            Qt.black))  # addRect px,py,x,y,QPen,QBrush or QRectF,QPen,QBrush
        # scene.addRect(): Return QGraphicsRectItem;Inherits: QGraphicsItem

        margin = 5.25 * PointSize
        self.borders.append(
            self.scene.addRect(rect.adjusted(margin, margin, -margin, -margin),
                               Qt.red))
Ejemplo n.º 13
0
class RoundRectItem(QGraphicsObject):
    def __init__(self, bounds, color, parent=None):
        super(RoundRectItem, self).__init__(parent)

        self.fillRect = False
        self.bounds = QRectF(bounds)
        self.pix = QPixmap()

        self.gradient = QLinearGradient()
        self.gradient.setStart(self.bounds.topLeft())
        self.gradient.setFinalStop(self.bounds.bottomRight())
        self.gradient.setColorAt(0, color)
        self.gradient.setColorAt(1, color.darker(200))

        self.setCacheMode(QGraphicsItem.ItemCoordinateCache)

    def setFill(self, fill):
        self.fillRect = fill
        self.update()

    def fill(self):
        return self.fillRect

    fill = pyqtProperty(bool, fill, setFill)

    def paint(self, painter, option, widget):
        painter.setPen(Qt.NoPen)
        painter.setBrush(QColor(0, 0, 0, 64))
        painter.drawRoundedRect(self.bounds.translated(2, 2), 25.0, 25.0)

        if self.fillRect:
            painter.setBrush(QApplication.palette().brush(QPalette.Window))
        else:
            painter.setBrush(self.gradient)

        painter.setPen(QPen(Qt.black, 1))
        painter.drawRoundedRect(self.bounds, 25.0, 25.0)
        if not self.pix.isNull():
            painter.scale(1.95, 1.95)
            painter.drawPixmap(-self.pix.width() / 2, -self.pix.height() / 2,
                               self.pix)

    def boundingRect(self):
        return self.bounds.adjusted(0, 0, 2, 2)

    def pixmap(self):
        return QPixmap(self.pix)

    def setPixmap(self, pixmap):
        self.pix = QPixmap(pixmap)
        self.update()
Ejemplo n.º 14
0
class MapObjectLabel(QGraphicsItem):

    def __init__(self, object, parent = None):
        super().__init__(parent)
        
        self.mBoundingRect = QRectF()
        self.mObject = object

        self.setFlags(QGraphicsItem.ItemIgnoresTransformations | QGraphicsItem.ItemIgnoresParentOpacity)
    
    def syncWithMapObject(self, renderer):
        nameVisible = self.mObject.isVisible() and self.mObject.name()!=''
        self.setVisible(nameVisible)
        if (not nameVisible):
            return
        metrics = QFontMetricsF(QGuiApplication.font())
        boundingRect = metrics.boundingRect(self.mObject.name())
        boundingRect.translate(-boundingRect.width() / 2, -labelDistance)
        boundingRect.adjust(-labelMargin*2, -labelMargin, labelMargin*2, labelMargin)
        pixelPos = renderer.pixelToScreenCoords_(self.mObject.position())
        bounds = objectBounds(self.mObject, renderer)
        # Adjust the bounding box for object rotation
        transform = QTransform()
        transform.translate(pixelPos.x(), pixelPos.y())
        transform.rotate(self.mObject.rotation())
        transform.translate(-pixelPos.x(), -pixelPos.y())
        bounds = transform.mapRect(bounds)
        # Center the object name on the object bounding box
        pos = QPointF((bounds.left() + bounds.right()) / 2, bounds.top())
        self.setPos(pos + self.mObject.objectGroup().offset())
        if (self.mBoundingRect != boundingRect):
            self.prepareGeometryChange()
            self.mBoundingRect = boundingRect

    def boundingRect(self):
        return self.mBoundingRect.adjusted(0, 0, 1, 1)
    
    def paint(self, painter, arg2, arg3):
        color = MapObjectItem.objectColor(self.mObject)
        painter.setRenderHint(QPainter.Antialiasing)
        painter.setBrush(Qt.black)
        painter.setPen(Qt.NoPen)
        painter.drawRoundedRect(self.mBoundingRect.translated(1, 1), 4, 4)
        painter.setBrush(color)
        painter.drawRoundedRect(self.mBoundingRect, 4, 4)
        textPos = QPointF(-(self.mBoundingRect.width() - labelMargin*4) / 2, -labelDistance)
        painter.drawRoundedRect(self.mBoundingRect, 4, 4)
        painter.setPen(Qt.black)
        painter.drawText(textPos + QPointF(1,1), self.mObject.name())
        painter.setPen(Qt.white)
        painter.drawText(textPos, self.mObject.name())
Ejemplo n.º 15
0
    def syncWithTileLayer(self):
        self.prepareGeometryChange()
        renderer = self.mMapDocument.renderer()
        boundingRect = QRectF(renderer.boundingRect(self.mLayer.bounds()))
        margins = self.mLayer.drawMargins()
        map = self.mLayer.map()
        if map:
            margins.setTop(margins.top() - map.tileHeight())
            margins.setRight(margins.right() - map.tileWidth())

        self.mBoundingRect = boundingRect.adjusted(-margins.left(),
                                                   -margins.top(),
                                                   margins.right(),
                                                   margins.bottom())
Ejemplo n.º 16
0
class RoundRectItem(QGraphicsObject):
    def __init__(self, bounds, color, parent=None):
        super(RoundRectItem, self).__init__(parent)

        self.fillRect = False
        self.bounds = QRectF(bounds)
        self.pix = QPixmap()

        self.gradient = QLinearGradient()
        self.gradient.setStart(self.bounds.topLeft())
        self.gradient.setFinalStop(self.bounds.bottomRight())
        self.gradient.setColorAt(0, color)
        self.gradient.setColorAt(1, color.darker(200))

        self.setCacheMode(QGraphicsItem.ItemCoordinateCache)

    def setFill(self, fill):
        self.fillRect = fill
        self.update()

    def fill(self):
        return self.fillRect

    fill = pyqtProperty(bool, fill, setFill)

    def paint(self, painter, option, widget):
        painter.setPen(Qt.NoPen)
        painter.setBrush(QColor(0, 0, 0, 64))
        painter.drawRoundedRect(self.bounds.translated(2, 2), 25.0, 25.0)

        if self.fillRect:
            painter.setBrush(QApplication.palette().brush(QPalette.Window))
        else:
            painter.setBrush(self.gradient)

        painter.setPen(QPen(Qt.black, 1))
        painter.drawRoundedRect(self.bounds, 25.0, 25.0)
        if not self.pix.isNull():
            painter.scale(1.95, 1.95)
            painter.drawPixmap(-self.pix.width() / 2, -self.pix.height() / 2, self.pix)

    def boundingRect(self):
        return self.bounds.adjusted(0, 0, 2, 2)

    def pixmap(self):
        return QPixmap(self.pix)

    def setPixmap(self, pixmap):
        self.pix = QPixmap(pixmap)
        self.update()
Ejemplo n.º 17
0
 def drawBase(self, p: QPainter, baseRect: QRectF):
     if self.m_barStyle == self.BarStyle.DONUT:
         p.setPen(QPen(self.palette().shadow().color(), self.m_outlinePenWidth))
         p.setBrush(self.palette().base())
         p.drawEllipse(baseRect)
     elif self.m_barStyle == self.BarStyle.LINE:
         p.setPen(QPen(self.palette().base().color(), self.m_outlinePenWidth))
         p.setBrush(Qt.NoBrush)
         p.drawEllipse(baseRect.adjusted(self.m_outlinePenWidth / 2, self.m_outlinePenWidth / 2,
                                         -self.m_outlinePenWidth / 2, -self.m_outlinePenWidth / 2))
     elif self.m_barStyle in (self.BarStyle.PIE, self.BarStyle.EXPAND):
         p.setPen(QPen(self.palette().base().color(), self.m_outlinePenWidth))
         p.setBrush(self.palette().base())
         p.drawEllipse(baseRect)
Ejemplo n.º 18
0
    def syncWithTileLayer(self):
        self.prepareGeometryChange()
        renderer = self.mMapDocument.renderer()
        boundingRect = QRectF(renderer.boundingRect(self.mLayer.bounds()))
        margins = self.mLayer.drawMargins()
        map = self.mLayer.map()
        if map:
            margins.setTop(margins.top() - map.tileHeight())
            margins.setRight(margins.right() - map.tileWidth())

        self.mBoundingRect = boundingRect.adjusted(-margins.left(),
                                              -margins.top(),
                                              margins.right(),
                                              margins.bottom())
Ejemplo n.º 19
0
class Spinner(QSvgWidget):
    icon_file = QtDynamicProperty('icon_file', type=unicode)
    icon_size = QtDynamicProperty('icon_size', type=QSize)
    icon_crop = QtDynamicProperty('icon_crop', type=int)

    def __init__(self, parent=None, icon='icons/spinner.svg'):
        super(Spinner, self).__init__(parent)
        self._original_viewbox = QRectF()
        self.icon_crop = 0
        self.icon_size = None
        self.icon_file = Resources.get(icon)

    def load(self, svg):
        super(Spinner, self).load(svg)
        self._original_viewbox = self.renderer().viewBoxF()
        self._update_viewbox(self.size())

    def event(self, event):
        if event.type() == QEvent.DynamicPropertyChange:
            if event.propertyName() == 'icon_crop':
                self._update_viewbox(self.size())
            elif event.propertyName() == 'icon_file':
                self.load(self.icon_file)
            elif event.propertyName() == 'icon_size':
                self.updateGeometry()
        return super(Spinner, self).event(event)

    def resizeEvent(self, event):
        super(Spinner, self).resizeEvent(event)
        self._update_viewbox(event.size())

    def sizeHint(self):
        return self.icon_size or super(Spinner, self).sizeHint()

    def _update_viewbox(self, size):
        if self._original_viewbox.isEmpty() or size.isEmpty():
            return
        if self.icon_crop >= 0:
            adjustment = self.icon_crop
        else:
            adjustment = self._original_viewbox.width() * self.icon_crop / (self._original_viewbox.width() + 2*self.icon_crop)  # (w - w * w/(w+2b))/2 = wb/(w+2b)
        viewbox = self._original_viewbox.adjusted(adjustment, adjustment, -adjustment, -adjustment)
        width = size.width()
        height = size.height()
        if height >= width:
            new_viewbox = QRectF(viewbox.x(), viewbox.y() + viewbox.height()/2 * (1 - height/width), viewbox.width(), viewbox.height() * height/width)
        else:
            new_viewbox = QRectF(viewbox.x() + viewbox.width()/2 * (1 - width/height), viewbox.y(), viewbox.width() * width/height, viewbox.height())
        self.renderer().setViewBox(new_viewbox)
Ejemplo n.º 20
0
 def paintEvent(self, event):
     pixmap = self._shadowPixmap
     widget_rect = QRectF(QPointF(0.0, 0.0), QSizeF(self.size()))
     frame_rect = QRectF(self.contentsRect())
     left, top, right, bottom = self.getContentsMargins()
     pixmap_rect = QRectF(QPointF(0, 0), QSizeF(pixmap.size()))
     # Shadow casting rectangle.
     pixmap_shadow_rect = pixmap_rect.adjusted(left, top, -right, -bottom)
     source_rects = self._shadowPixmapFragments(pixmap_rect,
                                                pixmap_shadow_rect)
     target_rects = self._shadowPixmapFragments(widget_rect, frame_rect)
     painter = QPainter(self)
     for source, target in zip(source_rects, target_rects):
         painter.drawPixmap(target, pixmap, source)
     painter.end()
Ejemplo n.º 21
0
class HandleItem(QGraphicsItem):
    def __init__(self, position, size=DEFAULT_HANDLE_SIZE, parent=None, color=Qt.green):
        super(HandleItem, self).__init__(parent)
        self.setPos(position)
        self.size = size
        self.color = color
        self.idd = DEFAULT_IDMAN.next()
        # self.setZValue(10)
        self.setFlags(self.flags() |
                      QGraphicsItem.ItemIsMovable |
                      QGraphicsItem.ItemSendsGeometryChanges |
                      QGraphicsItem.ItemIsFocusable)
        self.rect = QRectF(0, 0, size, size)
                    
    def boundingRect(self):
        size = self.size
        return self.rect.adjusted(-size,-size,0,0)
        
    def paint(self, painter, option, widget=None):
        qp = painter
        qp.setPen(QtGui.QColor(168, 34, 3))
        qp.setBrush(QBrush(self.color, Qt.SolidPattern))
        # size = self.size
        qp.drawEllipse(self.boundingRect())
    
    def points(self):
        return [[self.x(), self.y()]]

    def mousePressEvent(self, e):
        pass
        # if e.button() == 1:
        #     self.parentItem().main.bringToFront(self.parentItem().idd)
        # if e.button() == 2:
        #     self.parentItem().main.remove(self)
            
    def itemChange(self, change, value):
        if change == QGraphicsItem.ItemPositionChange:
            self.parentItem().itemChange(ControllableItem.HandlePositionHasChanged, value)
        return super(HandleItem, self).itemChange(change, value)
        
    def setSize(self, size):
        self.prepareGeometryChange()
        self.size = size
        self.rect = QRectF(0,0,size,size)
        
    def setColor(self, color):
        self.color = color
        self.update()
Ejemplo n.º 22
0
    def reconfigureRect(self, top_left: Vec2T, bottom_right: Vec2T,
                                finish: bool = False,
                                padding: int = 80):
        """Updates the bounding rect to the size of the childrenBoundingRect.
        Refreshes the outline and grab_corner locations.

        Called by ``partZDimensionsChangedSlot`` and ``partPropertyChangedSlot``.
        """
        outline = self.outline

        hasTL = True if top_left else False
        hasBR = True if bottom_right else False

        if hasTL ^ hasBR:  # called via resizeHandle mouseMove?
            ptTL = QPointF(*top_left) if top_left else outline.rect().topLeft()
            ptBR = QPointF(*bottom_right) if bottom_right else outline.rect().bottomRight()
            o_rect = QRectF(ptTL, ptBR)
            pad_xoffset = self._BOUNDING_RECT_PADDING*2
            new_size = int((o_rect.width()-_VH_XOFFSET-pad_xoffset)/_BASE_WIDTH)
            substep = self._model_part.subStepSize()
            snap_size = new_size - new_size % substep
            snap_offset = -(new_size % substep)*_BASE_WIDTH
            self.resize_handle_group.updateText(HandleEnum.RIGHT, snap_size)
            if finish:
                self._model_part.setAllVirtualHelixSizes(snap_size)
                o_rect = o_rect.adjusted(0, 0, snap_offset, 0)
                # print("finish", vh_size, new_size, substep, snap_size)
            self.outline.setRect(o_rect)
        else:
            # 1. Temporarily remove children that shouldn't affect size
            outline.setParentItem(None)
            self.model_bounds_hint.setParentItem(None)
            self.resize_handle_group.setParentItemAll(None)
            self.prexover_manager.setParentItem(None)
            # 2. Get the tight bounding rect
            self.setRect(self.childrenBoundingRect())  # vh_items only
            # 3. Restore children like nothing happened
            outline.setParentItem(self)
            self.model_bounds_hint.setParentItem(self)
            self.resize_handle_group.setParentItemAll(self)
            self.prexover_manager.setParentItem(self)
            self._configureOutline(outline)

        self.resetPen(self.modelColor(), 0)  # cosmetic
        self.resetBrush(styles.DEFAULT_BRUSH_COLOR, styles.DEFAULT_ALPHA)
        self.resize_handle_group.alignHandles(outline.rect())
        return outline.rect()
Ejemplo n.º 23
0
    def paint(self, painter: QPainter, option: QStyleOptionViewItem, index: QModelIndex):
        if self.colors:
            try:
                item = index.model().data(index)
                index = self.items.index(item) if item in self.items else int(item)
                color = self.colors[index]

                x, y, h = option.rect.x(), option.rect.y(), option.rect.height()

                rect = QRectF(x + 8, y + h / 2 - 8, 16, 16)
                painter.fillRect(rect, QColor("black"))
                rect = rect.adjusted(1, 1, -1, -1)
                painter.fillRect(rect, QColor(color.red(), color.green(), color.blue(), 255))
            except:
                super().paint(painter, option, index)
        else:
            super().paint(painter, option, index)
Ejemplo n.º 24
0
    def paint(self, painter: QPainter, option: QStyleOptionViewItem,
              index: QModelIndex):
        if self.colors:
            try:
                item = index.model().data(index)
                index = self.items.index(item) if item in self.items else int(
                    item)
                color = self.colors[index]

                x, y, h = option.rect.x(), option.rect.y(), option.rect.height(
                )

                rect = QRectF(x + 8, y + h / 2 - 8, 16, 16)
                painter.fillRect(rect, QColor("black"))
                rect = rect.adjusted(1, 1, -1, -1)
                painter.fillRect(
                    rect, QColor(color.red(), color.green(), color.blue(),
                                 255))
            except:
                super().paint(painter, option, index)
        else:
            super().paint(painter, option, index)
Ejemplo n.º 25
0
    def __init__(self, parent, row, col, num, rect: QRectF, disabled=False):
        super().__init__(parent=parent)
        self.rect = rect.adjusted(self.adj, self.adj, -self.adj, -self.adj)
        self.disabled = disabled
        self.row = row
        self.col = col

        # Create a link to the sudoku game instance.
        self.game = self.parent.parent.game

        if num == 0:
            self.num = ''
        else:
            self.num = num

        self.animations()

        if not self.disabled:
            self.setFlags(QGraphicsItem.ItemIsFocusable
                          | QGraphicsItem.ItemIsSelectable)
        self.setAcceptHoverEvents(True)
        self.setCacheMode(QGraphicsItem.DeviceCoordinateCache)
        self.setTransformOriginPoint(self.rect.center())
Ejemplo n.º 26
0
    def paintEvent(self, event):
        # TODO: Use QPainter.drawPixmapFragments on Qt 4.7
        opt = QStyleOption()
        opt.initFrom(self)

        pixmap = self.__shadowPixmap

        shadow_rect = QRectF(opt.rect)
        widget_rect = QRectF(self.widget().geometry())
        widget_rect.moveTo(self.radius_, self.radius_)

        left = top = right = bottom = self.radius_
        pixmap_rect = QRectF(QPointF(0, 0), QSizeF(pixmap.size()))

        # Shadow casting rectangle in the source pixmap.
        pixmap_shadow_rect = pixmap_rect.adjusted(left, top, -right, -bottom)
        source_rects = self.__shadowPixmapFragments(pixmap_rect,
                                                    pixmap_shadow_rect)
        target_rects = self.__shadowPixmapFragments(shadow_rect, widget_rect)

        painter = QPainter(self)
        for source, target in zip(source_rects, target_rects):
            painter.drawPixmap(target, pixmap, source)
        painter.end()
Ejemplo n.º 27
0
from .virtualhelixitem import VirtualHelixItem
from .activesliceitem import ActiveSliceItem

from . import slicestyles as styles
import cadnano.util as util
from cadnano import getReopen

from PyQt5.QtCore import QPointF, Qt, QRectF, QEvent, pyqtSignal, pyqtSlot, QObject
from PyQt5.QtGui import QBrush, QPainterPath, QPen
from PyQt5.QtWidgets import QGraphicsItem, QGraphicsEllipseItem

_RADIUS = styles.SLICE_HELIX_RADIUS
_DEFAULT_RECT = QRectF(0, 0, 2 * _RADIUS, 2 * _RADIUS)
HIGHLIGHT_WIDTH = styles.SLICE_HELIX_MOD_HILIGHT_WIDTH
DELTA = (HIGHLIGHT_WIDTH - styles.SLICE_HELIX_STROKE_WIDTH)/2.
_HOVER_RECT = _DEFAULT_RECT.adjusted(-DELTA, -DELTA, DELTA, DELTA)
_MOD_PEN = QPen(styles.BLUE_STROKE, HIGHLIGHT_WIDTH)

class PartItem(QGraphicsItem):
    _RADIUS = styles.SLICE_HELIX_RADIUS

    def __init__(self, model_part, parent=None):
        """
        Parent should be either a SliceRootItem, or an AssemblyItem.

        Invariant: keys in _empty_helix_hash = range(_nrows) x range(_ncols)
        where x is the cartesian product.
        
        Order matters for deselector, probe, and setlattice
        """
        super(PartItem, self).__init__(parent)
Ejemplo n.º 28
0
class Callout(QGraphicsItem):
    def __init__(self, chart):
        super().__init__(chart)

        self.m_chart = chart
        self.m_text = ""
        self.m_textRect = QRectF()
        self.m_rect = QRectF()
        self.m_anchor = QPointF()
        self.m_font = QFont()

    def boundingRect(self):
        anchor = self.mapFromParent(self.m_chart.mapToPosition(self.m_anchor))
        rect = QRectF()
        rect.setLeft(min(self.m_rect.left(), anchor.x()))
        rect.setRight(max(self.m_rect.right(), anchor.x()))
        rect.setTop(min(self.m_rect.top(), anchor.y()))
        rect.setBottom(max(self.m_rect.bottom(), anchor.y()))
        return rect

    def paint(self, painter, option, widget=None):
        path = QPainterPath()
        path.addRoundedRect(self.m_rect, 5, 5)

        anchor = self.mapFromParent(self.m_chart.mapToPosition(self.m_anchor))
        if not self.m_rect.contains(anchor):
            point1 = QPointF()
            point2 = QPointF()

            # establish the position of the anchor point in relation to m_rect
            above = anchor.y() <= self.m_rect.top()
            aboveCenter = (anchor.y() > self.m_rect.top()
                           and anchor.y() <= self.m_rect.center().y())
            belowCenter = (anchor.y() > self.m_rect.center().y()
                           and anchor.y() <= self.m_rect.bottom())
            below = anchor.y() > self.m_rect.bottom()

            onLeft = anchor.x() <= self.m_rect.left()
            leftOfCenter = (anchor.x() > self.m_rect.left()
                            and anchor.x() <= self.m_rect.center().x())
            rightOfCenter = (anchor.x() > self.m_rect.center().x()
                             and anchor.x() <= self.m_rect.right())
            onRight = anchor.x() > self.m_rect.right()

            # get the nearest m_rect corner.
            x = (onRight + rightOfCenter) * self.m_rect.width()
            y = (below + belowCenter) * self.m_rect.height()
            cornerCase = ((above and onLeft) or (above and onRight)
                          or (below and onLeft) or (below and onRight))
            vertical = abs(anchor.x() - x) > abs(anchor.y() - y)

            x1 = (x + leftOfCenter * 10 - rightOfCenter * 20 +
                  cornerCase * int(not vertical) *
                  (onLeft * 10 - onRight * 20))
            y1 = (y + aboveCenter * 10 - belowCenter * 20 +
                  cornerCase * int(vertical) * (above * 10 - below * 20))
            point1.setX(x1)
            point1.setY(y1)

            x2 = (x + leftOfCenter * 20 - rightOfCenter * 10 +
                  cornerCase * int(not vertical) *
                  (onLeft * 20 - onRight * 10))
            y2 = (y + aboveCenter * 20 - belowCenter * 10 +
                  cornerCase * int(vertical) * (above * 20 - below * 10))
            point2.setX(x2)
            point2.setY(y2)

            path.moveTo(point1)
            path.lineTo(anchor)
            path.lineTo(point2)
            path = path.simplified()

        painter.setBrush(QColor(255, 255, 255))
        painter.drawPath(path)
        painter.drawText(self.m_textRect, self.m_text)

    def mousePressEvent(self, event):
        event.setAccepted(True)

    def mouseMoveEvent(self, event):
        if event.buttons() & Qt.LeftButton:
            self.setPos(
                self.mapToParent(event.pos() -
                                 event.buttonDownPos(Qt.LeftButton)))
            event.setAccepted(True)
        else:
            event.setAccepted(False)

    def setText(self, text):
        self.m_text = text
        metrics = QFontMetrics(self.m_font)
        self.m_textRect = QRectF(
            metrics.boundingRect(QRect(0, 0, 150, 150), Qt.AlignLeft,
                                 self.m_text))
        self.m_textRect.translate(5, 5)
        self.prepareGeometryChange()
        self.m_rect = self.m_textRect.adjusted(-5, -5, 5, 5)

    def setAnchor(self, point):
        self.m_anchor = point

    def updateGeometry(self):
        self.prepareGeometryChange()
        self.setPos(
            self.m_chart.mapToPosition(self.m_anchor) + QPoint(10, -50))
Ejemplo n.º 29
0
# extra2 = QPainterPath()
# extra2.addEllipse(-0.35*IW, 0.5*IW, 0.7*IW, 0.3*IW)
# FWDPXI_PP += extra1
# FWDPXI_PP -= extra2

# REVPXI_PP.moveTo(-0.5*IW, -0.7*IW)
# REVPXI_PP.lineTo(0., 0.2*IW)
# REVPXI_PP.lineTo(0.5*IW, -0.7*IW)
# extra1 = QPainterPath()
# extra1.addEllipse(-0.5*IW, -0.9*IW, IW, 0.4*IW)
# REVPXI_PP += extra1

_RADIUS = styles.GRID_HELIX_RADIUS
_WEDGE_RECT_GAIN = 0.25
WEDGE_RECT = QRectF(0, 0, 2 * _RADIUS, 2 * _RADIUS)
WEDGE_RECT = WEDGE_RECT.adjusted(0, 0, _WEDGE_RECT_GAIN, _WEDGE_RECT_GAIN)
_WEDGE_RECT_CENTERPT = WEDGE_RECT.center()


class PropertyWrapperObject(QObject):
    """Summary

    Attributes:
        animations (dict): Description
        bondp2 (TYPE): Description
        item (TYPE): Description
        pen_alpha (TYPE): Description
        rotation (TYPE): Description
    """

    def __init__(self, item):
Ejemplo n.º 30
0
from .virtualhelixitem import VirtualHelixItem
from .activesliceitem import ActiveSliceItem

from cadnano.gui.views import styles
import cadnano.util as util
from cadnano import getReopen

from PyQt5.QtCore import QPointF, Qt, QRectF, QEvent, pyqtSignal, pyqtSlot, QObject
from PyQt5.QtGui import QBrush, QPainterPath, QPen
from PyQt5.QtWidgets import QGraphicsItem, QGraphicsEllipseItem

_RADIUS = styles.SLICE_HELIX_RADIUS
_DEFAULT_RECT = QRectF(0, 0, 2 * _RADIUS, 2 * _RADIUS)
HIGHLIGHT_WIDTH = styles.SLICE_HELIX_MOD_HILIGHT_WIDTH
DELTA = (HIGHLIGHT_WIDTH - styles.SLICE_HELIX_STROKE_WIDTH) / 2.
_HOVER_RECT = _DEFAULT_RECT.adjusted(-DELTA, -DELTA, DELTA, DELTA)
_MOD_PEN = QPen(styles.BLUE_STROKE, HIGHLIGHT_WIDTH)


class PartItem(QGraphicsItem):
    _RADIUS = styles.SLICE_HELIX_RADIUS

    def __init__(self, model_part, parent=None):
        """
        Parent should be either a SliceRootItem, or an AssemblyItem.

        Invariant: keys in _empty_helix_hash = range(_nrows) x range(_ncols)
        where x is the cartesian product.
        
        Order matters for deselector, probe, and setlattice
        """
Ejemplo n.º 31
0
class RoundRectItem(QGraphicsObject):
    """Base class for most graphic objects in our scene"""
    def __init__(self, bounds, color=None, parent=None):
        """
        Args:
            bounds - QRectF, geometry of object
            color - QColor or None
            parent - widget to contain this graphic item or None
        """
        super(RoundRectItem, self).__init__(parent)

        self._fillRect = False
        self._bounds = QRectF(bounds)
        self._pix = QPixmap()
        self._color = color

        self.setCacheMode(QGraphicsItem.ItemCoordinateCache)

    def setFill(self, fill: bool):
        """
        Changes the property of how the cell is filled.

        Args:
          fill: bool
        """
        self._fillRect = fill
        self.update()

    @property
    def _gradient(self):
        gradient = QLinearGradient()
        gradient.setStart(
            (self._bounds.topLeft() + self._bounds.topRight()) / 2)
        gradient.setFinalStop(
            (self._bounds.bottomLeft() + self._bounds.bottomRight()) / 2)
        gradient.setColorAt(0, self._color)
        gradient.setColorAt(1, self._color.darker(200))
        return gradient

    def paint(self, painter, option, widget):
        """Standard Qt paint event."""
        if self._color:
            painter.setPen(Qt.NoPen)
            painter.setBrush(QColor(0, 0, 0, 64))
            painter.drawRoundedRect(self._bounds.translated(2, 2), 25.0, 25.0)

            if self._fillRect:
                painter.setBrush(QApplication.palette().brush(QPalette.Window))
            else:
                painter.setBrush(self._gradient)

            painter.setPen(QPen(Qt.black, 1))
            painter.drawRoundedRect(self._bounds, 25.0, 25.0)

        if not self._pix.isNull():
            if self._rounded_pixmap:
                painter.setRenderHint(QPainter.Antialiasing, True)
                brush = QBrush(
                    self._pix.scaled(self._bounds.width(),
                                     self._bounds.height()))
                painter.setBrush(brush)
                painter.drawRoundedRect(self._bounds, 25.0, 25.0)
            else:
                painter.scale(self._bounds.width() / self._pix.width(),
                              self._bounds.height() / self._pix.height())
                painter.drawPixmap(-self._pix.width() / 2,
                                   -self._pix.height() / 2, self._pix)

    def boundingRect(self):
        """returns bounding rectangle"""
        return self._bounds.adjusted(0, 0, 2, 2)

    def setPixmap(self, pixmap_path: str, rounded_pixmap=False):
        """
        Sets new pixmap for this graphic object.

        Args:
          pixmap_path: path to image for pixmap
          rounded_pixmap: make the picture rounded (used, e.g., for lava in the cells)
        """
        self._rounded_pixmap = rounded_pixmap
        self._pix = QPixmap(pixmap_path)
        self.update()
Ejemplo n.º 32
0
class BboxEditor(QObject):
    changed = pyqtSignal()

    def __init__(self, parent=None):
        super().__init__(parent)
        self.bbox01 = QRectF()
        self.bboxDrawing = QRect()
        self.color = QColor()
        self.isActive = False
        self.posPress = QPoint()
        self.bbox01Press = QRect()
        self.isDragging = False
        self.prevWheelEventTimestamp = datetime.datetime.now()
        self.scalingMultiplier = 1
        self.targetRatio = 1
        self.stayInside = True

    def setTargetRatio(self, ratio):
        self.targetRatio = ratio
        self.setBbox01(self.bbox01)

    def setStayInside(self, stay):
        self.stayInside = stay
        self.setBbox01(self.bbox01)

    def bbox01KeepInsideDrawingArea(self):
        # r = w0*w / h0*h
        # h0*h = w0*w / r
        # h0 = w0*w / r / h
        w = self.bbox01.width() * self.bboxDrawing.width()
        h = self.bbox01.height() * self.bboxDrawing.height()
        print('bbox01KeepInsideDrawingArea() bboxDrawing:', self.bboxDrawing,
              'w:', w, 'h:', h)
        if h == 0:
            return
        if w / h != self.targetRatio:
            print('bbox01KeepInsideDrawingArea() bbox01 a:', self.bbox01,
                  'targetRatio:', self.targetRatio)
            self.bbox01.setHeight(w / self.targetRatio /
                                  self.bboxDrawing.height())
            print('bbox01KeepInsideDrawingArea() bbox01 b:', self.bbox01)
        if self.stayInside:
            if self.bbox01.width() > 1:
                self.bbox01.setWidth(1)
            if self.bbox01.height() > 1:
                self.bbox01.setHeight(1)
            if self.bbox01.x() < 0:
                self.bbox01.translate(-self.bbox01.x(), 0)
            if self.bbox01.y() < 0:
                self.bbox01.translate(0, -self.bbox01.y())
            if self.bbox01.x() + self.bbox01.width() > 1:
                self.bbox01.translate(
                    1 - (self.bbox01.x() + self.bbox01.width()), 0)
            if self.bbox01.y() + self.bbox01.height() > 1:
                self.bbox01.translate(
                    0, 1 - (self.bbox01.y() + self.bbox01.height()))
        print('bbox01KeepInsideDrawingArea() bbox01 c:', self.bbox01,
              'toPixels:', self.bbox01ToPixels())

    def bbox01ToPixels(self):
        r = QRect(
            self.bboxDrawing.x() + self.bbox01.x() * self.bboxDrawing.width(),
            self.bboxDrawing.y() + self.bbox01.y() * self.bboxDrawing.height(),
            self.bbox01.width() * self.bboxDrawing.width(),
            self.bbox01.width() * self.bboxDrawing.width() / self.targetRatio)
        #self.bbox01.height()*self.bboxDrawing.height())
        print('bbox01ToPixels() r:', r.width(), r.height(), 'bboxDrawing:',
              self.bboxDrawing, 'bbox01:', self.bbox01)
        return r

    def paint(self, qpainter):
        r = self.bbox01ToPixels()
        print('paint() bboxDrawing:', self.bboxDrawing, ' bbox01:',
              self.bbox01, 'r:', r)

        c = self.color
        w = 3 if self.isActive else 1
        #c.setAlpha(255 if self.isActive else 127)

        # Outer white rect
        pen = QPen(QColor(255, 255, 255))
        pen.setWidth(w + 2)
        qpainter.setPen(pen)
        qpainter.drawRect(r)

        # Main colored rect
        pen = QPen(c)
        pen.setWidth(w)
        qpainter.setPen(pen)
        qpainter.drawRect(r)

    def setColor(self, color):
        self.color = color
        self.changed.emit()

    def setDrawingArea(self, qrect):
        self.bboxDrawing = qrect
        self.changed.emit()

    def setBbox01(self, qrect):
        self.bbox01 = qrect
        self.bbox01KeepInsideDrawingArea()
        self.changed.emit()

    def getBbox01(self):
        return self.bbox01

    def setActive(self, active):
        self.isActive = active
        self.changed.emit()

    def mouseMoveEvent(self, e):
        if not self.isActive:
            return
        if self.isDragging:
            diff = e.pos() - self.posPress
            diff01 = QPointF(diff.x() / self.bboxDrawing.width(),
                             diff.y() / self.bboxDrawing.height())
            print('mouseMoveEvent() bbox01:', self.bbox01, 'diff:', diff,
                  'diff01:', diff01)
            self.setBbox01(self.bbox01Press.translated(diff01))

    def mousePressEvent(self, e):
        if not self.isActive:
            return
        bb = self.bbox01ToPixels()
        if (e.pos().x() >= bb.topLeft().x()) and \
         (e.pos().y() >= bb.topLeft().y()) and \
         e.pos().x() <= bb.bottomRight().x() and \
         e.pos().y() <= bb.bottomRight().y() \
         :
            self.isDragging = True
            self.posPress = e.pos()
            self.bbox01Press = self.bbox01

    def mouseReleaseEvent(self, e):
        if not self.isActive:
            return
        self.isDragging = False

    def wheelEvent(self, e):
        if not self.isActive:
            return
        t_diff = (datetime.datetime.now() -
                  self.prevWheelEventTimestamp).total_seconds()
        if t_diff < 0.1:
            self.scalingMultiplier *= 1.5
        else:
            self.scalingMultiplier = 1
        print('wheelEvent() t:', self.prevWheelEventTimestamp, '->',
              datetime.datetime.now(), 't_diff:', t_diff, 'angleDelta:',
              e.angleDelta(), 'scalingMultiplier:', self.scalingMultiplier)
        #sign = -1 if e.angleDelta().y() < 0 else 1
        #scale = 1 + 0.1*sign
        scale = 0.01
        scale *= self.scalingMultiplier
        scale += 1
        if e.angleDelta().y() > 0:
            scale = 1 / scale
        diff_x = (self.bbox01.width() * (1 - scale)) / 2
        diff_y = (self.bbox01.height() * (1 - scale)) / 2
        print('wheelEvent() scale:', scale, 'diff:', diff_x, diff_y)
        self.setBbox01(self.bbox01.adjusted(diff_x, diff_y, -diff_x, -diff_y))
        self.prevWheelEventTimestamp = datetime.datetime.now()

    def getBbox01(self):
        return self.bbox01
Ejemplo n.º 33
0
class PathNucleicAcidPartItem(QAbstractPartItem):
    """Summary

    Attributes:
        active_virtual_helix_item (cadnano.gui.views.pathview.virtualhelixitem.VirtualHelixItem): Description
        findChild (TYPE): Description
        grab_corner (TYPE): Description
        prexover_manager (TYPE): Description
    """
    findChild = util.findChild  # for debug
    _BOUNDING_RECT_PADDING = 0

    def __init__(self, model_part_instance, viewroot, parent):
        """parent should always be pathrootitem

        Args:
            model_part_instance (TYPE): Description
            viewroot (TYPE): Description
            parent (TYPE): Description
        """
        super(PathNucleicAcidPartItem, self).__init__(model_part_instance, viewroot, parent)
        self._getActiveTool = viewroot.manager.activeToolGetter
        self.active_virtual_helix_item = None
        m_p = self._model_part
        self._controller = NucleicAcidPartItemController(self, m_p)
        self.prexover_manager = PreXoverManager(self)
        self._virtual_helix_item_list = []
        self._vh_rect = QRectF()
        self.setAcceptHoverEvents(True)
        self._initModifierRect()
        self._proxy_parent = ProxyParentItem(self)
        self._proxy_parent.setFlag(QGraphicsItem.ItemHasNoContents)
        self._scale_2_model = m_p.baseWidth()/_BASE_WIDTH
        self._scale_2_Qt = _BASE_WIDTH / m_p.baseWidth()
        GC_SIZE = 10
        self.grab_corner = GrabCornerItem(GC_SIZE, m_p.getColor(), False, self)
    # end def

    def proxy(self):
        """Summary

        Returns:
            TYPE: Description
        """
        return self._proxy_parent
    # end def

    def modelColor(self):
        """Summary

        Returns:
            TYPE: Description
        """
        return self._model_part.getProperty('color')
    # end def

    def convertToModelZ(self, z):
        """scale Z-axis coordinate to the model

        Args:
            z (TYPE): Description
        """
        return z * self._scale_2_model
    # end def

    def convertToQtZ(self, z):
        """Summary

        Args:
            z (TYPE): Description

        Returns:
            TYPE: Description
        """
        return z * self._scale_2_Qt
    # end def

    def _initModifierRect(self):
        """docstring for _initModifierRect
        """
        self._can_show_mod_rect = False
        self._mod_rect = m_r = QGraphicsRectItem(_DEFAULT_RECT, self)
        m_r.setPen(_MOD_PEN)
        m_r.hide()
    # end def

    def vhItemForIdNum(self, id_num):
        """Returns the pathview VirtualHelixItem corresponding to id_num

        Args:
            id_num (int): VirtualHelix ID number. See `NucleicAcidPart` for description and related methods.
        """
        return self._virtual_helix_item_hash.get(id_num)

    ### SIGNALS ###

    ### SLOTS ###
    def partActiveVirtualHelixChangedSlot(self, part, id_num):
        """Summary

        Args:
            part (TYPE): Description
            id_num (int): VirtualHelix ID number. See `NucleicAcidPart` for description and related methods.

        Returns:
            TYPE: Description
        """
        vhi = self._virtual_helix_item_hash.get(id_num, None)
        self.setActiveVirtualHelixItem(vhi)
        self.setPreXoverItemsVisible(vhi)
    # end def

    def partActiveBaseInfoSlot(self, part, info):
        """Summary

        Args:
            part (TYPE): Description
            info (TYPE): Description

        Returns:
            TYPE: Description
        """
        pxoig = self.prexover_manager
        pxoig.deactivateNeighbors()
        if info and info is not None:
            id_num, is_fwd, idx, to_vh_id_num = info
            pxoig.activateNeighbors(id_num, is_fwd, idx)
    # end def

    def partZDimensionsChangedSlot(self, model_part, min_id_num, max_id_num, ztf=False):
        """Summary

        Args:
            model_part (Part): The model part
            min_id_num (TYPE): Description
            max_id_num (TYPE): Description
            ztf (bool, optional): Description

        Returns:
            TYPE: Description
        """
        if len(self._virtual_helix_item_list) > 0:
            vhi_hash = self._virtual_helix_item_hash
            vhi_max = vhi_hash[max_id_num]
            vhi_rect_max = vhi_max.boundingRect()
            self._vh_rect.setRight(vhi_rect_max.right() + vhi_max.x())

            vhi_min = vhi_hash[min_id_num]
            vhi_h_rect = vhi_min.handle().boundingRect()
            self._vh_rect.setLeft((vhi_h_rect.left() -
                                   styles.VH_XOFFSET +
                                   vhi_min.x()))
        if ztf:
            self.scene().views()[0].zoomToFit()
        self._updateBoundingRect()
    # end def

    def partSelectedChangedSlot(self, model_part, is_selected):
        """Summary

        Args:
            model_part (Part): The model part
            is_selected (TYPE): Description

        Returns:
            TYPE: Description
        """
        # print("partSelectedChangedSlot", is_selected)
        if is_selected:
            self.resetPen(styles.SELECTED_COLOR, styles.SELECTED_PEN_WIDTH)
            self.resetBrush(styles.SELECTED_BRUSH_COLOR, styles.SELECTED_ALPHA)
        else:
            self.resetPen(self.modelColor())
            self.resetBrush(styles.DEFAULT_BRUSH_COLOR, styles.DEFAULT_ALPHA)

    def partPropertyChangedSlot(self, model_part, property_key, new_value):
        """Summary

        Args:
            model_part (Part): The model part
            property_key (TYPE): Description
            new_value (TYPE): Description

        Returns:
            TYPE: Description
        """
        if self._model_part == model_part:
            self._model_props[property_key] = new_value
            if property_key == 'color':
                self._updateBoundingRect()
                for vhi in self._virtual_helix_item_list:
                    vhi.handle().refreshColor()
                self.grab_corner.setBrush(getBrushObj(new_value))
            elif property_key == 'is_visible':
                if new_value:
                    self.show()
                else:
                    self.hide()
            elif property_key == 'virtual_helix_order':
                vhi_dict = self._virtual_helix_item_hash
                new_list = [vhi_dict[id_num] for id_num in new_value]
                ztf = False
                self._setVirtualHelixItemList(new_list, zoom_to_fit=ztf)
    # end def

    def partVirtualHelicesTranslatedSlot(self, sender,
                                         vh_set, left_overs,
                                         do_deselect):
        """Summary

        Args:
            sender (obj): Model object that emitted the signal.
            vh_set (TYPE): Description
            left_overs (TYPE): Description
            do_deselect (TYPE): Description

        Returns:
            TYPE: Description
        """
        # self.prexover_manager.clearPreXoverItems()
        # if self.active_virtual_helix_item is not None:
        #     self.active_virtual_helix_item.deactivate()
        #     self.active_virtual_helix_item = None

        # if self.active_virtual_helix_item is not None:
        #     self.setPreXoverItemsVisible(self.active_virtual_helix_item)
        pass
    # end def

    def partRemovedSlot(self, sender):
        """docstring for partRemovedSlot

        Args:
            sender (obj): Model object that emitted the signal.
        """
        self.parentItem().removePartItem(self)
        scene = self.scene()
        scene.removeItem(self)
        self._model_part = None
        self._virtual_helix_item_hash = None
        self._virtual_helix_item_list = None
        self._controller.disconnectSignals()
        self._controller = None
        self.grab_corner = None
    # end def

    def partVirtualHelixAddedSlot(self, model_part, id_num, virtual_helix, neighbors):
        """
        When a virtual helix is added to the model, this slot handles
        the instantiation of a virtualhelix item.

        Args:
            model_part (Part): The model part
            id_num (int): VirtualHelix ID number. See `NucleicAcidPart` for description and related methods.
        """
        # print("NucleicAcidPartItem.partVirtualHelixAddedSlot")
        vhi = PathVirtualHelixItem(virtual_helix, self, self._viewroot)
        self._virtual_helix_item_hash[id_num] = vhi
        vhi_list = self._virtual_helix_item_list
        # reposition when first VH is added
        if len(vhi_list) == 0:
            view = self.window().path_graphics_view
            p = view.scene_root_item.childrenBoundingRect().bottomLeft()
            _p = _BOUNDING_RECT_PADDING
            self.setPos(p.x() + _p*6 + styles.VIRTUALHELIXHANDLEITEM_RADIUS, p.y() + _p*3)
            # self.setPos(p.x() + _VH_XOFFSET, p.y() + _p*3)

        vhi_list.append(vhi)
        ztf = not getBatch()
        self._setVirtualHelixItemList(vhi_list, zoom_to_fit=ztf)
    # end def

    def partVirtualHelixResizedSlot(self, sender, id_num, virtual_helix):
        """Notifies the virtualhelix at coord to resize.

        Args:
            sender (obj): Model object that emitted the signal.
            id_num (int): VirtualHelix ID number. See `NucleicAcidPart` for description and related methods.
        """
        vhi = self._virtual_helix_item_hash[id_num]
        # print("resize:", id_num, virtual_helix.getSize())
        vhi.resize()
    # end def

    def partVirtualHelixRemovingSlot(self, sender, id_num, virtual_helix, neighbors):
        """Summary

        Args:
            sender (obj): Model object that emitted the signal.
            id_num (int): VirtualHelix ID number. See `NucleicAcidPart` for description and related methods.

        Returns:
            TYPE: Description
        """
        self.removeVirtualHelixItem(id_num)
    # end def

    def partVirtualHelixRemovedSlot(self, sender, id_num):
        """ Step 2 of removing a VHI
        """
        ztf = not getBatch()
        self._setVirtualHelixItemList(self._virtual_helix_item_list,
            zoom_to_fit=ztf)
    # end def

    def partVirtualHelixPropertyChangedSlot(self, sender, id_num, virtual_helix, keys, values):
        """Summary

        Args:
            sender (obj): Model object that emitted the signal.
            id_num (int): VirtualHelix ID number. See `NucleicAcidPart` for description and related methods.
            keys (TYPE): Description
            values (TYPE): Description

        Returns:
            TYPE: Description
        """
        if self._model_part == sender:
            vh_i = self._virtual_helix_item_hash[id_num]
            vh_i.virtualHelixPropertyChangedSlot(keys, values)
    # end def

    def partVirtualHelicesSelectedSlot(self, sender, vh_set, is_adding):
        """is_adding (bool): adding (True) virtual helices to a selection
        or removing (False)

        Args:
            sender (obj): Model object that emitted the signal.
            vh_set (TYPE): Description
            is_adding (TYPE): Description
        """
        vhhi_group = self._viewroot.vhiHandleSelectionGroup()
        vh_hash = self._virtual_helix_item_hash
        doc = self._viewroot.document()
        if is_adding:
            # print("got the adding slot in path")
            for id_num in vh_set:
                vhi = vh_hash[id_num]
                vhhi = vhi.handle()
                vhhi.modelSelect(doc)
            # end for
            vhhi_group.processPendingToAddList()
        else:
            # print("got the removing slot in path")
            for id_num in vh_set:
                vhi = vh_hash[id_num]
                vhhi = vhi.handle()
                vhhi.modelDeselect(doc)
            # end for
            vhhi_group.processPendingToAddList()
    # end def

    ### ACCESSORS ###
    def removeVirtualHelixItem(self, id_num):
        """Summary

        Args:
            id_num (int): VirtualHelix ID number. See `NucleicAcidPart` for description and related methods.

        Returns:
            TYPE: Description
        """
        self.setActiveVirtualHelixItem(None)
        vhi = self._virtual_helix_item_hash[id_num]
        vhi.virtualHelixRemovedSlot()
        self._virtual_helix_item_list.remove(vhi)
        del self._virtual_helix_item_hash[id_num]
    # end def

    def window(self):
        """Summary

        Returns:
            TYPE: Description
        """
        return self.parentItem().window()
    # end def

    ### PRIVATE METHODS ###
    def _setVirtualHelixItemList(self, new_list, zoom_to_fit=True):
        """
        Give me a list of VirtualHelixItems and I'll parent them to myself if
        necessary, position them in a column, adopt their handles, and
        position them as well.

        Args:
            new_list (TYPE): Description
            zoom_to_fit (bool, optional): Description
        """
        y = 0  # How far down from the top the next PH should be
        vhi_rect = None
        vhi_h_rect = None
        vhi_h_selection_group = self._viewroot.vhiHandleSelectionGroup()
        for vhi in new_list:
            _, _, _z = vhi.cnModel().getAxisPoint(0)
            _z *= self._scale_2_Qt
            vhi.setPos(_z, y)
            if vhi_rect is None:
                vhi_rect = vhi.boundingRect()
                step = vhi_rect.height() + styles.PATH_HELIX_PADDING
            # end if

            # get the VirtualHelixHandleItem
            vhi_h = vhi.handle()
            do_reselect = False
            if vhi_h.parentItem() == vhi_h_selection_group:
                do_reselect = True

            vhi_h.tempReparent()    # so positioning works

            if vhi_h_rect is None:
                vhi_h_rect = vhi_h.boundingRect()

            vhi_h_x = _z - _VH_XOFFSET
            vhi_h_y = y + (vhi_rect.height() - vhi_h_rect.height()) / 2
            vhi_h.setPos(vhi_h_x, vhi_h_y)

            y += step
            self.updateXoverItems(vhi)
            if do_reselect:
                vhi_h_selection_group.addToGroup(vhi_h)
        # end for
        # this need only adjust top and bottom edges of the bounding rectangle
        self._vh_rect.setTop(-10)
        self._vh_rect.setBottom(y)
        self._virtual_helix_item_list = new_list

        # now update Z dimension (X in Qt space in the Path view)
        part = self.part()
        self.partZDimensionsChangedSlot(part, *part.zBoundsIds(), ztf=zoom_to_fit)
    # end def

    def resetPen(self, color, width=0):
        """Summary

        Args:
            color (TYPE): Description
            width (int, optional): Description

        Returns:
            TYPE: Description
        """
        pen = getPenObj(color, width)
        self.setPen(pen)
    # end def

    def resetBrush(self, color, alpha):
        """Summary

        Args:
            color (TYPE): Description
            alpha (TYPE): Description

        Returns:
            TYPE: Description
        """
        brush = getBrushObj(color, alpha=alpha)
        self.setBrush(brush)
    # end def

    def _updateBoundingRect(self):
        """
        Updates the bounding rect to the size of the childrenBoundingRect,
        and refreshes the addBases and removeBases buttons accordingly.

        Called by partZDimensionsChangedSlot and partPropertyChangedSlot
        """
        self.setPen(getPenObj(self.modelColor(), 0))
        self.resetBrush(styles.DEFAULT_BRUSH_COLOR, styles.DEFAULT_ALPHA)

        # self.setRect(self.childrenBoundingRect())
        _p = _BOUNDING_RECT_PADDING
        temp_rect = self._vh_rect.adjusted(-_p/2, -_p, _p, -_p/2)
        self.grab_corner.setTopLeft(temp_rect.topLeft())
        self.setRect(temp_rect)
    # end def

    ### PUBLIC METHODS ###
    def setModifyState(self, bool):
        """Hides the modRect when modify state disabled.

        Args:
            bool (TYPE): Description
        """
        self._can_show_mod_rect = bool
        if bool is False:
            self._mod_rect.hide()

    def getOrderedVirtualHelixList(self):
        """Used for encoding.
        """
        ret = []
        for vhi in self._virtual_helix_item_list:
            ret.append(vhi.coord())
        return ret
    # end def

    def reorderHelices(self, id_nums, index_delta):
        """
        Reorder helices by moving helices _pathHelixList[first:last]
        by a distance delta in the list. Notify each PathHelix and
        PathHelixHandle of its new location.

        Args:
            first (TYPE): Description
            last (TYPE): Description
            index_delta (TYPE): Description
        """
        vhi_list = self._virtual_helix_item_list
        helix_numbers = [vhi.idNum() for vhi in vhi_list]


        first_index = helix_numbers.index(id_nums[0])
        last_index = helix_numbers.index(id_nums[-1]) + 1

        insert_idxs = [helix_numbers.index(id_num) for id_num in id_nums]
        for id_num in id_nums:
            helix_numbers.remove(id_num)

        if index_delta < 0:  # move group earlier in the list
            new_index = max(0, index_delta + first_index) - len(id_nums)
        else:  # move group later in list
            new_index = min(len(vhi_list), index_delta + last_index ) - len(id_nums)
        new_list = helix_numbers[:new_index] + id_nums + helix_numbers[new_index:]
        # call the method to move the items and store the list
        self._model_part.setImportedVHelixOrder(new_list, check_batch=False)
    # end def

    def setActiveVirtualHelixItem(self, new_active_vhi):
        """Summary

        Args:
            new_active_vhi (TYPE): Description

        Returns:
            TYPE: Description
        """
        current_vhi = self.active_virtual_helix_item
        if new_active_vhi != current_vhi:
            if current_vhi is not None:
                current_vhi.deactivate()
            if new_active_vhi is not None:
                new_active_vhi.activate()
            self.active_virtual_helix_item = new_active_vhi
    # end def

    def setPreXoverItemsVisible(self, virtual_helix_item):
        """
        self._pre_xover_items list references prexovers parented to other
        PathHelices such that only the activeHelix maintains the list of
        visible prexovers

        Args:
            virtual_helix_item (cadnano.gui.views.pathview.virtualhelixitem.VirtualHelixItem): Description
        """
        vhi = virtual_helix_item

        if vhi is None:
            return

        # print("path.setPreXoverItemsVisible", virtual_helix_item.idNum())
        part = self.part()
        info = part.active_base_info
        if info and virtual_helix_item is not None:
            id_num, is_fwd, idx, to_vh_id_num = info
            per_neighbor_hits, pairs = part.potentialCrossoverMap(id_num, idx)
            self.prexover_manager.activateVirtualHelix(virtual_helix_item, idx, per_neighbor_hits)
        else:
            self.prexover_manager.reset()
    # end def

    def updateXoverItems(self, virtual_helix_item):
        """Summary

        Args:
            virtual_helix_item (cadnano.gui.views.pathview.virtualhelixitem.VirtualHelixItem): Description

        Returns:
            TYPE: Description
        """
        for item in virtual_helix_item.childItems():
            if isinstance(item, XoverNode3):
                item.refreshXover()
    # end def

    def updateStatusBar(self, status_string):
        """Shows status_string in the MainWindow's status bar.

        Args:
            status_string (str): The text to be displayed.
        """
        self.window().statusBar().showMessage(status_string)

    ### COORDINATE METHODS ###
    def keyPanDeltaX(self):
        """How far a single press of the left or right arrow key should move
        the scene (in scene space)
        """
        vhs = self._virtual_helix_item_list
        return vhs[0].keyPanDeltaX() if vhs else 5
    # end def

    def keyPanDeltaY(self):
        """How far an an arrow key should move the scene (in scene space)
        for a single press
        """
        vhs = self._virtual_helix_item_list
        if not len(vhs) > 1:
            return 5
        dy = vhs[0].pos().y() - vhs[1].pos().y()
        dummyRect = QRectF(0, 0, 1, dy)
        return self.mapToScene(dummyRect).boundingRect().height()
    # end def

    ### TOOL METHODS ###
    def mousePressEvent(self, event):
        """Handler for user mouse press.

        Args:
            event (QGraphicsSceneMouseEvent): Contains item, scene, and screen
            coordinates of the the event, and previous event.
        """
        self._viewroot.clearSelectionsIfActiveTool()
        return QGraphicsItem.mousePressEvent(self, event)

    def hoverMoveEvent(self, event):
        """
        Parses a mouseMoveEvent to extract strandSet and base index,
        forwarding them to approproate tool method as necessary.

        Args:
            event (TYPE): Description
        """
        active_tool = self._getActiveTool()
        tool_method_name = active_tool.methodPrefix() + "HoverMove"
        if hasattr(self, tool_method_name):
            getattr(self, tool_method_name)(event.pos())
    # end def

    def pencilToolHoverMove(self, pt):
        """Pencil the strand is possible.

        Args:
            pt (QPointF): mouse cursor location of pencil tool hover.
        """
        active_tool = self._getActiveTool()
        if not active_tool.isFloatingXoverBegin():
            temp_xover = active_tool.floatingXover()
            temp_xover.updateFloatingFromPartItem(self, pt)
Ejemplo n.º 34
0
class MovablePolygonVertex(QGraphicsObject):
    geometryChange = pyqtSignal(object)

    def __init__(self, parent=None):
        super(MovablePolygonVertex, self).__init__(parent)
        self.setZValue(1000)

        self.isMousePressed = False

        self.setFlags(QGraphicsItem.ItemIsSelectable |
                      QGraphicsItem.ItemIsFocusable |
                      QGraphicsItem.ItemIsMovable |
                      QGraphicsItem.ItemSendsGeometryChanges)
        self.setAcceptHoverEvents(True)

        self.buttonList = []
        self.points = []
        self.degree = 0
        self.setFocus(Qt.ActiveWindowFocusReason)

        self._boundingRect = QRectF()
        self._rect = QRectF()

    def getDegree(self):
        return self.degree

    def setPoints(self, ps):
        self.points.clear()
        self.degree = len(ps)
        for point in ps:
            self.points.append(QPointF(*point))
        self.updateResizeHandles()

    def setRect(self):
        polygon = QPolygonF(self.points)
        rect = polygon.boundingRect()
        self._rect = rect
        self._boundingRect = rect

    def prepareGeometryChange(self):
        self.geometryChange.emit([[p.x(), p.y()] for p in self.points])
        super(MovablePolygonVertex, self).prepareGeometryChange()

    def hoverMoveEvent(self, event):
        hoverMovePos = event.scenePos()
        mouseHoverArea = None
        for item in self.buttonList:
            if item.contains(hoverMovePos):
                mouseHoverArea = item
                break
        if mouseHoverArea:
            self.setCursor(QtCore.Qt.PointingHandCursor)
            return
        self.setCursor(QtCore.Qt.SizeAllCursor)
        super(MovablePolygonVertex, self).hoverMoveEvent(event)

    def hoverEnterEvent(self, event):
        self.setCursor(QtCore.Qt.SizeAllCursor)
        super(MovablePolygonVertex, self).hoverEnterEvent(event)

    def hoverLeaveEvent(self, event):
        self.setCursor(QtCore.Qt.ArrowCursor)
        super(MovablePolygonVertex, self).hoverLeaveEvent(event)

    def mousePressEvent(self, event):
        self.isMousePressed = True
        self.mousePressedPos = event.scenePos()
        self.pressedRectPos = None
        self.originalPoints = copy.deepcopy(self.points)
        for i, item in enumerate(self.buttonList):
            if item.contains(self.mousePressedPos):
                self.pressedRectPos = i
                break
        super(MovablePolygonVertex, self).mousePressEvent(event)

    def mouseReleaseEvent(self, event):
        self.isMousePressed = False
        self.updateResizeHandles()
        self.prepareGeometryChange()
        super(MovablePolygonVertex, self).mouseReleaseEvent(event)

    def paint(self, painter, option, widget):
        self.updateResizeHandles()
        self.draw(painter, option, widget, self._rect)
        for item in self.buttonList:
            painter.drawRect(item)

    def draw(self, painter, option, widget, rect):
        return

    def boundingRect(self):
        return self._boundingRect

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

    def mouseMoveEvent(self, event):
        mouseMovePos = event.scenePos()
        if self.isMousePressed:
            if self.pressedRectPos is None:
                for i, point in enumerate(self.points):
                    newPos = self.originalPoints[i] + (mouseMovePos - self.mousePressedPos)
                    point.setX(newPos.x())
                    point.setY(newPos.y())
            else:
                newPos = self.originalPoints[self.pressedRectPos] + (mouseMovePos - self.mousePressedPos)
                self.points[self.pressedRectPos].setX(newPos.x())
                self.points[self.pressedRectPos].setY(newPos.y())
        self.updateResizeHandles()
        self.prepareGeometryChange()

    def updateResizeHandles(self):
        self.resizeHandleSize = 4.0

        self.setRect()
        self._rect = self._rect.normalized()

        # FIXME:結構アドホック,複数のビューでシーンを表示してるときには問題が出る.
        views = self.scene().views()
        self.offset = self.resizeHandleSize * (views[0].mapToScene(1, 0).x() - views[0].mapToScene(0, 1).x())
        self._boundingRect = self._rect.adjusted(
                -self.offset*2,
                -self.offset*2,
                self.offset*2,
                self.offset*2
            )

        self.buttonList.clear()
        for point in self.points:
            rect = QRectF(
                    point.x()-self.offset,
                    point.y()-self.offset,
                    2*self.offset,
                    2*self.offset
                )
            self.buttonList.append(rect)
Ejemplo n.º 35
0
from PyQt5.QtWidgets import QGraphicsItem, QGraphicsEllipseItem, QGraphicsPathItem
from PyQt5.QtWidgets import QGraphicsSimpleTextItem, QGraphicsLineItem

from cadnano.enum import LatticeType, Parity, PartType, StrandType
from cadnano.gui.controllers.itemcontrollers.virtualhelixitemcontroller import VirtualHelixItemController
from cadnano.gui.views.abstractitems.abstractvirtualhelixitem import AbstractVirtualHelixItem
from cadnano.virtualhelix import VirtualHelix
from cadnano.gui.palette import getColorObj, getNoPen, getPenObj, getBrushObj, getNoBrush
from . import slicestyles as styles


# set up default, hover, and active drawing styles
_RADIUS = styles.SLICE_HELIX_RADIUS
_RECT = QRectF(0, 0, 2 * _RADIUS, 2 * _RADIUS)
rect_gain = 0.25
_RECT = _RECT.adjusted(rect_gain, rect_gain, rect_gain, rect_gain)
_FONT = styles.SLICE_NUM_FONT
_ZVALUE = styles.ZSLICEHELIX+3
_OUT_OF_SLICE_BRUSH_DEFAULT = getBrushObj(styles.OUT_OF_SLICE_FILL) # QBrush(QColor(250, 250, 250))
_USE_TEXT_BRUSH = getBrushObj(styles.USE_TEXT_COLOR)

_ROTARYDIAL_STROKE_WIDTH = 1
_ROTARYDIAL_PEN = getPenObj(styles.BLUE_STROKE, _ROTARYDIAL_STROKE_WIDTH)
_ROTARYDIAL_BRUSH = getBrushObj('#8099ccff')
_ROTARY_DELTA_WIDTH = 10

_HOVER_PEN = getPenObj('#ffffff', 128)
_HOVER_BRUSH = getBrushObj('#ffffff', alpha=5)


Ejemplo n.º 36
0
    def paint(self, painter):
        painter.save()
        size = min(self.width(), self.height())
        self.setWidth(size)
        self.setHeight(size)
        rect = QRectF(0, 0, self.width(), self.height())
        painter.setRenderHint(QPainter.Antialiasing)
        pen = painter.pen()
        pen.setCapStyle(self._pen_style)

        startAngle = -90 - self._start_angle
        if RadialBar.DialType.FullDial != self._dial_type:
            spanAngle = 0 - self._span_angle
        else:
            spanAngle = -360

        # Draw outer dial
        painter.save()
        pen.setWidth(self._dial_width)
        pen.setColor(self._dial_color)
        painter.setPen(pen)
        offset = self._dial_width / 2
        if self._dial_type == RadialBar.DialType.MinToMax:
            painter.drawArc(rect.adjusted(offset, offset, -offset, -offset),
                            startAngle * 16, spanAngle * 16)
        elif self._dial_type == RadialBar.DialType.FullDial:
            painter.drawArc(rect.adjusted(offset, offset, -offset, -offset),
                            -90 * 16, -360 * 16)

        painter.restore()

        # Draw background
        painter.save()
        painter.setBrush(self._background_color)
        painter.setPen(self._background_color)
        inner = offset * 2
        painter.drawEllipse(rect.adjusted(inner, inner, -inner, -inner))
        painter.restore()

        # Draw progress text with suffix
        painter.save()
        painter.setFont(self._text_font)
        pen.setColor(self._text_color)
        painter.setPen(pen)
        if self._show_text:
            painter.drawText(rect.adjusted(offset, offset, -offset, -offset),
                             Qt.AlignCenter,
                             str(self._value) + self._suffix_text)
        else:
            painter.drawText(rect.adjusted(offset, offset, -offset, -offset),
                             Qt.AlignCenter, self._suffix_text)
        painter.restore()

        # Draw progress bar
        painter.save()
        pen.setWidth(self._dial_width)
        pen.setColor(self._progress_color)
        valueAngle = float(
            float(self._value - self._min_value) /
            float(self._max_value - self._min_value)) * float(
                spanAngle)  # Map value to angle range
        painter.setPen(pen)
        painter.drawArc(rect.adjusted(offset, offset, -offset, -offset),
                        startAngle * 16, valueAngle * 16)
        painter.restore()
        painter.restore()
Ejemplo n.º 37
0
class RectItem(BaseItem):
    def __init__(self, model_item=None, prefix="", parent=None):
        BaseItem.__init__(self, model_item, prefix, parent)

        self._rect = None
        self._resize = False
        self._resize_start = None
        self._resize_start_rect = None
        self._upper_half_clicked = None
        self._left_half_clicked = None

        self._updateRect(self._dataToRect(self._model_item))
        LOG.debug("Constructed rect %s for model item %s" %
                  (self._rect, model_item))

    def __call__(self, model_item=None, parent=None):
        item = RectItem(model_item, parent)
        item.setPen(self.pen())
        item.setBrush(self.brush())
        return item

    def _dataToRect(self, model_item):
        if model_item is None:
            return QRectF()

        try:
            return QRectF(float(model_item[self.prefix() + 'x']),
                          float(model_item[self.prefix() + 'y']),
                          float(model_item[self.prefix() + 'width']),
                          float(model_item[self.prefix() + 'height']))
        except KeyError as e:
            LOG.debug("RectItem: Could not find expected key in item: " +
                      str(e) + ". Check your config!")
            self.setValid(False)
            return QRectF()

    def _updateRect(self, rect):
        if rect == self._rect:
            return

        self.prepareGeometryChange()
        self._rect = rect
        self.setPos(rect.topLeft())

    def updateModel(self):
        self._rect = QRectF(self.scenePos(), self._rect.size())
        self._model_item.update({
            self.prefix() + 'x':
            float(self._rect.topLeft().x()),
            self.prefix() + 'y':
            float(self._rect.topLeft().y()),
            self.prefix() + 'width':
            float(self._rect.width()),
            self.prefix() + 'height':
            float(self._rect.height()),
        })

    def boundingRect(self):
        return QRectF(QPointF(0, 0), self._rect.size())

    def paint(self, painter, option, widget=None):
        BaseItem.paint(self, painter, option, widget)

        pen = self.pen()
        if self.isSelected():
            pen.setStyle(Qt.DashLine)
        painter.setPen(pen)
        painter.drawRect(self.boundingRect())

    def dataChange(self):
        rect = self._dataToRect(self._model_item)
        self._updateRect(rect)

    def mousePressEvent(self, event):
        #if event.modifiers() & Qt.ControlModifier != 0:
        if event.button() & Qt.RightButton != 0:
            self._resize = True
            self._resize_start = event.scenePos()
            self._resize_start_rect = QRectF(self._rect)
            self._upper_half_clicked = (event.scenePos().y() <
                                        self._resize_start_rect.center().y())
            self._left_half_clicked = (event.scenePos().x() <
                                       self._resize_start_rect.center().x())
            event.accept()
        else:
            BaseItem.mousePressEvent(self, event)

    def mouseMoveEvent(self, event):
        if self._resize:
            diff = event.scenePos() - self._resize_start
            if self._left_half_clicked:
                x = self._resize_start_rect.x() + diff.x()
                w = self._resize_start_rect.width() - diff.x()
            else:
                x = self._resize_start_rect.x()
                w = self._resize_start_rect.width() + diff.x()

            if self._upper_half_clicked:
                y = self._resize_start_rect.y() + diff.y()
                h = self._resize_start_rect.height() - diff.y()
            else:
                y = self._resize_start_rect.y()
                h = self._resize_start_rect.height() + diff.y()

            rect = QRectF(QPointF(x, y), QSizeF(w, h)).normalized()

            self._updateRect(rect)
            self.updateModel()
            event.accept()
        else:
            BaseItem.mouseMoveEvent(self, event)

    def mouseReleaseEvent(self, event):
        if self._resize:
            self._resize = False
            event.accept()
        else:
            BaseItem.mouseReleaseEvent(self, event)

    def keyPressEvent(self, event):
        BaseItem.keyPressEvent(self, event)
        step = 1
        if event.modifiers() & Qt.ShiftModifier:
            step = 5
        ds = {
            Qt.Key_Left: (-step, 0),
            Qt.Key_Right: (step, 0),
            Qt.Key_Up: (0, -step),
            Qt.Key_Down: (0, step),
        }.get(event.key(), None)
        if ds is not None:
            if event.modifiers() & Qt.ControlModifier:
                rect = self._rect.adjusted(*((0, 0) + ds))
            else:
                rect = self._rect.adjusted(*(ds + ds))
            self._updateRect(rect)
            self.updateModel()
            event.accept()
Ejemplo n.º 38
0
# extra2 = QPainterPath()
# extra2.addEllipse(-0.35*IW, 0.5*IW, 0.7*IW, 0.3*IW)
# FWDPXI_PP += extra1
# FWDPXI_PP -= extra2

# REVPXI_PP.moveTo(-0.5*IW, -0.7*IW)
# REVPXI_PP.lineTo(0., 0.2*IW)
# REVPXI_PP.lineTo(0.5*IW, -0.7*IW)
# extra1 = QPainterPath()
# extra1.addEllipse(-0.5*IW, -0.9*IW, IW, 0.4*IW)
# REVPXI_PP += extra1

_RADIUS = styles.SLICE_HELIX_RADIUS
_WEDGE_RECT_GAIN = 0.25
WEDGE_RECT = QRectF(0, 0, 2 * _RADIUS, 2 * _RADIUS)
WEDGE_RECT = WEDGE_RECT.adjusted(0, 0, _WEDGE_RECT_GAIN, _WEDGE_RECT_GAIN)
_WEDGE_RECT_CENTERPT = WEDGE_RECT.center()


class PropertyWrapperObject(QObject):
    def __init__(self, item):
        """Summary

        Args:
            item (TYPE): Description
        """
        super(PropertyWrapperObject, self).__init__()
        self.item = item
        self.animations = {}

    def __get_bondP2(self):
Ejemplo n.º 39
0
    def setupGraphics(self):
        """
        Set up the graphics.
        """
        shape_rect = QRectF(-24, -24, 48, 48)

        self.shapeItem = NodeBodyItem(self)
        self.shapeItem.setShapeRect(shape_rect)
        self.shapeItem.setAnimationEnabled(self.__animationEnabled)

        # Rect for widget's 'ears'.
        anchor_rect = QRectF(-31, -31, 62, 62)
        self.inputAnchorItem = SinkAnchorItem(self)
        input_path = QPainterPath()
        start_angle = 180 - self.ANCHOR_SPAN_ANGLE / 2
        input_path.arcMoveTo(anchor_rect, start_angle)
        input_path.arcTo(anchor_rect, start_angle, self.ANCHOR_SPAN_ANGLE)
        self.inputAnchorItem.setAnchorPath(input_path)

        self.outputAnchorItem = SourceAnchorItem(self)
        output_path = QPainterPath()
        start_angle = self.ANCHOR_SPAN_ANGLE / 2
        output_path.arcMoveTo(anchor_rect, start_angle)
        output_path.arcTo(anchor_rect, start_angle, - self.ANCHOR_SPAN_ANGLE)
        self.outputAnchorItem.setAnchorPath(output_path)

        self.inputAnchorItem.hide()
        self.outputAnchorItem.hide()

        # Title caption item
        self.captionTextItem = NameTextItem(self)

        self.captionTextItem.setPlainText("")
        self.captionTextItem.setPos(0, 33)


        def iconItem(standard_pixmap):
            item = GraphicsIconItem(self, icon=standard_icon(standard_pixmap),
                                    iconSize=QSize(16, 16))
            item.hide()

            return item


        self.errorItem = iconItem(QStyle.SP_MessageBoxCritical)
        self.warningItem = iconItem(QStyle.SP_MessageBoxWarning)
        self.infoItem = iconItem(QStyle.SP_MessageBoxInformation)


        ################################
        # PyQt 5.10 crashes because of this call (2)
        #self.backgroundItem = QGraphicsPathItem(self)
        self.backgroundItem = QGraphicsPathItem(None)
        ################################

        backgroundrect = QPainterPath()
        backgroundrect.addRoundedRect(anchor_rect.adjusted(-4, -2, 4, 2),
                                      5, 5, mode=Qt.AbsoluteSize)
        self.backgroundItem.setPen(QPen(Qt.NoPen))
        self.backgroundItem.setBrush(QPalette().brush(QPalette.Highlight))
        self.backgroundItem.setOpacity(0.5)
        self.backgroundItem.setPath(backgroundrect)
        self.backgroundItem.setZValue(-10)
        self.backgroundItem.setVisible(self.isSelected())

        self.prepareGeometryChange()
        self.__boundingRect = None