class InteractiveItem(QGraphicsRectItem): def __init__(self, *arg, **karg): QGraphicsRectItem.__init__(self, *arg, **karg) self.node = None self.label = None self.setCursor(QtCore.Qt.PointingHandCursor) self.setAcceptsHoverEvents(True) def hoverEnterEvent(self, e): # There are many ways of adding interactive elements. With the # following code, I show/hide a text item over my custom # DynamicItemFace if not self.label: self.label = QGraphicsRectItem() self.label.setParentItem(self) # This is to ensure that the label is rendered over the # rest of item children (default ZValue for items is 0) self.label.setZValue(1) self.label.setBrush(QBrush(QColor("white"))) self.label.text = QGraphicsSimpleTextItem() self.label.text.setParentItem(self.label) self.label.text.setText(self.node.name) self.label.setRect(self.label.text.boundingRect()) self.label.setVisible(True) def hoverLeaveEvent(self, e): if self.label: self.label.setVisible(False)
class InteractiveLetterItem(QGraphicsRectItem): """This is a class""" def __init__(self, *arg, **karg): QGraphicsRectItem.__init__(self, *arg, **karg) self.codon = None self.label = None self.setAcceptsHoverEvents(True) def hoverEnterEvent(self, e): """ when mouse is over""" if not self.label: self.label = QGraphicsRectItem(parent=self) #self.label.setY(-18) self.label.setX(11) self.label.setBrush(QBrush(QColor("white"))) self.label.text = QGraphicsSimpleTextItem(parent=self.label) self.setZValue(1) self.label.text.setText(self.codon) self.label.setRect(self.label.text.boundingRect()) self.label.setVisible(True) def hoverLeaveEvent(self, e): """when mouse leaves area""" if self.label: self.label.setVisible(False) self.setZValue(0)
class InteractiveLetterItem(QGraphicsRectItem): """This is a class""" def __init__(self, *arg, **karg): QGraphicsRectItem.__init__(self, *arg, **karg) self.codon = None self.label = None self.setAcceptsHoverEvents(True) def hoverEnterEvent (self, e): """ when mouse is over""" if not self.label: self.label = QGraphicsRectItem(parent=self) #self.label.setY(-18) self.label.setX(11) self.label.setBrush(QBrush(QColor("white"))) self.label.text = QGraphicsSimpleTextItem(parent=self.label) self.setZValue(1) self.label.text.setText(self.codon) self.label.setRect(self.label.text.boundingRect()) self.label.setVisible(True) def hoverLeaveEvent(self, e): """when mouse leaves area""" if self.label: self.label.setVisible(False) self.setZValue(0)
class InteractiveItem(QGraphicsRectItem): def __init__(self, *arg, **karg): QGraphicsRectItem.__init__(self, *arg, **karg) self.node = None self.label = None self.setCursor(QtCore.Qt.PointingHandCursor) self.setAcceptsHoverEvents(True) def hoverEnterEvent (self, e): # There are many ways of adding interactive elements. With the # following code, I show/hide a text item over my custom # DynamicItemFace if not self.label: self.label = QGraphicsRectItem() self.label.setParentItem(self) # This is to ensure that the label is rendered over the # rest of item children (default ZValue for items is 0) self.label.setZValue(1) self.label.setBrush(QBrush(QColor("white"))) self.label.text = QGraphicsSimpleTextItem() self.label.text.setParentItem(self.label) self.label.text.setText(self.node.name) self.label.setRect(self.label.text.boundingRect()) self.label.setVisible(True) def hoverLeaveEvent(self, e): if self.label: self.label.setVisible(False)
class Meterbar(Button): def __init__(self, max=255, filename=None, width=None, height=None, x=0, y=0, pixmap=None, group=None, pos=None, size=None, padding=None): Button.__init__(self, filename, width, height, x, y, pixmap, group, pos, size, padding) self.max = max self.outer = QGraphicsRectItem(x,y,width,max + 2) self.outer.setPen(QPen(QColor(Qt.black), 1, Qt.SolidLine)) self.outer.setBrush(Qt.green) # self.outer.hide() self.inner = QGraphicsRectItem(x + 1,y + 1,width - 2,max) self.inner.setPen(QPen(QColor(Qt.green), 1, Qt.SolidLine)) self.inner.setBrush(Qt.blue) self.items = [self.outer, self.inner] self.current = 255 self.effect = QGraphicsDropShadowEffect() self.effect.setOffset(0, 0) self.effect.setBlurRadius(0) self.effect.setColor(Qt.green) self.item = self.outer self.addEffect('shadow', self.effect, True) self.addAnimation('glow', Glow(15, 300, self, maxRadius=80, minRadius=5)) # self.test(10) def test(self, x): self.tl = QTimeLine(10000) self.tl.setFrameRange(0, 10000) self.a = QGraphicsItemAnimation() self.a.setItem(self.inner) self.a.setTimeLine(self.tl) # self.a.setPosAt(0, QPointF(self.getX(), self.current)) # self.a.setTranslationAt(1, self.getX(), self.getY() + self.max - x + 1) self.a.setScaleAt(0, 1, 1) self.a.setScaleAt(1, 1, 0.1) self.current = x self.tl.start() def update(self, x): x2 = 1 - (float(x) * 1.0 / float(self.max)) # print x # return self.tl = QTimeLine(10) self.tl.setFrameRange(0, 10) self.a = QGraphicsItemAnimation() self.a.setItem(self.inner) self.a.setTimeLine(self.tl) # self.a.setPosAt(0, QPointF(self.getX(), self.current)) # self.a.setTranslationAt(1, self.getX(), self.getY() + self.max - x + 1) self.a.setScaleAt(0, 1, self.current) self.a.setScaleAt(1, 1, x2) self.current = x self.tl.start() if x > 3 : self.play('glow') def setScene(self, scene): self.scene = scene for item in self.items : self.scene.addItem(item)
class RectangleCurve(OWCurve): """ A plot item that shows a rectangle. This class accepts the same options as :obj:`.PolygonCurve`. The rectangle is calculated as the smallest rectangle that contains all points in ``xData`` and ``yData``. """ def __init__(self, pen = QPen(Qt.black), brush = QBrush(Qt.white), xData = None, yData = None, tooltip = None): OWCurve.__init__(self, xData, yData, tooltip=tooltip) self.set_pen(pen) self.set_brush(brush) self._item = QGraphicsRectItem(self) def update_properties(self): self._item.setRect(self.graph_transform().mapRect(self.data_rect())) self._item.setPen(self.pen()) self._item.setBrush(self.brush())
class GraphicsScene(QGraphicsScene): selectionRectPointChanged = Signal(QPointF) def __init__(self, *args): QGraphicsScene.__init__(self, *args) self.selectionRect = None def mousePressEvent(self, event): QGraphicsScene.mousePressEvent(self, event) def mouseMoveEvent(self, event): if event.buttons() & Qt.LeftButton: screenPos = event.screenPos() buttonDown = event.buttonDownScreenPos(Qt.LeftButton) if (screenPos - buttonDown).manhattanLength() > 2.0: self.updateSelectionRect(event) QGraphicsScene.mouseMoveEvent(self, event) def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton: if self.selectionRect: self.removeItem(self.selectionRect) self.selectionRect = None QGraphicsScene.mouseReleaseEvent(self, event) def updateSelectionRect(self, event): pos = event.scenePos() buttonDownPos = event.buttonDownScenePos(Qt.LeftButton) rect = QRectF(pos, buttonDownPos).normalized() rect = rect.intersected(self.sceneRect()) if not self.selectionRect: self.selectionRect = QGraphicsRectItem() self.selectionRect.setBrush(QColor(10, 10, 10, 20)) self.selectionRect.setPen(QPen(QColor(200, 200, 200, 200))) self.addItem(self.selectionRect) self.selectionRect.setRect(rect) if event.modifiers() & Qt.ControlModifier or \ event.modifiers() & Qt.ShiftModifier: path = self.selectionArea() else: path = QPainterPath() path.addRect(rect) self.setSelectionArea(path) self.selectionRectPointChanged.emit(pos)
def ugly_name_face(node, *args, **kargs): """ This is my item generator. It must receive a node object, and returns a Qt4 graphics item that can be used as a node face. """ width = node.dist * 2.5 height = 12 masterItem = InteractiveItem(0, 0, width, height) masterItem.node = node masterItem.setPen(QPen(QtCore.Qt.NoPen)) color_rect = QGraphicsRectItem(masterItem.rect()) color_rect.setParentItem(masterItem) color_rect.setBrush(QBrush(QColor(100, 100, 200, 100))) color_rect.setPen(QPen(QtCore.Qt.NoPen)) masterItem.color_rect = color_rect return masterItem
def render_drop_shadow_frame(pixmap, shadow_rect, shadow_color, offset, radius, rect_fill_color): pixmap.fill(QColor(0, 0, 0, 0)) scene = QGraphicsScene() rect = QGraphicsRectItem(shadow_rect) rect.setBrush(QColor(rect_fill_color)) rect.setPen(QPen(Qt.NoPen)) scene.addItem(rect) effect = QGraphicsDropShadowEffect(color=shadow_color, blurRadius=radius, offset=offset) rect.setGraphicsEffect(effect) scene.setSceneRect(QRectF(QPointF(0, 0), QSizeF(pixmap.size()))) painter = QPainter(pixmap) scene.render(painter) painter.end() scene.clear() scene.deleteLater() return pixmap
class RectangleCurve(OWCurve): """ A plot item that shows a rectangle. This class accepts the same options as :obj:`.PolygonCurve`. The rectangle is calculated as the smallest rectangle that contains all points in ``xData`` and ``yData``. """ def __init__(self, pen=QPen(Qt.black), brush=QBrush(Qt.white), xData=None, yData=None, tooltip=None): OWCurve.__init__(self, xData, yData, tooltip=tooltip) self.set_pen(pen) self.set_brush(brush) self._item = QGraphicsRectItem(self) def update_properties(self): self._item.setRect(self.graph_transform().mapRect(self.data_rect())) self._item.setPen(self.pen()) self._item.setBrush(self.brush())
def setTiles(self): #background brush = QBrush() pix = QPixmap(os.getcwd() + "/robotImages/tile.png") brush.setTexture(pix) brush.setStyle(24) self.setBackgroundBrush(brush) #wall #left left = QGraphicsRectItem() pix = QPixmap(os.getcwd() + "/robotImages/tileVert.png") left.setRect(QtCore.QRectF(0, 0, pix.width(), self.height)) brush.setTexture(pix) brush.setStyle(24) left.setBrush(brush) left.name = 'left' self.addItem(left) #right right = QGraphicsRectItem() right.setRect(self.width - pix.width(), 0, pix.width(), self.height) right.setBrush(brush) right.name = 'right' self.addItem(right) #top top = QGraphicsRectItem() pix = QPixmap(os.getcwd() + "/robotImages/tileHori.png") top.setRect(QtCore.QRectF(0, 0, self.width, pix.height())) brush.setTexture(pix) brush.setStyle(24) top.setBrush(brush) top.name = 'top' self.addItem(top) #bottom bottom = QGraphicsRectItem() bottom.setRect(0, self.height - pix.height(), self.width, pix.height()) bottom.setBrush(brush) bottom.name = 'bottom' self.addItem(bottom)
def drawHistogram(self): if self.result is None: return # Label the histogram #self.minValueLabel.setText(str(self.minValue)) #self.maxValueLabel.setText(str(self.maxValue)) minvaltext = QGraphicsTextItem(str(self.minValue)) minvaltextheight = minvaltext.boundingRect().height() maxvaltext = QGraphicsTextItem(str(self.maxValue)) maxvaltextwidth = maxvaltext.boundingRect().width() #self.showInfo(str(self.result)) # Check which element should be used for the histogram element = 1 maxvalue = 0.0 for i in range(len(self.result)): if self.result[i][element] > maxvalue: maxvalue = self.result[i][element] # Find the maximum value for scaling cutoffvalue = maxvalue if (self.frequencyRangeSpinBox.value() > 0): cutoffvalue = self.frequencyRangeSpinBox.value() #self.maxNumberLabel.setText(str(maxvalue)) #self.maxNumberLabel.setText(str(cutoffvalue)) self.scene.clear() if maxvalue == 0: return viewprect = QRectF(self.histogramGraphicsView.viewport().rect()) self.histogramGraphicsView.setSceneRect(viewprect) bottom = self.histogramGraphicsView.sceneRect().bottom() top = self.histogramGraphicsView.sceneRect().top() left = self.histogramGraphicsView.sceneRect().left() right = self.histogramGraphicsView.sceneRect().right() height = bottom - top - 1 width = right - left - 1 padding = 3 toppadding = 3 bottompadding = minvaltextheight # Determine the width of the left margin (depends on the y range) clog = log(cutoffvalue,10) clogint = int(clog) #clogrem = clog % clogint yincr = pow(10,clogint) dummytext = QGraphicsTextItem(str(yincr)) # The left padding must accomodate the y labels leftpadding = dummytext.boundingRect().width() #leftpadding = 30 # Find the width of the maximium frequency label maxfreqtext = QGraphicsTextItem(str(cutoffvalue)) maxfreqtextwidth = maxvaltext.boundingRect().width() rightpadding = maxfreqtextwidth width = width - (leftpadding + rightpadding) height = height - (toppadding + bottompadding) barwidth = width / self.bins #center = QPoint(left + width / 2.0, top + height / 2.0) #start = QPointF(self.histogramGraphicsView.mapToScene(center)) # Create the histogram for i in range(self.bins): #barheight = height * self.result[i][element] / maxvalue barheight = height * self.result[i][element] / cutoffvalue barrect = QGraphicsRectItem(QRectF(leftpadding + barwidth * i, height-barheight+toppadding, barwidth, barheight)) barbrush = QBrush(QColor(255,153,102)) barrect.setBrush(barbrush) self.scene.addItem(barrect) # Determine the increments for the horizontal lines if (cutoffvalue // yincr <= 5 and yincr > 1 ): yincr = yincr / 2 if (cutoffvalue // yincr < 5 and yincr > 10 ): yincr = yincr / 2 # Draw horizontal lines with labels yval = 0 while (yval <= cutoffvalue): scval = height + toppadding - yval * height / cutoffvalue hline = QGraphicsLineItem(QLineF(leftpadding-2, scval,width+(leftpadding),scval)) hlinepen = QPen(QColor(153,153,153)) hline.setPen(hlinepen) self.scene.addItem(hline) ylabtext = QGraphicsTextItem(str(int(yval))) ylabtextheight = ylabtext.boundingRect().height() ylabtextwidth = ylabtext.boundingRect().width() ylabtext.setPos(leftpadding - ylabtextwidth, scval - ylabtextheight/2) if (scval - ylabtextheight/2 > 0): self.scene.addItem(ylabtext) yval = yval + yincr #yincr = (cutoffvalue / 10) minvaltextwidth = minvaltext.boundingRect().width() minvaltext.setPos(leftpadding - minvaltextwidth/2, height + toppadding + bottompadding - minvaltextheight) self.scene.addItem(minvaltext) maxvaltext.setPos(leftpadding + width - maxvaltextwidth/2, height + toppadding + bottompadding - minvaltextheight) self.scene.addItem(maxvaltext) maxfreqtext.setPos(leftpadding + width, 0) self.scene.addItem(maxfreqtext)
class RepeatLegendItem(QGraphicsRectItem): Type = 70000 + 7 def __init__(self, color, parent=None): super(RepeatLegendItem, self).__init__(parent) # NOTE: need this distinction for cache mode based on # the Qt version otherwise rendering is broken if NO_ITEM_CACHING: self.setCacheMode(QGraphicsItem.NoCache) else: self.setCacheMode(QGraphicsItem.DeviceCoordinateCache) self.setZValue(1) self.setFlag(QGraphicsItem.ItemIsMovable) self._position = self.pos() self.penColor = color self.itemHeight = 20 self.itemWidth = 40 self._pen = QPen() self._pen.setWidthF(3.0) self._pen.setColor(self.penColor) self.setPen(self._pen) self.setRect(0, 0, self.itemWidth, self.itemHeight) self.setAcceptsHoverEvents(True) self._outline = None @property def height(self): return self.itemHeight @property def width(self): return self.itemWidth @property def color(self): return self.penColor @color.setter def color(self, newColor): self.penColor = newColor self._pen.setColor(self.penColor) self.setPen(self._pen) def hoverEnterEvent(self, event): """ Stuff related to hover enter events. For now we just show a rectangular outline. """ if not self._outline: self._outline = QGraphicsRectItem(\ self.boundingRect().adjusted(-1,-1,1,1), self) highlightColor = QColor(Qt.blue) highlightColor.setAlpha(30) self._outline.setBrush(highlightColor) highlightPen = QPen(Qt.blue) highlightPen.setWidth(2) self._outline.setPen(highlightPen) else: self._outline.show() def hoverLeaveEvent(self, event): """ Stuff related to hover leave events. For now we just show a rectangular outline. """ self._outline.hide() def mousePressEvent(self, event): """ We reimplement this function to store the position of the item when a user issues a mouse press. """ self._position = self.pos() if (event.modifiers() & Qt.ControlModifier): QApplication.setOverrideCursor(QCursor(Qt.SizeAllCursor)) else: event.ignore() return QGraphicsRectItem.mousePressEvent(self, event) def mouseReleaseEvent(self, event): """ We reimplement this function to check if its position has changed since the last mouse click. If yes we let the canvas know so it can store the action as a Redo/Undo event. """ QApplication.restoreOverrideCursor() # this is needed for undo/redo if self._position != self.pos(): self.scene().canvas_item_position_changed(self, self._position, self.pos()) return QGraphicsRectItem.mouseReleaseEvent(self, event)
class OWLegendGradient(QGraphicsObject): gradient_width = 20 def __init__(self, palette, values, parent): QGraphicsObject.__init__(self, parent) self.parent = parent self.palette = palette self.values = values self.legend = parent self.label_items = [QGraphicsTextItem(text, self) for text in values] for i in self.label_items: i.setTextWidth(50) self.rect = QRectF() self.gradient_item = QGraphicsRectItem(self) self.gradient = QLinearGradient() self.gradient.setStops([(v*0.1, self.palette[v*0.1]) for v in range(11) ]) self.orientation = Qt.Horizontal self.set_orientation(Qt.Vertical) def set_orientation(self, orientation): if self.orientation == orientation: return self.orientation = orientation if self.orientation == Qt.Vertical: height = max([item.boundingRect().height() for item in self.label_items]) total_height = height * max(5, len(self.label_items)) interval = (total_height - self.label_items[-1].boundingRect().height()) / (len(self.label_items) -1) self.gradient_item.setRect(10, 0, self.gradient_width, total_height) self.gradient.setStart(10, 0) self.gradient.setFinalStop(10, total_height) self.gradient_item.setBrush(QBrush(self.gradient)) self.gradient_item.setPen(QPen(Qt.NoPen)) y = 0 x = 30 for item in self.label_items: move_item_xy(item, x, y, self.parent.graph.animate_plot) y += interval self.rect = QRectF(10, 0, self.gradient_width + max([item.boundingRect().width() for item in self.label_items]), self.label_items[0].boundingRect().height() * max(5, len(self.label_items))) else: width = 50 height = max([item.boundingRect().height() for item in self.label_items]) total_width = width * max(5, len(self.label_items)) interval = (total_width - self.label_items[-1].boundingRect().width()) / (len(self.label_items) -1) self.gradient_item.setRect(0, 0, total_width, self.gradient_width) self.gradient.setStart(0, 0) self.gradient.setFinalStop(total_width, 0) self.gradient_item.setBrush(QBrush(self.gradient)) self.gradient_item.setPen(QPen(Qt.NoPen)) x = 0 y = 30 for item in self.label_items: move_item_xy(item, x, y, self.parent.graph.animate_plot) x += interval self.rect = QRectF(0, 0, total_width, self.gradient_width + height) def boundingRect(self): return getattr(self, 'rect', QRectF()) def paint(self, painter, option, widget): pass
class RepeatLegendItem(QGraphicsRectItem): Type = 70000 + 7 def __init__(self, color, parent = None): super(RepeatLegendItem, self).__init__(parent) # NOTE: need this distinction for cache mode based on # the Qt version otherwise rendering is broken if NO_ITEM_CACHING: self.setCacheMode(QGraphicsItem.NoCache) else: self.setCacheMode(QGraphicsItem.DeviceCoordinateCache) self.setZValue(1) self.setFlag(QGraphicsItem.ItemIsMovable) self._position = self.pos() self.penColor = color self.itemHeight = 20 self.itemWidth = 40 self._pen = QPen() self._pen.setWidthF(3.0) self._pen.setColor(self.penColor) self.setPen(self._pen) self.setRect(0, 0, self.itemWidth, self.itemHeight) self.setAcceptsHoverEvents(True) self._outline = None @property def height(self): return self.itemHeight @property def width(self): return self.itemWidth @property def color(self): return self.penColor @color.setter def color(self, newColor): self.penColor = newColor self._pen.setColor(self.penColor) self.setPen(self._pen) def hoverEnterEvent(self, event): """ Stuff related to hover enter events. For now we just show a rectangular outline. """ if not self._outline: self._outline = QGraphicsRectItem(\ self.boundingRect().adjusted(-1,-1,1,1), self) highlightColor = QColor(Qt.blue) highlightColor.setAlpha(30) self._outline.setBrush(highlightColor) highlightPen = QPen(Qt.blue) highlightPen.setWidth(2) self._outline.setPen(highlightPen) else: self._outline.show() def hoverLeaveEvent(self, event): """ Stuff related to hover leave events. For now we just show a rectangular outline. """ self._outline.hide() def mousePressEvent(self, event): """ We reimplement this function to store the position of the item when a user issues a mouse press. """ self._position = self.pos() if (event.modifiers() & Qt.ControlModifier): QApplication.setOverrideCursor(QCursor(Qt.SizeAllCursor)) else: event.ignore() return QGraphicsRectItem.mousePressEvent(self, event) def mouseReleaseEvent(self, event): """ We reimplement this function to check if its position has changed since the last mouse click. If yes we let the canvas know so it can store the action as a Redo/Undo event. """ QApplication.restoreOverrideCursor() # this is needed for undo/redo if self._position != self.pos(): self.scene().canvas_item_position_changed(self, self._position, self.pos()) return QGraphicsRectItem.mouseReleaseEvent(self, event)
class PatternLegendText(QGraphicsTextItem): Type = 70000 + 3 def __init__(self, text, parent = None): super(PatternLegendText, self).__init__(text, parent) # NOTE: need this distinction for cache mode based on # the Qt version otherwise rendering is broken if NO_ITEM_CACHING: self.setCacheMode(QGraphicsItem.NoCache) else: self.setCacheMode(QGraphicsItem.DeviceCoordinateCache) self.setZValue(1) self.setFlag(QGraphicsItem.ItemIsMovable) self.setTextInteractionFlags(Qt.TextEditorInteraction) self._position = self.pos() self._outline = None def hoverEnterEvent(self, event): """ Stuff related to hover enter events. For now we just show a rectangular outline. """ if not self._outline: self._outline = QGraphicsRectItem(self.boundingRect(), self) highlightColor = QColor(Qt.blue) highlightColor.setAlpha(30) self._outline.setBrush(highlightColor) highlightPen = QPen(Qt.blue) highlightPen.setWidth(2) self._outline.setPen(highlightPen) else: self._outline.show() def hoverLeaveEvent(self, event): """ Stuff related to hover leave events. For now we just show a rectangular outline. """ self._outline.hide() def keyPressEvent(self, event): """ Stuff to do during key press events. For now we have to adjust the outline box. """ QGraphicsTextItem.keyPressEvent(self, event) self.adjust_size() def adjust_size(self): """ This function takes care of changing the size of the outline rectangle, e.g., when text is added or removed or during font size changes. """ if self._outline: self._outline.setRect(self.boundingRect()) def mousePressEvent(self, event): """ We reimplement this function to store the position of the item when a user issues a mouse press. """ self._position = self.pos() if (event.modifiers() & Qt.ControlModifier): QApplication.setOverrideCursor(QCursor(Qt.SizeAllCursor)) self.setTextInteractionFlags(Qt.NoTextInteraction) return QGraphicsTextItem.mousePressEvent(self, event) def mouseReleaseEvent(self, event): """ We reimplement this function to check if its position has changed since the last mouse click. If yes we let the canvas know so it can store the action as a Redo/Undo event. """ self.setTextInteractionFlags(Qt.TextEditorInteraction) QApplication.restoreOverrideCursor() # this is needed for undo/redo if self._position != self.pos(): self.scene().canvas_item_position_changed(self, self._position, self.pos()) return QGraphicsTextItem.mouseReleaseEvent(self, event)
class PatternLegendItem(QGraphicsSvgItem): Type = 70000 + 2 def __init__(self, unitDim, width, height, defaultSymbol, defaultColor = QColor(Qt.white), zValue = 1, parent = None): super(PatternLegendItem, self).__init__(parent) # NOTE: need this distinction for cache mode based on # the Qt version otherwise rendering is broken if NO_ITEM_CACHING: self.setCacheMode(QGraphicsItem.NoCache) else: self.setCacheMode(QGraphicsItem.DeviceCoordinateCache) self.setZValue(zValue) self.setFlag(QGraphicsItem.ItemIsMovable, True) self.origin = QPointF(0.0, 0.0) self.unitDim = unitDim self.width = width self.height = height self.size = QSizeF(self.unitDim.width() * width, self.unitDim.height() * height) self.color = defaultColor self.symbol = None self._set_symbol(defaultSymbol) self._penSize = 1.0 self._pen = QPen() self._pen.setWidthF(self._penSize) self._pen.setJoinStyle(Qt.MiterJoin) self._pen.setColor(Qt.black) self.setAcceptsHoverEvents(True) self._outline = None def hoverEnterEvent(self, event): """ Stuff related to hover enter events. For now we just show a rectangular outline. """ if not self._outline: self._outline = QGraphicsRectItem(\ self.boundingRect().adjusted(-1,-1,1,1), self) highlightColor = QColor(Qt.blue) highlightColor.setAlpha(30) self._outline.setBrush(highlightColor) highlightPen = QPen(Qt.blue) highlightPen.setWidth(2) self._outline.setPen(highlightPen) else: self._outline.show() def hoverLeaveEvent(self, event): """ Stuff related to hover leave events. For now we just show a rectangular outline. """ self._outline.hide() def mousePressEvent(self, event): """ We reimplement this function to store the position of the item when a user issues a mouse press. """ self._position = self.pos() if (event.modifiers() & Qt.ControlModifier): QApplication.setOverrideCursor(QCursor(Qt.SizeAllCursor)) else: event.ignore() return QGraphicsSvgItem.mousePressEvent(self, event) def mouseReleaseEvent(self, event): """ We reimplement this function to check if its position has changed since the last mouse click. If yes we let the canvas know so it can store the action as a Redo/Undo event. """ QApplication.restoreOverrideCursor() # this is needed for redo/undo if self._position != self.pos(): self.scene().canvas_item_position_changed(self, self._position, self.pos()) return QGraphicsSvgItem.mouseReleaseEvent(self, event) def change_geometry(self, newDim): """ This slot changes the unit dimensions of the item. """ self.unitDim = newDim self.size = QSizeF(self.unitDim.width() * self.width, self.unitDim.height() * self.height) @property def name(self): """ Return the name of the knitting symbol we contain. """ return self.symbol["name"] def _set_symbol(self, newSymbol): """ Adds a new svg image of a knitting symbol to the scene. """ self.symbol = newSymbol svgPath = newSymbol["svgPath"] if not self.renderer().load(svgPath): errorMessage = ("PatternLegendItem._set_symbol: failed to load " "symbol %s" % svgPath) logger.error(errorMessage) return # apply color if present if "backgroundColor" in newSymbol: self.color = QColor(newSymbol["backgroundColor"]) def boundingRect(self): """ Return the bounding rectangle of the item. """ halfPen = self._penSize * 0.5 return QRectF(self.origin, self.size).adjusted(halfPen, halfPen, halfPen, halfPen) def paint(self, painter, option, widget): """ Paint ourselves. """ painter.setPen(self._pen) brush = QBrush(self.color) painter.setBrush(brush) halfPen = self._penSize * 0.5 painter.drawRect(\ QRectF(self.origin, self.size).adjusted(halfPen, halfPen, halfPen, halfPen)) self.renderer().render(painter, QRectF(self.origin, self.size))
def draw_colored_boxes(self, h): stick_colors = self.colors num_col_red = stick_colors.count("red") num_col_orange = stick_colors.count("orange") num_col_yellow = stick_colors.count("#EFDB00") num_col_gray = stick_colors.count("gray") colored_box_h = self.height + h - 5 if num_col_red: rect_red = QGraphicsRectItem(self.col_w * 0 - 1, self.coordY(self.ylim[1]) - 5, self.col_w * num_col_red, colored_box_h) qpen = QPen(QColor('red')) qpen.setWidth(1) qpen.setStyle( 5) # dash line : http://doc.qt.io/qt-4.8/qt.html#PenStyle-enum rect_red.setPen(qpen) rect_red.setBrush(QColor("#FFD1D1")) rect_red.setZValue(-1) rect_red.setParentItem(self.item) #rect_red.setOpacity(0.5) if num_col_orange: rect_orange = QGraphicsRectItem(self.col_w * num_col_red + 1, self.coordY(self.ylim[1]) - 5, self.col_w * num_col_orange - 2, colored_box_h) qpen = QPen(QColor('orange')) qpen.setWidth(1) qpen.setStyle( 5) # dash line : http://doc.qt.io/qt-4.8/qt.html#PenStyle-enum rect_orange.setPen(qpen) rect_orange.setBrush(QColor("#FFE3B0")) rect_orange.setZValue(-1) rect_orange.setParentItem(self.item) #rect_orange.setOpacity(0.5) if num_col_yellow: rect_yellow = QGraphicsRectItem( self.col_w * (num_col_orange + num_col_red) + 1, self.coordY(self.ylim[1]) - 5, self.col_w * num_col_yellow - 2, colored_box_h) qpen = QPen(QColor('#EFDB00')) qpen.setWidth(1) qpen.setStyle( 5) # dash line : http://doc.qt.io/qt-4.8/qt.html#PenStyle-enum rect_yellow.setPen(qpen) rect_yellow.setBrush(QColor("#FBFFA5")) rect_yellow.setZValue(-1) rect_yellow.setParentItem(self.item) #rect_yellow.setOpacity(0.5) if num_col_gray: rect_gray = QGraphicsRectItem( self.col_w * (num_col_orange + num_col_red + num_col_yellow) + 1, self.coordY(self.ylim[1]) - 5, self.col_w * num_col_gray, colored_box_h) qpen = QPen(QColor('gray')) qpen.setWidth(1) qpen.setStyle( 5) # dash line : http://doc.qt.io/qt-4.8/qt.html#PenStyle-enum rect_gray.setPen(qpen) rect_gray.setBrush(QColor("#E2E2E2")) rect_gray.setZValue(-1) rect_gray.setParentItem(self.item)
def draw_fun(self, x, y, val, col_width=10, col_height=10, color="gray"): color = get_corr_color(val) rect = QGraphicsRectItem(x, y, col_width, col_height, parent=self.item) rect.setPen(QPen(QColor('black'))) rect.setBrush(QColor(color))
class GradientLegendItem(QGraphicsObject, GraphicsWidgetAnchor): gradient_width = 20 def __init__(self, title, palette, values, parent): QGraphicsObject.__init__(self, parent) GraphicsWidgetAnchor.__init__(self) self.parent = self.legend = parent self.palette = palette self.values = values self.title = QGraphicsTextItem('%s:' % title, self) f = self.title.font() f.setBold(True) self.title.setFont(f) self.title_item = QGraphicsRectItem(self.title.boundingRect(), self) self.title_item.setPen(QPen(Qt.NoPen)) self.title_item.stackBefore(self.title) self.label_items = [QGraphicsTextItem(text, self) for text in values] for i in self.label_items: i.setTextWidth(50) self.rect = QRectF() self.gradient_item = QGraphicsRectItem(self) self.gradient = QLinearGradient() self.gradient.setStops([(v * 0.1, self.palette[v * 0.1]) for v in range(11)]) self.orientation = Qt.Horizontal self.set_orientation(Qt.Vertical) self.setFlag(QGraphicsItem.ItemIgnoresTransformations, True) self.setFlag(QGraphicsItem.ItemIsMovable, True) def set_orientation(self, orientation): return if self.orientation == orientation: return self.orientation = orientation if self.orientation == Qt.Vertical: height = max(item.boundingRect().height() for item in self.label_items) total_height = height * max(5, len(self.label_items)) interval = (total_height - self.label_items[-1].boundingRect().height() ) / (len(self.label_items) - 1) self.gradient_item.setRect(10, 0, self.gradient_width, total_height) self.gradient.setStart(10, 0) self.gradient.setFinalStop(10, total_height) self.gradient_item.setBrush(QBrush(self.gradient)) self.gradient_item.setPen(QPen(Qt.NoPen)) y = -20 # hja, no; dela --> pri boundingRect() zato pristejem +20 x = 0 move_item_xy(self.title, x, y, False) y = 10 x = 30 for item in self.label_items: move_item_xy(item, x, y, False) # self.parent.graph.animate_plot) y += interval self.rect = QRectF(10, 0, self.gradient_width + max(item.boundingRect().width() for item in self.label_items), self.label_items[0].boundingRect().height() * max(5, len(self.label_items))) else: # za horizontalno orientacijo nisem dodajal title-a width = 50 height = max(item.boundingRect().height() for item in self.label_items) total_width = width * max(5, len(self.label_items)) interval = (total_width - self.label_items[-1].boundingRect().width() ) / (len(self.label_items) - 1) self.gradient_item.setRect(0, 0, total_width, self.gradient_width) self.gradient.setStart(0, 0) self.gradient.setFinalStop(total_width, 0) self.gradient_item.setBrush(QBrush(self.gradient)) self.gradient_item.setPen(QPen(Qt.NoPen)) x = 0 y = 30 for item in self.label_items: move_item_xy(item, x, y, False) # self.parent.graph.animate_plot) x += interval self.rect = QRectF(0, 0, total_width, self.gradient_width + height) # noinspection PyPep8Naming def boundingRect(self): width = max(self.rect.width(), self.title_item.boundingRect().width()) height = self.rect.height() + self.title_item.boundingRect().height() return QRectF(self.rect.left(), self.rect.top(), width, height) def paint(self, painter, option, widget): pass
class OWLegendGradient(QGraphicsObject): gradient_width = 20 def __init__(self, palette, values, parent): QGraphicsObject.__init__(self, parent) self.parent = parent self.palette = palette self.values = values self.legend = parent self.label_items = [QGraphicsTextItem(text, self) for text in values] for i in self.label_items: i.setTextWidth(50) self.rect = QRectF() self.gradient_item = QGraphicsRectItem(self) self.gradient = QLinearGradient() self.gradient.setStops([(v * 0.1, self.palette[v * 0.1]) for v in range(11)]) self.orientation = Qt.Horizontal self.set_orientation(Qt.Vertical) def set_orientation(self, orientation): if self.orientation == orientation: return self.orientation = orientation if self.orientation == Qt.Vertical: height = max( [item.boundingRect().height() for item in self.label_items]) total_height = height * max(5, len(self.label_items)) interval = (total_height - self.label_items[-1].boundingRect().height()) / ( len(self.label_items) - 1) self.gradient_item.setRect(10, 0, self.gradient_width, total_height) self.gradient.setStart(10, 0) self.gradient.setFinalStop(10, total_height) self.gradient_item.setBrush(QBrush(self.gradient)) self.gradient_item.setPen(QPen(Qt.NoPen)) y = 0 x = 30 for item in self.label_items: move_item_xy(item, x, y, self.parent.graph.animate_plot) y += interval self.rect = QRectF( 10, 0, self.gradient_width + max([item.boundingRect().width() for item in self.label_items]), self.label_items[0].boundingRect().height() * max(5, len(self.label_items))) else: width = 50 height = max( [item.boundingRect().height() for item in self.label_items]) total_width = width * max(5, len(self.label_items)) interval = (total_width - self.label_items[-1].boundingRect().width()) / ( len(self.label_items) - 1) self.gradient_item.setRect(0, 0, total_width, self.gradient_width) self.gradient.setStart(0, 0) self.gradient.setFinalStop(total_width, 0) self.gradient_item.setBrush(QBrush(self.gradient)) self.gradient_item.setPen(QPen(Qt.NoPen)) x = 0 y = 30 for item in self.label_items: move_item_xy(item, x, y, self.parent.graph.animate_plot) x += interval self.rect = QRectF(0, 0, total_width, self.gradient_width + height) def boundingRect(self): return getattr(self, 'rect', QRectF()) def paint(self, painter, option, widget): pass
class PatternLegendText(QGraphicsTextItem): Type = 70000 + 3 def __init__(self, text, itemID=0, parent=None): super(PatternLegendText, self).__init__(text, parent) # NOTE: need this distinction for cache mode based on # the Qt version otherwise rendering is broken if NO_ITEM_CACHING: self.setCacheMode(QGraphicsItem.NoCache) else: self.setCacheMode(QGraphicsItem.DeviceCoordinateCache) self.itemID = itemID self.setZValue(1) self.setFlag(QGraphicsItem.ItemIsMovable) self.setTextInteractionFlags(Qt.TextEditorInteraction) self._position = self.pos() self._outline = None def hoverEnterEvent(self, event): """ Stuff related to hover enter events. For now we just show a rectangular outline. """ if not self._outline: self._outline = QGraphicsRectItem(self.boundingRect(), self) highlightColor = QColor(Qt.blue) highlightColor.setAlpha(30) self._outline.setBrush(highlightColor) highlightPen = QPen(Qt.blue) highlightPen.setWidth(2) self._outline.setPen(highlightPen) else: self._outline.show() def hoverLeaveEvent(self, event): """ Stuff related to hover leave events. For now we just show a rectangular outline. """ self._outline.hide() def keyPressEvent(self, event): """ Stuff to do during key press events. For now we have to adjust the outline box. """ QGraphicsTextItem.keyPressEvent(self, event) self.adjust_size() def adjust_size(self): """ This function takes care of changing the size of the outline rectangle, e.g., when text is added or removed or during font size changes. """ if self._outline: self._outline.setRect(self.boundingRect()) def mousePressEvent(self, event): """ We reimplement this function to store the position of the item when a user issues a mouse press. """ self._position = self.pos() if (event.modifiers() & Qt.ControlModifier): QApplication.setOverrideCursor(QCursor(Qt.SizeAllCursor)) self.setTextInteractionFlags(Qt.NoTextInteraction) return QGraphicsTextItem.mousePressEvent(self, event) def mouseReleaseEvent(self, event): """ We reimplement this function to check if its position has changed since the last mouse click. If yes we let the canvas know so it can store the action as a Redo/Undo event. """ self.setTextInteractionFlags(Qt.TextEditorInteraction) QApplication.restoreOverrideCursor() # this is needed for undo/redo if self._position != self.pos(): self.scene().canvas_item_position_changed(self, self._position, self.pos()) return QGraphicsTextItem.mouseReleaseEvent(self, event)
class RectangleSelectionAction(UserInteraction): """ Select items in the scene using a Rectangle selection """ def __init__(self, document, *args, **kwargs): UserInteraction.__init__(self, document, *args, **kwargs) # The initial selection at drag start self.initial_selection = None # Selection when last updated in a mouseMoveEvent self.last_selection = None # A selection rect (`QRectF`) self.selection_rect = None # Keyboard modifiers self.modifiers = 0 def mousePressEvent(self, event): pos = event.scenePos() any_item = self.scene.item_at(pos) if not any_item and event.button() & Qt.LeftButton: self.modifiers = event.modifiers() self.selection_rect = QRectF(pos, QSizeF(0, 0)) self.rect_item = QGraphicsRectItem( self.selection_rect.normalized()) self.rect_item.setPen( QPen(QBrush(QColor(51, 153, 255, 192)), 0.4, Qt.SolidLine, Qt.RoundCap)) self.rect_item.setBrush(QBrush(QColor(168, 202, 236, 192))) self.rect_item.setZValue(-100) # Clear the focus if necessary. if not self.scene.stickyFocus(): self.scene.clearFocus() if not self.modifiers & Qt.ControlModifier: self.scene.clearSelection() event.accept() return True else: self.cancel(self.ErrorReason) return False def mouseMoveEvent(self, event): if not self.rect_item.scene(): # Add the rect item to the scene when the mouse moves. self.scene.addItem(self.rect_item) self.update_selection(event) return True def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton: if self.initial_selection is None: # A single click. self.scene.clearSelection() else: self.update_selection(event) self.end() return True def update_selection(self, event): """ Update the selection rectangle from a QGraphicsSceneMouseEvent `event` instance. """ if self.initial_selection is None: self.initial_selection = set(self.scene.selectedItems()) self.last_selection = self.initial_selection pos = event.scenePos() self.selection_rect = QRectF(self.selection_rect.topLeft(), pos) # Make sure the rect_item does not cause the scene rect to grow. rect = self._bound_selection_rect(self.selection_rect.normalized()) # Need that 0.5 constant otherwise the sceneRect will still # grow (anti-aliasing correction by QGraphicsScene?) pw = self.rect_item.pen().width() + 0.5 self.rect_item.setRect(rect.adjusted(pw, pw, -pw, -pw)) selected = self.scene.items(self.selection_rect.normalized(), Qt.IntersectsItemShape, Qt.AscendingOrder) selected = set([item for item in selected if \ item.flags() & Qt.ItemIsSelectable]) if self.modifiers & Qt.ControlModifier: for item in selected | self.last_selection | \ self.initial_selection: item.setSelected((item in selected) ^ (item in self.initial_selection)) else: for item in selected.union(self.last_selection): item.setSelected(item in selected) self.last_selection = set(self.scene.selectedItems()) def end(self): self.initial_selection = None self.last_selection = None self.modifiers = 0 self.rect_item.hide() if self.rect_item.scene() is not None: self.scene.removeItem(self.rect_item) UserInteraction.end(self) def viewport_rect(self): """ Return the bounding rect of the document's viewport on the scene. """ view = self.document.view() vsize = view.viewport().size() viewportrect = QRect(0, 0, vsize.width(), vsize.height()) return view.mapToScene(viewportrect).boundingRect() def _bound_selection_rect(self, rect): """ Bound the selection `rect` to a sensible size. """ srect = self.scene.sceneRect() vrect = self.viewport_rect() maxrect = srect.united(vrect) return rect.intersected(maxrect)
def __init__(self, world): QGraphicsPolygonItem.__init__(self) ############################# ### Build graph ############################# graph = pydot.Dot() graph.set_node_defaults(color = 'red', fontcolor = 'red', label = '\<orphan\>') graph.set('overlap', 'prism') # build adjacency graph from world for area in world.areas: # create node for each room node = pydot.Node(area.id) node.set( 'label', area.name ) if area == world.player.currentArea: node.set( 'color', 'blue' ) node.set( 'fontcolor', 'blue' ) else: node.set( 'color', 'black' ) node.set( 'fontcolor', 'black' ) graph.add_node(node) # link to adjacent rooms for feature in area.features: for action in feature.actions: finalEvent = None for event in action.events: if type(event) == events.PlayerMoveEvent: finalEvent = pydot.Edge( src=area.id, dst=event.properties['destination'] ) if finalEvent is not None: graph.add_edge( finalEvent ) ################################ ### Generate SVG from graph ################################ ps = graph.create_svg(prog='neato') ######################################### ### Build graphics items from SVG ######################################### # build xml tree ns = {'svg': 'http://www.w3.org/2000/svg'} doc = ET.fromstring(ps) # grab the root node properties rootNode = doc.xpath('/svg:svg/svg:g[1]', namespaces=ns)[0] polygon = rootNode.xpath('./svg:polygon', namespaces=ns)[0] pointStr = polygon.xpath('./@points', namespaces=ns)[0] penColor = QString(polygon.xpath('./@stroke', namespaces=ns)[0]) fillColor = QString(polygon.xpath('./@fill', namespaces=ns)[0]) # parse root polygon path path = QPolygonF() for pair in pointStr.split(' '): dims = pair.split(',') point = QPointF( float(dims[0]), float(dims[1]) ) path.append(point) self.setPolygon(path) # fill in root node colors if QColor.isValidColor(penColor): self.setPen( QColor(penColor) ) if QColor.isValidColor(fillColor): self.setBrush( QColor(fillColor) ) # build each graph node for xmlNode in rootNode.xpath('./svg:g', namespaces=ns): group = QGraphicsRectItem(self) group.setPen( Qt.transparent ) group.setBrush( Qt.transparent ) if xmlNode.attrib['class'] == 'node': # find the area object name = xmlNode.xpath('./svg:title', namespaces=ns)[0].text group.setData( 0, QString(world.areas[world.areaLookup[name]].id) ) # get the ellipse info ellipseNode = xmlNode.xpath('./svg:ellipse', namespaces=ns)[0] elProps = { k: float(ellipseNode.attrib[k]) for k in ['cx', 'cy', 'rx', 'ry']} rect = QRectF( elProps['cx']-elProps['rx'], elProps['cy']-elProps['ry'], 2*elProps['rx'], 2*elProps['ry']) penColor = QString(ellipseNode.attrib['stroke']) ellipseItem = QGraphicsEllipseItem(rect, group) if QColor.isValidColor(penColor): ellipseItem.setPen( QColor(penColor) ) # get the text info textNode = xmlNode.xpath('./svg:text', namespaces=ns)[0] text = textNode.text textItem = QGraphicsTextItem(text, group) penColor = textNode.attrib.get('fill', 'black') nodePoint = QPointF(float(textNode.attrib['x']), float(textNode.attrib['y'])) textItem.setPos( nodePoint - textItem.boundingRect().center() + QPointF(0.0,-4.0)) if QColor.isValidColor(penColor): textItem.setDefaultTextColor( QColor(penColor) ) group.setRect( ellipseItem.boundingRect() ) group.setFlags( QGraphicsRectItem.ItemIsSelectable ) elif xmlNode.attrib['class'] == 'edge': # parse the line portion of the arrow line = xmlNode.xpath('./svg:path', namespaces=ns)[0] path = QPainterPath() # pull info from xml file linePath = line.attrib['d'] lineColor = line.attrib['stroke'] # parse path coords points = re.findall( '(-?\d+\.\d+),(-?\d+\.\d+)', linePath ) if len(points) != 4: continue startPoint = QPointF( float(points[0][0]), float(points[0][1]) ) path.moveTo(startPoint) curvePoints = [] for pointCoord in points[1:]: curvePoints.append( QPointF(float(pointCoord[0]), float(pointCoord[1])) ) path.cubicTo( curvePoints[0], curvePoints[1], curvePoints[2] ) # construct path item pathItem = QGraphicsPathItem(path, group) if QColor.isValidColor(lineColor): pathItem.setPen( QColor(lineColor) ) polyNode = xmlNode.xpath('./svg:polygon', namespaces=ns)[0] # pull info from xml file pointStr = polyNode.xpath('./@points', namespaces=ns)[0] penColor = QString(polyNode.xpath('./@stroke', namespaces=ns)[0]) fillColor = QString(polyNode.xpath('./@fill', namespaces=ns)[0]) # parse polygon path path = QPolygonF() for pair in pointStr.split(' '): dims = pair.split(',') point = QPointF( float(dims[0]), float(dims[1]) ) path.append(point) # construct polygon item polygonItem = QGraphicsPolygonItem(path, group) if QColor.isValidColor(penColor): polygonItem.setPen( QColor(penColor) ) if QColor.isValidColor(fillColor): polygonItem.setBrush( QColor(fillColor) ) group.setRect( pathItem.boundingRect() and polygonItem.boundingRect() )
class RectangleSelectionAction(UserInteraction): """ Select items in the scene using a Rectangle selection """ def __init__(self, document, *args, **kwargs): UserInteraction.__init__(self, document, *args, **kwargs) # The initial selection at drag start self.initial_selection = None # Selection when last updated in a mouseMoveEvent self.last_selection = None # A selection rect (`QRectF`) self.selection_rect = None # Keyboard modifiers self.modifiers = 0 def mousePressEvent(self, event): pos = event.scenePos() any_item = self.scene.item_at(pos) if not any_item and event.button() & Qt.LeftButton: self.modifiers = event.modifiers() self.selection_rect = QRectF(pos, QSizeF(0, 0)) self.rect_item = QGraphicsRectItem( self.selection_rect.normalized() ) self.rect_item.setPen( QPen(QBrush(QColor(51, 153, 255, 192)), 0.4, Qt.SolidLine, Qt.RoundCap) ) self.rect_item.setBrush( QBrush(QColor(168, 202, 236, 192)) ) self.rect_item.setZValue(-100) # Clear the focus if necessary. if not self.scene.stickyFocus(): self.scene.clearFocus() if not self.modifiers & Qt.ControlModifier: self.scene.clearSelection() event.accept() return True else: self.cancel(self.ErrorReason) return False def mouseMoveEvent(self, event): if not self.rect_item.scene(): # Add the rect item to the scene when the mouse moves. self.scene.addItem(self.rect_item) self.update_selection(event) return True def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton: if self.initial_selection is None: # A single click. self.scene.clearSelection() else: self.update_selection(event) self.end() return True def update_selection(self, event): """ Update the selection rectangle from a QGraphicsSceneMouseEvent `event` instance. """ if self.initial_selection is None: self.initial_selection = set(self.scene.selectedItems()) self.last_selection = self.initial_selection pos = event.scenePos() self.selection_rect = QRectF(self.selection_rect.topLeft(), pos) # Make sure the rect_item does not cause the scene rect to grow. rect = self._bound_selection_rect(self.selection_rect.normalized()) # Need that 0.5 constant otherwise the sceneRect will still # grow (anti-aliasing correction by QGraphicsScene?) pw = self.rect_item.pen().width() + 0.5 self.rect_item.setRect(rect.adjusted(pw, pw, -pw, -pw)) selected = self.scene.items(self.selection_rect.normalized(), Qt.IntersectsItemShape, Qt.AscendingOrder) selected = set([item for item in selected if \ item.flags() & Qt.ItemIsSelectable]) if self.modifiers & Qt.ControlModifier: for item in selected | self.last_selection | \ self.initial_selection: item.setSelected( (item in selected) ^ (item in self.initial_selection) ) else: for item in selected.union(self.last_selection): item.setSelected(item in selected) self.last_selection = set(self.scene.selectedItems()) def end(self): self.initial_selection = None self.last_selection = None self.modifiers = 0 self.rect_item.hide() if self.rect_item.scene() is not None: self.scene.removeItem(self.rect_item) UserInteraction.end(self) def viewport_rect(self): """ Return the bounding rect of the document's viewport on the scene. """ view = self.document.view() vsize = view.viewport().size() viewportrect = QRect(0, 0, vsize.width(), vsize.height()) return view.mapToScene(viewportrect).boundingRect() def _bound_selection_rect(self, rect): """ Bound the selection `rect` to a sensible size. """ srect = self.scene.sceneRect() vrect = self.viewport_rect() maxrect = srect.united(vrect) return rect.intersected(maxrect)
class PatternLegendItem(QGraphicsSvgItem): Type = 70000 + 2 def __init__(self, unitDim, width, height, defaultSymbol, itemID=0, defaultColor=QColor(Qt.white), zValue=1, parent=None): super(PatternLegendItem, self).__init__(parent) # NOTE: need this distinction for cache mode based on # the Qt version otherwise rendering is broken if NO_ITEM_CACHING: self.setCacheMode(QGraphicsItem.NoCache) else: self.setCacheMode(QGraphicsItem.DeviceCoordinateCache) self.itemID = itemID self.setZValue(zValue) self.setFlag(QGraphicsItem.ItemIsMovable, True) self.origin = QPointF(0.0, 0.0) self.unitDim = unitDim self.width = width self.height = height self.size = QSizeF(self.unitDim.width() * width, self.unitDim.height() * height) self.color = defaultColor self.symbol = None self._set_symbol(defaultSymbol) self._penSize = 1.0 self._pen = QPen() self._pen.setWidthF(self._penSize) self._pen.setJoinStyle(Qt.MiterJoin) self._pen.setColor(Qt.black) self.setAcceptsHoverEvents(True) self._outline = None def hoverEnterEvent(self, event): """ Stuff related to hover enter events. For now we just show a rectangular outline. """ if not self._outline: self._outline = QGraphicsRectItem(\ self.boundingRect().adjusted(-1,-1,1,1), self) highlightColor = QColor(Qt.blue) highlightColor.setAlpha(30) self._outline.setBrush(highlightColor) highlightPen = QPen(Qt.blue) highlightPen.setWidth(2) self._outline.setPen(highlightPen) else: self._outline.show() def hoverLeaveEvent(self, event): """ Stuff related to hover leave events. For now we just show a rectangular outline. """ self._outline.hide() def mousePressEvent(self, event): """ We reimplement this function to store the position of the item when a user issues a mouse press. """ self._position = self.pos() if (event.modifiers() & Qt.ControlModifier): QApplication.setOverrideCursor(QCursor(Qt.SizeAllCursor)) else: event.ignore() return QGraphicsSvgItem.mousePressEvent(self, event) def mouseReleaseEvent(self, event): """ We reimplement this function to check if its position has changed since the last mouse click. If yes we let the canvas know so it can store the action as a Redo/Undo event. """ QApplication.restoreOverrideCursor() # this is needed for redo/undo if self._position != self.pos(): self.scene().canvas_item_position_changed(self, self._position, self.pos()) return QGraphicsSvgItem.mouseReleaseEvent(self, event) def change_geometry(self, newDim): """ This slot changes the unit dimensions of the item. """ self.unitDim = newDim self.size = QSizeF(self.unitDim.width() * self.width, self.unitDim.height() * self.height) @property def name(self): """ Return the name of the knitting symbol we contain. """ return self.symbol["name"] def _set_symbol(self, newSymbol): """ Adds a new svg image of a knitting symbol to the scene. """ self.symbol = newSymbol svgPath = newSymbol["svgPath"] if not self.renderer().load(svgPath): errorMessage = ("PatternLegendItem._set_symbol: failed to load " "symbol %s" % svgPath) logger.error(errorMessage) return # apply color if present if "backgroundColor" in newSymbol: self.color = QColor(newSymbol["backgroundColor"]) def boundingRect(self): """ Return the bounding rectangle of the item. """ halfPen = self._penSize * 0.5 return QRectF(self.origin, self.size).adjusted(halfPen, halfPen, halfPen, halfPen) def paint(self, painter, option, widget): """ Paint ourselves. """ painter.setPen(self._pen) brush = QBrush(self.color) painter.setBrush(brush) halfPen = self._penSize * 0.5 painter.drawRect(\ QRectF(self.origin, self.size).adjusted(halfPen, halfPen, halfPen, halfPen)) self.renderer().render(painter, QRectF(self.origin, self.size))