def bgc_name_face(node, *args, **kargs): """ This is the item generator. It must receive a node object, and returns a Qt4 graphics item that can be used as a node face. """ # Receive an arbitrary number of arguments, in this case width and # Height of the faces and the information about the BGC width = args[0] height = args[1] # Add the popup interactive_face = InteractiveItem("Class : {}\nRelated MIBiG : {}\nCluster family : {}".format(args[2], args[4], args[3]), 0, 0, width, height) # Keep a link within the item to access node info interactive_face.node = node # Remove border around the masterItem interactive_face.setPen(QPen(QtCore.Qt.NoPen)) # Add ellipse around text ellipse = QGraphicsEllipseItem(interactive_face.rect()) ellipse.setParentItem(interactive_face) # Change ellipse color ellipse.setBrush(QBrush(QColor(args[6]))) # Add node name within the ellipse text = QGraphicsTextItem(args[5]) text.setTextWidth(50) text.setParentItem(ellipse) # Center text according to masterItem size text_width = text.boundingRect().width() text_height = text.boundingRect().height() center = interactive_face.boundingRect().center() text.setPos(center.x()-text_width/2, center.y()-text_height/2) return interactive_face
def get_text_item(self): text_item = QGraphicsTextItem(self.text.text, None) text_item.setDefaultTextColor(self.text.style.colour) # QGraphicsTextItem #text_item.setPen(self.text.style.colour) # QGraphicsSimpleTextItem text_item.setFont(self.text.style.font) text_item.setPos(0,0) return text_item
def showTextLabel(self, x, y, secure=25): """ add labels of principle peaks of spectrum or chroma on the plot, return the labels, that we can show hide """ maxis=[]#will contain tuple(rt, intens) indexes=[] #from core.MetObjects import MSAbstractTypes from scipy.ndimage import gaussian_filter1d as gauss z=gauss(y, 1) #z = MSAbstractTypes.computeBaseLine(z, 92., 0.8) i=0 while i <len(z)-1: while z[i+1] >= z[i] and i < len(y)-2: i+=1 maxis.append((x[i], y[i])) indexes.append(i) while z[i+1] <= z[i] and i<len(z)-2: i+=1 i+=1 labels=[] for t in sorted(maxis, key=lambda x:x[1])[-5:]: g=QGraphicsTextItem(str(t[0])) g.setFlag(QGraphicsItem.ItemIgnoresTransformations) font=QApplication.font() font.setPointSizeF(6.5) g.setFont(font) g.setDefaultTextColor(Qt.black) g.setPos(t[0], t[1]) labels.append(g) self.pw.addItem(g) return labels
def showTextLabel(self, x, y, secure=25): """ add labels of principle peaks of spectrum or chroma on the plot, return the labels, that we can show hide """ maxis = [] #will contain tuple(rt, intens) indexes = [] #from core.MetObjects import MSAbstractTypes from scipy.ndimage import gaussian_filter1d as gauss z = gauss(y, 1) #z = MSAbstractTypes.computeBaseLine(z, 92., 0.8) i = 0 while i < len(z) - 1: while z[i + 1] >= z[i] and i < len(y) - 2: i += 1 maxis.append((x[i], y[i])) indexes.append(i) while z[i + 1] <= z[i] and i < len(z) - 2: i += 1 i += 1 labels = [] for t in sorted(maxis, key=lambda x: x[1])[-5:]: g = QGraphicsTextItem(str(t[0])) g.setFlag(QGraphicsItem.ItemIgnoresTransformations) font = QApplication.font() font.setPointSizeF(6.5) g.setFont(font) g.setDefaultTextColor(Qt.black) g.setPos(t[0], t[1]) labels.append(g) self.pw.addItem(g) return labels
def scientific_name_face(node, *args, **kwargs): scientific_name_text = QGraphicsTextItem() #underscore = node.name.replace("_", " ") words = node.name.split("_") text = [] if len(words) < 2: # some sort of acronym or bin name, leave it alone text = words elif len(words) > 2: if len(words) >= 5: text.extend( ['<b>' + words[0] + ' <i> ' + words[1], words[2] + ' </i> ']) text.extend(words[3:] + ['</b>']) elif len(words) == 3: text.extend([ ' <span style="color:grey"><i> ' + words[0], words[1] + words[2] + ' </i></span>' ]) else: # assume that everything after the # second word is strain name # which should not get italicized text.extend([ ' <span style="color:grey"><i> ' + words[0], words[1] + ' </i></span>' ]) text.extend(words[2:]) else: text.extend([ ' <span style="color:grey"><i> ' + words[0], words[1] + ' </i></span> ' ]) scientific_name_text.setHtml(' '.join(text)) # below is a bit of a hack - I've found that the height of the bounding # box gives a bit too much padding around the name, so I just minus 10 # from the height and recenter it. Don't know whether this is a generally # applicable number to use #myFont = QFont() masterItem = QGraphicsRectItem( 0, 0, scientific_name_text.boundingRect().width(), scientific_name_text.boundingRect().height() - 10) scientific_name_text.setParentItem(masterItem) center = masterItem.boundingRect().center() scientific_name_text.setPos( masterItem.boundingRect().x(), center.y() - scientific_name_text.boundingRect().height() / 2) # I don't want a border around the masterItem masterItem.setPen(QPen(QtCore.Qt.NoPen)) return masterItem
def qt_test(): """ Test that Qt actually works """ scene = QGraphicsScene() text = QGraphicsTextItem(None, scene) text.setHtml("<h2 align=\"center\">hello</h2><h2 align=\"center\">world 12334345354444444444444444444444444</h2>123"); text.setPos(QPointF(25,25)) view = QGraphicsView(scene) view.show() sys.exit(app.exec_())
class Marker(orangeqt.PlotItem): """ Displays a text marker on the plot. :param text: The text to display. It can be HTML-formatted :type tex: str :param x: The x coordinate of the marker's position :type x: float :param y: The y coordinate of the marker's position :type y: float :param align: The text alignment :type align: :param bold: If ``True``, the text will be show bold. :type bold: int :param color: The text color :type color: QColor :param brushColor: The color of the brush user to paint the background :type color: QColor :param size: Font size :type size: int Markers have the QGraphicsItem.ItemIgnoresTransformations flag set by default, so text remains the same size when zooming. There is no need to scale the manually. """ def __init__(self, text, x, y, align, bold=0, color=None, brushColor=None, size=None): orangeqt.PlotItem.__init__(self) self.setFlag(QGraphicsItem.ItemIgnoresTransformations, True) self._item = QGraphicsTextItem(text, parent=self) self._data_point = QPointF(x, y) f = self._item.font() f.setBold(bold) if size: f.setPointSize(size) self._item.setFont(f) self._item.setPos(x, y) def update_properties(self): self._item.setPos(self.graph_transform().map(self._data_point))
def annotate(self): text, bool_ = QInputDialog.getText(self.view, "Annotation dialog", "Annotation:") g=QGraphicsTextItem(str(text)) g.setFlag(QGraphicsItem.ItemIgnoresTransformations) g.setFlag(QGraphicsItem.ItemIsMovable) g.setTextInteractionFlags(Qt.TextEditorInteraction) font=qApp.instance().font() font.setPointSizeF(10.) g.setFont(font) g.setDefaultTextColor(Qt.blue) g.setPos(500,1e4) self.trashItems.append(g) self.pw.addItem(g)
def label(self): if self._label: return self._label font = QFont("Times", 30, QFont.Bold) label = QGraphicsTextItem("Part 1") label.setVisible(False) label.setFont(font) label.setParentItem(self) label.setPos(0, -40) label.setTextInteractionFlags(Qt.TextEditorInteraction) label.inputMethodEvent = None self._label = label return label
def appendOffsetItems(self, linesToAppend): count = 0 x = 0 y = 25 + (len(self.offsetItems) * (self.pageh + 2)) # print "Y append offset ", y while count <= linesToAppend: item = QGraphicsTextItem() item.setDefaultTextColor(QColor(Qt.red)) item.setFont(self.font) item.setPos(x, y) self.offsetItems.append(item) self.scene.addItem(item) y += self.pageh + 2 count += 1
def set_functions_list(self, functionsList, prefix="", sufix=""): self.funtionsList = functionsList self.funtionsListItems = [] self.maxHeight = 0 tempHeight = 0 for element in functionsList: tempElement = QGraphicsTextItem(self) tempElement.setPlainText(prefix + element + sufix) tempElement.setPos(0, tempHeight) tempHeight += tempElement.document().size().height() if self.maxWidth < tempElement.document().size().width(): self.maxWidth = tempElement.document().size().width() self.funtionsListItems.append(tempElement) self.maxHeight = tempHeight
def annotate(self): text, bool_ = QInputDialog.getText(self.view, "Annotation dialog", "Annotation:") g = QGraphicsTextItem(str(text)) g.setFlag(QGraphicsItem.ItemIgnoresTransformations) g.setFlag(QGraphicsItem.ItemIsMovable) g.setTextInteractionFlags(Qt.TextEditorInteraction) font = qApp.instance().font() font.setPointSizeF(10.) g.setFont(font) g.setDefaultTextColor(Qt.blue) g.setPos(500, 1e4) self.trashItems.append(g) self.pw.addItem(g)
def scientific_name_face(node, *args, **kwargs): scientific_name_text = QGraphicsTextItem() words = node.visual_label.split() text = [] if hasattr(node, 'bg_col'): container_div = '<div style="background-color:{};">'.format(node.bgcolor) text.append(container_div) if len(words) < 2: # some sort of acronym or bin name, leave it alone text.extend(words) elif len(words) > 2: if words[0] == 'Candidatus': # for candidatus names, only the Candidatus part is italicised # name shortening it for brevity text.append('<i>Ca.</i>') text.extend(words[1:]) elif re.match('^[A-Z]+$', words[0]): # If the first word is in all caps then it is an abreviation # so we don't want to italicize that at all text.extend(words) else: # assume that everything after the second word is strain name # which should not get italicised text.extend(['<i>'+words[0],words[1]+'</i>']) text.extend(words[2:]) else: text.extend(['<i>'+words[0],words[1]+'</i>']) if hasattr(node, 'bg_col'): text.append('</div>') scientific_name_text.setHtml(' '.join(text)) #print(scientific_name_text.boundingRect().width(), scientific_name_text.boundingRect().height()) # below is a bit of a hack - I've found that the height of the bounding # box gives a bit too much padding around the name, so I just minus 10 # from the height and recenter it. Don't know whether this is a generally # applicable number to use masterItem = QGraphicsRectItem(0, 0, scientific_name_text.boundingRect().width(), scientific_name_text.boundingRect().height() - 10) scientific_name_text.setParentItem(masterItem) center = masterItem.boundingRect().center() scientific_name_text.setPos(masterItem.boundingRect().x(), center.y() - scientific_name_text.boundingRect().height()/2) # I dont want a border around the masterItem masterItem.setPen(QPen(QtCore.Qt.NoPen)) return masterItem
def initOffsetItems(self): count = 0 x = 0 y = 25 while count <= self.displayLines: item = QGraphicsTextItem() item.setDefaultTextColor(QColor(Qt.red)) item.setFont(self.font) item.setPos(x, y) self.offsetItems.append(item) y += self.pageh + 2 count += 1 #Add Items in scene for item in self.offsetItems: self.scene.addItem(item)
def setPos(self, x, y): self.x, self.y = x, y rect = QGraphicsTextItem.boundingRect(self) if self.vertical: h, w = rect.height(), rect.width() rect.setWidth(h) rect.setHeight(-w) if int(self.alignment & Qt.AlignRight): x -= rect.width() elif int(self.alignment & Qt.AlignHCenter): x -= rect.width() / 2. if int(self.alignment & Qt.AlignBottom): y -= rect.height() elif int(self.alignment & Qt.AlignVCenter): y -= rect.height() / 2. QGraphicsTextItem.setPos(self, x, y)
class TimestampItem(QGraphicsRectItem): """ Represents a block in the diagram """ def __init__(self, parent, name='Untitled', width=180, height=40): """ Constructor """ QGraphicsRectItem.__init__(self) self.parentWidget = parent if sys.version_info > (3, ): if isinstance(name, bytes): name = str(name, "utf8", errors="ignore") self.label = QGraphicsTextItem(name, self) self.setColor(blockColor="#FFFFFF") self.changeSize(width, height) def setColor(self, blockColor): """ Set color """ color = QColor(0, 0, 0) color.setNamedColor(blockColor) self.setPen(QPen(color, 1)) self.setBrush(QBrush(color)) def changeSize(self, w, h): """ Resize block function """ # Limit the block size self.setRect(0.0, 0.0, w, h) # center label: rect = self.label.boundingRect() lw, lh = rect.width(), rect.height() lx = (w - lw) / 2 ly = (h - lh) / 2 self.label.setPos(lx, ly) return w, h
class OWLegendItem(QGraphicsObject): """ Represents a legend item with a title and a point symbol. :param name: The text to display :type name: str :param point: The point symbol :type point: :obj:`.OWPoint` :param parent: The parent item, passed to QGraphicsItem :type parent: :obj:`QGraphicsItem` .. seealso:: :meth:`.OWLegend.add_item`, :meth:`.OWLegend.add_curve`. """ def __init__(self, name, point, parent): QGraphicsObject.__init__(self, parent) self.text_item = QGraphicsTextItem(name, self) if point: s = point.size() height = max(2 * s, self.text_item.boundingRect().height()) else: height = self.text_item.boundingRect().height() p = 0.5 * height self.text_item.setPos(height, 0) self.point_item = point if point: self.point_item.setParentItem(self) self.point_item.setPos(p, p) self._rect = QRectF(0, 0, height + self.text_item.boundingRect().width(), height) self.rect_item = QGraphicsRectItem(self._rect, self) self.rect_item.setPen(QPen(Qt.NoPen)) self.rect_item.stackBefore(self.text_item) if self.point_item: self.rect_item.stackBefore(self.point_item) def boundingRect(self): return self._rect def paint(self, painter, option, widget): pass
class OWLegendItem(QGraphicsObject): """ Represents a legend item with a title and a point symbol. :param name: The text to display :type name: str :param point: The point symbol :type point: :obj:`.OWPoint` :param parent: The parent item, passed to QGraphicsItem :type parent: :obj:`QGraphicsItem` .. seealso:: :meth:`.OWLegend.add_item`, :meth:`.OWLegend.add_curve`. """ def __init__(self, name, point, parent): QGraphicsObject.__init__(self, parent) self.text_item = QGraphicsTextItem(name, self) if point: s = point.size() height = max(2*s, self.text_item.boundingRect().height()) else: height = self.text_item.boundingRect().height() p = 0.5 * height self.text_item.setPos(height, 0) self.point_item = point if point: self.point_item.setParentItem(self) self.point_item.setPos(p, p) self._rect = QRectF(0, 0, height + self.text_item.boundingRect().width(), height ) self.rect_item = QGraphicsRectItem(self._rect, self) self.rect_item.setPen(QPen(Qt.NoPen)) self.rect_item.stackBefore(self.text_item) if self.point_item: self.rect_item.stackBefore(self.point_item) def boundingRect(self): return self._rect def paint(self, painter, option, widget): pass
def trinomial_face(binom, spp, ftype="Verdana", fsize=10, fgcolor="black", fstyle="normal", bold=False): """ Stolen from: https://connorskennerton.wordpress.com/2016/11/16/python-ete3-formatting-organism-names-the-way-i-want/ """ font = QFont(ftype, fsize) font.setBold(bold) if fstyle == "italic": font.setStyle(QFont.StyleItalic) elif fstyle == "oblique": font.setStyle(QFont.StyleOblique) text = QGraphicsTextItem() text.setFont(font) if spp is None: text.setHtml("<i>{}</i>".format(binom)) else: text.setHtml("<i>{}</i> {}".format(binom, spp)) rect = QGraphicsRectItem(0, 0, text.boundingRect().width(), text.boundingRect().height() - 10) text.setParentItem(rect) center = rect.boundingRect().center() text.setPos(rect.boundingRect().x(), center.y() - text.boundingRect().height() / 2) # no border rect.setPen(QPen(QtCore.Qt.NoPen)) return ete3.faces.StaticItemFace(rect)
class VennIntersectionArea(QGraphicsPathItem): def __init__(self, parent=None, text=""): super(QGraphicsPathItem, self).__init__(parent) self.setAcceptHoverEvents(True) self.setPen(QPen(Qt.NoPen)) self.text = QGraphicsTextItem(self) layout = self.text.document().documentLayout() layout.documentSizeChanged.connect(self._onLayoutChanged) self._text = "" self._anchor = QPointF() def setText(self, text): if self._text != text: self._text = text self.text.setPlainText(text) def text(self): return self._text def setTextAnchor(self, pos): if self._anchor != pos: self._anchor = pos self._updateTextAnchor() def hoverEnterEvent(self, event): self.setZValue(self.zValue() + 1) return QGraphicsPathItem.hoverEnterEvent(self, event) def hoverLeaveEvent(self, event): self.setZValue(self.zValue() - 1) return QGraphicsPathItem.hoverLeaveEvent(self, event) def mousePressEvent(self, event): if event.button() == Qt.LeftButton: if event.modifiers() & Qt.AltModifier: self.setSelected(False) elif event.modifiers() & Qt.ControlModifier: self.setSelected(not self.isSelected()) elif event.modifiers() & Qt.ShiftModifier: self.setSelected(True) else: for area in self.parentWidget().vennareas(): area.setSelected(False) self.setSelected(True) def mouseReleaseEvent(self, event): pass def paint(self, painter, option, widget=None): painter.save() path = self.path() brush = QBrush(self.brush()) pen = QPen(self.pen()) if option.state & QStyle.State_Selected: pen.setColor(Qt.red) brush.setStyle(Qt.DiagCrossPattern) brush.setColor(QColor(40, 40, 40, 100)) elif option.state & QStyle.State_MouseOver: pen.setColor(Qt.blue) if option.state & QStyle.State_MouseOver: brush.setColor(QColor(100, 100, 100, 100)) if brush.style() == Qt.NoBrush: # Make sure the highlight is actually visible. brush.setStyle(Qt.SolidPattern) painter.setPen(pen) painter.setBrush(brush) painter.drawPath(path) painter.restore() def itemChange(self, change, value): if change == QGraphicsPathItem.ItemSelectedHasChanged: self.setZValue(self.zValue() + (1 if value else -1)) return QGraphicsPathItem.itemChange(self, change, value) def _updateTextAnchor(self): rect = self.text.boundingRect() pos = anchor_rect(rect, self._anchor) self.text.setPos(pos) def _onLayoutChanged(self): self._updateTextAnchor()
class VennIntersectionArea(QGraphicsPathItem): def __init__(self, parent=None, text=""): super(QGraphicsPathItem, self).__init__(parent) self.setAcceptHoverEvents(True) self.setPen(QPen(Qt.NoPen)) self.text = QGraphicsTextItem(self) layout = self.text.document().documentLayout() layout.documentSizeChanged.connect(self._onLayoutChanged) self._text = "" self._anchor = QPointF() def setText(self, text): if self._text != text: self._text = text self.text.setPlainText(text) def text(self): return self._text def setTextAnchor(self, pos): if self._anchor != pos: self._anchor = pos self._updateTextAnchor() def hoverEnterEvent(self, event): self.setZValue(self.zValue() + 1) return QGraphicsPathItem.hoverEnterEvent(self, event) def hoverLeaveEvent(self, event): self.setZValue(self.zValue() - 1) return QGraphicsPathItem.hoverLeaveEvent(self, event) def paint(self, painter, option, widget=None): painter.save() path = self.path() brush = QBrush(self.brush()) pen = QPen(self.pen()) if option.state & QStyle.State_Selected: pen.setColor(Qt.red) brush.setStyle(Qt.DiagCrossPattern) brush.setColor(QColor(40, 40, 40, 100)) elif option.state & QStyle.State_MouseOver: pen.setColor(Qt.blue) if option.state & QStyle.State_MouseOver: brush.setColor(QColor(100, 100, 100, 100)) if brush.style() == Qt.NoBrush: # Make sure the highlight is actually visible. brush.setStyle(Qt.SolidPattern) painter.setPen(pen) painter.setBrush(brush) painter.drawPath(path) painter.restore() def itemChange(self, change, value): if change == QGraphicsPathItem.ItemSelectedHasChanged: self.setZValue(self.zValue() + (1 if value else -1)) return QGraphicsPathItem.itemChange(self, change, value) def _updateTextAnchor(self): rect = self.text.boundingRect() pos = anchor_rect(rect, self._anchor) self.text.setPos(pos) def _onLayoutChanged(self): self._updateTextAnchor()
class hexView(QGraphicsView): def __init__(self, parent): QGraphicsView.__init__(self, None, parent) self.init(parent) self.initShape() def init(self, parent): self.whex = parent self.heditor = self.whex.heditor #Init scene self.__scene = QGraphicsScene(self) self.setScene(self.__scene) #Get heditor stuff self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setAlignment(Qt.AlignLeft) def setItems(self): self.__scene.addItem(self.whex.offsetitem) self.__scene.addItem(self.whex.hexitem) self.__scene.addItem(self.whex.asciitem) def initShape(self): self.initHeads() #Line decoration offsetLine = QGraphicsLineItem(QLineF(90, 0, 90, 700)) asciiLine = QGraphicsLineItem(QLineF(480, 0, 480, 700)) #Add to scene self.__scene.addItem(offsetLine) self.__scene.addItem(asciiLine) def setCursors(self): self.__scene.addItem(self.whex.hexcursor) self.__scene.addItem(self.whex.asciicursor) def initHeads(self): self.offHead = QGraphicsTextItem() self.hexHead = QGraphicsTextItem() self.asciiHead = QGraphicsTextItem() #Set Color self.offHead.setDefaultTextColor(QColor(Qt.red)) self.hexHead.setDefaultTextColor(QColor(Qt.black)) self.asciiHead.setDefaultTextColor(QColor(Qt.darkCyan)) #Create Font self.font = QFont("Gothic") self.font.setFixedPitch(1) self.font.setBold(False) self.font.setPixelSize(14) #Set Font self.offHead.setFont(self.font) self.hexHead.setFont(self.font) self.asciiHead.setFont(self.font) #Set Text self.offHead.setPlainText("Offset") self.hexHead.setPlainText( "0 1 2 3 4 5 6 7 8 9 A B C D E F") self.asciiHead.setPlainText("Ascii") #Position self.offHead.setPos(20, 0) self.hexHead.setPos(95, 0) self.asciiHead.setPos(520, 0) #Add to scene self.__scene.addItem(self.offHead) self.__scene.addItem(self.hexHead) self.__scene.addItem(self.asciiHead) headLine = QGraphicsLineItem(QLineF(0, 20, 615, 20)) self.__scene.addItem(headLine) def move(self, step, way): #step: line = 1 * bytesPerLine, page = pagesize, wheel = 3 * bytesPerLine offset = self.heditor.currentOffset if way == 0: #UP if (offset - (step * self.heditor.bytesPerLine)) >= 0: self.heditor.readOffset(offset - (step * self.heditor.bytesPerLine)) if self.whex.isLFMOD(): self.whex.scroll.setValue( self.whex.offsetToValue(offset - step * (self.heditor.bytesPerLine))) else: self.whex.scroll.setValue(self.whex.scroll.value() - step) else: self.heditor.readOffset(0) self.whex.scroll.setValue(0) elif way == 1: #Down if (offset + (step * self.heditor.bytesPerLine)) <= ( self.heditor.filesize - (step * self.heditor.bytesPerLine)): self.heditor.readOffset(offset + (step * self.heditor.bytesPerLine)) if self.whex.isLFMOD(): self.whex.scroll.setValue( self.whex.offsetToValue(offset + step * (self.heditor.bytesPerLine))) else: self.whex.scroll.setValue(self.whex.scroll.value() + step) else: self.heditor.readOffset(self.heditor.filesize - 5 * (self.heditor.bytesPerLine)) self.whex.scroll.setValue(self.whex.scroll.max) #################################### # Navigation Operations # #################################### def wheelEvent(self, event): offset = self.heditor.currentOffset if event.delta() > 0: self.move(3, 0) else: self.move(3, 1) def keyPressEvent(self, keyEvent): # off = self.heditor.currentOffset if keyEvent.matches(QKeySequence.MoveToNextPage): self.move(self.heditor.pageSize / self.heditor.bytesPerLine, 1) elif keyEvent.matches(QKeySequence.MoveToPreviousPage): self.move(self.heditor.pageSize / self.heditor.bytesPerLine, 0) elif keyEvent.matches(QKeySequence.MoveToNextWord): print "Next Word" elif keyEvent.matches(QKeySequence.MoveToPreviousWord): print "Previous word" elif keyEvent.matches(QKeySequence.MoveToNextLine): print "Next Line" elif keyEvent.matches(QKeySequence.MoveToPreviousLine): print "Previous Line"
class NodeItem(QGraphicsObject): """ An widget node item in the canvas. """ #: Signal emitted when the scene position of the node has changed. positionChanged = Signal() #: Signal emitted when the geometry of the channel anchors changes. anchorGeometryChanged = Signal() #: Signal emitted when the item has been activated (by a mouse double #: click or a keyboard) activated = Signal() #: The item is under the mouse. hovered = Signal() #: Span of the anchor in degrees ANCHOR_SPAN_ANGLE = 90 #: Z value of the item Z_VALUE = 100 def __init__(self, widget_description=None, parent=None, **kwargs): QGraphicsObject.__init__(self, parent, **kwargs) self.setFlag(QGraphicsItem.ItemSendsGeometryChanges, True) self.setFlag(QGraphicsItem.ItemHasNoContents, True) self.setFlag(QGraphicsItem.ItemIsSelectable, True) self.setFlag(QGraphicsItem.ItemIsMovable, True) self.setFlag(QGraphicsItem.ItemIsFocusable, True) # central body shape item self.shapeItem = None # in/output anchor items self.inputAnchorItem = None self.outputAnchorItem = None # title text item self.captionTextItem = None # error, warning, info items self.errorItem = None self.warningItem = None self.infoItem = None self.__title = "" self.__processingState = 0 self.__progress = -1 self.__error = None self.__warning = None self.__info = None self.__anchorLayout = None self.__animationEnabled = False self.setZValue(self.Z_VALUE) self.setupGraphics() self.setWidgetDescription(widget_description) @classmethod def from_node(cls, node): """ Create an :class:`NodeItem` instance and initialize it from a :class:`SchemeNode` instance. """ self = cls() self.setWidgetDescription(node.description) # self.setCategoryDescription(node.category) return self @classmethod def from_node_meta(cls, meta_description): """ Create an `NodeItem` instance from a node meta description. """ self = cls() self.setWidgetDescription(meta_description) return self def setupGraphics(self): """ Set up the graphics. """ shape_rect = QRectF(-24, -24, 48, 48) self.shapeItem = NodeBodyItem(self) self.shapeItem.setShapeRect(shape_rect) self.shapeItem.setAnimationEnabled(self.__animationEnabled) # Rect for widget's 'ears'. anchor_rect = QRectF(-31, -31, 62, 62) self.inputAnchorItem = SinkAnchorItem(self) input_path = QPainterPath() start_angle = 180 - self.ANCHOR_SPAN_ANGLE / 2 input_path.arcMoveTo(anchor_rect, start_angle) input_path.arcTo(anchor_rect, start_angle, self.ANCHOR_SPAN_ANGLE) self.inputAnchorItem.setAnchorPath(input_path) self.outputAnchorItem = SourceAnchorItem(self) output_path = QPainterPath() start_angle = self.ANCHOR_SPAN_ANGLE / 2 output_path.arcMoveTo(anchor_rect, start_angle) output_path.arcTo(anchor_rect, start_angle, - self.ANCHOR_SPAN_ANGLE) self.outputAnchorItem.setAnchorPath(output_path) self.inputAnchorItem.hide() self.outputAnchorItem.hide() # Title caption item self.captionTextItem = QGraphicsTextItem(self) self.captionTextItem.setPlainText("") self.captionTextItem.setPos(0, 33) def iconItem(standard_pixmap): item = GraphicsIconItem(self, icon=standard_icon(standard_pixmap), iconSize=QSize(16, 16)) item.hide() return item self.errorItem = iconItem(QStyle.SP_MessageBoxCritical) self.warningItem = iconItem(QStyle.SP_MessageBoxWarning) self.infoItem = iconItem(QStyle.SP_MessageBoxInformation) # TODO: Remove the set[Widget|Category]Description. The user should # handle setting of icons, title, ... def setWidgetDescription(self, desc): """ Set widget description. """ self.widget_description = desc if desc is None: return icon = icon_loader.from_description(desc).get(desc.icon) if icon: self.setIcon(icon) if not self.title(): self.setTitle(desc.name) if desc.inputs: self.inputAnchorItem.show() if desc.outputs: self.outputAnchorItem.show() tooltip = NodeItem_toolTipHelper(self) self.setToolTip(tooltip) def setWidgetCategory(self, desc): """ Set the widget category. """ self.category_description = desc if desc and desc.background: background = NAMED_COLORS.get(desc.background, desc.background) color = QColor(background) if color.isValid(): self.setColor(color) def setIcon(self, icon): """ Set the node item's icon (:class:`QIcon`). """ if isinstance(icon, QIcon): self.icon_item = GraphicsIconItem(self.shapeItem, icon=icon, iconSize=QSize(36, 36)) self.icon_item.setPos(-18, -18) else: raise TypeError def setColor(self, color, selectedColor=None): """ Set the widget color. """ if selectedColor is None: selectedColor = saturated(color, 150) palette = create_palette(color, selectedColor) self.shapeItem.setPalette(palette) def setPalette(self, palette): # TODO: The palette should override the `setColor` raise NotImplementedError def setTitle(self, title): """ Set the node title. The title text is displayed at the bottom of the node. """ self.__title = title self.__updateTitleText() def title(self): """ Return the node title. """ return self.__title title_ = Property(unicode, fget=title, fset=setTitle, doc="Node title text.") def setFont(self, font): """ Set the title text font (:class:`QFont`). """ if font != self.font(): self.prepareGeometryChange() self.captionTextItem.setFont(font) self.__updateTitleText() def font(self): """ Return the title text font. """ return self.captionTextItem.font() def setAnimationEnabled(self, enabled): """ Set the node animation enabled state. """ if self.__animationEnabled != enabled: self.__animationEnabled = enabled self.shapeItem.setAnimationEnabled(enabled) def animationEnabled(self): """ Are node animations enabled. """ return self.__animationEnabled def setProcessingState(self, state): """ Set the node processing state i.e. the node is processing (is busy) or is idle. """ if self.__processingState != state: self.__processingState = state self.shapeItem.setProcessingState(state) if not state: # Clear the progress meter. self.setProgress(-1) if self.__animationEnabled: self.shapeItem.ping() def processingState(self): """ The node processing state. """ return self.__processingState processingState_ = Property(int, fget=processingState, fset=setProcessingState) def setProgress(self, progress): """ Set the node work progress state (number between 0 and 100). """ if progress is None or progress < 0: progress = -1 progress = max(min(progress, 100), -1) if self.__progress != progress: self.__progress = progress self.shapeItem.setProgress(progress) self.__updateTitleText() def progress(self): """ Return the node work progress state. """ return self.__progress progress_ = Property(float, fget=progress, fset=setProgress, doc="Node progress state.") def setProgressMessage(self, message): """ Set the node work progress message. .. note:: Not yet implemented """ pass def setErrorMessage(self, message): if self.__error != message: self.__error = message self.__updateMessages() def setWarningMessage(self, message): if self.__warning != message: self.__warning = message self.__updateMessages() def setInfoMessage(self, message): if self.__info != message: self.__info = message self.__updateMessages() def newInputAnchor(self): """ Create and return a new input :class:`AnchorPoint`. """ if not (self.widget_description and self.widget_description.inputs): raise ValueError("Widget has no inputs.") anchor = AnchorPoint() self.inputAnchorItem.addAnchor(anchor, position=1.0) positions = self.inputAnchorItem.anchorPositions() positions = uniform_linear_layout(positions) self.inputAnchorItem.setAnchorPositions(positions) return anchor def removeInputAnchor(self, anchor): """ Remove input anchor. """ self.inputAnchorItem.removeAnchor(anchor) positions = self.inputAnchorItem.anchorPositions() positions = uniform_linear_layout(positions) self.inputAnchorItem.setAnchorPositions(positions) def newOutputAnchor(self): """ Create and return a new output :class:`AnchorPoint`. """ if not (self.widget_description and self.widget_description.outputs): raise ValueError("Widget has no outputs.") anchor = AnchorPoint(self) self.outputAnchorItem.addAnchor(anchor, position=1.0) positions = self.outputAnchorItem.anchorPositions() positions = uniform_linear_layout(positions) self.outputAnchorItem.setAnchorPositions(positions) return anchor def removeOutputAnchor(self, anchor): """ Remove output anchor. """ self.outputAnchorItem.removeAnchor(anchor) positions = self.outputAnchorItem.anchorPositions() positions = uniform_linear_layout(positions) self.outputAnchorItem.setAnchorPositions(positions) def inputAnchors(self): """ Return a list of all input anchor points. """ return self.inputAnchorItem.anchorPoints() def outputAnchors(self): """ Return a list of all output anchor points. """ return self.outputAnchorItem.anchorPoints() def setAnchorRotation(self, angle): """ Set the anchor rotation. """ self.inputAnchorItem.setRotation(angle) self.outputAnchorItem.setRotation(angle) self.anchorGeometryChanged.emit() def anchorRotation(self): """ Return the anchor rotation. """ return self.inputAnchorItem.rotation() def boundingRect(self): # TODO: Important because of this any time the child # items change geometry the self.prepareGeometryChange() # needs to be called. return self.childrenBoundingRect() def shape(self): # Shape for mouse hit detection. # TODO: Should this return the union of all child items? return self.shapeItem.shape() def __updateTitleText(self): """ Update the title text item. """ title_safe = escape(self.title()) if self.progress() > 0: text = '<div align="center">%s<br/>%i%%</div>' % \ (title_safe, int(self.progress())) else: text = '<div align="center">%s</div>' % \ (title_safe) # The NodeItems boundingRect could change. self.prepareGeometryChange() self.captionTextItem.setHtml(text) self.captionTextItem.document().adjustSize() width = self.captionTextItem.textWidth() self.captionTextItem.setPos(-width / 2.0, 33) def __updateMessages(self): """ Update message items (position, visibility and tool tips). """ items = [self.errorItem, self.warningItem, self.infoItem] messages = [self.__error, self.__warning, self.__info] for message, item in zip(messages, items): item.setVisible(bool(message)) item.setToolTip(message or "") shown = [item for item in items if item.isVisible()] count = len(shown) if count: spacing = 3 rects = [item.boundingRect() for item in shown] width = sum(rect.width() for rect in rects) width += spacing * max(0, count - 1) height = max(rect.height() for rect in rects) origin = self.shapeItem.boundingRect().top() - spacing - height origin = QPointF(-width / 2, origin) for item, rect in zip(shown, rects): item.setPos(origin) origin = origin + QPointF(rect.width() + spacing, 0) def mousePressEvent(self, event): if self.shapeItem.path().contains(event.pos()): return QGraphicsObject.mousePressEvent(self, event) else: event.ignore() def mouseDoubleClickEvent(self, event): if self.shapeItem.path().contains(event.pos()): QGraphicsObject.mouseDoubleClickEvent(self, event) QTimer.singleShot(0, self.activated.emit) else: event.ignore() def contextMenuEvent(self, event): if self.shapeItem.path().contains(event.pos()): return QGraphicsObject.contextMenuEvent(self, event) else: event.ignore() def focusInEvent(self, event): self.shapeItem.setHasFocus(True) return QGraphicsObject.focusInEvent(self, event) def focusOutEvent(self, event): self.shapeItem.setHasFocus(False) return QGraphicsObject.focusOutEvent(self, event) def itemChange(self, change, value): if change == QGraphicsItem.ItemSelectedChange: self.shapeItem.setSelected(value.toBool()) elif change == QGraphicsItem.ItemPositionHasChanged: self.positionChanged.emit() return QGraphicsObject.itemChange(self, change, value)
class pageView(QGraphicsView): def __init__(self, wpage): QGraphicsView.__init__(self) self.init(wpage) self.initShape() # self.selection = pageSelection(self.heditor) def init(self, wpage): self.wpage = wpage self.heditor = wpage.heditor self.filesize = self.heditor.filesize self.start = True self.pagew = 20 self.pageh = 20 self.pageItems = [] self.offsetItems = [] self.displayLines = 0 def initShape(self): #Scene self.scene = QGraphicsScene() self.setScene(self.scene) #Font self.initFont() #Headers self.setHeads(self.heditor.pagesPerBlock) self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setAlignment(Qt.AlignLeft) def initFont(self): self.font = QFont("Gothic") self.font.setFixedPitch(1) self.font.setBold(False) self.font.setPixelSize(14) def setHeads(self, pagesPerBlock): if self.heditor.pageOffView: self.setOffsetHead() else: self.setBlockHead() self.setPageHead(self.heditor.pagesPerBlock) linesize = 95 + (self.heditor.pagesPerBlock * (self.pagew + 2)) #Decoration headLine = QGraphicsLineItem(QLineF(0, 20, linesize, 20)) self.scene.addItem(headLine) headOffLine = QGraphicsLineItem(QLineF(90, 0, 90, 700)) self.scene.addItem(headOffLine) def setOffsetHead(self): self.offHead = QGraphicsTextItem() self.offHead.setDefaultTextColor(QColor(Qt.red)) self.offHead.setFont(self.font) self.offHead.setPlainText("Offset(Kb)") self.offHead.setPos(5, 0) self.scene.addItem(self.offHead) def setPageHead(self, len): count = 0 x = 95 while count < len: item = QGraphicsSimpleTextItem() item.setFont(self.font) item.setText("%.2x" % count) item.setPos(x, 3) self.scene.addItem(item) x += self.pagew + 2 count += 1 def setBlockHead(self): self.blockHead = QGraphicsTextItem() self.blockHead.setDefaultTextColor(QColor(Qt.red)) self.blockHead.setFont(self.font) self.blockHead.setPlainText("Block") self.blockHead.setPos(15, 0) self.scene.addItem(self.blockHead) def initOffsetItems(self): count = 0 x = 0 y = 25 while count <= self.displayLines: item = QGraphicsTextItem() item.setDefaultTextColor(QColor(Qt.red)) item.setFont(self.font) item.setPos(x, y) self.offsetItems.append(item) y += self.pageh + 2 count += 1 #Add Items in scene for item in self.offsetItems: self.scene.addItem(item) def initPageItems(self): id = 0 countpage = 0 startx = 95 starty = 25 x = startx y = starty line = 0 while line <= self.displayLines: while countpage < self.heditor.pagesPerBlock: p = page(x, y, id, self) self.pageItems.append(p) id += 1 # self.scene.addItem(sec) x += self.pagew + 2 countpage += 1 x = startx y += self.pageh + 2 countpage = 0 line += 1 #Add items in scene for item in self.pageItems: self.scene.addItem(item) def hidePageItems(self, startid): end = len(self.pageItems) for item in self.pageItems[startid:end]: item.setVisible(False) def setAllPageItemsVisible(self): for item in self.pageItems: item.setVisible(True) def hideOffsetItems(self, startid): end = len(self.offsetItems) for item in self.offsetItems[startid:end]: item.setVisible(False) def setAllOffsetItemsVisible(self): for item in self.offsetItems: item.setVisible(True) def appendOffsetItems(self, linesToAppend): count = 0 x = 0 y = 25 + (len(self.offsetItems) * (self.pageh + 2)) # print "Y append offset ", y while count <= linesToAppend: item = QGraphicsTextItem() item.setDefaultTextColor(QColor(Qt.red)) item.setFont(self.font) item.setPos(x, y) self.offsetItems.append(item) self.scene.addItem(item) y += self.pageh + 2 count += 1 def appendPageItems(self, linesToAppend): count = 0 cp = 0 x = 95 y = 25 + ((len(self.pageItems) / self.heditor.pagesPerBlock) * (self.pageh + 2)) id = len(self.pageItems) while count <= linesToAppend: while cp < self.heditor.pagesPerBlock: item = page(x, y, id, self) self.pageItems.append(item) self.scene.addItem(item) id += 1 x += self.pagew + 2 cp += 1 count += 1 x = 95 y += self.pageh + 2 def refreshOffsetItems(self, offset): #Check if end of pages or if number of pages < display pages self.setAllOffsetItemsVisible() block = (offset / self.heditor.pageSize) / self.heditor.pagesPerBlock startBlockOffset = block * (self.heditor.pagesPerBlock * self.heditor.pageSize) lineToDisplay = ((self.filesize - offset) / self.heditor.pageSize) / self.heditor.pagesPerBlock if ((self.filesize - offset) / self.heditor.pageSize) % self.heditor.pagesPerBlock > 0: lineToDisplay += 1 if lineToDisplay >= self.displayLines: offset = startBlockOffset for item in self.offsetItems[0:self.displayLines]: if self.heditor.decimalview: if self.heditor.pageOffView: offlabel = QString("%.10d" % (offset / 1024)) else: offlabel = QString("%.10d" % (offset / (self.heditor.pageSize * self.heditor.pagesPerBlock))) else: if self.heditor.pageOffView: offlabel = QString("%.10x" % (offset / 1024)) else: offlabel = QString("%.10x" % (offset / (self.heditor.pageSize * self.heditor.pagesPerBlock))) item.setPlainText(offlabel) offset = offset + (self.heditor.pagesPerBlock * self.heditor.pageSize) self.heditor.startBlockOffset = startBlockOffset else: if lineToDisplay == 0: lineToDisplay = 5 offset = startBlockOffset - (lineToDisplay * self.heditor.pagesPerBlock * self.heditor.pageSize) if ((self.filesize - offset) / self.heditor.pageSize) % self.heditor.pagesPerBlock > 0: lineToDisplay += 1 self.heditor.startBlockOffset = offset for item in self.offsetItems[0:lineToDisplay]: if self.heditor.decimalview: if self.heditor.pageOffView: offlabel = QString("%.10d" % (offset / 1024)) else: offlabel = QString("%.10d" % (offset / (self.heditor.pageSize * self.heditor.pagesPerBlock))) else: if self.heditor.pageOffView: offlabel = QString("%.10x" % (offset / 1024)) else: offlabel = QString("%.10x" % (offset / (self.heditor.pageSize * self.heditor.pagesPerBlock))) item.setPlainText(offlabel) offset = offset + (self.heditor.pagesPerBlock * self.heditor.pageSize) self.hideOffsetItems(lineToDisplay) def refreshPageItems(self, offset): self.setAllPageItemsVisible() maxpages = self.displayLines * self.heditor.pagesPerBlock displaypages = (self.filesize - offset) / self.heditor.pageSize if displaypages <= maxpages: if displaypages == 0: startline = self.lines - 5 startOffset = startline * (self.heditor.pageSize * self.heditor.pagesPerBlock) rangeOffset = self.filesize - startOffset newdisplaypages = rangeOffset / self.heditor.pageSize if rangeOffset % self.heditor.pageSize > 0: newdisplaypages += 1 self.hidePageItems(newdisplaypages) self.heditor.startBlockOffset = startOffset else: rangeOffset = self.filesize - offset rangePages = rangeOffset / self.heditor.pageSize rangeLines = rangePages / self.heditor.pagesPerBlock newdisplaypages = rangeOffset / self.heditor.pageSize if rangeOffset % self.heditor.pageSize > 0: newdisplaypages += 1 self.hidePageItems(newdisplaypages) self.heditor.startBlockOffset = offset else: self.heditor.startBlockOffset = offset self.heditor.pageselection.update() def refreshAllContent(self): self.scene.clear() del self.offsetItems[:] del self.pageItems[:] self.setHeads(self.heditor.pagesPerBlock) self.initOffsetItems() self.initPageItems() self.refreshOffsetItems(self.heditor.startBlockOffset) self.refreshPageItems(self.heditor.startBlockOffset) def lineToOffset(self, line): offset = (line * (self.heditor.pagesPerBlock * self.heditor.pageSize)) return offset def lineToOffsetKb(self, line): offset = (line * (self.heditor.pagesPerBlock * self.heditor.pageSize)) / 1024 return offset def lineToOffsetMb(self, line): offset = ((line * (self.heditor.pagesPerBlock * self.heditor.pageSize)) / 1024) / 1024 return offset def lineToOffsetGb(self, line): offset = (((line * (self.heditor.pagesPerBlock * self.heditor.pageSize)) / 1024) / 1024) / 1024 return offset ############################ # Colorize Pages # ############################ def refreshPagesColor(self, id): # print "Refresh: ", id self.cleanSelection() self.pageItems[id].setBrush(QBrush(Qt.green, Qt.SolidPattern)) def cleanSelection(self): item = self.pageItems[self.selectedPage] item.setBrush(item.brush) ############################ # Resize Event # ############################ def resizeEvent(self, sizEvent): y = sizEvent.size().height() disline = (y / self.pageh) #Start if self.start == True: if self.height() < self.heditor.mainWindow.height(): if disline > self.displayLines: self.displayLines = (y / self.pageh) #Lines self.lines = self.filesize / (self.heditor.pagesPerBlock * self.heditor.pageSize) #Init self.initOffsetItems() self.initPageItems() #Refresh self.refreshOffsetItems(0) self.refreshPageItems(0) if self.lines > self.displayLines: self.wpage.setScrollBar() else: self.wpage.scroll = False self.start = False else: range = disline - self.displayLines if range > 0: self.displayLines = (y / self.pageh) #Append self.appendOffsetItems(range) self.appendPageItems(range) #Refresh self.refreshOffsetItems(self.heditor.startBlockOffset) self.refreshPageItems(self.heditor.startBlockOffset) # self.heditor.footer.pixel.view.resizeEvent(sizEvent) ############################ # CallBacks # ############################ def wheelEvent(self, event): offset = self.heditor.startBlockOffset # up = False if self.wpage.scroll: if event.delta() > 0: #UP subOffset = 3 * self.heditor.pagesPerBlock * self.heditor.pageSize if offset - subOffset > 0: offset = offset - subOffset else: offset = 0 else: #DOWN addOffset = 3 * self.heditor.pagesPerBlock * self.heditor.pageSize if offset + addOffset < self.filesize: offset = offset + addOffset else: offset = self.filesize - (5 * self.heditor.pagesPerBlock * self.heditor.pageSize) #Set ScrollBar value: if offset < self.filesize - (5 * self.heditor.pagesPerBlock * self.heditor.pageSize): value = self.wpage.scroll.offsetToValue(offset) self.wpage.scroll.setValue(value) self.refreshOffsetItems(offset) self.refreshPageItems(offset) def keyPressEvent(self, keyEvent): pass #if keyEvent.matches(QKeySequence.MoveToNextPage): #print "Next block" #elif keyEvent.matches(QKeySequence.MoveToPreviousPage): #print "Previous block" #elif keyEvent.matches(QKeySequence.MoveToNextLine): #print "Next Line" #elif keyEvent.matches(QKeySequence.MoveToPreviousLine): #print "Previous Line" #else: #pass def resetSelection(self): for item in self.pageItems: item.setBrush(item.brush) def getPageID(self, x, y): startx = 95 starty = 25 #Set scrollbar seek hscroll = self.horizontalScrollBar() if hscroll.value() > 0: startx -= hscroll.value() xrange = x - startx if xrange > 0: xcut = (xrange / (self.pagew + 2)) # print xcut else: xcut = 0 yrange = y - starty if yrange > 0: ycut = yrange / (self.pageh + 2) else: ycut = 0 id = (ycut * self.heditor.pagesPerBlock) + xcut return id def mousePressEvent(self, event): button = event.button() pos = event.pos() if event.button() == 1: #Get CLicked coordonates x = pos.x() y = pos.y() id = self.getPageID(x, y) self.resetSelection() self.heditor.pageselection.select(id, self.heditor.startBlockOffset, 0) def mouseMoveEvent(self, event): pos = event.pos() x = pos.x() y = pos.y() if self.heditor.pageselection.mode == 1: id = self.getPageID(x, y) self.resetSelection() self.heditor.pageselection.select(id, self.heditor.startBlockOffset, 1) # else: # id = self.getPageID(x, y) # self.pageItems[id].setBrush(self) def mouseReleaseEvent(self, event): self.heditor.pageselection.mode = 0
class OWAxis(QGraphicsItem): Role = OWPalette.Axis def __init__(self, id, title = '', title_above = False, title_location = AxisMiddle, line = None, arrows = 0, plot = None): QGraphicsItem.__init__(self) self.setFlag(QGraphicsItem.ItemHasNoContents) self.setZValue(AxisZValue) self.id = id self.title = title self.title_location = title_location self.data_line = line self.plot = plot self.graph_line = None self.size = None self.scale = None self.tick_length = (10, 5, 0) self.arrows = arrows self.title_above = title_above self.line_item = QGraphicsLineItem(self) self.title_item = QGraphicsTextItem(self) self.end_arrow_item = None self.start_arrow_item = None self.show_title = False self.scale = None path = QPainterPath() path.setFillRule(Qt.WindingFill) path.moveTo(0, 3.09) path.lineTo(0, -3.09) path.lineTo(9.51, 0) path.closeSubpath() self.arrow_path = path self.label_items = [] self.label_bg_items = [] self.tick_items = [] self._ticks = [] self.zoom_transform = QTransform() self.labels = None self.auto_range = None self.auto_scale = True self.zoomable = False self.update_callback = None self.max_text_width = 50 self.text_margin = 5 self.always_horizontal_text = False @staticmethod def compute_scale(min, max): magnitude = int(3*log10(abs(max-min)) + 1) if magnitude % 3 == 0: first_place = 1 elif magnitude % 3 == 1: first_place = 2 else: first_place = 5 magnitude = magnitude // 3 - 1 step = first_place * pow(10, magnitude) first_val = ceil(min/step) * step return first_val, step def update_ticks(self): self._ticks = [] major, medium, minor = self.tick_length if self.labels is not None and not self.auto_scale: for i, text in enumerate(self.labels): self._ticks.append( ( i, text, medium, 1 ) ) else: if self.scale and not self.auto_scale: min, max, step = self.scale elif self.auto_range: min, max = self.auto_range if min is not None and max is not None: step = (max - min)/10 else: return else: return if max == min: return val, step = self.compute_scale(min, max) while val <= max: self._ticks.append( ( val, "%.4g" % val, medium, step ) ) val += step def update_graph(self): if self.update_callback: self.update_callback() def update(self, zoom_only = False): self.update_ticks() line_color = self.plot.color(OWPalette.Axis) text_color = self.plot.color(OWPalette.Text) if not self.graph_line or not self.scene(): return self.line_item.setLine(self.graph_line) self.line_item.setPen(line_color) if self.title: self.title_item.setHtml('<b>' + self.title + '</b>') self.title_item.setDefaultTextColor(text_color) if self.title_location == AxisMiddle: title_p = 0.5 elif self.title_location == AxisEnd: title_p = 0.95 else: title_p = 0.05 title_pos = self.graph_line.pointAt(title_p) v = self.graph_line.normalVector().unitVector() dense_text = False if hasattr(self, 'title_margin'): offset = self.title_margin elif self._ticks: if self.should_be_expanded(): offset = 55 dense_text = True else: offset = 35 else: offset = 10 if self.title_above: title_pos = title_pos + (v.p2() - v.p1())*(offset + QFontMetrics(self.title_item.font()).height()) else: title_pos = title_pos - (v.p2() - v.p1())*offset ## TODO: Move it according to self.label_pos self.title_item.setVisible(self.show_title) self.title_item.setRotation(-self.graph_line.angle()) c = self.title_item.mapToParent(self.title_item.boundingRect().center()) tl = self.title_item.mapToParent(self.title_item.boundingRect().topLeft()) self.title_item.setPos(title_pos - c + tl) ## Arrows if not zoom_only: if self.start_arrow_item: self.scene().removeItem(self.start_arrow_item) self.start_arrow_item = None if self.end_arrow_item: self.scene().removeItem(self.end_arrow_item) self.end_arrow_item = None if self.arrows & AxisStart: if not zoom_only or not self.start_arrow_item: self.start_arrow_item = QGraphicsPathItem(self.arrow_path, self) self.start_arrow_item.setPos(self.graph_line.p1()) self.start_arrow_item.setRotation(-self.graph_line.angle() + 180) self.start_arrow_item.setBrush(line_color) self.start_arrow_item.setPen(line_color) if self.arrows & AxisEnd: if not zoom_only or not self.end_arrow_item: self.end_arrow_item = QGraphicsPathItem(self.arrow_path, self) self.end_arrow_item.setPos(self.graph_line.p2()) self.end_arrow_item.setRotation(-self.graph_line.angle()) self.end_arrow_item.setBrush(line_color) self.end_arrow_item.setPen(line_color) ## Labels n = len(self._ticks) resize_plot_item_list(self.label_items, n, QGraphicsTextItem, self) resize_plot_item_list(self.label_bg_items, n, QGraphicsRectItem, self) resize_plot_item_list(self.tick_items, n, QGraphicsLineItem, self) test_rect = QRectF(self.graph_line.p1(), self.graph_line.p2()).normalized() test_rect.adjust(-1, -1, 1, 1) n_v = self.graph_line.normalVector().unitVector() if self.title_above: n_p = n_v.p2() - n_v.p1() else: n_p = n_v.p1() - n_v.p2() l_v = self.graph_line.unitVector() l_p = l_v.p2() - l_v.p1() for i in range(n): pos, text, size, step = self._ticks[i] hs = 0.5 * step tick_pos = self.map_to_graph( pos ) if not test_rect.contains(tick_pos): self.tick_items[i].setVisible(False) self.label_items[i].setVisible(False) continue item = self.label_items[i] item.setVisible(True) if not zoom_only: if self.id in XAxes or getattr(self, 'is_horizontal', False): item.setHtml( '<center>' + Qt.escape(text.strip()) + '</center>') else: item.setHtml(Qt.escape(text.strip())) item.setTextWidth(-1) text_angle = 0 if dense_text: w = min(item.boundingRect().width(), self.max_text_width) item.setTextWidth(w) if self.title_above: label_pos = tick_pos + n_p * (w + self.text_margin) + l_p * item.boundingRect().height()/2 else: label_pos = tick_pos + n_p * self.text_margin + l_p * item.boundingRect().height()/2 text_angle = -90 if self.title_above else 90 else: w = min(item.boundingRect().width(), QLineF(self.map_to_graph(pos - hs), self.map_to_graph(pos + hs) ).length()) label_pos = tick_pos + n_p * self.text_margin - l_p * w/2 item.setTextWidth(w) if not self.always_horizontal_text: if self.title_above: item.setRotation(-self.graph_line.angle() - text_angle) else: item.setRotation(self.graph_line.angle() - text_angle) item.setPos(label_pos) item.setDefaultTextColor(text_color) self.label_bg_items[i].setRect(item.boundingRect()) self.label_bg_items[i].setPen(QPen(Qt.NoPen)) self.label_bg_items[i].setBrush(self.plot.color(OWPalette.Canvas)) item = self.tick_items[i] item.setVisible(True) tick_line = QLineF(v) tick_line.translate(-tick_line.p1()) tick_line.setLength(size) if self.title_above: tick_line.setAngle(tick_line.angle() + 180) item.setLine( tick_line ) item.setPen(line_color) item.setPos(self.map_to_graph(pos)) @staticmethod def make_title(label, unit = None): lab = '<i>' + label + '</i>' if unit: lab = lab + ' [' + unit + ']' return lab def set_line(self, line): self.graph_line = line self.update() def set_title(self, title): self.title = title self.update() def set_show_title(self, b): self.show_title = b self.update() def set_labels(self, labels): self.labels = labels self.graph_line = None self.auto_scale = False self.update_ticks() self.update_graph() def set_scale(self, min, max, step_size): self.scale = (min, max, step_size) self.graph_line = None self.auto_scale = False self.update_ticks() self.update_graph() def set_tick_length(self, minor, medium, major): self.tick_length = (minor, medium, major) self.update() def map_to_graph(self, x): min, max = self.plot.bounds_for_axis(self.id) if min == max: return QPointF() line_point = self.graph_line.pointAt( (x-min)/(max-min) ) end_point = line_point * self.zoom_transform return self.projection(end_point, self.graph_line) @staticmethod def projection(point, line): norm = line.normalVector() norm.translate(point - norm.p1()) p = QPointF() type = line.intersect(norm, p) return p def continuous_labels(self): min, max, step = self.scale magnitude = log10(abs(max-min)) def paint(self, painter, option, widget): pass def boundingRect(self): return QRectF() def ticks(self): if not self._ticks: self.update_ticks() return self._ticks def bounds(self): if self.labels: return -0.2, len(self.labels) -0.8 elif self.scale: min, max, _step = self.scale return min, max elif self.auto_range: return self.auto_range else: return 0, 1 def should_be_expanded(self): self.update_ticks() return self.id in YAxes or self.always_horizontal_text or sum(len(t[1]) for t in self._ticks) * 12 > self.plot.width()
class BlockItem(QGraphicsRectItem): """ Represents a block in the diagram """ def __init__(self, parent, name='Untitled', width=180, height=40, blockColor="#A5A2A5", data=None, bold=False, italic=False, status=True): """ Constructor """ QGraphicsRectItem.__init__(self) self.parentWidget = parent self.internalData = data self.status = status color = QColor(0, 0, 0) color.setNamedColor(blockColor) self.setPen(QPen(color, 2)) if sys.version_info > (3, ) and isinstance(name, bytes): name = str(name, "utf8", errors="ignore") self.label = QGraphicsTextItem(name, self) self.setFlags(self.ItemIsSelectable) self.setCursor(QCursor(Qt.PointingHandCursor)) self.changeSize(width, height) def setData(self, data): """ Set data """ self.internalData = data def setColor(self, blockColor): """ Set color """ color = QColor(0, 0, 0) color.setNamedColor(blockColor) self.setPen(QPen(color, 1)) self.setBrush(QBrush(color)) def changeSize(self, w, h): """ Resize block function """ # Limit the block size self.setRect(0.0, 0.0, w, h) # center label: rect = self.label.boundingRect() lw, lh = rect.width(), rect.height() lx = (w - lw) / 2 ly = (h - lh) / 2 self.label.setPos(lx, ly) return w, h def mouseReleaseEvent(self, event): """ On mouse release event """ if self.internalData is not None: data = self.internalData if isinstance(self.internalData, list): # [('Step 1', {'expected': 'result expected', 'action': 'step description', # 'actual': 'success', 'result': 'PASS', # 'summary': 'step sample'}), ('%payload-v1%', {'raw': '', # 'len': 0, 'time': 1421484488.314928})] data_tmp = self.internalData[0] data = "%s\n" % data_tmp[0] data += "\nSummary: %s" % data_tmp[1]['summary'] data += "\n\nAction: %s" % data_tmp[1]['action'] data += "\nExpected: %s" % data_tmp[1]['expected'] data += "\n\nResult: %s" % data_tmp[1]['result'] if 'actual' in data_tmp[1]: data += "\nActual: %s" % data_tmp[1]['actual'] self.parentWidget.logEdit.setText(data) else: self.parentWidget.logEdit.setText("")
class OWAxis(QGraphicsItem): Role = OWPalette.Axis def __init__(self, id, title='', title_above=False, title_location=AxisMiddle, line=None, arrows=AxisEnd, plot=None): QGraphicsItem.__init__(self) self.setFlag(QGraphicsItem.ItemHasNoContents) self.setZValue(AxisZValue) self.id = id self.title = title self.title_location = title_location self.data_line = line self.plot = plot self.graph_line = None self.size = None self.scale = None self.tick_length = (10, 5, 0) self.arrows = arrows self.title_above = title_above self.line_item = QGraphicsLineItem(self) self.title_item = QGraphicsTextItem(self) self.end_arrow_item = None self.start_arrow_item = None self.show_title = False self.scale = None path = QPainterPath() path.setFillRule(Qt.WindingFill) path.moveTo(0, 3.09) path.lineTo(0, -3.09) path.lineTo(9.51, 0) path.closeSubpath() self.arrow_path = path self.label_items = [] self.label_bg_items = [] self.tick_items = [] self._ticks = [] self.zoom_transform = QTransform() self.labels = None self.auto_range = None self.auto_scale = True self.zoomable = False self.update_callback = None self.max_text_width = 50 self.text_margin = 5 self.always_horizontal_text = False def update_ticks(self): self._ticks = [] major, medium, minor = self.tick_length if self.labels is not None and not self.auto_scale: for i, text in enumerate(self.labels): self._ticks.append((i, text, medium, 1)) else: if self.scale and not self.auto_scale: min, max, step = self.scale elif self.auto_range: min, max = self.auto_range if min is not None and max is not None: step = (max - min) / 10 else: return else: return if max == min: return magnitude = int(3 * log10(abs(max - min)) + 1) if magnitude % 3 == 0: first_place = 1 elif magnitude % 3 == 1: first_place = 2 else: first_place = 5 magnitude = magnitude / 3 - 1 step = first_place * pow(10, magnitude) val = ceil(min / step) * step while val <= max: self._ticks.append((val, "%.4g" % val, medium, step)) val = val + step def update_graph(self): if self.update_callback: self.update_callback() def update(self, zoom_only=False): self.update_ticks() line_color = self.plot.color(OWPalette.Axis) text_color = self.plot.color(OWPalette.Text) if not self.graph_line or not self.scene(): return self.line_item.setLine(self.graph_line) self.line_item.setPen(line_color) if self.title: self.title_item.setHtml('<b>' + self.title + '</b>') self.title_item.setDefaultTextColor(text_color) if self.title_location == AxisMiddle: title_p = 0.5 elif self.title_location == AxisEnd: title_p = 0.95 else: title_p = 0.05 title_pos = self.graph_line.pointAt(title_p) v = self.graph_line.normalVector().unitVector() dense_text = False if hasattr(self, 'title_margin'): offset = self.title_margin elif self._ticks: if self.should_be_expanded(): offset = 55 dense_text = True else: offset = 35 else: offset = 10 if self.title_above: title_pos = title_pos + (v.p2() - v.p1()) * ( offset + QFontMetrics(self.title_item.font()).height()) else: title_pos = title_pos - (v.p2() - v.p1()) * offset ## TODO: Move it according to self.label_pos self.title_item.setVisible(self.show_title) self.title_item.setRotation(-self.graph_line.angle()) c = self.title_item.mapToParent( self.title_item.boundingRect().center()) tl = self.title_item.mapToParent( self.title_item.boundingRect().topLeft()) self.title_item.setPos(title_pos - c + tl) ## Arrows if not zoom_only: if self.start_arrow_item: self.scene().removeItem(self.start_arrow_item) self.start_arrow_item = None if self.end_arrow_item: self.scene().removeItem(self.end_arrow_item) self.end_arrow_item = None if self.arrows & AxisStart: if not zoom_only or not self.start_arrow_item: self.start_arrow_item = QGraphicsPathItem( self.arrow_path, self) self.start_arrow_item.setPos(self.graph_line.p1()) self.start_arrow_item.setRotation(-self.graph_line.angle() + 180) self.start_arrow_item.setBrush(line_color) self.start_arrow_item.setPen(line_color) if self.arrows & AxisEnd: if not zoom_only or not self.end_arrow_item: self.end_arrow_item = QGraphicsPathItem(self.arrow_path, self) self.end_arrow_item.setPos(self.graph_line.p2()) self.end_arrow_item.setRotation(-self.graph_line.angle()) self.end_arrow_item.setBrush(line_color) self.end_arrow_item.setPen(line_color) ## Labels n = len(self._ticks) resize_plot_item_list(self.label_items, n, QGraphicsTextItem, self) resize_plot_item_list(self.label_bg_items, n, QGraphicsRectItem, self) resize_plot_item_list(self.tick_items, n, QGraphicsLineItem, self) test_rect = QRectF(self.graph_line.p1(), self.graph_line.p2()).normalized() test_rect.adjust(-1, -1, 1, 1) n_v = self.graph_line.normalVector().unitVector() if self.title_above: n_p = n_v.p2() - n_v.p1() else: n_p = n_v.p1() - n_v.p2() l_v = self.graph_line.unitVector() l_p = l_v.p2() - l_v.p1() for i in range(n): pos, text, size, step = self._ticks[i] hs = 0.5 * step tick_pos = self.map_to_graph(pos) if not test_rect.contains(tick_pos): self.tick_items[i].setVisible(False) self.label_items[i].setVisible(False) continue item = self.label_items[i] item.setVisible(True) if not zoom_only: if self.id in XAxes or getattr(self, 'is_horizontal', False): item.setHtml('<center>' + Qt.escape(text.strip()) + '</center>') else: item.setHtml(Qt.escape(text.strip())) item.setTextWidth(-1) text_angle = 0 if dense_text: w = min(item.boundingRect().width(), self.max_text_width) item.setTextWidth(w) if self.title_above: label_pos = tick_pos + n_p * ( w + self.text_margin ) + l_p * item.boundingRect().height() / 2 else: label_pos = tick_pos + n_p * self.text_margin + l_p * item.boundingRect( ).height() / 2 text_angle = -90 if self.title_above else 90 else: w = min( item.boundingRect().width(), QLineF(self.map_to_graph(pos - hs), self.map_to_graph(pos + hs)).length()) label_pos = tick_pos + n_p * self.text_margin - l_p * w / 2 item.setTextWidth(w) if not self.always_horizontal_text: if self.title_above: item.setRotation(-self.graph_line.angle() - text_angle) else: item.setRotation(self.graph_line.angle() - text_angle) item.setPos(label_pos) item.setDefaultTextColor(text_color) self.label_bg_items[i].setRect(item.boundingRect()) self.label_bg_items[i].setPen(QPen(Qt.NoPen)) self.label_bg_items[i].setBrush(self.plot.color(OWPalette.Canvas)) item = self.tick_items[i] item.setVisible(True) tick_line = QLineF(v) tick_line.translate(-tick_line.p1()) tick_line.setLength(size) if self.title_above: tick_line.setAngle(tick_line.angle() + 180) item.setLine(tick_line) item.setPen(line_color) item.setPos(self.map_to_graph(pos)) @staticmethod def make_title(label, unit=None): lab = '<i>' + label + '</i>' if unit: lab = lab + ' [' + unit + ']' return lab def set_line(self, line): self.graph_line = line self.update() def set_title(self, title): self.title = title self.update() def set_show_title(self, b): self.show_title = b self.update() def set_labels(self, labels): self.labels = labels self.graph_line = None self.auto_scale = False self.update_ticks() self.update_graph() def set_scale(self, min, max, step_size): self.scale = (min, max, step_size) self.graph_line = None self.auto_scale = False self.update_ticks() self.update_graph() def set_tick_length(self, minor, medium, major): self.tick_length = (minor, medium, major) self.update() def map_to_graph(self, x): min, max = self.plot.bounds_for_axis(self.id) if min == max: return QPointF() line_point = self.graph_line.pointAt((x - min) / (max - min)) end_point = line_point * self.zoom_transform return self.projection(end_point, self.graph_line) @staticmethod def projection(point, line): norm = line.normalVector() norm.translate(point - norm.p1()) p = QPointF() type = line.intersect(norm, p) return p def continuous_labels(self): min, max, step = self.scale magnitude = log10(abs(max - min)) def paint(self, painter, option, widget): pass def boundingRect(self): return QRectF() def ticks(self): if not self._ticks: self.update_ticks() return self._ticks def bounds(self): if self.labels: return -0.2, len(self.labels) - 0.8 elif self.scale: min, max, _step = self.scale return min, max elif self.auto_range: return self.auto_range else: return 0, 1 def should_be_expanded(self): self.update_ticks() return self.id in YAxes or self.always_horizontal_text or sum( len(t[1]) for t in self._ticks) * 12 > self.plot.width()
class VennIntersectionArea(QGraphicsPathItem): def __init__(self, parent=None, text=""): super(QGraphicsPathItem, self).__init__(parent) self.setAcceptHoverEvents(True) self.setPen(QPen(Qt.NoPen)) self.text = QGraphicsTextItem(self) layout = self.text.document().documentLayout() layout.documentSizeChanged.connect(self._onLayoutChanged) self._text = "" self._anchor = QPointF() def setText(self, text): if self._text != text: self._text = text self.text.setPlainText(text) def text(self): return self._text def setTextAnchor(self, pos): if self._anchor != pos: self._anchor = pos self._updateTextAnchor() def hoverEnterEvent(self, event): self.setZValue(self.zValue() + 1) return QGraphicsPathItem.hoverEnterEvent(self, event) def hoverLeaveEvent(self, event): self.setZValue(self.zValue() - 1) return QGraphicsPathItem.hoverLeaveEvent(self, event) # def mousePressEvent(self, event): # pos = event.pos() # parent = self.parentItem() # pbrect = parent.boundingRect() # w, h = pbrect.width(), pbrect.height() # print "(%.3f, %.3f)" % (pos.x() / w, pos.y() / h) # super(VennIntersectionArea, self).mousePressEvent(event) def paint(self, painter, option, widget=None): painter.save() path = self.path() brush = QBrush(self.brush()) pen = QPen(self.pen()) if option.state & QStyle.State_Selected: pen.setColor(Qt.red) brush.setStyle(Qt.DiagCrossPattern) brush.setColor(QColor(40, 40, 40, 100)) elif option.state & QStyle.State_MouseOver: pen.setColor(Qt.blue) if option.state & QStyle.State_MouseOver: brush.setColor(QColor(100, 100, 100, 100)) if brush.style() == Qt.NoBrush: # Make sure the highlight is actually visible. brush.setStyle(Qt.SolidPattern) painter.setPen(pen) painter.setBrush(brush) painter.drawPath(path) painter.restore() def itemChange(self, change, value): if change == QGraphicsPathItem.ItemSelectedHasChanged: if value.toBool(): self.setZValue(self.zValue() + 1) else: self.setZValue(self.zValue() - 1) return QGraphicsPathItem.itemChange(self, change, value) def _updateTextAnchor(self): rect = self.text.boundingRect() pos = anchor_rect(rect, self._anchor) self.text.setPos(pos) def _onLayoutChanged(self): self._updateTextAnchor()
class MyView(QGraphicsView): ''' Näkymä. ''' def __init__(self, kappalelista): ''' Constructor ''' super(MyView, self).__init__() self.kappalelista = kappalelista self.setMouseTracking(True) self.liitosOk = False self.tempLiitos = [] self.tempVastin = [] self.textItem = None def mousePressEvent(self, event): selected_items = self.scene().selectedItems() if not selected_items: currentItem = self.itemAt(event.pos()) if currentItem is not None: if currentItem.brush().color() == QColor(170,0,0) or currentItem.brush().color() == QColor(150,210,230): currentItem = currentItem.parentItem() currentItem.setSelected(True) currentItem.parentItem().setZValue(1) for liitoskohta in currentItem.parentItem().liitoskohdat: if not liitoskohta.isFree(): liitoskohta.setFree() else: currentItem = selected_items[0] collision = False for anotherItem in self.kappalelista: if anotherItem.item != currentItem: if currentItem.collidesWithItem(anotherItem.item,0x1): collision = True if collision == False: currentItem.setSelected(False) currentItem.parentItem().setZValue(0) if self.liitosOk: n = len(self.tempLiitokset) for i in range(0,n): self.tempLiitokset[i].liita(self.tempVastineet[i],0) def keyPressEvent(self, event): selected_items = self.scene().selectedItems() if selected_items: key = event.key() currentItem = selected_items[0] if key == 0x01000014: #Key_Right currentItem.parentItem().pyorita(5) if key == 0x01000012: #Key_Left currentItem.parentItem().pyorita(-5) if key == 0x01000007: #Delete currentItem.parentItem().poista() def rakenna(self): for currentItem in self.kappalelista: for anotherItem in self.kappalelista: if anotherItem != currentItem: for liitoskohta in currentItem.liitoskohdat: if liitoskohta.vapaa: for vastakohta in anotherItem.liitoskohdat: if vastakohta.vapaa: if liitoskohta.collidesWithItem(vastakohta,0x1): liitoskohta.liita(vastakohta,1) def LoopText(self): self.textItem = QGraphicsTextItem() self.textItem.setPlainText('Muodostui silmukka') self.scene().addItem(self.textItem) self.textItem.setZValue(2) self.textItem.setPos(200,0) fontti = QFont() fontti.setPointSize(40) self.textItem.setFont(fontti) timer = QTimer() timer.singleShot(3000,self.removeLoopText) def removeLoopText(self): self.scene().removeItem(self.textItem)
class NodeItem(QGraphicsObject): """ An widget node item in the canvas. """ #: Signal emitted when the scene position of the node has changed. positionChanged = Signal() #: Signal emitted when the geometry of the channel anchors changes. anchorGeometryChanged = Signal() #: Signal emitted when the item has been activated (by a mouse double #: click or a keyboard) activated = Signal() #: The item is under the mouse. hovered = Signal() #: Span of the anchor in degrees ANCHOR_SPAN_ANGLE = 90 #: Z value of the item Z_VALUE = 100 def __init__(self, widget_description=None, parent=None, **kwargs): QGraphicsObject.__init__(self, parent, **kwargs) self.setFlag(QGraphicsItem.ItemSendsGeometryChanges, True) self.setFlag(QGraphicsItem.ItemHasNoContents, True) self.setFlag(QGraphicsItem.ItemIsSelectable, True) self.setFlag(QGraphicsItem.ItemIsMovable, True) self.setFlag(QGraphicsItem.ItemIsFocusable, True) # central body shape item self.shapeItem = None # in/output anchor items self.inputAnchorItem = None self.outputAnchorItem = None # title text item self.captionTextItem = None # error, warning, info items self.errorItem = None self.warningItem = None self.infoItem = None self.__title = "" self.__processingState = 0 self.__progress = -1 self.__error = None self.__warning = None self.__info = None self.__anchorLayout = None self.__animationEnabled = False self.setZValue(self.Z_VALUE) self.setupGraphics() self.setWidgetDescription(widget_description) @classmethod def from_node(cls, node): """ Create an :class:`NodeItem` instance and initialize it from a :class:`SchemeNode` instance. """ self = cls() self.setWidgetDescription(node.description) # self.setCategoryDescription(node.category) return self @classmethod def from_node_meta(cls, meta_description): """ Create an `NodeItem` instance from a node meta description. """ self = cls() self.setWidgetDescription(meta_description) return self def setupGraphics(self): """ Set up the graphics. """ shape_rect = QRectF(-24, -24, 48, 48) self.shapeItem = NodeBodyItem(self) self.shapeItem.setShapeRect(shape_rect) self.shapeItem.setAnimationEnabled(self.__animationEnabled) # Rect for widget's 'ears'. anchor_rect = QRectF(-31, -31, 62, 62) self.inputAnchorItem = SinkAnchorItem(self) input_path = QPainterPath() start_angle = 180 - self.ANCHOR_SPAN_ANGLE / 2 input_path.arcMoveTo(anchor_rect, start_angle) input_path.arcTo(anchor_rect, start_angle, self.ANCHOR_SPAN_ANGLE) self.inputAnchorItem.setAnchorPath(input_path) self.outputAnchorItem = SourceAnchorItem(self) output_path = QPainterPath() start_angle = self.ANCHOR_SPAN_ANGLE / 2 output_path.arcMoveTo(anchor_rect, start_angle) output_path.arcTo(anchor_rect, start_angle, -self.ANCHOR_SPAN_ANGLE) self.outputAnchorItem.setAnchorPath(output_path) self.inputAnchorItem.hide() self.outputAnchorItem.hide() # Title caption item self.captionTextItem = QGraphicsTextItem(self) self.captionTextItem.setPlainText("") self.captionTextItem.setPos(0, 33) def iconItem(standard_pixmap): item = GraphicsIconItem(self, icon=standard_icon(standard_pixmap), iconSize=QSize(16, 16)) item.hide() return item self.errorItem = iconItem(QStyle.SP_MessageBoxCritical) self.warningItem = iconItem(QStyle.SP_MessageBoxWarning) self.infoItem = iconItem(QStyle.SP_MessageBoxInformation) # TODO: Remove the set[Widget|Category]Description. The user should # handle setting of icons, title, ... def setWidgetDescription(self, desc): """ Set widget description. """ self.widget_description = desc if desc is None: return icon = icon_loader.from_description(desc).get(desc.icon) if icon: self.setIcon(icon) if not self.title(): self.setTitle(desc.name) if desc.inputs: self.inputAnchorItem.show() if desc.outputs: self.outputAnchorItem.show() tooltip = NodeItem_toolTipHelper(self) self.setToolTip(tooltip) def setWidgetCategory(self, desc): """ Set the widget category. """ self.category_description = desc if desc and desc.background: background = NAMED_COLORS.get(desc.background, desc.background) color = QColor(background) if color.isValid(): self.setColor(color) def setIcon(self, icon): """ Set the node item's icon (:class:`QIcon`). """ if isinstance(icon, QIcon): self.icon_item = GraphicsIconItem(self.shapeItem, icon=icon, iconSize=QSize(36, 36)) self.icon_item.setPos(-18, -18) else: raise TypeError def setColor(self, color, selectedColor=None): """ Set the widget color. """ if selectedColor is None: selectedColor = saturated(color, 150) palette = create_palette(color, selectedColor) self.shapeItem.setPalette(palette) def setPalette(self, palette): # TODO: The palette should override the `setColor` raise NotImplementedError def setTitle(self, title): """ Set the node title. The title text is displayed at the bottom of the node. """ self.__title = title self.__updateTitleText() def title(self): """ Return the node title. """ return self.__title title_ = Property(unicode, fget=title, fset=setTitle, doc="Node title text.") def setFont(self, font): """ Set the title text font (:class:`QFont`). """ if font != self.font(): self.prepareGeometryChange() self.captionTextItem.setFont(font) self.__updateTitleText() def font(self): """ Return the title text font. """ return self.captionTextItem.font() def setAnimationEnabled(self, enabled): """ Set the node animation enabled state. """ if self.__animationEnabled != enabled: self.__animationEnabled = enabled self.shapeItem.setAnimationEnabled(enabled) def animationEnabled(self): """ Are node animations enabled. """ return self.__animationEnabled def setProcessingState(self, state): """ Set the node processing state i.e. the node is processing (is busy) or is idle. """ if self.__processingState != state: self.__processingState = state self.shapeItem.setProcessingState(state) if not state: # Clear the progress meter. self.setProgress(-1) if self.__animationEnabled: self.shapeItem.ping() def processingState(self): """ The node processing state. """ return self.__processingState processingState_ = Property(int, fget=processingState, fset=setProcessingState) def setProgress(self, progress): """ Set the node work progress state (number between 0 and 100). """ if progress is None or progress < 0: progress = -1 progress = max(min(progress, 100), -1) if self.__progress != progress: self.__progress = progress self.shapeItem.setProgress(progress) self.__updateTitleText() def progress(self): """ Return the node work progress state. """ return self.__progress progress_ = Property(float, fget=progress, fset=setProgress, doc="Node progress state.") def setProgressMessage(self, message): """ Set the node work progress message. .. note:: Not yet implemented """ pass def setErrorMessage(self, message): if self.__error != message: self.__error = message self.__updateMessages() def setWarningMessage(self, message): if self.__warning != message: self.__warning = message self.__updateMessages() def setInfoMessage(self, message): if self.__info != message: self.__info = message self.__updateMessages() def newInputAnchor(self): """ Create and return a new input :class:`AnchorPoint`. """ if not (self.widget_description and self.widget_description.inputs): raise ValueError("Widget has no inputs.") anchor = AnchorPoint() self.inputAnchorItem.addAnchor(anchor, position=1.0) positions = self.inputAnchorItem.anchorPositions() positions = uniform_linear_layout(positions) self.inputAnchorItem.setAnchorPositions(positions) return anchor def removeInputAnchor(self, anchor): """ Remove input anchor. """ self.inputAnchorItem.removeAnchor(anchor) positions = self.inputAnchorItem.anchorPositions() positions = uniform_linear_layout(positions) self.inputAnchorItem.setAnchorPositions(positions) def newOutputAnchor(self): """ Create and return a new output :class:`AnchorPoint`. """ if not (self.widget_description and self.widget_description.outputs): raise ValueError("Widget has no outputs.") anchor = AnchorPoint(self) self.outputAnchorItem.addAnchor(anchor, position=1.0) positions = self.outputAnchorItem.anchorPositions() positions = uniform_linear_layout(positions) self.outputAnchorItem.setAnchorPositions(positions) return anchor def removeOutputAnchor(self, anchor): """ Remove output anchor. """ self.outputAnchorItem.removeAnchor(anchor) positions = self.outputAnchorItem.anchorPositions() positions = uniform_linear_layout(positions) self.outputAnchorItem.setAnchorPositions(positions) def inputAnchors(self): """ Return a list of all input anchor points. """ return self.inputAnchorItem.anchorPoints() def outputAnchors(self): """ Return a list of all output anchor points. """ return self.outputAnchorItem.anchorPoints() def setAnchorRotation(self, angle): """ Set the anchor rotation. """ self.inputAnchorItem.setRotation(angle) self.outputAnchorItem.setRotation(angle) self.anchorGeometryChanged.emit() def anchorRotation(self): """ Return the anchor rotation. """ return self.inputAnchorItem.rotation() def boundingRect(self): # TODO: Important because of this any time the child # items change geometry the self.prepareGeometryChange() # needs to be called. return self.childrenBoundingRect() def shape(self): # Shape for mouse hit detection. # TODO: Should this return the union of all child items? return self.shapeItem.shape() def __updateTitleText(self): """ Update the title text item. """ title_safe = escape(self.title()) if self.progress() > 0: text = '<div align="center">%s<br/>%i%%</div>' % \ (title_safe, int(self.progress())) else: text = '<div align="center">%s</div>' % \ (title_safe) # The NodeItems boundingRect could change. self.prepareGeometryChange() self.captionTextItem.setHtml(text) self.captionTextItem.document().adjustSize() width = self.captionTextItem.textWidth() self.captionTextItem.setPos(-width / 2.0, 33) def __updateMessages(self): """ Update message items (position, visibility and tool tips). """ items = [self.errorItem, self.warningItem, self.infoItem] messages = [self.__error, self.__warning, self.__info] for message, item in zip(messages, items): item.setVisible(bool(message)) item.setToolTip(message or "") shown = [item for item in items if item.isVisible()] count = len(shown) if count: spacing = 3 rects = [item.boundingRect() for item in shown] width = sum(rect.width() for rect in rects) width += spacing * max(0, count - 1) height = max(rect.height() for rect in rects) origin = self.shapeItem.boundingRect().top() - spacing - height origin = QPointF(-width / 2, origin) for item, rect in zip(shown, rects): item.setPos(origin) origin = origin + QPointF(rect.width() + spacing, 0) def mousePressEvent(self, event): if self.shapeItem.path().contains(event.pos()): return QGraphicsObject.mousePressEvent(self, event) else: event.ignore() def mouseDoubleClickEvent(self, event): if self.shapeItem.path().contains(event.pos()): QGraphicsObject.mouseDoubleClickEvent(self, event) QTimer.singleShot(0, self.activated.emit) else: event.ignore() def contextMenuEvent(self, event): if self.shapeItem.path().contains(event.pos()): return QGraphicsObject.contextMenuEvent(self, event) else: event.ignore() def focusInEvent(self, event): self.shapeItem.setHasFocus(True) return QGraphicsObject.focusInEvent(self, event) def focusOutEvent(self, event): self.shapeItem.setHasFocus(False) return QGraphicsObject.focusOutEvent(self, event) def itemChange(self, change, value): if change == QGraphicsItem.ItemSelectedChange: self.shapeItem.setSelected(value.toBool()) elif change == QGraphicsItem.ItemPositionHasChanged: self.positionChanged.emit() return QGraphicsObject.itemChange(self, change, value)
class CanvasProps (QGraphicsItem): def __init__(self, parent=None, scene=None): QGraphicsItem.__init__ (self) self.parent = parent self.helper = self.parent.getHelper() #self.setFlags (QGraphicsItem.ItemIsSelectable) self.setAcceptsHoverEvents (True) self.pen_color = QPen (Qt.black, 2) self.color = QColor (Qt.white).dark (150) # init Canvas Animation Tweening self.timeline = QTimeLine (200) self.timeline.setFrameRange (0, 100) self.anim = QGraphicsItemAnimation () self.anim.setItem (self) self.anim.setTimeLine (self.timeline) self.helper.connect (self.timeline, SIGNAL("finished()"), self.moveFurtherUp) self.anim_active = False #self._nodename = QGraphicsTextItem ('text '+str(self.node_id), self) self._nodename = QGraphicsTextItem ('', self) self._nodename.setPos (QPointF (18, 20)) self._nodename.setDefaultTextColor (QColor (Qt.white).light (255)) self._nodename.setFont (QFont ("Helvetica", 11, QFont.Bold, False)) self._nodename.setTextWidth(120) self._nodename.setToolTip (self._nodename.toPlainText ()) #self._nodename.setHtml("<h2 align=\"center\">hello</h2><h2 align=\"center\">world 1234345345</h2>123"); self.props_list = [] self.props_textItem_value_list = [] self.FACTOR = 4.0 self._canvas_height = 0 def boundingRect (self): return QRectF (0, 0, 122, 150) def shape (self): path = QPainterPath () path.addRect (0, 0, 122, 20) return path def paint (self, painter, option, unused_widget): if option.state & QStyle.State_Selected: fillColor = self.color.dark (100) else: fillColor = self.color if option.state & QStyle.State_MouseOver: fillColor = fillColor.light (120) if option.levelOfDetail < 0.2: if option.levelOfDetail < 0.125: painter.fillRect (QRectF (0, 0, 110, 70), fillColor) return painter.setPen (QPen (Qt.black, 0)) painter.setBrush (fillColor) painter.drawRect (0, 0, 120, 20) return oldPen = painter.pen () pen = oldPen width = 0 if option.state & QStyle.State_Selected: width += 2 pen.setWidth (width) if option.state & QStyle.State_Sunken: level = 120 else: level = 100 painter.setBrush (QBrush (fillColor.dark (level))) #painter.drawRoundRect (QRect (0, 0, 80, 34+self.height), 20) painter.drawRect (QRect (0, 20, 120, 30+9*self._canvas_height)) # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def addProp (self, prop_name, prop_value): i = len (self.props_list) self.props_list.append (QGraphicsTextItem (prop_name + ' : ', self)) self.props_textItem_value_list.append (CustomFloatingText (prop_value, self)) # (1) adding the prop's name. self.props_list[i].setPos (QPointF (7, 35+i*10)) self.props_list[i].setDefaultTextColor (QColor (Qt.white).light (255)) self.props_list[i].setFont (QFont ("Helvetica", 9, QFont.StyleItalic, False)) self.props_list[i].setTextWidth (55) self.props_list[i].setToolTip (self.props_list[i].toPlainText ()) # (2) adding the prop's value. self.props_textItem_value_list[i].setTextInteractionFlags (Qt.TextEditable) self.props_textItem_value_list[i].setPos (QPointF (55, 35+i*10)) self.props_textItem_value_list[i].setDefaultTextColor (QColor (Qt.white).light (255)) self.props_textItem_value_list[i].setFont (QFont ("Helvetica", 9, QFont.StyleNormal, False)) self.props_textItem_value_list[i].setTextWidth (55) receiver = lambda value: self.parent.listenToChangedPropsValues (prop_name, value) self.helper.connect (self.props_textItem_value_list[i], SIGNAL ("textChanged(QString)"), receiver) def getProps (self): tmp_list = [] l = len (self.props_list) for i in range (0, l): tmp_list[i] = [self.props_list[i].toPlainText(), self.props_textItem_value_list[i].toPlainText()] return tmp_list def setTitle (self, title): self._nodename.setPlainText (title) def setCanvasHeightInUnits (self, ch): self._canvas_height = ch # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def moveDown (self, canvas_height_in_units): self.anim_active = True self.upwards_flag = False self.canvas_height = canvas_height_in_units self.timeline.stop () self.anim.setPosAt (0, QPointF(0, 1+(self.canvas_height+1)*self.FACTOR)) self.anim.setPosAt (1, QPointF(0, 1+(self.canvas_height+2)*self.FACTOR)) self.timeline.start () self.update () def moveUp (self, canvas_height_in_units): if self.anim_active == False: self.anim_active = True self.upwards_flag = True self.canvas_height = canvas_height_in_units self.timeline.stop () self.anim.setPosAt (0, QPointF(0, 1+(self.canvas_height+1)*self.FACTOR)) self.anim.setPosAt (1, QPointF(0, 1+(self.canvas_height) *self.FACTOR)) self.timeline.start () self.update () # this method double-checks whether the canvas needs to be further up as a # result of receiving other asynchronous "delete link" SIGNALs while moving up. def moveFurtherUp (self): self.anim_active = False if self.upwards_flag==True: if self.parent.getMaxLen() < self.canvas_height: self.moveUp (self.canvas_height-1) # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def hoverEnterEvent (self, e): self._nodename.setToolTip (self._nodename.toPlainText ()) QGraphicsItem.hoverEnterEvent (self, e) '''
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() )
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 hexView(QGraphicsView): def __init__(self, parent): QGraphicsView.__init__(self) self.init(parent) self.initShape() def init(self, parent): self.whex = parent self.bdiff = self.whex.bdiff #Init scene self.scene = QGraphicsScene() self.setScene(self.scene) #Get bdiff stuff self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setAlignment(Qt.AlignLeft) def setItems(self): self.scene.addItem(self.whex.offsetitem) self.scene.addItem(self.whex.hexitem) self.scene.addItem(self.whex.asciitem) def initShape(self): self.initHeads() #Line decoration offsetLine = QGraphicsLineItem(QLineF(90, 0, 90, 700)) asciiLine = QGraphicsLineItem(QLineF(480, 0, 480, 700)) #Add to scene self.scene.addItem(offsetLine) self.scene.addItem(asciiLine) def initHeads(self): self.offHead = QGraphicsTextItem() self.hexHead = QGraphicsTextItem() self.asciiHead = QGraphicsTextItem() #Set Color self.offHead.setDefaultTextColor(QColor(Qt.red)) self.hexHead.setDefaultTextColor(QColor(Qt.black)) self.asciiHead.setDefaultTextColor(QColor(Qt.darkCyan)) #Create Font self.font = QFont("Gothic") self.font.setFixedPitch(1) self.font.setBold(False) self.font.setPixelSize(14) #Set Font self.offHead.setFont(self.font) self.hexHead.setFont(self.font) self.asciiHead.setFont(self.font) #Set Text self.offHead.setPlainText("Offset") self.hexHead.setPlainText("0 1 2 3 4 5 6 7 8 9 A B C D E F") self.asciiHead.setPlainText("Ascii") #Position self.offHead.setPos(20, 0) self.hexHead.setPos(95, 0) self.asciiHead.setPos(520, 0) #Add to scene self.scene.addItem(self.offHead) self.scene.addItem(self.hexHead) self.scene.addItem(self.asciiHead) headLine = QGraphicsLineItem(QLineF(0, 20, 615, 20)) self.scene.addItem(headLine) def setSyncView(self, whexview): self.whexviewsync = whexview def move(self, step, way): #step: line = 1 * bytesPerLine, page = pagesize, wheel = 3 * bytesPerLine offset = self.bdiff.currentOffset # print offset if way == 0: #UP if (offset - (step * self.bdiff.bytesPerLine)) >= 0: self.bdiff.readOffset(offset - (step * self.bdiff.bytesPerLine)) if self.bdiff.scrollbar.isLFMOD(): self.bdiff.scrollbar.setValue(self.bdiff.scrollbar.offsetToValue(offset - (step * self.bdiff.bytesPerLine))) else: self.bdiff.scrollbar.setValue(self.bdiff.scrollbar.value() - step) else: self.bdiff.readOffset(0) self.bdiff.scrollbar.setValue(0) elif way == 1: #Down if (offset + (step * self.bdiff.bytesPerLine)) <= (self.bdiff.masterFileSize - (step * self.bdiff.bytesPerLine)): self.bdiff.readOffset(offset + (step * self.bdiff.bytesPerLine)) if self.bdiff.scrollbar.isLFMOD(): self.bdiff.scrollbar.setValue(self.bdiff.scrollbar.offsetToValue(offset + (step * self.bdiff.bytesPerLine))) else: self.bdiff.scrollbar.setValue(self.bdiff.scrollbar.value() + step) else: self.bdiff.readOffset(self.bdiff.masterFileSize - 5 * (self.bdiff.bytesPerLine)) self.bdiff.scrollbar.setValue(self.bdiff.scrollbar.max) #################################### # Navigation Operations # #################################### def wheelEvent(self, event): offset = self.bdiff.currentOffset if event.delta() > 0: self.move(3, 0) self.whexviewsync.move(3, 0) else: self.move(3, 1) self.whexviewsync.move(3, 1) def keyPressEvent(self, keyEvent): off = self.bdiff.currentOffset if keyEvent.matches(QKeySequence.MoveToNextPage): self.move(self.bdiff.pageSize / self.bdiff.bytesPerLine, 1) self.whexviewsync.move(self.bdiff.pageSize / self.bdiff.bytesPerLine, 1) elif keyEvent.matches(QKeySequence.MoveToPreviousPage): self.move(self.bdiff.pageSize / self.bdiff.bytesPerLine, 0) self.whexviewsync.move(self.bdiff.pageSize / self.bdiff.bytesPerLine, 0) elif keyEvent.matches(QKeySequence.MoveToNextLine): self.move(1, 1) self.whexviewsync.move(1, 1) elif keyEvent.matches(QKeySequence.MoveToPreviousLine): self.move(1, 0) self.whexviewsync.move(1, 0)
class ItemUsuario(ItemMovel): def __init__(self, usuario, rect=QRectF(0, 0, 100, 50), parent=None): super().__init__(False, True, rect, parent) self._numConversasNaoVisualizadas = 0 self.selected = False self._textItem = QGraphicsTextItem(self) self._textItem.setFont(self.fontUser()) self._textItem.setPos(0, 10) self.setaImg = ResourceUtil.getImage('images/right.png').scaled(80, 40, aspectRatioMode=Qt.KeepAspectRatio) self.topoImg = ResourceUtil.getImage('images/fundo/topo.png') self.background = ResourceUtil.getImage('images/postit3.png') self.setUsuario(usuario) def setUsuario(self, usuario): self._usuario = usuario self.atualizaTexto() def getUsuario(self): return self._usuario def setNumConversasNaoVisualizadas(self, num): self._numConversasNaoVisualizadas = num self.atualizaTexto() def atualizaTexto(self): texto = "<center>{0} - {1}".format(self._usuario.getNome(), self._usuario.getIP()) if self._numConversasNaoVisualizadas > 0: texto += " <b>({0})</b>".format(self._numConversasNaoVisualizadas) texto += "</center>" self._textItem.setHtml(texto) def setRect(self, rect): super().setRect(rect) self._textItem.setTextWidth(rect.size().width() - self.setaImg.rect().width()) def paint(self, painter, widget, option): painter.setPen(Qt.NoPen) if self.selected: rect = self.boundingRect() rectImg = self.setaImg.rect() painter.drawImage(rectImg.adjusted(rect.width() - rectImg.width(), 0, rect.width() - rectImg.width(), 0), self.setaImg) painter.drawImage(self.boundingRect(), self.background) """if self.isUnderMouse(): painter.drawImage(self.boundingRect().adjusted(0,10,0,0), self.topoImg) painter.save() painter.setPen(Qt.NoPen) st = Status.getInstance(self.getUsuario().getStatus()) if st == Status.ONLINE: painter.setBrush(QColor(0,255,0,50)) elif st == Status.OCUPADO: painter.setBrush(QColor(255,0,0,50)) elif st == Status.AUSENTE: painter.setBrush(QColor(240, 226, 31, 50)) painter.drawRoundedRect(self.getRect(), 7, 5) painter.restore()""" super().paint(painter, widget, option) def fontUser(self): font = QFont("LoveYaLikeASister") font.setBold(True) return font
class TaskGraphicsItem (QGraphicsEllipseItem): def __init__(self, rect=None): super(TaskGraphicsItem, self).__init__() if rect is not None: self.setRect(rect) self.setPen(QPen(Qt.NoPen)) # Setup the text item self.textItem = QGraphicsTextItem() self.textItem.setParentItem(self) self.textItem.rotate(-90) self.textItem.setDefaultTextColor(QColor(255, 255, 255)) # The dimensions to reach via a LERP. self.startPos = QPointF(0, 0) self.endPos = QPointF(0, 0) self.startDiameter = 1 self.endDiameter = 1 self.centerMark = QGraphicsEllipseItem() self.centerMark.setBrush(QBrush(Qt.white)) self.centerMark.setPen(QPen(Qt.NoPen)) self.centerMark.setParentItem(self) self.pid = -1 # To determine if it is associated with an active process. self.used = False def mousePressEvent(self, event): print "Clicked On Ellipse at: ", self.rect().topLeft() def set_pid(self, pid): self.pid = pid def set_name(self, str_name): self.textItem.setPlainText(str_name) def update_name_pos(self): rect = self.boundingRect() text_rect = self.textItem.boundingRect() # Center text (on the x-axis) and offset (on the y-axis) so it doesn't overlap the ellipse item. x_text = rect.x() + rect.width()/2 - text_rect.height()/2 y_text = rect.y() + 100 + text_rect.width() + rect.height() self.textItem.setPos(x_text, y_text) # Time step is in seconds. def update(self, time_step): diameter = self.rect().width() + self.lerp_rate(self.startDiameter, self.endDiameter, time_step) if diameter <= 1: diameter = 1 pos = self.rect().topLeft() x = pos.x() + self.lerp_rate(self.startPos.x(), self.endPos.x(), time_step) y = pos.y() + self.lerp_rate(self.startPos.y(), self.endPos.y(), time_step) self.setRect(QRectF(x, y, diameter, diameter)) self.update_name_pos() self.update_center_mark() def update_center_mark(self): scale = self.scene().views()[0].currentScale hwidth = self.rect().width() / 2.0 diam = 2.0 / scale # Only mark center for large enough items. if hwidth * 0.2 > diam: self.centerMark.setVisible(True) hdiam = diam / 2.0 pos = self.rect().topLeft() x = pos.x() - hdiam + hwidth y = pos.y() - hdiam + hwidth self.centerMark.setRect(QRectF(x, y, diam, diam)) else: self.centerMark.setVisible(False) # Return the linear interpolation rate. Reach start to end at a rate of 'growth rate' @staticmethod def lerp_rate(start, end, time_step): return (end - start) * time_step