Exemplo n.º 1
0
    def image(cls, **kwargs):
        """
        Returns an image suitable for the palette.
        :rtype: QPixmap
        """
        # INITIALIZATION
        pixmap = QPixmap(kwargs['w'], kwargs['h'])
        pixmap.fill(Qt.transparent)
        painter = QPainter(pixmap)
        # INITIALIZE EDGE LINE
        pp1 = QPointF(((kwargs['w'] - 52) / 2), kwargs['h'] / 2)
        pp2 = QPointF(((kwargs['w'] - 52) / 2) + 52 - 2, kwargs['h'] / 2)
        line = QLineF(pp1, pp2)
        # CALCULATE HEAD COORDINATES
        angle = radians(line.angle())
        p1 = QPointF(line.p2().x() + 2, line.p2().y())
        p2 = p1 - QPointF(sin(angle + M_PI / 3.0) * 8, cos(angle + M_PI / 3.0) * 8)
        p3 = p1 - QPointF(sin(angle + M_PI - M_PI / 3.0) * 8, cos(angle + M_PI - M_PI / 3.0) * 8)
        # INITIALIZE EDGE HEAD
        head = QPolygonF([p1, p2, p3])
        # DRAW THE POLYGON
        painter.setRenderHint(QPainter.Antialiasing)
        painter.setPen(QPen(QColor(0, 0, 0), 1.1, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
        painter.drawLine(line)
        # DRAW HEAD
        painter.setPen(QPen(QColor(0, 0, 0), 1.1, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
        painter.setBrush(QColor(0, 0, 0))
        painter.drawPolygon(head)
        # DRAW THE TEXT ON TOP OF THE EDGE
        space = 2 if Platform.identify() is Platform.Darwin else 0
        painter.setFont(Font('Arial', 9, Font.Light))
        painter.drawText(pp1.x() + space, (kwargs['h'] / 2) - 4, 'instanceOf')

        return pixmap
Exemplo n.º 2
0
    def buildNodeFromShapeNode(self, item, element):
        """
        Build a node using the given item type and QDomElement.
        :type item: Item
        :type element: QDomElement
        :rtype: AbstractNode
        """
        data = element.firstChildElement('data')
        while not data.isNull():

            if data.attribute('key', '') == self.keys['node_key']:

                shapeNode = data.firstChildElement('y:ShapeNode')
                geometry = shapeNode.firstChildElement('y:Geometry')

                kwargs = {
                    'id': element.attribute('id'),
                    'height': float(geometry.attribute('height')),
                    'width': float(geometry.attribute('width')),
                }

                node = self.factory.create(item, self.scene, **kwargs)
                # yEd uses the TOP-LEFT corner as (0,0) coordinate => we need to translate our
                # position (0,0), which is instead at the center of the shape, so that the TOP-LEFT
                # corner of the shape in yEd matches the TOP-LEFT corner of the shape in Eddy.
                # Additionally we force-snap the position to the grid so that items say aligned.
                pos = QPointF(float(geometry.attribute('x')), float(geometry.attribute('y')))
                pos = pos + QPointF(node.width() / 2, node.height() / 2)
                pos = QPointF(snapF(pos.x(), DiagramScene.GridSize), snapF(pos.y(), DiagramScene.GridSize))
                node.setPos(pos)
                return node

            data = data.nextSiblingElement('data')

        return None
Exemplo n.º 3
0
    def _get_selected_edge(self, pos: QPointF, transform: QTransform, horizontal_selection: bool):
        x1, x2 = self.x, self.x + self.width
        y1, y2 = self.y, self.y + self.height
        x, y = pos.x(), pos.y()

        spacing = 5
        spacing /= transform.m11() if horizontal_selection else transform.m22()

        if horizontal_selection:
            x1a, x1b = x1 - spacing, x1 + spacing
            y1a, y1b = y1, y2
            x2a, x2b = x2 - spacing, x2 + spacing
            y2a, y2b = y1, y2
        else:
            x1a, x1b, x2a, x2b = x1, x2, x1, x2
            y1a, y1b = min(y1 - spacing, y1 + spacing), max(y1 - spacing, y1 + spacing)
            y2a, y2b = min(y2 - spacing, y2 + spacing), max(y2 - spacing, y2 + spacing)

        if x1a < x < x1b and y1a < y < y1b:
            self.selected_edge = 0
            return 0

        if x2a < x < x2b and y2a < y < y2b:
            self.selected_edge = 1
            return 1

        self.selected_edge = None
        return None
Exemplo n.º 4
0
    def mouseIsOnIO(self, mousePos, click = False):    	
    	#Returns the IO that the mouse is on
        for i in range(0, len(self.ioList)):
            #Adjust if IO is centered on a side
            if self.ioList[i][3] == 'left':
                yTranslation = self.yTranslationLeftIO
            else:
                yTranslation = self.yTranslationRightIO

            #Get point of IO
            IOPoint = QPointF(self.ioList[i][0], self.ioList[i][1] + yTranslation)

            #If mouse is over IO -> return IO
            if mousePos.x() > IOPoint.x() and mousePos.x() < IOPoint.x() + self.ioWidth:
                if mousePos.y() > IOPoint.y() and mousePos.y() < IOPoint.y() + self.ioHeight:
                    # entry point for drawing graphs.......
                    # if click:
                    #     print('mouse on IO: ' + str(i) + ' (' + str(self.ioList[i][3]) + ', ' + str(self.ioList[i][4]) + ')')
                    
                    #Update the hover paramater of the IO
                    self.ioList.insert(i, (self.ioList[i][0], self.ioList[i][1], self.ioList[i][2], self.ioList[i][3], self.ioList[i][4], True, self.ioList[i][6]))
                    del self.ioList[i + 1]

                    self.setFlag(QGraphicsItem.ItemIsSelectable, False)
                    self.setFlag(QGraphicsItem.ItemIsMovable, False)
                    self.hover = False
                    return i
        #If no IO is found under the mouse -> make sure hovering is enabled and return -1
        self.hover = True
        self.setHoveringToFalse()
        return -1
Exemplo n.º 5
0
    def calcRowCol(self, point: QPointF):
        """ Calculate the network row and column that a point is int
            calc the row and column indexes of a point

            The following is the algorithm:
            1.  Find the distance between the point and the left (or top)
            2.  Divide the distance with the width of path to find the relative position
            3.  Multipile this relative position with the number of rows/cols
            4.  Convert the result to int to find the indexes
            5.  If the index is the number of row/col reduce the index
                (This is for the case the the point is on the boundary and in this
                case the relative position is 1 which will cause the indexes to
                be the number of rows/cols - out of the matrix indexes)

            Args:
                point (QPointF) : The point to resolve

            Returns:
                int : The network row that the point is in
                int : The network column that the point is in  

        """
        partialX = (point.x() - self.charPath.boundingRect().left()) / self.charPath.boundingRect().width()
        partialY = (point.y() - self.charPath.boundingRect().top()) / self.charPath.boundingRect().height()
        col_idx = int(partialX * self.netCols)
        row_idx = int(partialY * self.netRows)
        if row_idx == self.netRows:
            row_idx -= 1
        if col_idx == self.netCols:
            col_idx -= 1
        return row_idx, col_idx
Exemplo n.º 6
0
  def render(self, widget):

    painter = widget.painter

    if not painter:
      return

    previousRenderHint = painter.renderHints()
    painter.setRenderHints(previousRenderHint | QPainter.Antialiasing)

    painter.setPen(Qt.NoPen)
    painter.setBrush(QColor(253, 242, 245))

    painter.drawEllipse(QRectF(self.pos - self.toPointF(self.size/2), self.size))

    mouseOffset = QPointF(widget.mousePosition) \
                  - self.pos \
                  - QPointF(widget.frameGeometry().topLeft())

    ox, oy = mouseOffset.x(), mouseOffset.y()
    distance = math.sqrt(ox**2 + oy**2)

    if distance > self.eyesight_radius:
      ox *= self.eyesight_radius / distance
      oy *= self.eyesight_radius / distance

    px = self.pos.x() + ox/self.eyesight_radius * (self.size-self.pupil_size).width() / 2
    py = self.pos.y() + oy/self.eyesight_radius * (self.size-self.pupil_size).height() / 2

    pos = QPointF(px, py)

    painter.setBrush(Qt.black)
    painter.drawEllipse(QRectF(pos - self.toPointF(self.pupil_size/2), self.pupil_size))

    painter.setRenderHints(previousRenderHint)
Exemplo n.º 7
0
 def __init__(self):
     super().__init__()
     self.MAR = 50
     self.points = []
     self.top_left = QPointF(float('Inf'), float('Inf'))
     self.bottom_right = QPointF(-float('Inf'), -float('Inf'))
     self.rect = QRectF()
Exemplo n.º 8
0
    def applyLayerValue(self, id, val):
        layer = self.mObject
        layerIndex = self.mMapDocument.map().layers().indexOf(layer)
        command = None
        x = id
        if x==PropertyId.NameProperty:
            command = RenameLayer(self.mMapDocument, layerIndex, val)
        elif x==PropertyId.VisibleProperty:
            command = SetLayerVisible(self.mMapDocument, layerIndex, val)
        elif x==PropertyId.OpacityProperty:
            command = SetLayerOpacity(self.mMapDocument, layerIndex, val)
        elif x==PropertyId.OffsetXProperty or x==PropertyId.OffsetYProperty:
            offset = QPointF(layer.offset())

            if id == PropertyId.OffsetXProperty:
                offset.setX(val)
            else:
                offset.setY(val)

            command = SetLayerOffset(self.mMapDocument, layerIndex, offset)
        else:
            x = layer.layerType()
            if x==Layer.TileLayerType:
                self.applyTileLayerValue(id, val)
            elif x==Layer.ObjectGroupType:
                self.applyObjectGroupValue(id, val)
            elif x==Layer.ImageLayerType:
                self.applyImageLayerValue(id, val)
        if (command):
            self.mMapDocument.undoStack().push(command)
Exemplo n.º 9
0
    def is_in_roi(self, pos: QPointF):
        x1 = self.rect().x()
        x2 = x1 + self.rect().width()
        y1 = self.rect().y()
        y2 = y1 + self.rect().width()

        if x1 < pos.x() < x2 and y1 < pos.y() < y2:
            return True

        return False
Exemplo n.º 10
0
    def update_bounding_rect(self, pt):
        """插入新顶点时,更新 bounding rect

        Args:
            pt (QPointF): 新插入的顶点
        """
        self.top_left = QPointF(min(self.top_left.x(), pt.x()), min(self.top_left.y(), pt.y()))
        self.bottom_right = QPointF(max(self.bottom_right.x(), pt.x()), max(self.bottom_right.y(), pt.y()))
        self.rect = QRectF(self.top_left, self.bottom_right).adjusted(-self.MAR, -self.MAR, self.MAR, self.MAR)
        self.prepareGeometryChange()
Exemplo n.º 11
0
class Eye:

  pupil_size      = QSizeF(5, 5)
  eyesight_radius = 100.0


  def __init__(self, x, y, w, h):

    ## x, y are the coordinates of the center of the eye.
    ## w, h are the total width and height of the eye.

    self.size = QSizeF(w, h)
    self.pos  = QPointF(x, y)


  def toPointF(self, size):

    return QPointF(size.width(), size.height())


  def render(self, widget):

    painter = widget.painter

    if not painter:
      return

    previousRenderHint = painter.renderHints()
    painter.setRenderHints(previousRenderHint | QPainter.Antialiasing)

    painter.setPen(Qt.NoPen)
    painter.setBrush(QColor(253, 242, 245))

    painter.drawEllipse(QRectF(self.pos - self.toPointF(self.size/2), self.size))

    mouseOffset = QPointF(widget.mousePosition) \
                  - self.pos \
                  - QPointF(widget.frameGeometry().topLeft())

    ox, oy = mouseOffset.x(), mouseOffset.y()
    distance = math.sqrt(ox**2 + oy**2)

    if distance > self.eyesight_radius:
      ox *= self.eyesight_radius / distance
      oy *= self.eyesight_radius / distance

    px = self.pos.x() + ox/self.eyesight_radius * (self.size-self.pupil_size).width() / 2
    py = self.pos.y() + oy/self.eyesight_radius * (self.size-self.pupil_size).height() / 2

    pos = QPointF(px, py)

    painter.setBrush(Qt.black)
    painter.drawEllipse(QRectF(pos - self.toPointF(self.pupil_size/2), self.pupil_size))

    painter.setRenderHints(previousRenderHint)
Exemplo n.º 12
0
def moveUIPoint(contour, point, delta):
    if point.segmentType is None:
        # point is an offCurve. Get its sibling onCurve and the other
        # offCurve.
        onCurve, otherPoint = _getOffCurveSiblingPoints(contour, point)
        # if the onCurve is selected, the offCurve will move along with it
        if onCurve.selected:
            return
        point.move(delta)
        if not onCurve.smooth:
            contour.dirty = True
            return
        # if the onCurve is smooth, we need to either...
        if otherPoint.segmentType is None and not otherPoint.selected:
            # keep the other offCurve inline
            line = QLineF(point.x, point.y, onCurve.x, onCurve.y)
            otherLine = QLineF(
                onCurve.x, onCurve.y, otherPoint.x, otherPoint.y)
            line.setLength(line.length() + otherLine.length())
            otherPoint.x = line.x2()
            otherPoint.y = line.y2()
        else:
            # keep point in tangency with onCurve -> otherPoint segment,
            # ie. do an orthogonal projection
            line = QLineF(otherPoint.x, otherPoint.y, onCurve.x, onCurve.y)
            n = line.normalVector()
            n.translate(QPointF(point.x, point.y) - n.p1())
            targetPoint = QPointF()
            n.intersect(line, targetPoint)
            # check that targetPoint is beyond its neighbor onCurve
            # we do this by calculating position of the offCurve and second
            # onCurve relative to the first onCurve. If there is no symmetry
            # in at least one of the axis, then we need to clamp
            onCurvePoint = line.p2()
            onDistance = line.p1() - onCurvePoint
            newDistance = targetPoint - onCurvePoint
            if (onDistance.x() >= 0) != (newDistance.x() <= 0) or \
                    (onDistance.y() >= 0) != (newDistance.y() <= 0):
                targetPoint = onCurvePoint
            # ok, now set pos
            point.x, point.y = targetPoint.x(), targetPoint.y()
    else:
        # point is an onCurve. Move its offCurves along with it.
        index = contour.index(point)
        point.move(delta)
        for d in (-1, 1):
            # edge-case: contour open, trailing offCurve and moving first
            # onCurve in contour
            if contour.open and index == 0 and d == -1:
                continue
            pt = contour.getPoint(index + d)
            if pt.segmentType is None:
                pt.move(delta)
    contour.dirty = True
Exemplo n.º 13
0
    def helixIndex(self, point: QPointF) -> Vec2T:
        """Returns the (row, col) of the base which point lies within.

        Returns:
            point (tuple) in virtual_helix_item coordinates

        Args:
            point (TYPE): Description
        """
        x = int(int(point.x()) / _BW)
        y = int(int(point.y()) / _BW)
        return (x, y)
Exemplo n.º 14
0
    def getModelPos(self, pos: QPointF) -> Vec3T:
        """Y-axis is inverted in Qt +y === DOWN

        Args:
            pos: a position in this scene

        Returns:
            position in model coordinates
        """
        sf = self.scale_factor
        x, y = pos.x()/sf, -1.0*pos.y()/sf
        return x, y, 0.
Exemplo n.º 15
0
    def __init__(self, sourceNode, destNode):
        super(Edge, self).__init__()

        self.arrowSize = 10.0
        self.sourcePoint = QPointF()
        self.destPoint = QPointF()

        self.setAcceptedMouseButtons(Qt.NoButton)
        self.source = sourceNode
        self.dest = destNode
        self.source.addEdge(self)
        self.dest.addEdge(self)
        self.adjust()
Exemplo n.º 16
0
 def setPoints(self, xa, ya, xb, yb):
     """
     Public method to set the start and end points of the line.
     
     <b>Note:</b> This method does not redraw the item.
     
     @param xa x-coordinate of the start point (float)
     @param ya y-coordinate of the start point (float)
     @param xb x-coordinate of the end point (float)
     @param yb y-coordinate of the end point (float)
     """
     self._origin = QPointF(xa, ya)
     self._end = QPointF(xb, yb)
Exemplo n.º 17
0
class PolygonBase(QGraphicsWidget):
    def __init__(self):
        super().__init__()
        self.MAR = 50
        self.points = []
        self.top_left = QPointF(float('Inf'), float('Inf'))
        self.bottom_right = QPointF(-float('Inf'), -float('Inf'))
        self.rect = QRectF()

    def boundingRect(self):
        return self.rect

    def update_bounding_rect(self, pt):
        """插入新顶点时,更新 bounding rect

        Args:
            pt (QPointF): 新插入的顶点
        """
        self.top_left = QPointF(min(self.top_left.x(), pt.x()), min(self.top_left.y(), pt.y()))
        self.bottom_right = QPointF(max(self.bottom_right.x(), pt.x()), max(self.bottom_right.y(), pt.y()))
        self.rect = QRectF(self.top_left, self.bottom_right).adjusted(-self.MAR, -self.MAR, self.MAR, self.MAR)
        self.prepareGeometryChange()

    def move_bounding_rect(self, offset):
        """移动多边形时,更新 bounding rect

        Args:
            offset (QPointF): 平移向量
        """
        self.top_left += offset
        self.bottom_right += offset
        self.rect.adjust(offset.x(), offset.y(), offset.x(), offset.y())
        self.prepareGeometryChange()

    def get_points(self):
        """获取多边形中的顶点列表

        Returns:
            points (list[QPointF]): 顶点列表
        """
        return self.points

    def get_vertices(self):
        """获取多边形中的顶点列表

        Returns:
            vertices (list[list[float]]): 顶点列表
        """
        vertices = [[vertex.x(), vertex.y()] for vertex in self.points]
        return vertices
Exemplo n.º 18
0
 def intersectLineGeometry(self, lineGeo, breakShape):
     """
     Try to break lineGeo with the given breakShape. Will return the intersection points of lineGeo with breakShape.
     """
     # TODO geos should be abs
     intersections = []
     line = QLineF(lineGeo.Ps.x, lineGeo.Ps.y, lineGeo.Pe.x, lineGeo.Pe.y)
     for breakGeo in breakShape.geos.abs_iter():
         if isinstance(breakGeo, LineGeo):
             breakLine = QLineF(breakGeo.Ps.x, breakGeo.Ps.y, breakGeo.Pe.x, breakGeo.Pe.y)
             intersection = QPointF(0, 0)  # values do not matter
             res = line.intersect(breakLine, intersection)
             if res == QLineF.BoundedIntersection:
                 intersections.append(Point(intersection.x(), intersection.y()))
     return intersections
Exemplo n.º 19
0
  def __init__(self, x, y, w, h):

    ## x, y are the coordinates of the center of the eye.
    ## w, h are the total width and height of the eye.

    self.size = QSizeF(w, h)
    self.pos  = QPointF(x, y)
Exemplo n.º 20
0
    def setGraph(self, graphData):
        if graphData != None:
            self.graphData = graphData

            # set widget size based on min/max positions of nodes
            if not self.graphData is None:
                minX, minY = sys.maxsize, sys.maxsize
                maxX, maxY = 0, 0
                for n in self.graphData.nodes():
                    x, y = self.graphData.node[n]['pos']
                    minX = min(minX, x - 50)
                    minY = min(minY, y - 50)
                    maxX = max(maxX, x + 50)
                    maxY = max(maxY, y + 50)

                # Determine the center of the graph
                self.centerOfGraph = QPointF((minX + maxX) / 2, (minY + maxY) / 2)

            self.placeGraphObjects()

            #Resize scene to be slightly larger than the graph
            self.scene.updateSceneRect()

            self.resetView()
            self.update()
Exemplo n.º 21
0
    def __init__(self, parent = None):
        super().__init__(self.tr("Select Objects"),
              QIcon(":images/22x22/tool-select-objects.png"),
              QKeySequence(self.tr("S")),
              parent)
        self.mSelectionRectangle = SelectionRectangle()
        self.mOriginIndicator = OriginIndicator()
        self.mMousePressed = False
        self.mHoveredObjectItem = None
        self.mClickedObjectItem = None
        self.mClickedRotateHandle = None
        self.mClickedResizeHandle = None
        self.mResizingLimitHorizontal = False
        self.mResizingLimitVertical = False
        self.mMode = Mode.Resize
        self.mAction = Action.NoAction
        self.mRotateHandles = [0, 0, 0, 0]
        self.mResizeHandles = [0, 0, 0, 0, 0, 0, 0, 0]
        self.mAlignPosition = QPointF()
        self.mMovingObjects = QVector()
        self.mScreenStart = QPoint()
        self.mStart = QPointF()
        self.mModifiers = 0
        self.mOrigin = QPointF()

        for i in range(AnchorPosition.CornerAnchorCount):
            self.mRotateHandles[i] = RotateHandle(i)
        for i in range(AnchorPosition.AnchorCount):
            self.mResizeHandles[i] = ResizeHandle(i)
Exemplo n.º 22
0
 def __init__(self,winParent):
     super(TeleopWidget, self).__init__()
     self.winParent=winParent
     self.line = QPointF(0, 0);
     self.qimage=QtGui.QImage()
     self.qimage.load(':images/ball.png')
     self.stopSIG.connect(self.stop)
     self.initUI()
Exemplo n.º 23
0
    def __init__(self, time_sig = '4/4', num_measures = 4, quantize_val = '1/8'):
        QGraphicsScene.__init__(self)
        self.setBackgroundBrush(QColor(50, 50, 50))
        self.mousePos = QPointF()

        self.notes = []
        self.selected_notes = []
        self.piano_keys = []

        self.marquee_select = False
        self.insert_mode = False
        self.velocity_mode = False
        self.place_ghost = False
        self.ghost_note = None
        self.default_ghost_vel = 100
        self.ghost_vel = self.default_ghost_vel

        ## dimensions
        self.padding = 2

        ## piano dimensions
        self.note_height = 10
        self.start_octave = -2
        self.end_octave = 8
        self.notes_in_octave = 12
        self.total_notes = (self.end_octave - self.start_octave) \
                * self.notes_in_octave + 1
        self.piano_height = self.note_height * self.total_notes
        self.octave_height = self.notes_in_octave * self.note_height

        self.piano_width = 34

        ## height
        self.header_height = 20
        self.total_height = self.piano_height - self.note_height + self.header_height
        #not sure why note_height is subtracted

        ## width
        self.full_note_width = 250 # i.e. a 4/4 note
        self.snap_value = None
        self.quantize_val = quantize_val

        ### dummy vars that will be changed
        self.time_sig = 0
        self.measure_width = 0
        self.num_measures = 0
        self.max_note_length = 0
        self.grid_width = 0
        self.value_width = 0
        self.grid_div = 0
        self.piano = None
        self.header = None
        self.play_head = None

        self.setTimeSig(time_sig)
        self.setMeasures(num_measures)
        self.setGridDiv()
        self.default_length = 1. / self.grid_div
Exemplo n.º 24
0
    def getX(self, pos: QPointF) -> float:
        """
        Args:
            pos: Description

        Returns:
            ``x`` position
        """
        return pos.x()
Exemplo n.º 25
0
    def animate(self):
        self.angle += (math.pi / 30)
        xs = 200 * math.sin(self.angle) - 40 + 25
        ys = 200 * math.cos(self.angle) - 40 + 25
        self.m_lightSource.setPos(xs, ys)

        for item in self.m_items:
            effect = item.graphicsEffect()

            delta = QPointF(item.x() - xs, item.y() - ys)
            effect.setOffset(QPointF(delta.toPoint() / 30))

            dd = math.hypot(delta.x(), delta.y())
            color = effect.color()
            color.setAlphaF(max(0.4, min(1 - dd / 200.0, 0.7)))
            effect.setColor(color)

        self.m_scene.update()
Exemplo n.º 26
0
    def zoom(self, step, anchor="center"):
        """
        Zooms the view by *step* increments (with a scale factor of
        1.2^*step*), anchored to *anchor*:

        - QPoint_: center on that point
        - "cursor": center on the mouse cursor position
        - "center": center on the viewport
        - None: don’t anchor, i.e. stick to the viewport’s top-left.

        # TODO: improve docs from QGraphicsView descriptions.

        The default is "center".

        .. _QPoint: http://doc.qt.io/qt-5/qpoint.html
        """
        oldScale = self._scale
        newScale = self._scale * pow(1.2, step)
        scrollArea = self._scrollArea
        if newScale < 1e-2 or newScale > 1e3:
            return
        if scrollArea is not None:
            # compute new scrollbar position
            # http://stackoverflow.com/a/32269574/2037879
            hSB = scrollArea.horizontalScrollBar()
            vSB = scrollArea.verticalScrollBar()
            viewport = scrollArea.viewport()
            if isinstance(anchor, QPoint):
                pos = anchor
            elif anchor == "cursor":
                pos = self.mapFromGlobal(QCursor.pos())
            elif anchor == "center":
                pos = self.mapFromParent(
                    QPoint(viewport.width() / 2, viewport.height() / 2))
            else:
                raise ValueError("invalid anchor value: {}".format(anchor))
            scrollBarPos = QPointF(hSB.value(), vSB.value())
            deltaToPos = pos / oldScale
            delta = deltaToPos * (newScale - oldScale)
        self.setScale(newScale)
        self.update()
        if scrollArea is not None:
            hSB.setValue(scrollBarPos.x() + delta.x())
            vSB.setValue(scrollBarPos.y() + delta.y())
Exemplo n.º 27
0
    def __init__(self, parent, index=0):
        QDial.__init__(self, parent)

        self.fMinimum   = 0.0
        self.fMaximum   = 1.0
        self.fRealValue = 0.0

        self.fIsHovered = False
        self.fHoverStep = self.HOVER_MIN

        self.fIndex     = index
        self.fPixmap    = QPixmap(":/bitmaps/dial_01d.png")
        self.fPixmapNum = "01"

        if self.fPixmap.width() > self.fPixmap.height():
            self.fPixmapOrientation = self.HORIZONTAL
        else:
            self.fPixmapOrientation = self.VERTICAL

        self.fLabel     = ""
        self.fLabelPos  = QPointF(0.0, 0.0)
        self.fLabelFont = QFont(self.font())
        self.fLabelFont.setPointSize(6)
        self.fLabelWidth  = 0
        self.fLabelHeight = 0

        if self.palette().window().color().lightness() > 100:
            # Light background
            c = self.palette().dark().color()
            self.fLabelGradientColor1 = c
            self.fLabelGradientColor2 = QColor(c.red(), c.green(), c.blue(), 0)
            self.fLabelGradientColorT = [self.palette().buttonText().color(), self.palette().mid().color()]
        else:
            # Dark background
            self.fLabelGradientColor1 = QColor(0, 0, 0, 255)
            self.fLabelGradientColor2 = QColor(0, 0, 0, 0)
            self.fLabelGradientColorT = [Qt.white, Qt.darkGray]

        self.fLabelGradient = QLinearGradient(0, 0, 0, 1)
        self.fLabelGradient.setColorAt(0.0, self.fLabelGradientColor1)
        self.fLabelGradient.setColorAt(0.6, self.fLabelGradientColor1)
        self.fLabelGradient.setColorAt(1.0, self.fLabelGradientColor2)

        self.fLabelGradientRect = QRectF(0.0, 0.0, 0.0, 0.0)

        self.fCustomPaintMode  = self.CUSTOM_PAINT_MODE_NULL
        self.fCustomPaintColor = QColor(0xff, 0xff, 0xff)

        self.updateSizes()

        # Fake internal value, 10'000 precision
        QDial.setMinimum(self, 0)
        QDial.setMaximum(self, 10000)
        QDial.setValue(self, 0)

        self.valueChanged.connect(self.slot_valueChanged)
Exemplo n.º 28
0
    def mouseMovedWhileCreatingObject(self, pos, modifiers):
        renderer = self.mapDocument().renderer()
        pixelCoords = renderer.screenToPixelCoords_(pos)
        # Update the size of the new map object
        objectPos = self.mNewMapObjectItem.mapObject().position()
        newSize = QPointF(max(0.0, pixelCoords.x() - objectPos.x()),
                        max(0.0, pixelCoords.y() - objectPos.y()))
        # Holding shift creates circle or square
        if (modifiers & Qt.ShiftModifier):
            m = max(newSize.x(), newSize.y())
            newSize.setX(m)
            newSize.setY(m)

        SnapHelper(renderer, modifiers).snap(newSize)
        self.mNewMapObjectItem.resizeObject(QSizeF(newSize.x(), newSize.y()))
Exemplo n.º 29
0
    def beginDrawing(self, pos, sliceRect):
        """

        pos -- QPointF-like
        """
        self.sliceRect = sliceRect
        self.scene.clear()
        self.bb = QRect()
        self.pos = QPointF(pos.x(), pos.y())
        self._hasMoved = False
Exemplo n.º 30
0
 def setEndPoint(self, x, y):
     """
     Public method to set the end point.
     
     <b>Note:</b> This method does not redraw the item.
     
     @param x x-coordinate of the end point (float)
     @param y y-coordinate of the end point (float)
     """
     self._end = QPointF(x, y)
Exemplo n.º 31
0
    def __updatePath(self):
        """ Updates the connections path, using the start and end points """

        path = QPainterPath(self.__start)

        # the end point is further left than the start point, so draw two half circles and a straight line
        if self.__start.x() > self.__end.x():
            yDiff = abs(self.__end.y() - self.__start.y())
            middleY = (self.__start.y() + self.__end.y()) / 2

            # calculate the control points needed for the first half circle
            curve1End = QPointF(self.__start.x(), middleY)
            curve1CP1 = QPointF(self.__start.x() + yDiff / 2, self.__start.y())
            curve1CP2 = QPointF(self.__start.x() + yDiff / 2, middleY)

            # calculate the control points needed for the second half circle
            curve2Start = QPointF(self.__end.x(), middleY)
            curve2CP1 = QPointF(self.__end.x() - yDiff / 2, middleY)
            curve2CP2 = QPointF(self.__end.x() - yDiff / 2, self.__end.y())

            # draw the first half circle
            path.cubicTo(curve1CP1.x(), curve1CP1.y(), curve1CP2.x(),
                         curve1CP2.y(), curve1End.x(), curve1End.y())

            # draw the straight line
            path.lineTo(curve2Start.x(), curve2Start.y())

            # draw the second half circle
            path.cubicTo(curve2CP1.x(), curve2CP1.y(), curve2CP2.x(),
                         curve2CP2.y(), self.__end.x(), self.__end.y())

        # the start point is further left than the end point, so draw a Bezier curve between both
        else:
            path.cubicTo((self.__start.x() + self.__end.x()) / 2,
                         self.__start.y(),
                         (self.__start.x() + self.__end.x()) / 2,
                         self.__end.y(), self.__end.x(), self.__end.y())

        self.setPath(path)

        self.update()
Exemplo n.º 32
0
class ConnectionItem(QGraphicsPathItem):
    """ A ConnectionItem represents a top-bottom connection in the graphics scene """
    def __init__(self, nodeEditor, parent=None):
        super(ConnectionItem, self).__init__(parent)

        # make selectable
        self.setFlag(QGraphicsPathItem.ItemIsSelectable, True)

        # draw behind node items
        self.setZValue(0.5)

        self.__isInPlace = False
        self.__nodeEditor = nodeEditor

        self.__hidden = False

        self.__topConnector = None
        self.__bottomConnector = None

        self.__start = QPointF(0, 0)
        self.__end = QPointF(0, 0)

        # create a renderer to separate drawing from logic
        self.__renderer = ConnectionItemRenderer(self)

        self.__updatePath()

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

    def shape(self):
        stroker = QPainterPathStroker()
        stroker.setWidth(Constants.connectionItemSize * 3)
        return stroker.createStroke(self.path())

    def setStart(self, start):
        """ Sets the start position of the connection and recalculates the path """

        self.__start = start
        self.__updatePath()

    def setEnd(self, end):
        """ Sets the end position of the connection and recalculates the path """

        self.__end = end
        self.__updatePath()

    def getTopConnector(self):
        """ Returns the connections top connector """
        return self.__topConnector

    def getBottomConnector(self):
        """ Returns the connections bottom connector """
        return self.__bottomConnector

    def setConnector(self, connector):
        """ Sets the top/bottom connector of the connection. Whether the top or bottom connector gets set,
        is decided by information provided by the connector """

        if connector.isTopConnector():
            self.setTopConnector(connector)
        else:
            self.setBottomConnector(connector)

    def setTopConnector(self, connector):
        """ Sets the top connector and updates the connections path """

        self.__topConnector = connector
        self.__start = connector.scenePos()

        self.updateData()
        self.__updatePath()

    def setBottomConnector(self, connector):
        """ Sets the bottom connector and updates the connections path """

        self.__bottomConnector = connector
        self.__end = connector.scenePos()

        self.updateData()
        self.__updatePath()

    def setHidden(self, hidden):
        """ Sets the connection to be hidden/shown and updates the rendering """

        self.__hidden = hidden
        self.update()

    def updateMousePosition(self, pos):
        """ Updates the start/end of the connection if the connection is getting dragged (created)  """

        if self.__topConnector is None:
            self.__start = pos
        elif self.__bottomConnector is None:
            self.__end = pos

        self.__updatePath()

    def updateData(self):
        """ Updates the connections internal in-place and phase variables to update the rendering """

        # set in-place
        if self.__bottomConnector is not None:
            self.__isInPlace = self.__bottomConnector.isInPlace()
        else:
            self.__isInPlace = False

        # update
        self.update()

    def __updatePath(self):
        """ Updates the connections path, using the start and end points """

        path = QPainterPath(self.__start)

        # the end point is further left than the start point, so draw two half circles and a straight line
        if self.__start.x() > self.__end.x():
            yDiff = abs(self.__end.y() - self.__start.y())
            middleY = (self.__start.y() + self.__end.y()) / 2

            # calculate the control points needed for the first half circle
            curve1End = QPointF(self.__start.x(), middleY)
            curve1CP1 = QPointF(self.__start.x() + yDiff / 2, self.__start.y())
            curve1CP2 = QPointF(self.__start.x() + yDiff / 2, middleY)

            # calculate the control points needed for the second half circle
            curve2Start = QPointF(self.__end.x(), middleY)
            curve2CP1 = QPointF(self.__end.x() - yDiff / 2, middleY)
            curve2CP2 = QPointF(self.__end.x() - yDiff / 2, self.__end.y())

            # draw the first half circle
            path.cubicTo(curve1CP1.x(), curve1CP1.y(), curve1CP2.x(),
                         curve1CP2.y(), curve1End.x(), curve1End.y())

            # draw the straight line
            path.lineTo(curve2Start.x(), curve2Start.y())

            # draw the second half circle
            path.cubicTo(curve2CP1.x(), curve2CP1.y(), curve2CP2.x(),
                         curve2CP2.y(), self.__end.x(), self.__end.y())

        # the start point is further left than the end point, so draw a Bezier curve between both
        else:
            path.cubicTo((self.__start.x() + self.__end.x()) / 2,
                         self.__start.y(),
                         (self.__start.x() + self.__end.x()) / 2,
                         self.__end.y(), self.__end.x(), self.__end.y())

        self.setPath(path)

        self.update()

    def checkSameConnectorTypeRestriction(self, connector):
        """ Check, whether the connector type (top/bottom) is already set in the connection """

        if self.__topConnector is not None and connector.isTopConnector():
            return False
        elif self.__bottomConnector is not None and not connector.isTopConnector(
        ):
            return False
        return True

    def getConnectorIfNotFullyConnected(self):
        """ Returns the only connected connector, if only one connector is connected """

        if self.__topConnector is not None and self.__bottomConnector is None:
            return self.__topConnector
        elif self.__topConnector is None and self.__bottomConnector is not None:
            return self.__bottomConnector
        return None

    def getHidden(self):
        """ Returns whether the connection is hidden """
        return self.__hidden

    def getNodeEditor(self):
        """ Returns the node prototxt_editor object (for the renderer) """
        return self.__nodeEditor

    def getPhase(self):
        """ Returns the internal phase """
        if self.getTopConnector() is not None:
            return self.getTopConnector().getPhase()
        else:
            return self.getBottomConnector().getPhase()

    def getIsInPlace(self):
        """ Returns the internal in-place value """
        return self.__isInPlace

    def contextMenuEvent(self, event):
        """ Creates the context menu """
        contextMenu = QMenu()

        menuText = "Hide"
        if self.__hidden:
            menuText = "Show"

        # add action to show/hide the connection
        toggleHideAction = contextMenu.addAction(menuText)
        if not self.__nodeEditor.disable:
            removeAction = contextMenu.addAction("Remove")

        # show context menu
        action = contextMenu.exec_(event.screenPos())
        if action is not None:
            if action == toggleHideAction:
                self.__hidden = not self.__hidden
                if self.__hidden:
                    self.__nodeEditor.tryToAddHiddenConnection(self)
                else:
                    self.__nodeEditor.tryToRemoveHiddenConnection(self)
                self.update()

            elif not self.__nodeEditor.disable and action == removeAction:
                # deselect all Layers
                self.__nodeEditor.tryToClearSelection()
                # deselect all other connections
                for item in self.__nodeEditor.getScene().selectedItems():
                    item.setSelected(False)
                # select this connection
                self.setSelected(True)
                # remove this connection
                self.__nodeEditor.tryToDeleteSelection()
Exemplo n.º 33
0
    def createGradient(self):

        center = QPointF(0, 0)
        self.gradient = QRadialGradient(center, self._outerRadius, center)
        self.gradient.setColorAt(0.5, QColor(self._innerColor))
        self.gradient.setColorAt(1.0, QColor(self._outerColor))
Exemplo n.º 34
0
 def size_points_on_scene(self, scene, rsize):
     rx, ry = self.size_on_scene(scene, rsize)
     return QPointF(rx, 0), QPointF(0, ry)
Exemplo n.º 35
0
    def __calculateEndingPoints_topToBottom(self):
        """
        Private method to calculate the ending points of the association item.
        
        The ending points are calculated from the top center of the lower item
        to the bottom center of the upper item.
        """
        if self.itemA is None or self.itemB is None:
            return

        self.prepareGeometryChange()

        rectA = self.__mapRectFromItem(self.itemA)
        rectB = self.__mapRectFromItem(self.itemB)
        midA = QPointF(rectA.x() + rectA.width() / 2.0,
                       rectA.y() + rectA.height() / 2.0)
        midB = QPointF(rectB.x() + rectB.width() / 2.0,
                       rectB.y() + rectB.height() / 2.0)
        if midA.y() > midB.y():
            startP = QPointF(rectA.x() + rectA.width() / 2.0, rectA.y())
            endP = QPointF(rectB.x() + rectB.width() / 2.0,
                           rectB.y() + rectB.height())
        else:
            startP = QPointF(rectA.x() + rectA.width() / 2.0,
                             rectA.y() + rectA.height())
            endP = QPointF(rectB.x() + rectB.width() / 2.0, rectB.y())
        self.setPoints(startP.x(), startP.y(), endP.x(), endP.y())
Exemplo n.º 36
0
    def updateLinePos(self, scenePos):
        if self.m_ready_to_disc:
            if self.m_port_type == PORT_TYPE_AUDIO_JACK:
                pen = QPen(canvas.theme.line_audio_jack_sel, 2, Qt.DotLine)
            elif self.m_port_type == PORT_TYPE_MIDI_JACK:
                pen = QPen(canvas.theme.line_midi_jack_sel, 2, Qt.DotLine)
            elif self.m_port_type == PORT_TYPE_MIDI_ALSA:
                pen = QPen(canvas.theme.line_midi_alsa_sel, 2, Qt.DotLine)
            elif self.m_port_type == PORT_TYPE_PARAMETER:
                pen = QPen(canvas.theme.line_parameter_sel, 2, Qt.DotLine)
            else:
                pen = QPen(Qt.black)
        else:
            if self.m_port_type == PORT_TYPE_AUDIO_JACK:
                pen = QPen(canvas.theme.line_audio_jack_sel, 2)
            elif self.m_port_type == PORT_TYPE_MIDI_JACK:
                pen = QPen(canvas.theme.line_midi_jack_sel, 2)
            elif self.m_port_type == PORT_TYPE_MIDI_ALSA:
                pen = QPen(canvas.theme.line_midi_alsa_sel, 2)
            elif self.m_port_type == PORT_TYPE_PARAMETER:
                pen = QPen(canvas.theme.line_parameter_sel, 2)
            else:
                pen = QPen(Qt.black)

        pen.setCapStyle(Qt.FlatCap)
        pen.setWidthF(pen.widthF() + 0.00001)
        self.setPen(pen)

        phi = 0.75 if self.m_portgrp_lenght > 2 else 0.62
        phito = 0.75 if self.m_portgrp_lenght_to > 2 else 0.62

        if self.parentItem().type() == CanvasPortType:
            if self.m_portgrp_lenght > 1:
                first_old_y = canvas.theme.port_height * phi
                last_old_y = canvas.theme.port_height * (
                    self.m_portgrp_lenght - phi)
                delta = (last_old_y - first_old_y) / (self.m_portgrp_lenght -
                                                      1)
                old_y = first_old_y + (self.m_port_posinportgrp * delta) \
                        - canvas.theme.port_height * self.m_port_posinportgrp
            else:
                old_y = canvas.theme.port_height / 2

            if self.m_portgrp_lenght_to == 1:
                new_y = 0
            else:
                first_new_y = canvas.theme.port_height * phito
                last_new_y = canvas.theme.port_height * (
                    self.m_portgrp_lenght_to - phito)
                delta = (last_new_y -
                         first_new_y) / (self.m_portgrp_lenght_to - 1)
                new_y1 = first_new_y + (self.m_port_posinportgrp_to * delta)
                new_y = new_y1 - ( (last_new_y - first_new_y) / 2 ) \
                        - canvas.theme.port_height * phito

        elif self.parentItem().type() == CanvasPortGroupType:
            first_old_y = canvas.theme.port_height * phi
            last_old_y = canvas.theme.port_height * (self.m_portgrp_lenght -
                                                     phi)
            delta = (last_old_y - first_old_y) / (self.m_portgrp_lenght - 1)
            old_y = first_old_y + (self.m_port_posinportgrp * delta)

            if self.m_portgrp_lenght_to == 1:
                new_y = 0
            elif (self.m_port_posinportgrp_to == self.m_port_posinportgrp
                  and self.m_portgrp_lenght == self.m_portgrp_lenght_to):
                new_y = old_y - ( (last_old_y - first_old_y) / 2 ) \
                        - (canvas.theme.port_height * phi)
            else:
                first_new_y = canvas.theme.port_height * phito
                last_new_y = canvas.theme.port_height * (
                    self.m_portgrp_lenght_to - phito)
                delta = (last_new_y -
                         first_new_y) / (self.m_portgrp_lenght_to - 1)
                new_y1 = first_new_y + (self.m_port_posinportgrp_to * delta)
                new_y = new_y1 - ( (last_new_y - first_new_y) / 2 ) \
                        - (canvas.theme.port_height * phito)

        final_x = scenePos.x() - self.p_itemX
        final_y = scenePos.y() - self.p_itemY + new_y

        if self.m_port_mode == PORT_MODE_OUTPUT:
            old_x = self.p_width + 12
            mid_x = abs(final_x - old_x) / 2
            new_x1 = old_x + mid_x
            new_x2 = final_x - mid_x

            diffxy = abs(final_y - old_y) - abs(final_x - old_x)
            if diffxy > 0:
                new_x1 += abs(diffxy)
                new_x2 -= abs(diffxy)

        elif self.m_port_mode == PORT_MODE_INPUT:
            old_x = 0
            mid_x = abs(final_x - old_x) / 2
            new_x1 = old_x - mid_x
            new_x2 = final_x + mid_x

            diffxy = abs(final_y - old_y) - abs(final_x - old_x)
            if diffxy > 0:
                new_x1 -= abs(diffxy)
                new_x2 += abs(diffxy)
        else:
            return

        path = QPainterPath(QPointF(old_x, old_y))
        path.cubicTo(new_x1, old_y, new_x2, final_y, final_x, final_y)
        self.setPath(path)
Exemplo n.º 37
0
        self.setRect(rect)
        self.isSet = True

    def setP1(self, point):
        rect = self.rect()
        rect.setX(point.x()-rect.width()/2.)
        rect.setY(point.y()+rect.height()/2.)
        self.setRect(rect)


if __name__ == '__main__':
    # ça marche --> voici deux examples de shapes
    test = Ellipse2D(0, 0, 100, 100)
    # print(test.x(), test.y(), test.width(), test.height())
    print(test.contains(QPointF(50, 50)))
    print(test.contains(QPointF(15, 15)))
    print(test.contains(QPointF(-1, -1)))
    print(test.contains(QPointF(0, 0)))
    print(test.contains(QPointF(100, 100)))
    print(test.contains(QPointF(100, 100.1)))
    print(test.x())
    print(test.y())
    print(test.translate(QPoint(10, 10)))
    print(test.x())
    print(test.y())

    # p1 = test.p1()
    # print(p1.x(), p1.y())
    # p2 = test.p2()
    # print(p2.x(), p2.y())
Exemplo n.º 38
0
    def add_plot(
        self,
        plot: 'ChartPlotWidget',  # noqa
        digits: int = 0,
    ) -> None:
        # add ``pg.graphicsItems.InfiniteLine``s
        # vertical and horizonal lines and a y-axis label
        vl = plot.addLine(x=0, pen=self.lines_pen, movable=False)
        vl.setCacheMode(QtGui.QGraphicsItem.DeviceCoordinateCache)

        hl = plot.addLine(y=0, pen=self.lines_pen, movable=False)
        hl.setCacheMode(QtGui.QGraphicsItem.DeviceCoordinateCache)
        hl.hide()

        yl = YAxisLabel(
            parent=plot.getAxis('right'),
            digits=digits or self.digits,
            opacity=_ch_label_opac,
            bg_color='default',
        )
        yl.hide()  # on startup if mouse is off screen

        # TODO: checkout what ``.sigDelayed`` can be used for
        # (emitted once a sufficient delay occurs in mouse movement)
        px_moved = pg.SignalProxy(
            plot.scene().sigMouseMoved,
            rateLimit=_mouse_rate_limit,
            slot=self.mouseMoved,
            delay=_debounce_delay,
        )
        px_enter = pg.SignalProxy(
            plot.sig_mouse_enter,
            rateLimit=_mouse_rate_limit,
            slot=lambda: self.mouseAction('Enter', plot),
            delay=_debounce_delay,
        )
        px_leave = pg.SignalProxy(
            plot.sig_mouse_leave,
            rateLimit=_mouse_rate_limit,
            slot=lambda: self.mouseAction('Leave', plot),
            delay=_debounce_delay,
        )
        self.graphics[plot] = {
            'vl': vl,
            'hl': hl,
            'yl': yl,
            'px': (px_moved, px_enter, px_leave),
        }
        self.plots.append(plot)

        # Determine where to place x-axis label.
        # Place below the last plot by default, ow
        # keep x-axis right below main chart
        plot_index = -1 if _xaxis_at == 'bottom' else 0

        self.xaxis_label = XAxisLabel(
            parent=self.plots[plot_index].getAxis('bottom'),
            opacity=_ch_label_opac,
            bg_color='default',
        )
        # place label off-screen during startup
        self.xaxis_label.setPos(self.plots[0].mapFromView(QPointF(0, 0)))
Exemplo n.º 39
0
    def initialize(self):
        self.init_file()

        self.focus_widget(
            QMouseEvent(QEvent.MouseButtonPress, QPointF(0, 0), Qt.LeftButton,
                        Qt.LeftButton, Qt.NoModifier))
Exemplo n.º 40
0
class MapObject(Object):
    ##
    # Enumerates the different object shapes. Rectangle is the default shape.
    # When a polygon is set, the shape determines whether it should be
    # interpreted as a filled polygon or a line.
    ##
    Rectangle, Polygon, Polyline, Ellipse = range(4)

    def __init__(self, *args):
        super().__init__(Object.MapObjectType)

        self.mPolygon = QPolygonF()
        self.mName = QString()
        self.mPos = QPointF()
        self.mCell = Cell()
        self.mType = QString()
        self.mId = 0
        self.mShape = MapObject.Rectangle
        self.mObjectGroup = None
        self.mRotation = 0.0
        self.mVisible = True

        l = len(args)
        if l == 0:
            self.mSize = QSizeF(0, 0)
        elif l == 4:
            name, _type, pos, size = args

            self.mName = name
            self.mType = _type
            self.mPos = pos
            self.mSize = QSizeF(size)

    ##
    # Returns the id of this object. Each object gets an id assigned that is
    # unique for the map the object is on.
    ##
    def id(self):
        return self.mId

    ##
    # Sets the id of this object.
    ##
    def setId(self, id):
        self.mId = id

    ##
    # Returns the name of this object. The name is usually just used for
    # identification of the object in the editor.
    ##
    def name(self):
        return self.mName

    ##
    # Sets the name of this object.
    ##
    def setName(self, name):
        self.mName = name

    ##
    # Returns the type of this object. The type usually says something about
    # how the object is meant to be interpreted by the engine.
    ##
    def type(self):
        return self.mType

    ##
    # Sets the type of this object.
    ##
    def setType(self, type):
        self.mType = type

    ##
    # Returns the position of this object.
    ##
    def position(self):
        return QPointF(self.mPos)

    ##
    # Sets the position of this object.
    ##
    def setPosition(self, pos):
        self.mPos = pos

    ##
    # Returns the x position of this object.
    ##
    def x(self):
        return self.mPos.x()

    ##
    # Sets the x position of this object.
    ##
    def setX(self, x):
        self.mPos.setX(x)

    ##
    # Returns the y position of this object.
    ##
    def y(self):
        return self.mPos.y()

    ##
    # Sets the x position of this object.
    ##
    def setY(self, y):
        self.mPos.setY(y)

    ##
    # Returns the size of this object.
    ##
    def size(self):
        return self.mSize

    ##
    # Sets the size of this object.
    ##
    def setSize(self, *args):
        l = len(args)
        if l == 1:
            size = args[0]
            self.mSize = QSizeF(size)
        elif l == 2:
            width, height = args
            self.setSize(QSizeF(width, height))

    ##
    # Returns the width of this object.
    ##
    def width(self):
        return self.mSize.width()

    ##
    # Sets the width of this object.
    ##
    def setWidth(self, width):
        self.mSize.setWidth(width)

    ##
    # Returns the height of this object.
    ##
    def height(self):
        return self.mSize.height()

    ##
    # Sets the height of this object.
    ##
    def setHeight(self, height):
        self.mSize.setHeight(height)

    ##
    # Sets the polygon associated with this object. The polygon is only used
    # when the object shape is set to either Polygon or Polyline.
    #
    # \sa setShape()
    ##
    def setPolygon(self, polygon):
        self.mPolygon = polygon

    ##
    # Returns the polygon associated with this object. Returns an empty
    # polygon when no polygon is associated with this object.
    ##
    def polygon(self):
        return QPolygonF(self.mPolygon)

    ##
    # Sets the shape of the object.
    ##
    def setShape(self, shape):
        self.mShape = shape

    ##
    # Returns the shape of the object.
    ##
    def shape(self):
        return self.mShape

    ##
    # Shortcut to getting a QRectF from position() and size().
    ##
    def bounds(self):
        return QRectF(self.mPos, self.mSize)

    ##
    # Shortcut to getting a QRectF from position() and size() that uses cell tile if present.
    ##
    def boundsUseTile(self):
        if (self.mCell.isEmpty()):
            # No tile so just use regular bounds
            return self.bounds()

        # Using the tile for determing boundary
        # Note the position given is the bottom-left corner so correct for that
        return QRectF(
            QPointF(self.mPos.x(),
                    self.mPos.y() - self.mCell.tile.height()),
            self.mCell.tile.size())

    ##
    # Sets the tile that is associated with this object. The object will
    # display as the tile image.
    #
    # \warning The object shape is ignored for tile objects!
    ##
    def setCell(self, cell):
        self.mCell = cell

    ##
    # Returns the tile associated with this object.
    ##
    def cell(self):
        return self.mCell

    ##
    # Returns the object group this object belongs to.
    ##
    def objectGroup(self):
        return self.mObjectGroup

    ##
    # Sets the object group this object belongs to. Should only be called
    # from the ObjectGroup class.
    ##
    def setObjectGroup(self, objectGroup):
        self.mObjectGroup = objectGroup

    ##
    # Returns the rotation of the object in degrees.
    ##
    def rotation(self):
        return self.mRotation

    ##
    # Sets the rotation of the object in degrees.
    ##
    def setRotation(self, rotation):
        self.mRotation = rotation

    ##
    # This is somewhat of a workaround for dealing with the ways different objects
    # align.
    #
    # Traditional rectangle objects have top-left alignment.
    # Tile objects have bottom-left alignment on orthogonal maps, but
    # bottom-center alignment on isometric maps.
    #
    # Eventually, the object alignment should probably be configurable. For
    # backwards compatibility, it will need to be configurable on a per-object
    # level.
    ##
    def alignment(self):
        if (self.mCell.isEmpty()):
            return Alignment.TopLeft
        elif (self.mObjectGroup):
            map = self.mObjectGroup.map()
            if map:
                if (map.orientation() == Map.Orientation.Isometric):
                    return Alignment.Bottom

        return Alignment.BottomLeft

    def isVisible(self):
        return self.mVisible

    def setVisible(self, visible):
        self.mVisible = visible

    ##
    # Flip this object in the given \a direction. This doesn't change the size
    # of the object.
    ##
    def flip(self, direction):
        if (not self.mCell.isEmpty()):
            if (direction == FlipDirection.FlipHorizontally):
                self.mCell.flippedHorizontally = not self.mCell.flippedHorizontally
            elif (direction == FlipDirection.FlipVertically):
                self.mCell.flippedVertically = not self.mCell.flippedVertically

        if (not self.mPolygon.isEmpty()):
            center2 = self.mPolygon.boundingRect().center() * 2
            if (direction == FlipDirection.FlipHorizontally):
                for i in range(self.mPolygon.size()):
                    # oh, QPointF mPolygon returned is a copy of internal object
                    self.mPolygon[i] = QPointF(
                        center2.x() - self.mPolygon[i].x(),
                        self.mPolygon[i].y())
            elif (direction == FlipDirection.FlipVertically):
                for i in range(self.mPolygon.size()):
                    self.mPolygon[i] = QPointF(
                        self.mPolygon[i].x(),
                        center2.y() - self.mPolygon[i].y())

    ##
    # Returns a duplicate of this object. The caller is responsible for the
    # ownership of this newly created object.
    ##
    def clone(self):
        o = MapObject(self.mName, self.mType, self.mPos, self.mSize)
        o.setProperties(self.properties())
        o.setPolygon(self.mPolygon)
        o.setShape(self.mShape)
        o.setCell(self.mCell)
        o.setRotation(self.mRotation)
        return o
Exemplo n.º 41
0
 def position(self):
     return QPointF(self.mPos)
Exemplo n.º 42
0
class Label:
    '''
    A plain ol' "scene label" using an underlying ``QGraphicsTextItem``.

    After hacking for many days on multiple "label" systems inside
    ``pyqtgraph`` yet again we're left writing our own since it seems
    all of those are over complicated, ad-hoc, transform-mangling,
    messes which can't accomplish the simplest things via their inputs
    (such as pinning to the left hand side of a view box).

    Here we do the simple thing where the label uses callables to figure
    out the (x, y) coordinate "pin point": nice and simple.

    This type is another effort (see our graphics) to start making
    small, re-usable label components that can actually be used to build
    production grade UIs...

    '''
    def __init__(
        self,
        view: pg.ViewBox,
        fmt_str: str,
        color: str = 'default_light',
        x_offset: float = 0,
        font_size: str = 'small',
        opacity: float = 1,
        fields: dict = {},
        parent: pg.GraphicsObject = None,
        update_on_range_change: bool = True,
    ) -> None:

        vb = self.vb = view
        self._fmt_str = fmt_str
        self._view_xy = QPointF(0, 0)

        self.scene_anchor: Optional[Callable[..., QPointF]] = None

        self._x_offset = x_offset

        txt = self.txt = QtWidgets.QGraphicsTextItem(parent=parent)
        txt.setCacheMode(QtWidgets.QGraphicsItem.DeviceCoordinateCache)

        vb.scene().addItem(txt)

        # configure font size based on DPI
        dpi_font = DpiAwareFont(font_size=font_size, )
        dpi_font.configure_to_dpi()
        txt.setFont(dpi_font.font)
        txt.setOpacity(opacity)

        # register viewbox callbacks
        if update_on_range_change:
            vb.sigRangeChanged.connect(self.on_sigrange_change)

        self._hcolor: str = ''
        self.color = color

        self.fields = fields
        self.orient_v = 'bottom'

        self._anchor_func = self.txt.pos().x

        # not sure if this makes a diff
        self.txt.setCacheMode(QtWidgets.QGraphicsItem.DeviceCoordinateCache)

        # TODO: edit and selection support
        # https://doc.qt.io/qt-5/qt.html#TextInteractionFlag-enum
        # self.setTextInteractionFlags(QtGui.Qt.TextEditorInteraction)

    @property
    def color(self) -> str:
        return self._hcolor

    @color.setter
    def color(self, color: str) -> None:
        self.txt.setDefaultTextColor(pg.mkColor(hcolor(color)))
        self._hcolor = color

    def update(self) -> None:
        '''
        Update this label either by invoking its user defined anchoring
        function, or by positioning to the last recorded data view
        coordinates.

        '''
        # move label in scene coords to desired position
        anchor = self.scene_anchor
        if anchor:
            self.txt.setPos(anchor())

        else:
            # position based on last computed view coordinate
            self.set_view_pos(self._view_xy.y())

    def on_sigrange_change(self, vr, r) -> None:
        return self.update()

    @property
    def w(self) -> float:
        return self.txt.boundingRect().width()

    def scene_br(self) -> QRectF:
        txt = self.txt
        return txt.mapToScene(txt.boundingRect()).boundingRect()

    @property
    def h(self) -> float:
        return self.txt.boundingRect().height()

    def vbr(self) -> QRectF:
        return self.vb.boundingRect()

    def set_x_anchor_func(
        self,
        func: Callable,
    ) -> None:
        assert isinstance(func(), float)
        self._anchor_func = func

    def set_view_pos(
        self,
        y: float,
        x: Optional[float] = None,
    ) -> None:

        if x is None:
            scene_x = self._anchor_func() or self.txt.pos().x()
            x = self.vb.mapToView(QPointF(scene_x, scene_x)).x()

        # get new (inside the) view coordinates / position
        self._view_xy = QPointF(x, y)

        # map back to the outer UI-land "scene" coordinates
        s_xy = self.vb.mapFromView(self._view_xy)

        if self.orient_v == 'top':
            s_xy = QPointF(s_xy.x(), s_xy.y() - self.h)

        # move label in scene coords to desired position
        self.txt.setPos(s_xy)

        assert s_xy == self.txt.pos()

    @property
    def fmt_str(self) -> str:
        return self._fmt_str

    @fmt_str.setter
    def fmt_str(self, fmt_str: str) -> None:
        self._fmt_str = fmt_str

    def format(self, **fields: dict) -> str:

        out = {}

        # this is hacky support for single depth
        # calcs of field data from field data
        # ex. to calculate a $value = price * size
        for k, v in fields.items():

            if isfunction(v):
                out[k] = v(fields)

            else:
                out[k] = v

        text = self._fmt_str.format(**out)

        # for large numbers with a thousands place
        text = text.replace(',', ' ')

        self.txt.setPlainText(text)

    def render(self) -> None:
        self.format(**self.fields)

    def show(self) -> None:
        self.txt.show()
        self.txt.update()

    def hide(self) -> None:
        self.txt.hide()

    def delete(self) -> None:
        self.vb.scene().removeItem(self.txt)
 def setPoints(self, points):
     self.points = points
     rect = QRectF(QPointF(*points[0]), QPointF(*points[1]))
     self.setRect(rect)
Exemplo n.º 44
0
_OFFSET1 = _BASE_WIDTH / 4
_DEFAULT_RECT = QRectF(0, 0, _BW, _BW)
_B_PEN = QPen(styles.BLUE_STROKE, styles.INSERTWIDTH)
_R_PEN = QPen(styles.RED_STROKE, styles.SKIPWIDTH)
_NO_PEN = QPen(Qt.NoPen)


def _insertGen(path, start, c1, p1, c2):
    path.moveTo(start)
    path.quadTo(c1, p1)
    path.quadTo(c2, start)


# end def

_PATH_START = QPointF(_HBW, _HBW)
_PATH_MID_UP = QPointF(_HBW, -_BW)
_PATH_UP_UP_CTRL_PT = QPointF(-_HBW, -_BW)
_PATH_UP_DOWN_CTRL_PT = QPointF(1.5 * _BW, -_BW)
_PATH_MID_DOWN = QPointF(_HBW, 2 * _BW)
_PATH_DOWN_DOWN_CTRL_PT = QPointF(-_HBW, 2 * _BW)
_PATH_DOWN_UP_CTRL_PT = QPointF(1.5 * _BW, 2 * _BW)
_INSERT_PATH_UP = QPainterPath()
_insertGen(_INSERT_PATH_UP, _PATH_START, _PATH_UP_UP_CTRL_PT,\
         _PATH_MID_UP, _PATH_UP_DOWN_CTRL_PT)
_INSERT_PATH_UP.translate(_OFFSET1, 0)
_INSERT_PATH_UP_RECT = _INSERT_PATH_UP.boundingRect()
_INSERT_PATH_DOWN = QPainterPath()
_insertGen(_INSERT_PATH_DOWN, _PATH_START, _PATH_DOWN_DOWN_CTRL_PT,\
         _PATH_MID_DOWN, _PATH_DOWN_UP_CTRL_PT)
_INSERT_PATH_DOWN.translate(_OFFSET1, 0)
Exemplo n.º 45
0
 def screenToTileCoords(self, x, y):
     p = RenderParams(self.map())
     if (p.staggerX):
         if p.staggerEven:
             _x = p.sideOffsetX
         else:
             _x = 0
         x -= _x
     else:
         if p.staggerEven:
             _x = p.sideOffsetY
         else:
             _x = 0
         y -= _x
     # Start with the coordinates of a grid-aligned tile
     referencePoint = QPoint(math.floor(x / p.tileWidth), math.floor(y / p.tileHeight))
     # Relative x and y position on the base square of the grid-aligned tile
     rel = QPointF(x - referencePoint.x() * p.tileWidth,
                       y - referencePoint.y() * p.tileHeight)
     # Adjust the reference point to the correct tile coordinates
     if p.staggerX:
         staggerAxisIndex = referencePoint.x()
     else:
         staggerAxisIndex = referencePoint.y()
     staggerAxisIndex *= 2
     if (p.staggerEven):
         staggerAxisIndex += 1
     y_pos = rel.x() * ( p.tileHeight / p.tileWidth)
     # Check whether the cursor is in any of the corners (neighboring tiles)
     if (p.sideOffsetY - y_pos > rel.y()):
         return QPointF(self.topLeft(referencePoint.x(), referencePoint.y()))
     if (-p.sideOffsetY + y_pos > rel.y()):
         return QPointF(self.topRight(referencePoint.x(), referencePoint.y()))
     if (p.sideOffsetY + y_pos < rel.y()):
         return QPointF(self.bottomLeft(referencePoint.x(), referencePoint.y()))
     if (p.sideOffsetY * 3 - y_pos < rel.y()):
         return QPointF(self.bottomRight(referencePoint.x(), referencePoint.y()))
     return QPointF(referencePoint)
Exemplo n.º 46
0
 def onMouseMove_drag(self, imageview, event):
     imageview._deltaPan = QPointF(event.pos() - imageview._lastPanPoint)
     imageview._panning()
     imageview._lastPanPoint = event.pos()
Exemplo n.º 47
0
 def _draw_animal_direction(self, painter, animal):
     painter.setPen(QPen(QColor(0, 0, 0), 2))
     painter.drawLine(
         QPointF(animal.x, animal.y),
         QPointF(animal.x + math.cos(animal.angle) * animal.size,
                 animal.y + math.sin(animal.angle) * animal.size))
Exemplo n.º 48
0
 def mouseMoveEvent(self, event):
     if not event.buttons() & Qt.LeftButton:
         super().mouseMoveEvent(event)
         return
     contour = self._targetContour
     if contour is None:
         return
     # we don't make any check here, mousePressEvent did it for us
     pos = event.pos()
     # selected point
     pt = contour[-1]
     if not contour.open:
         pt_ = contour[0]
         if pt_.selected:
             pt = pt_
     if pt.segmentType and not self._shouldMoveOnCurve:
         # don't make a curve until enough distance is reached
         widget = self.parent()
         rect = QRectF(self._origin, event.localPos())
         widgetRect = widget.mapRectFromCanvas(rect)
         if (widgetRect.bottomRight() - widgetRect.topLeft(
                 )).manhattanLength() < 10:
             return
         # go
         onSmooth = not event.modifiers() & Qt.AltModifier
         pt.selected = False
         pt.smooth = len(contour) > 1 and onSmooth
         contour.holdNotifications()
         if pt.segmentType == "line" and onSmooth:
             self._coerceSegmentToCurve(contour, pt, pos)
         elif pt.smooth and contour.open:
             # if there's a curve segment behind, we need to update the
             # offCurve's position to inverse
             if len(contour) > 1:
                 onCurveBefore = contour[-2]
                 onCurveBefore.x = 2 * pt.x - pos.x()
                 onCurveBefore.y = 2 * pt.y - pos.y()
         if contour.open:
             contour.addPoint((pos.x(), pos.y()))
         contour[-1].selected = True
         contour.postNotification(
             notification="Contour.SelectionChanged")
         contour.releaseHeldNotifications()
     else:
         if pt.segmentType:
             onCurve = pt
         elif contour.open:
             onCurve = contour[-2]
         else:
             onCurve = contour[0]
         if event.modifiers() & Qt.ShiftModifier:
             pos = self.clampToOrigin(
                 event.localPos(), QPointF(onCurve.x, onCurve.y)).toPoint()
         if self._shouldMoveOnCurve:
             dx = pos.x() - pt.x
             dy = pos.y() - pt.y
             moveUIPoint(contour, onCurve, (dx, dy))
         else:
             pt.x = pos.x()
             pt.y = pos.y()
             if contour.open and len(contour) >= 3 and onCurve.smooth:
                 if onCurve.segmentType == "line":
                     self._coerceSegmentToCurve(contour, onCurve, pos)
                 otherSidePoint = contour[-3]
                 otherSidePoint.x = 2 * onCurve.x - pos.x()
                 otherSidePoint.y = 2 * onCurve.y - pos.y()
         contour.dirty = True
Exemplo n.º 49
0
    def __findIntersection(self, p1, p2, p3, p4):
        """
        Private method to calculate the intersection point of two lines.
        
        The first line is determined by the points p1 and p2, the second
        line by p3 and p4. If the intersection point is not contained in
        the segment p1p2, then it returns (-1.0, -1.0).
        
        For the function's internal calculations remember:<br />
        QT coordinates start with the point (0,0) as the topleft corner
        and x-values increase from left to right and y-values increase
        from top to bottom; it means the visible area is quadrant I in
        the regular XY coordinate system
        
        <pre>
            Quadrant II     |   Quadrant I
           -----------------|-----------------
            Quadrant III    |   Quadrant IV
        </pre>
        
        In order for the linear function calculations to work in this method
        we must switch x and y values (x values become y values and viceversa)
        
        @param p1 first point of first line (QPointF)
        @param p2 second point of first line (QPointF)
        @param p3 first point of second line (QPointF)
        @param p4 second point of second line (QPointF)
        @return the intersection point (QPointF)
        """
        x1 = p1.y()
        y1 = p1.x()
        x2 = p2.y()
        y2 = p2.x()
        x3 = p3.y()
        y3 = p3.x()
        x4 = p4.y()
        y4 = p4.x()

        # line 1 is the line between (x1, y1) and (x2, y2)
        # line 2 is the line between (x3, y3) and (x4, y4)
        no_line1 = True  # it is false, if line 1 is a linear function
        no_line2 = True  # it is false, if line 2 is a linear function
        slope1 = 0.0
        slope2 = 0.0
        b1 = 0.0
        b2 = 0.0

        if x2 != x1:
            slope1 = (y2 - y1) / (x2 - x1)
            b1 = y1 - slope1 * x1
            no_line1 = False
        if x4 != x3:
            slope2 = (y4 - y3) / (x4 - x3)
            b2 = y3 - slope2 * x3
            no_line2 = False

        pt = QPointF()
        # if either line is not a function
        if no_line1 and no_line2:
            # if the lines are not the same one
            if x1 != x3:
                return QPointF(-1.0, -1.0)
            # if the lines are the same ones
            if y3 <= y4:
                if y3 <= y1 and y1 <= y4:
                    return QPointF(y1, x1)
                else:
                    return QPointF(y2, x2)
            else:
                if y4 <= y1 and y1 <= y3:
                    return QPointF(y1, x1)
                else:
                    return QPointF(y2, x2)
        elif no_line1:
            pt.setX(slope2 * x1 + b2)
            pt.setY(x1)
            if y1 >= y2:
                if not (y2 <= pt.x() and pt.x() <= y1):
                    pt.setX(-1.0)
                    pt.setY(-1.0)
            else:
                if not (y1 <= pt.x() and pt.x() <= y2):
                    pt.setX(-1.0)
                    pt.setY(-1.0)
            return pt
        elif no_line2:
            pt.setX(slope1 * x3 + b1)
            pt.setY(x3)
            if y3 >= y4:
                if not (y4 <= pt.x() and pt.x() <= y3):
                    pt.setX(-1.0)
                    pt.setY(-1.0)
            else:
                if not (y3 <= pt.x() and pt.x() <= y4):
                    pt.setX(-1.0)
                    pt.setY(-1.0)
            return pt

        if slope1 == slope2:
            pt.setX(-1.0)
            pt.setY(-1.0)
            return pt

        pt.setY((b2 - b1) / (slope1 - slope2))
        pt.setX(slope1 * pt.y() + b1)
        # the intersection point must be inside the segment (x1, y1) (x2, y2)
        if x2 >= x1 and y2 >= y1:
            if not ((x1 <= pt.y() and pt.y() <= x2) and
                    (y1 <= pt.x() and pt.x() <= y2)):
                pt.setX(-1.0)
                pt.setY(-1.0)
        elif x2 < x1 and y2 >= y1:
            if not ((x2 <= pt.y() and pt.y() <= x1) and
                    (y1 <= pt.x() and pt.x() <= y2)):
                pt.setX(-1.0)
                pt.setY(-1.0)
        elif x2 >= x1 and y2 < y1:
            if not ((x1 <= pt.y() and pt.y() <= x2) and
                    (y2 <= pt.x() and pt.x() <= y1)):
                pt.setX(-1.0)
                pt.setY(-1.0)
        else:
            if not ((x2 <= pt.y() and pt.y() <= x1) and
                    (y2 <= pt.x() and pt.x() <= y1)):
                pt.setX(-1.0)
                pt.setY(-1.0)

        return pt
Exemplo n.º 50
0
    def drawPitchScale(self, painter, area, intrusion, drawNumbersLeft,
                       drawNumbersRight):
        unused(intrusion)
        # The area should be quadratic but if not width is the major size.
        w = area.width()
        if w < area.height():
            w = area.height()

        pen = QPen()
        pen.setWidthF(self.lineWidth)
        pen.setColor(Qt.white)
        painter.setPen(pen)

        savedTransform = painter.transform()

        # find the mark nearest center
        snap = qRound(
            self.pitch /
            self.PITCH_SCALE_RESOLUTION) * self.PITCH_SCALE_RESOLUTION
        _min = snap - self.PITCH_SCALE_HALFRANGE
        _max = snap + self.PITCH_SCALE_HALFRANGE
        degrees = _min
        while degrees <= _max:
            isMajor = degrees % (self.PITCH_SCALE_RESOLUTION * 2) == 0
            linewidth = self.PITCH_SCALE_MINORWIDTH
            if isMajor:
                linewidth = self.PITCH_SCALE_MAJORWIDTH
            if abs(degrees) > self.PITCH_SCALE_WIDTHREDUCTION_FROM:
                # we want: 1 at PITCH_SCALE_WIDTHREDUCTION_FROM and PITCH_SCALE_WIDTHREDUCTION at 90.
                # That is PITCH_SCALE_WIDTHREDUCTION + (1-PITCH_SCALE_WIDTHREDUCTION) * f(pitch)
                # where f(90)=0 and f(PITCH_SCALE_WIDTHREDUCTION_FROM)=1
                # f(p) = (90-p) * 1/(90-PITCH_SCALE_WIDTHREDUCTION_FROM)
                # or PITCH_SCALE_WIDTHREDUCTION + f(pitch) - f(pitch) * PITCH_SCALE_WIDTHREDUCTION
                # or PITCH_SCALE_WIDTHREDUCTION (1-f(pitch)) + f(pitch)
                fromVertical = -90 - self.pitch
                if self.pitch >= 0:
                    fromVertical = 90 - self.pitch
                if fromVertical < 0:
                    fromVertical = -fromVertical
                temp = fromVertical * 1 / (
                    90.0 - self.PITCH_SCALE_WIDTHREDUCTION_FROM)
                linewidth *= (self.PITCH_SCALE_WIDTHREDUCTION * (1 - temp) +
                              temp)
            shift = self.pitchAngleToTranslation(w, self.pitch - degrees)

            # TODO: Intrusion detection and evasion. That is, don't draw
            # where the compass has intruded.
            painter.translate(0, shift)
            start = QPointF(-linewidth * w, 0)
            end = QPointF(linewidth * w, 0)
            painter.drawLine(start, end)

            if isMajor and (drawNumbersLeft or drawNumbersRight):
                displayDegrees = degrees
                if displayDegrees > 90:
                    displayDegrees = 180 - displayDegrees
                elif displayDegrees < -90:
                    displayDegrees = -180 - displayDegrees
                if self.SHOW_ZERO_ON_SCALES or degrees:
                    if drawNumbersLeft:
                        self.drawTextRightCenter(
                            painter, '{0}'.format(displayDegrees),
                            self.mediumTextSize,
                            -self.PITCH_SCALE_MAJORWIDTH * w - 10, 0)
                    if drawNumbersRight:
                        self.drawTextLeftCenter(
                            painter, '{0}'.format(displayDegrees),
                            self.mediumTextSize,
                            self.PITCH_SCALE_MAJORWIDTH * w + 10, 0)

            painter.setTransform(savedTransform)
            degrees += self.PITCH_SCALE_RESOLUTION
Exemplo n.º 51
0
    def createGraphics(self):
        """ Create the graphical representation of the FMU's inputs and outputs """
        def variableColor(variable):
            if variable.type == 'Real':
                return QColor.fromRgb(0, 0, 127)
            elif variable.type in ['Integer', 'Enumeration']:
                return QColor.fromRgb(255, 127, 0)
            elif variable.type == 'Boolean':
                return QColor.fromRgb(255, 0, 255)
            elif variable.type == 'String':
                return QColor.fromRgb(0, 128, 0)
            else:
                return QColor.fromRgb(0, 0, 0)

        inputVariables = []
        outputVariables = []
        maxInputLabelWidth = 0
        maxOutputLabelWidth = 0

        textItem = QGraphicsTextItem()
        fontMetrics = QFontMetricsF(textItem.font())

        for variable in self.modelDescription.modelVariables:
            if variable.causality == 'input':
                inputVariables.append(variable)
            elif variable.causality == 'output':
                outputVariables.append(variable)

        for variable in inputVariables:
            maxInputLabelWidth = max(maxInputLabelWidth,
                                     fontMetrics.width(variable.name))

        for variable in outputVariables:
            maxOutputLabelWidth = max(maxOutputLabelWidth,
                                      fontMetrics.width(variable.name))

        from math import floor

        scene = QGraphicsScene()
        self.ui.graphicsView.setScene(scene)
        group = QGraphicsItemGroup()
        scene.addItem(group)
        group.setPos(200.5, -50.5)
        lh = 15  # line height

        w = max(150., maxInputLabelWidth + maxOutputLabelWidth + 20)
        h = max(50., 10 + lh * max(len(inputVariables), len(outputVariables)))

        block = QGraphicsRectItem(0, 0, w, h, group)
        block.setPen(QColor.fromRgb(0, 0, 255))

        pen = QPen()
        pen.setWidthF(1)

        font = QFont()
        font.setPixelSize(10)

        # inputs
        y = floor((h - len(inputVariables) * lh) / 2 - 2)
        for variable in inputVariables:
            text = QGraphicsTextItem(variable.name, group)
            text.setDefaultTextColor(QColor.fromRgb(0, 0, 255))
            text.setFont(font)
            text.setX(3)
            text.setY(y)

            polygon = QPolygonF([
                QPointF(-13.5, y + 4),
                QPointF(1, y + 11),
                QPointF(-13.5, y + 18)
            ])

            path = QPainterPath()
            path.addPolygon(polygon)
            path.closeSubpath()
            contour = QGraphicsPathItem(path, group)
            contour.setPen(QPen(Qt.NoPen))
            contour.setBrush(variableColor(variable))

            y += lh

        # outputs
        y = floor((h - len(outputVariables) * lh) / 2 - 2)
        for variable in outputVariables:
            text = QGraphicsTextItem(variable.name, group)
            text.setDefaultTextColor(QColor.fromRgb(0, 0, 255))
            text.setFont(font)
            text.setX(w - 3 - text.boundingRect().width())
            text.setY(y)

            polygon = QPolygonF([
                QPointF(w, y + 0 + 7.5),
                QPointF(w + 7, y + 3.5 + 7.5),
                QPointF(w, y + 7 + 7.5)
            ])

            path = QPainterPath()
            path.addPolygon(polygon)
            path.closeSubpath()
            contour = QGraphicsPathItem(path, group)
            pen = QPen()
            pen.setColor(variableColor(variable))
            pen.setJoinStyle(Qt.MiterJoin)
            contour.setPen(pen)

            y += lh
Exemplo n.º 52
0
 def paint(self, painter, option, widget):
     painter.setPen(Qt.white)
     painter.drawEllipse(QPointF(0.0, 0.0), 5.0, 5.0)
Exemplo n.º 53
0
 def nodePos(self, idx):
     return QPointF(self.m_nodePositions[idx])
Exemplo n.º 54
0
 def update_polygon(self):
     angle = self.line().angle() * math.pi / 180
     dx = self.selection_offset * math.sin(angle)
     dy = self.selection_offset * math.cos(angle)
     offset1 = QPointF(dx, dy)
     offset2 = QPointF(-dx, -dy)
     if self.head is None and self.tail is None:
         self.selection_polygon = QPolygonF([
             self.line().p1() + offset1,
             self.line().p1() + offset2,
             self.line().p2() + offset2,
             self.line().p2() + offset1
         ])
     elif self.tail is None:
         head_angle = self.head.angle() * math.pi / 180
         head_dx = self.selection_offset * math.sin(head_angle)
         head_dy = self.selection_offset * math.cos(head_angle)
         head_offset1 = QPointF(head_dx, head_dy)
         head_offset2 = QPointF(-head_dx, -head_dy)
         self.selection_polygon = QPolygonF([
             self.line().p1() + offset1,
             self.head.p1() + head_offset1,
             self.head.p1() + head_offset2,
             self.line().p1() + offset2,
             self.line().p2() + offset2,
             self.line().p2() + offset1
         ])
     elif self.head is None:
         tail_angle = self.tail.angle() * math.pi / 180
         tail_dx = self.selection_offset * math.sin(tail_angle)
         tail_dy = self.selection_offset * math.cos(tail_angle)
         tail_offset1 = QPointF(tail_dx, tail_dy)
         tail_offset2 = QPointF(-tail_dx, -tail_dy)
         self.selection_polygon = QPolygonF([
             self.line().p1() + offset1,
             self.line().p1() + offset2,
             self.line().p2() + offset2,
             self.tail.p2() + tail_offset2,
             self.tail.p2() + tail_offset1,
             self.line().p2() + offset1
         ])
     else:
         head_angle = self.head.angle() * math.pi / 180
         head_dx = self.selection_offset * math.sin(head_angle)
         head_dy = self.selection_offset * math.cos(head_angle)
         head_offset1 = QPointF(head_dx, head_dy)
         head_offset2 = QPointF(-head_dx, -head_dy)
         tail_angle = self.tail.angle() * math.pi / 180
         tail_dx = self.selection_offset * math.sin(tail_angle)
         tail_dy = self.selection_offset * math.cos(tail_angle)
         tail_offset1 = QPointF(tail_dx, tail_dy)
         tail_offset2 = QPointF(-tail_dx, -tail_dy)
         self.selection_polygon = QPolygonF([
             self.line().p1() + offset1,
             self.head.p1() + head_offset1,
             self.head.p1() + head_offset2,
             self.line().p1() + offset2,
             self.line().p2() + offset2,
             self.tail.p2() + tail_offset2,
             self.tail.p2() + tail_offset1,
             self.line().p2() + offset1
         ])
Exemplo n.º 55
0
    def drawAIAirframeFixedFeatures(self, painter, area):
        '''
        red line from -7/10 to -5/10 half-width
        red line from 7/10 to 5/10 half-width
        red slanted line from -2/10 half-width to 0
        red slanted line from 2/10 half-width to 0
        red arrow thing under roll scale
        prepareTransform(painter, width, height);
        '''
        painter.resetTransform()
        painter.translate(area.center())

        w = area.width()
        h = area.height()

        pen = QPen()
        pen.setWidthF(self.lineWidth * 1.5)
        pen.setColor(QColor(255, 0, 0))
        painter.setPen(pen)

        length = 0.15
        side = 0.5
        # The 2 lines at sides.
        painter.drawLine(QPointF(-side * w, 0),
                         QPointF(-(side - length) * w, 0))
        painter.drawLine(QPointF(side * w, 0), QPointF((side - length) * w, 0))

        pen.setColor(QColor(255, 255, 255))
        painter.setPen(pen)
        v = abs(self.__getAdditionalParameter('voltage'))
        a = abs(self.__getAdditionalParameter('current'))
        # Power usage
        self.drawTextLeftCenter(painter, '{:.1f}V'.format(v),
                                self.smallTestSize, -side * w * 0.9,
                                side * w / 4)
        self.drawTextLeftCenter(painter, '{:.1f}A'.format(a),
                                self.smallTestSize, -side * w * 0.9,
                                side * w / 4 + self.mediumTextSize * 1.1)
        # GPS groundspeed / IAS
        spd = ''
        if self.isGPSSpeedPrimary:
            # TODO add option to hide air speed when there is no air speed sensor
            spd = 'IAS ---' if self.primarySpeed == self.UNKNOWN_SPEED else 'IAS {:.1f}'.format(
                self.primarySpeed)
        else:
            spd = 'GS ---' if self.groundspeed == self.UNKNOWN_SPEED else 'GS {:.1f}'.format(
                self.groundspeed)
        self.drawTextLeftCenter(painter, spd, self.smallTestSize,
                                -side * w * 0.9,
                                side * w / 4 + self.mediumTextSize * 3.3)
        # Number of GPS satellites
        s = self.__getAdditionalParameter('gps_satellite')
        s = 0 if s == 255 else s
        self.drawTextRightCenter(painter, '{} {}'.format(chr(0x1F6F0), s),
                                 self.smallTestSize, side * w * 0.9,
                                 side * w / 4)
        # RC receiver RSSI
        s = self.__getAdditionalParameter('rc_rssi')
        s = 0 if s == 255 else s
        s /= 254.0
        self.drawTextRightCenter(painter,
                                 '{} {}'.format(chr(0x1F4F6), int(s * 100.0)),
                                 self.smallTestSize, side * w * 0.9,
                                 side * w / 4 + self.smallTestSize * 1.5)

        pen.setColor(QColor(255, 0, 0))
        painter.setPen(pen)
        rel = length / math.sqrt(2)
        # The gull
        painter.drawLine(QPointF(rel * w, rel * w / 2), QPoint(0, 0))
        painter.drawLine(QPointF(-rel * w, rel * w / 2), QPoint(0, 0))

        # The roll scale marker.
        markerPath = QPainterPath(QPointF(0, -w * self.ROLL_SCALE_RADIUS + 1))
        markerPath.lineTo(
            -h * self.ROLL_SCALE_MARKERWIDTH / 2,
            -w * (self.ROLL_SCALE_RADIUS - self.ROLL_SCALE_MARKERHEIGHT) + 1)
        markerPath.lineTo(
            h * self.ROLL_SCALE_MARKERWIDTH / 2,
            -w * (self.ROLL_SCALE_RADIUS - self.ROLL_SCALE_MARKERHEIGHT) + 1)
        markerPath.closeSubpath()
        painter.drawPath(markerPath)
Exemplo n.º 56
0
 def mapToViewport(self, pos):
     return QPointF(pos.x(), pos.y())
Exemplo n.º 57
0
 def setNodePos(self, idx, pos):
     self.m_nodePositions[idx] = QPointF(pos)
Exemplo n.º 58
0
    def drawAIGlobalFeatures(self, painter, mainArea, paintArea):
        painter.resetTransform()
        painter.translate(mainArea.center())

        pitchPixels = self.pitchAngleToTranslation(mainArea.height(),
                                                   self.pitch)
        gradientEnd = self.pitchAngleToTranslation(mainArea.height(), 60)

        if math.isnan(self.roll) == False:  # check for NaN
            painter.rotate(-self.roll)
        painter.translate(0, pitchPixels)

        # Calculate the radius of area we need to paint to cover all.
        rtx = painter.transform().inverted()[0]

        topLeft = rtx.map(paintArea.topLeft())
        topRight = rtx.map(paintArea.topRight())
        bottomLeft = rtx.map(paintArea.bottomLeft())
        bottomRight = rtx.map(paintArea.bottomRight())
        # Just KISS... make a rectangluar basis.
        minx = self.min4(topLeft.x(), topRight.x(), bottomLeft.x(),
                         bottomRight.x())
        maxx = self.max4(topLeft.x(), topRight.x(), bottomLeft.x(),
                         bottomRight.x())
        miny = self.min4(topLeft.y(), topRight.y(), bottomLeft.y(),
                         bottomRight.y())
        maxy = self.max4(topLeft.y(), topRight.y(), bottomLeft.y(),
                         bottomRight.y())

        hzonLeft = QPoint(minx, 0)
        hzonRight = QPoint(maxx, 0)

        skyPath = QPainterPath(hzonLeft)
        skyPath.lineTo(QPointF(minx, miny))
        skyPath.lineTo(QPointF(maxx, miny))
        skyPath.lineTo(hzonRight)
        skyPath.closeSubpath()

        # TODO: The gradient is wrong now.
        skyGradient = QLinearGradient(0, -gradientEnd, 0, 0)
        skyGradient.setColorAt(0, QColor.fromHsvF(0.6, 1.0, 0.7))
        skyGradient.setColorAt(1, QColor.fromHsvF(0.6, 0.25, 0.9))
        skyBrush = QBrush(skyGradient)
        painter.fillPath(skyPath, skyBrush)

        groundPath = QPainterPath(hzonRight)
        groundPath.lineTo(maxx, maxy)
        groundPath.lineTo(minx, maxy)
        groundPath.lineTo(hzonLeft)
        groundPath.closeSubpath()

        groundGradient = QLinearGradient(0, gradientEnd, 0, 0)
        groundGradient.setColorAt(0, QColor.fromHsvF(0.25, 1, 0.5))
        groundGradient.setColorAt(1, QColor.fromHsvF(0.25, 0.25, 0.5))
        groundBrush = QBrush(groundGradient)
        painter.fillPath(groundPath, groundBrush)

        pen = QPen()
        pen.setWidthF(self.lineWidth)
        pen.setColor(QColor(0, 255, 0))
        painter.setPen(pen)

        start = QPointF(-mainArea.width(), 0)
        end = QPoint(mainArea.width(), 0)
        painter.drawLine(start, end)
    def mouseMoveEvent(self, event):
        mouseMovePos = event.scenePos()
        if self.mouseIsPressed:
            if self.mousePressArea == 'topRect':
                self._rect.setTop(self.rectPress.y() -
                                  (self.mousePressPos.y() - mouseMovePos.y()))
            elif self.mousePressArea == 'bottomRect':
                self._rect.setBottom(self.rectPress.bottom() -
                                     (self.mousePressPos.y() -
                                      mouseMovePos.y()))
            elif self.mousePressArea == 'leftRect':
                self._rect.setLeft(self.rectPress.left() -
                                   (self.mousePressPos.x() - mouseMovePos.x()))
            elif self.mousePressArea == 'rightRect':
                self._rect.setRight(self.rectPress.right() -
                                    (self.mousePressPos.x() -
                                     mouseMovePos.x()))
            elif self.mousePressArea == 'topleftRect':
                self._rect.setTopLeft(self.rectPress.topLeft() -
                                      (self.mousePressPos - mouseMovePos))
            elif self.mousePressArea == 'toprightRect':
                self._rect.setTopRight(self.rectPress.topRight() -
                                       (self.mousePressPos - mouseMovePos))
            elif self.mousePressArea == 'bottomleftRect':
                self._rect.setBottomLeft(self.rectPress.bottomLeft() -
                                         (self.mousePressPos - mouseMovePos))
            elif self.mousePressArea == 'bottomrightRect':
                self._rect.setBottomRight(self.rectPress.bottomRight() -
                                          (self.mousePressPos - mouseMovePos))
            elif self.mousePressArea == 'topRotation':
                rectCenter = self._rect.center()
                pressedPos = self.mousePressPos
                #mouseMovePos
                A = (pressedPos - rectCenter)
                B = (mouseMovePos - rectCenter)
                pro = A.x() * B.x() + A.y() * B.y()
                theta = np.arctan2(A.x() * B.y() - A.y() * B.x(), pro)
                #theta = self.rotationAngle+theta
                self._rect.moveCenter(QPointF(0, 0))
                #
                self.setAngle(theta)
                pos = self.rectPress.center()
                rad = self.rotationAngle
                self._rect.moveCenter(
                    QPointF(pos.x() * np.cos(rad) - np.sin(rad) * pos.y(),
                            pos.x() * np.sin(rad) + np.cos(rad) * pos.y()))
                #print("RotationBegginn")
            else:
                #pos = self.mousePressPos - mouseMovePos
                pos = self.rectPress.center() - (self.mousePressPos -
                                                 mouseMovePos)
                rad = -1 * self.rotationAngle
                deltaPos = (self.mousePressPos - mouseMovePos)
                self._rect.moveCenter(
                    QPointF(
                        self.rectPress.center().x() -
                        (np.cos(rad) * deltaPos.x() -
                         np.sin(rad) * deltaPos.y()),
                        self.rectPress.center().y() -
                        (np.sin(rad) * deltaPos.x() +
                         np.cos(rad) * deltaPos.y())))

        self.updateResizeHandles()
        self.prepareGeometryChange()
Exemplo n.º 60
0
def main():
    import sys

    app = QApplication(sys.argv)

    series0 = QLineSeries()
    series1 = QLineSeries()

    series0 << QPointF(1, 5) << QPointF(3, 7) << QPointF(7, 6) << QPointF(
        9, 7) << QPointF(12, 6) << QPointF(16, 7) << QPointF(18, 5)
    series1 << QPointF(1, 3) << QPointF(3, 4) << QPointF(7, 3) << QPointF(
        8, 2) << QPointF(12, 3) << QPointF(16, 4) << QPointF(18, 3)

    series = QAreaSeries(series0, series1)
    series.setName("Batman")
    pen = QPen(0x059605)
    pen.setWidth(3)
    series.setPen(pen)

    gradient = QLinearGradient(QPointF(0, 0), QPointF(0, 1))
    gradient.setColorAt(0.0, QColor(0x3CC63C))
    gradient.setColorAt(1.0, QColor(0x26F626))
    gradient.setCoordinateMode(QGradient.ObjectBoundingMode)
    series.setBrush(gradient)

    chart = QChart()
    chart.addSeries(series)
    chart.setTitle("Simple areachart example")
    chart.createDefaultAxes()
    chart.axes(Qt.Horizontal)[0].setRange(0, 20)
    chart.axes(Qt.Vertical)[0].setRange(0, 10)

    chartView = QChartView(chart)
    chartView.setRenderHint(QPainter.Antialiasing)

    window = QMainWindow()
    window.setCentralWidget(chartView)
    window.resize(400, 300)
    window.show()

    sys.exit(app.exec_())