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 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 label(self): if self._label: return self._label label = QGraphicsTextItem("") label.setVisible(False) label.setFont(self._font) label.setParentItem(self) label.setTextInteractionFlags(Qt.TextEditorInteraction) label.inputMethodEvent = self.inputProcess self._label = label self._label.hide() return label
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 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 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)
class OWLegendTitle(QGraphicsObject): """ A legend item that shows ``text`` with a bold font and no symbol. """ def __init__(self, text, parent): QGraphicsObject.__init__(self, parent) self.text_item = QGraphicsTextItem(text + ':', self) f = self.text_item.font() f.setBold(True) self.text_item.setFont(f) self.rect_item = QGraphicsRectItem(self.text_item.boundingRect(), self) self.rect_item.setPen(QPen(Qt.NoPen)) self.rect_item.stackBefore(self.text_item) def boundingRect(self): return self.text_item.boundingRect() 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 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 LinkItem(QGraphicsObject): """ A Link item in the canvas that connects two :class:`.NodeItem`\s in the canvas. The link curve connects two `Anchor` items (see :func:`setSourceItem` and :func:`setSinkItem`). Once the anchors are set the curve automatically adjusts its end points whenever the anchors move. An optional source/sink text item can be displayed above the curve's central point (:func:`setSourceName`, :func:`setSinkName`) """ #: Z value of the item Z_VALUE = 0 def __init__(self, *args): QGraphicsObject.__init__(self, *args) self.setFlag(QGraphicsItem.ItemHasNoContents, True) self.setAcceptedMouseButtons(Qt.RightButton | Qt.LeftButton) self.setAcceptHoverEvents(True) self.setZValue(self.Z_VALUE) self.sourceItem = None self.sourceAnchor = None self.sinkItem = None self.sinkAnchor = None self.curveItem = LinkCurveItem(self) self.sourceIndicator = LinkAnchorIndicator(self) self.sinkIndicator = LinkAnchorIndicator(self) self.sourceIndicator.hide() self.sinkIndicator.hide() self.linkTextItem = QGraphicsTextItem(self) self.__sourceName = "" self.__sinkName = "" self.__dynamic = False self.__dynamicEnabled = False self.hover = False def setSourceItem(self, item, anchor=None): """ Set the source `item` (:class:`.NodeItem`). Use `anchor` (:class:`.AnchorPoint`) as the curve start point (if ``None`` a new output anchor will be created using ``item.newOutputAnchor()``). Setting item to ``None`` and a valid anchor is a valid operation (for instance while mouse dragging one end of the link). """ if item is not None and anchor is not None: if anchor not in item.outputAnchors(): raise ValueError("Anchor must be belong to the item") if self.sourceItem != item: if self.sourceAnchor: # Remove a previous source item and the corresponding anchor self.sourceAnchor.scenePositionChanged.disconnect( self._sourcePosChanged ) if self.sourceItem is not None: self.sourceItem.removeOutputAnchor(self.sourceAnchor) self.sourceItem = self.sourceAnchor = None self.sourceItem = item if item is not None and anchor is None: # Create a new output anchor for the item if none is provided. anchor = item.newOutputAnchor() # Update the visibility of the start point indicator. self.sourceIndicator.setVisible(bool(item)) if anchor != self.sourceAnchor: if self.sourceAnchor is not None: self.sourceAnchor.scenePositionChanged.disconnect( self._sourcePosChanged ) self.sourceAnchor = anchor if self.sourceAnchor is not None: self.sourceAnchor.scenePositionChanged.connect( self._sourcePosChanged ) self.__updateCurve() def setSinkItem(self, item, anchor=None): """ Set the sink `item` (:class:`.NodeItem`). Use `anchor` (:class:`.AnchorPoint`) as the curve end point (if ``None`` a new input anchor will be created using ``item.newInputAnchor()``). Setting item to ``None`` and a valid anchor is a valid operation (for instance while mouse dragging one and of the link). """ if item is not None and anchor is not None: if anchor not in item.inputAnchors(): raise ValueError("Anchor must be belong to the item") if self.sinkItem != item: if self.sinkAnchor: # Remove a previous source item and the corresponding anchor self.sinkAnchor.scenePositionChanged.disconnect( self._sinkPosChanged ) if self.sinkItem is not None: self.sinkItem.removeInputAnchor(self.sinkAnchor) self.sinkItem = self.sinkAnchor = None self.sinkItem = item if item is not None and anchor is None: # Create a new input anchor for the item if none is provided. anchor = item.newInputAnchor() # Update the visibility of the end point indicator. self.sinkIndicator.setVisible(bool(item)) if self.sinkAnchor != anchor: if self.sinkAnchor is not None: self.sinkAnchor.scenePositionChanged.disconnect( self._sinkPosChanged ) self.sinkAnchor = anchor if self.sinkAnchor is not None: self.sinkAnchor.scenePositionChanged.connect( self._sinkPosChanged ) self.__updateCurve() def setFont(self, font): """ Set the font for the channel names text item. """ if font != self.font(): self.linkTextItem.setFont(font) self.__updateText() def font(self): """ Return the font for the channel names text. """ return self.linkTextItem.font() def setChannelNamesVisible(self, visible): """ Set the visibility of the channel name text. """ self.linkTextItem.setVisible(visible) def setSourceName(self, name): """ Set the name of the source (used in channel name text). """ if self.__sourceName != name: self.__sourceName = name self.__updateText() def sourceName(self): """ Return the source name. """ return self.__sourceName def setSinkName(self, name): """ Set the name of the sink (used in channel name text). """ if self.__sinkName != name: self.__sinkName = name self.__updateText() def sinkName(self): """ Return the sink name. """ return self.__sinkName def _sinkPosChanged(self, *arg): self.__updateCurve() def _sourcePosChanged(self, *arg): self.__updateCurve() def __updateCurve(self): self.prepareGeometryChange() if self.sourceAnchor and self.sinkAnchor: source_pos = self.sourceAnchor.anchorScenePos() sink_pos = self.sinkAnchor.anchorScenePos() source_pos = self.curveItem.mapFromScene(source_pos) sink_pos = self.curveItem.mapFromScene(sink_pos) # Adaptive offset for the curve control points to avoid a # cusp when the two points have the same y coordinate # and are close together delta = source_pos - sink_pos dist = math.sqrt(delta.x() ** 2 + delta.y() ** 2) cp_offset = min(dist / 2.0, 60.0) # TODO: make the curve tangent orthogonal to the anchors path. path = QPainterPath() path.moveTo(source_pos) path.cubicTo(source_pos + QPointF(cp_offset, 0), sink_pos - QPointF(cp_offset, 0), sink_pos) self.curveItem.setPath(path) self.sourceIndicator.setPos(source_pos) self.sinkIndicator.setPos(sink_pos) self.__updateText() else: self.setHoverState(False) self.curveItem.setPath(QPainterPath()) def __updateText(self): self.prepareGeometryChange() if self.__sourceName or self.__sinkName: if self.__sourceName != self.__sinkName: text = u"{0} \u2192 {1}".format(self.__sourceName, self.__sinkName) else: # If the names are the same show only one. # Is this right? If the sink has two input channels of the # same type having the name on the link help elucidate # the scheme. text = self.__sourceName else: text = "" self.linkTextItem.setPlainText(text) path = self.curveItem.path() if not path.isEmpty(): center = path.pointAtPercent(0.5) angle = path.angleAtPercent(0.5) brect = self.linkTextItem.boundingRect() transform = QTransform() transform.translate(center.x(), center.y()) transform.rotate(-angle) # Center and move above the curve path. transform.translate(-brect.width() / 2, -brect.height()) self.linkTextItem.setTransform(transform) def removeLink(self): self.setSinkItem(None) self.setSourceItem(None) self.__updateCurve() def setHoverState(self, state): if self.hover != state: self.prepareGeometryChange() self.hover = state self.sinkIndicator.setHoverState(state) self.sourceIndicator.setHoverState(state) self.curveItem.setHoverState(state) def hoverEnterEvent(self, event): # Hover enter event happens when the mouse enters any child object # but we only want to show the 'hovered' shadow when the mouse # is over the 'curveItem', so we install self as an event filter # on the LinkCurveItem and listen to its hover events. self.curveItem.installSceneEventFilter(self) return QGraphicsObject.hoverEnterEvent(self, event) def hoverLeaveEvent(self, event): # Remove the event filter to prevent unnecessary work in # scene event filter when not needed self.curveItem.removeSceneEventFilter(self) return QGraphicsObject.hoverLeaveEvent(self, event) def sceneEventFilter(self, obj, event): if obj is self.curveItem: if event.type() == QEvent.GraphicsSceneHoverEnter: self.setHoverState(True) elif event.type() == QEvent.GraphicsSceneHoverLeave: self.setHoverState(False) return QGraphicsObject.sceneEventFilter(self, obj, event) def boundingRect(self): return self.childrenBoundingRect() def shape(self): return self.curveItem.shape() def setEnabled(self, enabled): """ Reimplemented from :class:`QGraphicsObject` Set link enabled state. When disabled the link is rendered with a dashed line. """ # This getter/setter pair override a property from the base class. # They should be renamed to e.g. setLinkEnabled/linkEnabled self.curveItem.setLinkEnabled(enabled) def isEnabled(self): return self.curveItem.isLinkEnabled() def setDynamicEnabled(self, enabled): """ Set the link's dynamic enabled state. If the link is `dynamic` it will be rendered in red/green color respectively depending on the state of the dynamic enabled state. """ if self.__dynamicEnabled != enabled: self.__dynamicEnabled = enabled if self.__dynamic: self.__updatePen() def isDynamicEnabled(self): """ Is the link dynamic enabled. """ return self.__dynamicEnabled def setDynamic(self, dynamic): """ Mark the link as dynamic (i.e. it responds to :func:`setDynamicEnabled`). """ if self.__dynamic != dynamic: self.__dynamic = dynamic self.__updatePen() def isDynamic(self): """ Is the link dynamic. """ return self.__dynamic def __updatePen(self): self.prepareGeometryChange() if self.__dynamic: if self.__dynamicEnabled: color = QColor(0, 150, 0, 150) else: color = QColor(150, 0, 0, 150) normal = QPen(QBrush(color), 2.0) hover = QPen(QBrush(color.darker(120)), 2.1) else: normal = QPen(QBrush(QColor("#9CACB4")), 2.0) hover = QPen(QBrush(QColor("#7D7D7D")), 2.1) self.curveItem.setCurvePenSet(normal, hover)
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) '''
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 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 LinkItem(QGraphicsObject): """ A Link item in the canvas that connects two :class:`.NodeItem`\s in the canvas. The link curve connects two `Anchor` items (see :func:`setSourceItem` and :func:`setSinkItem`). Once the anchors are set the curve automatically adjusts its end points whenever the anchors move. An optional source/sink text item can be displayed above the curve's central point (:func:`setSourceName`, :func:`setSinkName`) """ #: Z value of the item Z_VALUE = 0 def __init__(self, *args): QGraphicsObject.__init__(self, *args) self.setFlag(QGraphicsItem.ItemHasNoContents, True) self.setAcceptedMouseButtons(Qt.RightButton | Qt.LeftButton) self.setAcceptHoverEvents(True) self.setZValue(self.Z_VALUE) self.sourceItem = None self.sourceAnchor = None self.sinkItem = None self.sinkAnchor = None self.curveItem = LinkCurveItem(self) self.sourceIndicator = LinkAnchorIndicator(self) self.sinkIndicator = LinkAnchorIndicator(self) self.sourceIndicator.hide() self.sinkIndicator.hide() self.linkTextItem = QGraphicsTextItem(self) self.__sourceName = "" self.__sinkName = "" self.__dynamic = False self.__dynamicEnabled = False self.hover = False def setSourceItem(self, item, anchor=None): """ Set the source `item` (:class:`.NodeItem`). Use `anchor` (:class:`.AnchorPoint`) as the curve start point (if ``None`` a new output anchor will be created using ``item.newOutputAnchor()``). Setting item to ``None`` and a valid anchor is a valid operation (for instance while mouse dragging one end of the link). """ if item is not None and anchor is not None: if anchor not in item.outputAnchors(): raise ValueError("Anchor must be belong to the item") if self.sourceItem != item: if self.sourceAnchor: # Remove a previous source item and the corresponding anchor self.sourceAnchor.scenePositionChanged.disconnect( self._sourcePosChanged) if self.sourceItem is not None: self.sourceItem.removeOutputAnchor(self.sourceAnchor) self.sourceItem = self.sourceAnchor = None self.sourceItem = item if item is not None and anchor is None: # Create a new output anchor for the item if none is provided. anchor = item.newOutputAnchor() # Update the visibility of the start point indicator. self.sourceIndicator.setVisible(bool(item)) if anchor != self.sourceAnchor: if self.sourceAnchor is not None: self.sourceAnchor.scenePositionChanged.disconnect( self._sourcePosChanged) self.sourceAnchor = anchor if self.sourceAnchor is not None: self.sourceAnchor.scenePositionChanged.connect( self._sourcePosChanged) self.__updateCurve() def setSinkItem(self, item, anchor=None): """ Set the sink `item` (:class:`.NodeItem`). Use `anchor` (:class:`.AnchorPoint`) as the curve end point (if ``None`` a new input anchor will be created using ``item.newInputAnchor()``). Setting item to ``None`` and a valid anchor is a valid operation (for instance while mouse dragging one and of the link). """ if item is not None and anchor is not None: if anchor not in item.inputAnchors(): raise ValueError("Anchor must be belong to the item") if self.sinkItem != item: if self.sinkAnchor: # Remove a previous source item and the corresponding anchor self.sinkAnchor.scenePositionChanged.disconnect( self._sinkPosChanged) if self.sinkItem is not None: self.sinkItem.removeInputAnchor(self.sinkAnchor) self.sinkItem = self.sinkAnchor = None self.sinkItem = item if item is not None and anchor is None: # Create a new input anchor for the item if none is provided. anchor = item.newInputAnchor() # Update the visibility of the end point indicator. self.sinkIndicator.setVisible(bool(item)) if self.sinkAnchor != anchor: if self.sinkAnchor is not None: self.sinkAnchor.scenePositionChanged.disconnect( self._sinkPosChanged) self.sinkAnchor = anchor if self.sinkAnchor is not None: self.sinkAnchor.scenePositionChanged.connect( self._sinkPosChanged) self.__updateCurve() def setFont(self, font): """ Set the font for the channel names text item. """ if font != self.font(): self.linkTextItem.setFont(font) self.__updateText() def font(self): """ Return the font for the channel names text. """ return self.linkTextItem.font() def setChannelNamesVisible(self, visible): """ Set the visibility of the channel name text. """ self.linkTextItem.setVisible(visible) def setSourceName(self, name): """ Set the name of the source (used in channel name text). """ if self.__sourceName != name: self.__sourceName = name self.__updateText() def sourceName(self): """ Return the source name. """ return self.__sourceName def setSinkName(self, name): """ Set the name of the sink (used in channel name text). """ if self.__sinkName != name: self.__sinkName = name self.__updateText() def sinkName(self): """ Return the sink name. """ return self.__sinkName def _sinkPosChanged(self, *arg): self.__updateCurve() def _sourcePosChanged(self, *arg): self.__updateCurve() def __updateCurve(self): self.prepareGeometryChange() if self.sourceAnchor and self.sinkAnchor: source_pos = self.sourceAnchor.anchorScenePos() sink_pos = self.sinkAnchor.anchorScenePos() source_pos = self.curveItem.mapFromScene(source_pos) sink_pos = self.curveItem.mapFromScene(sink_pos) # Adaptive offset for the curve control points to avoid a # cusp when the two points have the same y coordinate # and are close together delta = source_pos - sink_pos dist = math.sqrt(delta.x()**2 + delta.y()**2) cp_offset = min(dist / 2.0, 60.0) # TODO: make the curve tangent orthogonal to the anchors path. path = QPainterPath() path.moveTo(source_pos) path.cubicTo(source_pos + QPointF(cp_offset, 0), sink_pos - QPointF(cp_offset, 0), sink_pos) self.curveItem.setPath(path) self.sourceIndicator.setPos(source_pos) self.sinkIndicator.setPos(sink_pos) self.__updateText() else: self.setHoverState(False) self.curveItem.setPath(QPainterPath()) def __updateText(self): self.prepareGeometryChange() if self.__sourceName or self.__sinkName: if self.__sourceName != self.__sinkName: text = u"{0} \u2192 {1}".format(self.__sourceName, self.__sinkName) else: # If the names are the same show only one. # Is this right? If the sink has two input channels of the # same type having the name on the link help elucidate # the scheme. text = self.__sourceName else: text = "" self.linkTextItem.setPlainText(text) path = self.curveItem.path() if not path.isEmpty(): center = path.pointAtPercent(0.5) angle = path.angleAtPercent(0.5) brect = self.linkTextItem.boundingRect() transform = QTransform() transform.translate(center.x(), center.y()) transform.rotate(-angle) # Center and move above the curve path. transform.translate(-brect.width() / 2, -brect.height()) self.linkTextItem.setTransform(transform) def removeLink(self): self.setSinkItem(None) self.setSourceItem(None) self.__updateCurve() def setHoverState(self, state): if self.hover != state: self.prepareGeometryChange() self.hover = state self.sinkIndicator.setHoverState(state) self.sourceIndicator.setHoverState(state) self.curveItem.setHoverState(state) def hoverEnterEvent(self, event): # Hover enter event happens when the mouse enters any child object # but we only want to show the 'hovered' shadow when the mouse # is over the 'curveItem', so we install self as an event filter # on the LinkCurveItem and listen to its hover events. self.curveItem.installSceneEventFilter(self) return QGraphicsObject.hoverEnterEvent(self, event) def hoverLeaveEvent(self, event): # Remove the event filter to prevent unnecessary work in # scene event filter when not needed self.curveItem.removeSceneEventFilter(self) return QGraphicsObject.hoverLeaveEvent(self, event) def sceneEventFilter(self, obj, event): if obj is self.curveItem: if event.type() == QEvent.GraphicsSceneHoverEnter: self.setHoverState(True) elif event.type() == QEvent.GraphicsSceneHoverLeave: self.setHoverState(False) return QGraphicsObject.sceneEventFilter(self, obj, event) def boundingRect(self): return self.childrenBoundingRect() def shape(self): return self.curveItem.shape() def setEnabled(self, enabled): """ Reimplemented from :class:`QGraphicsObject` Set link enabled state. When disabled the link is rendered with a dashed line. """ # This getter/setter pair override a property from the base class. # They should be renamed to e.g. setLinkEnabled/linkEnabled self.curveItem.setLinkEnabled(enabled) def isEnabled(self): return self.curveItem.isLinkEnabled() def setDynamicEnabled(self, enabled): """ Set the link's dynamic enabled state. If the link is `dynamic` it will be rendered in red/green color respectively depending on the state of the dynamic enabled state. """ if self.__dynamicEnabled != enabled: self.__dynamicEnabled = enabled if self.__dynamic: self.__updatePen() def isDynamicEnabled(self): """ Is the link dynamic enabled. """ return self.__dynamicEnabled def setDynamic(self, dynamic): """ Mark the link as dynamic (i.e. it responds to :func:`setDynamicEnabled`). """ if self.__dynamic != dynamic: self.__dynamic = dynamic self.__updatePen() def isDynamic(self): """ Is the link dynamic. """ return self.__dynamic def __updatePen(self): self.prepareGeometryChange() if self.__dynamic: if self.__dynamicEnabled: color = QColor(0, 150, 0, 150) else: color = QColor(150, 0, 0, 150) normal = QPen(QBrush(color), 2.0) hover = QPen(QBrush(color.darker(120)), 2.1) else: normal = QPen(QBrush(QColor("#9CACB4")), 2.0) hover = QPen(QBrush(QColor("#7D7D7D")), 2.1) self.curveItem.setCurvePenSet(normal, hover)
class GradientLegendItem(QGraphicsObject, GraphicsWidgetAnchor): gradient_width = 20 def __init__(self, title, palette, values, parent): QGraphicsObject.__init__(self, parent) GraphicsWidgetAnchor.__init__(self) self.parent = self.legend = parent self.palette = palette self.values = values self.title = QGraphicsTextItem('%s:' % title, self) f = self.title.font() f.setBold(True) self.title.setFont(f) self.title_item = QGraphicsRectItem(self.title.boundingRect(), self) self.title_item.setPen(QPen(Qt.NoPen)) self.title_item.stackBefore(self.title) self.label_items = [QGraphicsTextItem(text, self) for text in values] for i in self.label_items: i.setTextWidth(50) self.rect = QRectF() self.gradient_item = QGraphicsRectItem(self) self.gradient = QLinearGradient() self.gradient.setStops([(v * 0.1, self.palette[v * 0.1]) for v in range(11)]) self.orientation = Qt.Horizontal self.set_orientation(Qt.Vertical) self.setFlag(QGraphicsItem.ItemIgnoresTransformations, True) self.setFlag(QGraphicsItem.ItemIsMovable, True) def set_orientation(self, orientation): return if self.orientation == orientation: return self.orientation = orientation if self.orientation == Qt.Vertical: height = max(item.boundingRect().height() for item in self.label_items) total_height = height * max(5, len(self.label_items)) interval = (total_height - self.label_items[-1].boundingRect().height() ) / (len(self.label_items) - 1) self.gradient_item.setRect(10, 0, self.gradient_width, total_height) self.gradient.setStart(10, 0) self.gradient.setFinalStop(10, total_height) self.gradient_item.setBrush(QBrush(self.gradient)) self.gradient_item.setPen(QPen(Qt.NoPen)) y = -20 # hja, no; dela --> pri boundingRect() zato pristejem +20 x = 0 move_item_xy(self.title, x, y, False) y = 10 x = 30 for item in self.label_items: move_item_xy(item, x, y, False) # self.parent.graph.animate_plot) y += interval self.rect = QRectF(10, 0, self.gradient_width + max(item.boundingRect().width() for item in self.label_items), self.label_items[0].boundingRect().height() * max(5, len(self.label_items))) else: # za horizontalno orientacijo nisem dodajal title-a width = 50 height = max(item.boundingRect().height() for item in self.label_items) total_width = width * max(5, len(self.label_items)) interval = (total_width - self.label_items[-1].boundingRect().width() ) / (len(self.label_items) - 1) self.gradient_item.setRect(0, 0, total_width, self.gradient_width) self.gradient.setStart(0, 0) self.gradient.setFinalStop(total_width, 0) self.gradient_item.setBrush(QBrush(self.gradient)) self.gradient_item.setPen(QPen(Qt.NoPen)) x = 0 y = 30 for item in self.label_items: move_item_xy(item, x, y, False) # self.parent.graph.animate_plot) x += interval self.rect = QRectF(0, 0, total_width, self.gradient_width + height) # noinspection PyPep8Naming def boundingRect(self): width = max(self.rect.width(), self.title_item.boundingRect().width()) height = self.rect.height() + self.title_item.boundingRect().height() return QRectF(self.rect.left(), self.rect.top(), width, height) def paint(self, painter, option, widget): pass
class 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 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 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 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