Exemple #1
0
class FinishLine(QGraphicsItemGroup, AbstractSector):

    def __init__(self, parent, pos, angle, pit=False):
        QGraphicsItemGroup.__init__(self, parent)
        AbstractSector.__init__(self, pos, angle)
        self.setZValue(3)
        self.black = QGraphicsPathItem(self)
        self.white = QGraphicsPathItem(self)
        start = 3 * (_trackWidth / 2)
        end = -start - abs(_pitDistance if pit else 0)
        rowdelta = _trackWidth / 4
        for item, y in [(self.black, -rowdelta),
                        (self.white, rowdelta)]:
            item.setCacheMode(QGraphicsPathItem.DeviceCoordinateCache)
            self.addToGroup(item)
            path = QPainterPath()
            path.moveTo(start, y)
            path.lineTo(end, y)
            path.moveTo(end, -y)
            path.lineTo(start, -y)
            item.setPath(path)
        pen = QPen(Qt.black, _trackWidth / 2)
        pen.setCapStyle(Qt.FlatCap)
        pen.setDashPattern([1, 1])
        self.black.setPen(QPen(pen))
        pen.setColor(Qt.white)
        self.white.setPen(pen)
Exemple #2
0
class ParallelCoordinatesCurve(OWCurve):
    def __init__(self, n_attributes, y_values, color, name=""):
        OWCurve.__init__(self, tooltip=name)
        self._item = QGraphicsPathItem(self)
        self.path = QPainterPath()
        self.fitted = False

        self.n_attributes = n_attributes
        self.n_rows = int(len(y_values) / n_attributes)

        self.set_style(OWCurve.Lines)
        if isinstance(color, tuple):
            self.set_pen(QPen(QColor(*color)))
        else:
            self.set_pen(QPen(QColor(color)))

        x_values = list(range(n_attributes)) * self.n_rows
        self.set_data(x_values, y_values)

    def update_properties(self):
        self.redraw_path()

    def redraw_path(self):
        self.path = QPainterPath()
        for segment in self.segment(self.data()):
            if self.fitted:
                self.draw_cubic_path(segment)
            else:
                self.draw_normal_path(segment)
        self._item.setPath(self.graph_transform().map(self.path))
        self._item.setPen(self.pen())

    def segment(self, data):
        for i in range(self.n_rows):
            yield data[i * self.n_attributes:(i + 1) * self.n_attributes]

    def draw_cubic_path(self, segment):
        for (x1, y1), (x2, y2) in zip(segment, segment[1:]):
            self.path.moveTo(x1, y1)
            self.path.cubicTo(QPointF(x1 + 0.5, y1),
                              QPointF(x2 - 0.5, y2), QPointF(x2, y2))

    def draw_normal_path(self, segment):
        if not segment:
            return

        x, y = segment[0]
        self.path.moveTo(x, y)
        for x, y in segment[1:]:
            self.path.lineTo(x, y)
 def _addPath(self):
   iNode = 2 * model._nodes.index(self.__node)
   x0,y0 = record.states[0][iNode:iNode+2]
   path = QPainterPath()
   path.moveTo(x0,-y0)
   item = QGraphicsPathItem()
   item.setPen( QPen( QColor(0,0,255), 0 ) )
   item.setPath(path)
   self._path = item
   for state in record.states[1:]:
     self._addPoint(state)
   if hasattr(record,'changeListeners'):
     record.changeListeners.append(self._addPoint)
   groupCurves.addToGroup(item)
Exemple #4
0
class ParallelCoordinatesCurve(OWCurve):
    def __init__(self, n_attributes, y_values, color, name=""):
        OWCurve.__init__(self, tooltip=name)
        self._item = QGraphicsPathItem(self)
        self.path = QPainterPath()
        self.fitted = False

        self.n_attributes = n_attributes
        self.n_rows = int(len(y_values) / n_attributes)

        self.set_style(OWCurve.Lines)
        if isinstance(color, tuple):
            self.set_pen(QPen(QColor(*color)))
        else:
            self.set_pen(QPen(QColor(color)))

        x_values = list(range(n_attributes)) * self.n_rows
        self.set_data(x_values, y_values)

    def update_properties(self):
        self.redraw_path()

    def redraw_path(self):
        self.path = QPainterPath()
        for segment in self.segment(self.data()):
            if self.fitted:
                self.draw_cubic_path(segment)
            else:
                self.draw_normal_path(segment)
        self._item.setPath(self.graph_transform().map(self.path))
        self._item.setPen(self.pen())

    def segment(self, data):
        for i in range(self.n_rows):
            yield data[i * self.n_attributes:(i + 1) * self.n_attributes]

    def draw_cubic_path(self, segment):
        for (x1, y1), (x2, y2) in zip(segment, segment[1:]):
            self.path.moveTo(x1, y1)
            self.path.cubicTo(QPointF(x1 + 0.5, y1), QPointF(x2 - 0.5, y2),
                              QPointF(x2, y2))

    def draw_normal_path(self, segment):
        if not segment:
            return

        x, y = segment[0]
        self.path.moveTo(x, y)
        for x, y in segment[1:]:
            self.path.lineTo(x, y)
class ParallelCoordinatesCurve(OWCurve):
    def __init__(self, attrCount, yData, color, name=""):
        OWCurve.__init__(self, tooltip=name)
        self._item = QGraphicsPathItem(self)
        self.fitted = False
        self.set_style(OWCurve.Lines)

        lineCount = len(yData) / attrCount
        self.attrCount = attrCount

        if type(color) == tuple:
            self.set_pen(QPen(QColor(*color)))
        else:
            self.set_pen(QPen(QColor(color)))

        self.set_data(range(attrCount) * lineCount, yData)

    def update_properties(self):
        if self.fitted:
            path = self.cubicPath()
        else:
            path = QPainterPath()
            for x, y in self.data():
                path.lineTo(x, y)
        self._item.setPath(self.graph_transform().map(path))
        self._item.setPen(self.pen())

    def cubicPath(self):
        path = QPainterPath()
        data = self.data()
        for i in range(len(data) / self.attrCount):
            segment = data[i * self.attrCount:(i + 1) * self.attrCount]
            for i, p in enumerate(segment[:-1]):
                x1, y1 = p
                x2, y2 = segment[i + 1]
                path.moveTo(x1, y1)
                path.cubicTo(QPointF(x1 + 0.5, y1), QPointF(x2 - 0.5, y2),
                             QPointF(x2, y2))
        return path
class ParallelCoordinatesCurve(OWCurve):
    def __init__(self, attrCount, yData, color, name = ""):
        OWCurve.__init__(self, tooltip=name)
	self._item = QGraphicsPathItem(self)
        self.fitted = False
        self.set_style(OWCurve.Lines)

        lineCount = len(yData) / attrCount
        self.attrCount = attrCount

        if type(color) == tuple:
            self.set_pen(QPen(QColor(*color)))
        else:
            self.set_pen(QPen(QColor(color)))
            
	self.set_data(range(attrCount) * lineCount, yData)

    def update_properties(self):
	if self.fitted:
	    path = self.cubicPath()
	else:
	    path = QPainterPath()
	    for x, y in self.data():
		path.lineTo(x, y)
        self._item.setPath(self.graph_transform().map(path))
        self._item.setPen(self.pen())
	
    def cubicPath(self):
        path = QPainterPath()
        data = self.data()
        for i in range(len(data) / self.attrCount):
            segment = data[i*self.attrCount: (i + 1)*self.attrCount]
            for i, p in enumerate(segment[:-1]):
                x1, y1 = p
                x2, y2 = segment[i + 1]
                path.moveTo(x1, y1)
                path.cubicTo(QPointF(x1 + 0.5, y1), QPointF(x2 - 0.5, y2), QPointF(x2, y2))
        return path
Exemple #7
0
class PlotGrid(orangeqt.PlotItem):
    """
        Draws a grid onto the plot

        :param plot: If specified, the grid will be attached to the ``plot``.
        :type plot: :obj:`.OWPlot`
    """

    def __init__(self, plot=None):
        orangeqt.PlotItem.__init__(self)
        self._x_enabled = True
        self._y_enabled = True
        self._path_item = QGraphicsPathItem(self)
        self.set_in_background(True)
        if plot:
            self.attach(plot)
            self._path_item.setPen(plot.color(OWPalette.Grid))

    def set_x_enabled(self, b):
        """
            Enables or disabled vertial grid lines
        """
        if b < 0:
            b = not self._x_enabled
        self._x_enabled = b
        self.update_properties()

    def is_x_enabled(self):
        """
            Returns whether vertical grid lines are enabled
        """
        return self._x_enabled

    def set_y_enabled(self, b):
        """
            Enables or disabled horizontal grid lines
        """
        if b < 0:
            b = not self._y_enabled
        self._y_enabled = b
        self.update_properties()

    def is_y_enabled(self):
        """
            Returns whether horizontal grid lines are enabled
        """
        return self._y_enabled

    def set_pen(self, pen):
        """
            Sets the pen used for drawing the grid lines
        """
        self._path_item.setPen(pen)

    def update_properties(self):
        p = self.plot()
        if p is None:
            return
        x_id, y_id = self.axes()
        rect = p.data_rect_for_axes(x_id, y_id)
        path = QPainterPath()
        if self._x_enabled and x_id in p.axes:
            for pos, label, size, _w in p.axes[x_id].ticks():
                path.moveTo(pos, rect.bottom())
                path.lineTo(pos, rect.top())
        if self._y_enabled and y_id in p.axes:
            for pos, label, size, _w in p.axes[y_id].ticks():
                path.moveTo(rect.left(), pos)
                path.lineTo(rect.right(), pos)
        self._path_item.setPath(self.graph_transform().map(path))
Exemple #8
0
class TextAnnotation(Annotation):
    """Text annotation item for the canvas scheme.

    """
    editingFinished = Signal()
    """Emitted when the editing is finished (i.e. the item loses focus)."""

    textEdited = Signal()
    """Emitted when the edited text changes."""
    def __init__(self, parent=None, **kwargs):
        Annotation.__init__(self, parent, **kwargs)
        self.setFlag(QGraphicsItem.ItemIsMovable)
        self.setFlag(QGraphicsItem.ItemIsSelectable)

        self.setFocusPolicy(Qt.ClickFocus)

        self.__textMargins = (2, 2, 2, 2)

        rect = self.geometry().translated(-self.pos())
        self.__framePen = QPen(Qt.NoPen)
        self.__framePathItem = QGraphicsPathItem(self)
        self.__framePathItem.setPen(self.__framePen)

        self.__textItem = GraphicsTextEdit(self)
        self.__textItem.setPlaceholderText(self.tr("Enter text here"))
        self.__textItem.setPos(2, 2)
        self.__textItem.setTextWidth(rect.width() - 4)
        self.__textItem.setTabChangesFocus(True)
        self.__textItem.setTextInteractionFlags(Qt.NoTextInteraction)
        self.__textItem.setFont(self.font())
        self.__textInteractionFlags = Qt.NoTextInteraction

        layout = self.__textItem.document().documentLayout()
        layout.documentSizeChanged.connect(self.__onDocumentSizeChanged)

        self.__updateFrame()

    def adjustSize(self):
        """Resize to a reasonable size.
        """
        self.__textItem.setTextWidth(-1)
        self.__textItem.adjustSize()
        size = self.__textItem.boundingRect().size()
        left, top, right, bottom = self.textMargins()
        geom = QRectF(self.pos(), size + QSizeF(left + right, top + bottom))
        self.setGeometry(geom)

    def setFramePen(self, pen):
        """Set the frame pen. By default Qt.NoPen is used (i.e. the frame
        is not shown).
        """
        if pen != self.__framePen:
            self.__framePen = QPen(pen)
            self.__updateFrameStyle()

    def framePen(self):
        """Return the frame pen.
        """
        return QPen(self.__framePen)

    def setFrameBrush(self, brush):
        """Set the frame brush.
        """
        self.__framePathItem.setBrush(brush)

    def frameBrush(self):
        """Return the frame brush.
        """
        return self.__framePathItem.brush()

    def __updateFrameStyle(self):
        if self.isSelected():
            pen = QPen(QColor(96, 158, 215), 1.25, Qt.DashDotLine)
        else:
            pen = self.__framePen

        self.__framePathItem.setPen(pen)

    def setPlainText(self, text):
        """Set the annotation plain text.
        """
        self.__textItem.setPlainText(text)

    def toPlainText(self):
        return self.__textItem.toPlainText()

    def setHtml(self, text):
        """Set the annotation rich text.
        """
        self.__textItem.setHtml(text)

    def toHtml(self):
        return self.__textItem.toHtml()

    def setDefaultTextColor(self, color):
        """Set the default text color.
        """
        self.__textItem.setDefaultTextColor(color)

    def defaultTextColor(self):
        return self.__textItem.defaultTextColor()

    def setTextMargins(self, left, top, right, bottom):
        """Set the text margins.
        """
        margins = (left, top, right, bottom)
        if self.__textMargins != margins:
            self.__textMargins = margins
            self.__textItem.setPos(left, top)
            self.__textItem.setTextWidth(
                max(self.geometry().width() - left - right, 0))

    def textMargins(self):
        """Return the text margins.
        """
        return self.__textMargins

    def document(self):
        """Return the QTextDocument instance used internally.
        """
        return self.__textItem.document()

    def setTextCursor(self, cursor):
        self.__textItem.setTextCursor(cursor)

    def textCursor(self):
        return self.__textItem.textCursor()

    def setTextInteractionFlags(self, flags):
        self.__textInteractionFlags = flags

    def textInteractionFlags(self):
        return self.__textInteractionFlags

    def setDefaultStyleSheet(self, stylesheet):
        self.document().setDefaultStyleSheet(stylesheet)

    def mouseDoubleClickEvent(self, event):
        Annotation.mouseDoubleClickEvent(self, event)

        if event.buttons() == Qt.LeftButton and \
                self.__textInteractionFlags & Qt.TextEditable:
            self.startEdit()

    def startEdit(self):
        """Start the annotation text edit process.
        """
        self.__textItem.setTextInteractionFlags(self.__textInteractionFlags)
        self.__textItem.setFocus(Qt.MouseFocusReason)

        # Install event filter to find out when the text item loses focus.
        self.__textItem.installSceneEventFilter(self)
        self.__textItem.document().contentsChanged.connect(self.textEdited)

    def endEdit(self):
        """End the annotation edit.
        """
        self.__textItem.setTextInteractionFlags(Qt.NoTextInteraction)
        self.__textItem.removeSceneEventFilter(self)
        self.__textItem.document().contentsChanged.disconnect(self.textEdited)
        cursor = self.__textItem.textCursor()
        cursor.clearSelection()
        self.__textItem.setTextCursor(cursor)
        self.editingFinished.emit()

    def __onDocumentSizeChanged(self, size):
        # The size of the text document has changed. Expand the text
        # control rect's height if the text no longer fits inside.
        try:
            rect = self.geometry()
            _, top, _, bottom = self.textMargins()
            if rect.height() < (size.height() + bottom + top):
                rect.setHeight(size.height() + bottom + top)
                self.setGeometry(rect)
        except Exception:
            log.error("error in __onDocumentSizeChanged", exc_info=True)

    def __updateFrame(self):
        rect = self.geometry()
        rect.moveTo(0, 0)
        path = QPainterPath()
        path.addRect(rect)
        self.__framePathItem.setPath(path)

    def resizeEvent(self, event):
        width = event.newSize().width()
        left, _, right, _ = self.textMargins()
        self.__textItem.setTextWidth(max(width - left - right, 0))
        self.__updateFrame()
        QGraphicsWidget.resizeEvent(self, event)

    def sceneEventFilter(self, obj, event):
        if obj is self.__textItem and event.type() == QEvent.FocusOut:
            self.__textItem.focusOutEvent(event)
            self.endEdit()
            return True

        return Annotation.sceneEventFilter(self, obj, event)

    def itemChange(self, change, value):
        if change == QGraphicsItem.ItemSelectedHasChanged:
            self.__updateFrameStyle()

        return Annotation.itemChange(self, change, value)

    def changeEvent(self, event):
        if event.type() == QEvent.FontChange:
            self.__textItem.setFont(self.font())

        Annotation.changeEvent(self, event)
Exemple #9
0
class TextAnnotation(Annotation):
    """Text annotation item for the canvas scheme.

    """
    editingFinished = Signal()
    """Emitted when the editing is finished (i.e. the item loses focus)."""

    textEdited = Signal()
    """Emitted when the edited text changes."""

    def __init__(self, parent=None, **kwargs):
        Annotation.__init__(self, parent, **kwargs)
        self.setFlag(QGraphicsItem.ItemIsMovable)
        self.setFlag(QGraphicsItem.ItemIsSelectable)

        self.setFocusPolicy(Qt.ClickFocus)

        self.__textMargins = (2, 2, 2, 2)

        rect = self.geometry().translated(-self.pos())
        self.__framePathItem = QGraphicsPathItem(self)
        self.__framePathItem.setPen(QPen(Qt.NoPen))

        self.__textItem = GraphicsTextEdit(self)
        self.__textItem.setPlaceholderText(self.tr("Enter text here"))
        self.__textItem.setPos(2, 2)
        self.__textItem.setTextWidth(rect.width() - 4)
        self.__textItem.setTabChangesFocus(True)
        self.__textItem.setTextInteractionFlags(Qt.NoTextInteraction)
        self.__textItem.setFont(self.font())
        self.__textInteractionFlags = Qt.NoTextInteraction

        layout = self.__textItem.document().documentLayout()
        layout.documentSizeChanged.connect(self.__onDocumentSizeChanged)

        self.__updateFrame()

    def adjustSize(self):
        """Resize to a reasonable size.
        """
        self.__textItem.setTextWidth(-1)
        self.__textItem.adjustSize()
        size = self.__textItem.boundingRect().size()
        left, top, right, bottom = self.textMargins()
        geom = QRectF(self.pos(), size + QSizeF(left + right, top + bottom))
        self.setGeometry(geom)

    def setFramePen(self, pen):
        """Set the frame pen. By default Qt.NoPen is used (i.e. the frame
        is not shown).

        """
        self.__framePathItem.setPen(pen)

    def framePen(self):
        """Return the frame pen.
        """
        return self.__framePathItem.pen()

    def setFrameBrush(self, brush):
        """Set the frame brush.
        """
        self.__framePathItem.setBrush(brush)

    def frameBrush(self):
        """Return the frame brush.
        """
        return self.__framePathItem.brush()

    def setPlainText(self, text):
        """Set the annotation plain text.
        """
        self.__textItem.setPlainText(text)

    def toPlainText(self):
        return self.__textItem.toPlainText()

    def setHtml(self, text):
        """Set the annotation rich text.
        """
        self.__textItem.setHtml(text)

    def toHtml(self):
        return self.__textItem.toHtml()

    def setDefaultTextColor(self, color):
        """Set the default text color.
        """
        self.__textItem.setDefaultTextColor(color)

    def defaultTextColor(self):
        return self.__textItem.defaultTextColor()

    def setTextMargins(self, left, top, right, bottom):
        """Set the text margins.
        """
        margins = (left, top, right, bottom)
        if self.__textMargins != margins:
            self.__textMargins = margins
            self.__textItem.setPos(left, top)
            self.__textItem.setTextWidth(
                max(self.geometry().width() - left - right, 0)
            )

    def textMargins(self):
        """Return the text margins.
        """
        return self.__textMargins

    def document(self):
        """Return the QTextDocument instance used internally.
        """
        return self.__textItem.document()

    def setTextCursor(self, cursor):
        self.__textItem.setTextCursor(cursor)

    def textCursor(self):
        return self.__textItem.textCursor()

    def setTextInteractionFlags(self, flags):
        self.__textInteractionFlags = flags

    def textInteractionFlags(self):
        return self.__textInteractionFlags

    def setDefaultStyleSheet(self, stylesheet):
        self.document().setDefaultStyleSheet(stylesheet)

    def mouseDoubleClickEvent(self, event):
        Annotation.mouseDoubleClickEvent(self, event)

        if event.buttons() == Qt.LeftButton and \
                self.__textInteractionFlags & Qt.TextEditable:
            self.startEdit()

    def startEdit(self):
        """Start the annotation text edit process.
        """
        self.__textItem.setTextInteractionFlags(self.__textInteractionFlags)
        self.__textItem.setFocus(Qt.MouseFocusReason)

        # Install event filter to find out when the text item loses focus.
        self.__textItem.installSceneEventFilter(self)
        self.__textItem.document().contentsChanged.connect(
            self.textEdited
        )

    def endEdit(self):
        """End the annotation edit.
        """
        self.__textItem.setTextInteractionFlags(Qt.NoTextInteraction)
        self.__textItem.removeSceneEventFilter(self)
        self.__textItem.document().contentsChanged.disconnect(
            self.textEdited
        )
        self.editingFinished.emit()

    def __onDocumentSizeChanged(self, size):
        # The size of the text document has changed. Expand the text
        # control rect's height if the text no longer fits inside.
        try:
            rect = self.geometry()
            _, top, _, bottom = self.textMargins()
            if rect.height() < (size.height() + bottom + top):
                rect.setHeight(size.height() + bottom + top)
                self.setGeometry(rect)
        except Exception:
            log.error("error in __onDocumentSizeChanged",
                      exc_info=True)

    def __updateFrame(self):
        rect = self.geometry()
        rect.moveTo(0, 0)
        path = QPainterPath()
        path.addRect(rect)
        self.__framePathItem.setPath(path)

    def resizeEvent(self, event):
        width = event.newSize().width()
        left, _, right, _ = self.textMargins()
        self.__textItem.setTextWidth(max(width - left - right, 0))
        self.__updateFrame()
        QGraphicsWidget.resizeEvent(self, event)

    def sceneEventFilter(self, obj, event):
        if obj is self.__textItem and event.type() == QEvent.FocusOut:
            self.__textItem.focusOutEvent(event)
            self.endEdit()
            return True

        return Annotation.sceneEventFilter(self, obj, event)

    def itemChange(self, change, value):
        if change == QGraphicsItem.ItemSelectedHasChanged:
            if self.isSelected():
                self.setFramePen(QPen(Qt.DashDotLine))
            else:
                self.setFramePen(QPen(Qt.NoPen))

        return Annotation.itemChange(self, change, value)

    def changeEvent(self, event):
        if event.type() == QEvent.FontChange:
            self.__textItem.setFont(self.font())

        Annotation.changeEvent(self, event)
Exemple #10
0
class PlotGrid(orangeqt.PlotItem):
    """
        Draws a grid onto the plot

        :param plot: If specified, the grid will be attached to the ``plot``.
        :type plot: :obj:`.OWPlot`
    """
    def __init__(self, plot=None):
        orangeqt.PlotItem.__init__(self)
        self._x_enabled = True
        self._y_enabled = True
        self._path_item = QGraphicsPathItem(self)
        self.set_in_background(True)
        if plot:
            self.attach(plot)
            self._path_item.setPen(plot.color(OWPalette.Grid))

    def set_x_enabled(self, b):
        """
            Enables or disabled vertial grid lines
        """
        if b < 0:
            b = not self._x_enabled
        self._x_enabled = b
        self.update_properties()

    def is_x_enabled(self):
        """
            Returns whether vertical grid lines are enabled
        """
        return self._x_enabled

    def set_y_enabled(self, b):
        """
            Enables or disabled horizontal grid lines
        """
        if b < 0:
            b = not self._y_enabled
        self._y_enabled = b
        self.update_properties()

    def is_y_enabled(self):
        """
            Returns whether horizontal grid lines are enabled
        """
        return self._y_enabled

    def set_pen(self, pen):
        """
            Sets the pen used for drawing the grid lines
        """
        self._path_item.setPen(pen)

    def update_properties(self):
        p = self.plot()
        if p is None:
            return
        x_id, y_id = self.axes()
        rect = p.data_rect_for_axes(x_id, y_id)
        path = QPainterPath()
        if self._x_enabled and x_id in p.axes:
            for pos, label, size, _w in p.axes[x_id].ticks():
                path.moveTo(pos, rect.bottom())
                path.lineTo(pos, rect.top())
        if self._y_enabled and y_id in p.axes:
            for pos, label, size, _w in p.axes[y_id].ticks():
                path.moveTo(rect.left(), pos)
                path.lineTo(rect.right(), pos)
        self._path_item.setPath(self.graph_transform().map(path))
Exemple #11
0
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()
Exemple #12
0
	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() )
Exemple #13
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()
Exemple #14
0
class AxisScene(QGraphicsScene):
    def __init__(self, parent = None):
        super(AxisScene, self).__init__(parent)
        self.guidePen = QPen(QColor("blue"),1)
        self.dot = QGraphicsEllipseItem(-10, -10, 20, 20)
        self.dot.setPos(QPointF(0,0))
        self.dot.setPen(QPen(QColor("red"), 4))
        self.dot.setBrush(QColor("black"))
        self.lastPos = {}
        self.lastPos['x'] = 0
        self.lastPos['y'] = 0
        self.grid = False
        self.gridPen = QPen(QColor("blue"), 2)
        self.pathItem = QGraphicsPathItem()
        self.pathItem.setPen(QPen(QColor("red"), 1, Qt.DotLine))
        self.path = None
        self.xAxis = "Select Axis..."
        self.yAxis = self.xAxis
        self.addItem(self.dot)
    
    def setXAxisName(self, x):
        self.xAxis = "Axis " + str(x)
        self.invalidate()

    def setYAxisName(self, y):
        self.yAxis = "Axis " + str(y)
        self.invalidate()

    def pathToggled(self, toggled):
        if toggled:
            self.path = QPainterPath()
            self.path.moveTo(0,0)
            self.pathItem.setPath(self.path)
            self.addItem(self.pathItem)
        else:
            if self.path != None:
                self.removeItem(self.pathItem)
            self.path = None
        self.invalidate()

    def gridToggled(self, toggled):
        self.grid = toggled
        self.invalidate()

    def updateDotX(self, x):
        self.lastPos['x'] = x * (self.sceneRect().width() / 2)
        self.update(self.lastPos['x'], self.lastPos['y'])
    
    def updateDotY(self, y):
        self.lastPos['y'] = y * (self.sceneRect().height() / 2)
        self.update(self.lastPos['x'], self.lastPos['y'])
    
    def update(self, x, y):
        if self.path != None:
            self.path.lineTo(x, y)
            self.pathItem.setPath(self.path)
        self.dot.setPos(self.lastPos['x'], self.lastPos['y'])
        self.invalidate()
    
    def drawBackground(self, painter, rect):
        if self.grid:
            painter.setClipRect(rect)
            painter.setPen(self.gridPen)

    def drawForeground(self, painter, rect):
        painter.setClipRect(rect)
        painter.setPen(self.gridPen)
        r = self.sceneRect()
        if self.grid:
            painter.drawLine(r.center().x(), r.top(), r.center().x(), r.bottom())
            painter.drawLine(r.left(), r.center().y(), r.right(), r.center().y())
            painter.setPen(QPen(QColor("red"), 1))
            painter.drawText(QRectF(r.left(), r.center().y(), 80, 80), self.xAxis)
            painter.drawText(QRectF(r.center().x()+5, r.top(), 80, 80), self.yAxis)
        if self.path != None:
            painter.setPen(QPen(QColor("red"), 1))
            painter.drawLine(QPointF(self.lastPos['x'], r.top()), QPointF(self.lastPos['x'], r.bottom()))
            painter.drawLine(QPointF(r.left(), self.lastPos['y']), QPointF(r.right(), self.lastPos['y']))