"""
Base class for visualization items.
"""
cycleValuesOnKeypress = {}
hotkeys = {}
defaultAutoTextKeys = []
def __init__(self, model_item=None, prefix="", parent=None):
"""
Creates a visualization item.
"""
self._model_item = model_item
if self._model_item is not None:
self._model_item.model().dataChanged.connect(self.onDataChanged)
# initialize members
self._prefix = prefix
self._auto_text_keys = self.defaultAutoTextKeys[:]
self._text = ""
self._text_bg_brush = None
self._text_item.setPos(0, 0)
self._text_item.setAcceptHoverEvents(False)
self._text_item.
setFlags(QGraphicsItem.
ItemIgnoresTransformations) self._text_item.setHtml(self._compile_text())
self._valid = True
if len(self.cycleValuesOnKeypress) > 0:
logging.warning("cycleValueOnKeypress is deprecated and will be removed in the future. " +
"Set BaseItem.hotkeys instead with cycleValue()")
self.changeColor()
def changeColor(self):
if self._model_item is not None:
c = self._model_item.getColor()
if c is not None:
self.setColor(c)
return
self.setColor(Qt.yellow)
def onDataChanged(self, indexFrom, indexTo):
# FIXME why is this not updated, when changed graphically via attribute box ?
#print "onDataChanged", self._model_item.index(), indexFrom, indexTo, indexFrom.parent()
if indexFrom == self._model_item.index():
self.changeColor()
#print "hit"
# self._text_item.setHtml(self._compile_text())
def modelItem(self):
"""
Returns the model item of this items.
"""
return self._model_item
def index(self):
"""
Returns the index of this item.
"""
return self._model_item.index()
def prefix(self):
"""
Returns the key prefix of the item.
"""
return self._prefix
def setPen(self, pen):
pen
= QPen(pen
) # convert to pen if argument is a QColor self._text_item.setDefaultTextColor(pen.color())
def setText(self, text=""):
"""
Sets a text to be displayed on this item.
"""
self._text = text
self._text_item.setHtml(self._compile_text())
def text(self):
return self._text
def setTextBackgroundBrush(self, brush=None):
"""
Sets the brush to be used to fill the background region
behind the text. Set to None to not draw a background
(leave transparent).
"""
self._text_bg_brush = brush
def textBackgroundBrush(self):
"""
Returns the background brush for the text region.
"""
return self._text_bg_brush
def setAutoTextKeys(self, keys=None):
"""
Sets the keys for which the values from the annotations
are displayed automatically as text.
"""
self._auto_text_keys = keys or []
self._text_item.setHtml(self._compile_text())
def autoTextKeys(self):
"""
Returns the list of keys for which the values from
the annotations are displayed as text automatically.
"""
return self._auto_text_keys
def isValid(self):
"""
Return whether this graphics item is valid, i.e. has
a matching, valid model item connected to it. An item is
by default valid, will only be set invalid on failure.
"""
return self._valid
def setValid(self, val):
self._valid = val
def _compile_text(self):
text_lines = []
if self._text != "" and self._text is not None:
text_lines.append(self._text)
for key in self._auto_text_keys:
text_lines.append("%s: %s" % \
(key, self._model_item.get(key, "")))
return '<br/>'.join(text_lines)
def dataChanged(self):
self.dataChange()
self._text_item.setHtml(self._compile_text())
self.update()
def dataChange(self):
pass
def updateModel(self, ann=None):
if ann is not None:
self._model_item.update(ann)
def boundingRect(self):
def setColor(self, color):
self.setPen(color)
self.setBrush(color)
self.update()
def paint(self, painter, option, widget=None):
pass
def itemChange(self, change, value):
self.updateModel()
def keyPressEvent(self, event):
"""
This handles the value cycling as defined in cycleValuesOnKeypress.
"""
if str(event.text()) in self.cycleValuesOnKeypress:
itemkey, valuelist = self.cycleValuesOnKeypress[str(event.text())]
if isinstance(itemkey, IgnorePrefix):
itemkey = itemkey.value
else:
itemkey = self.prefix() + itemkey
if len(valuelist) > 0:
oldvalue = self._model_item.get(itemkey, None)
if oldvalue is None:
nextindex = 0
else:
try:
nextindex = valuelist.index(oldvalue) + 1
nextindex %= len(valuelist)
except ValueError:
nextindex = 0
newvalue = valuelist[nextindex]
if newvalue is None:
if oldvalue is not None:
self._model_item.delete(itemkey)
else:
self._model_item[itemkey] = valuelist[nextindex]
self.dataChanged()
event.accept()
elif str(event.text()) in self.hotkeys:
self.hotkeys[str(event.text())](self)
event.accept()
class PointItem(BaseItem):
"""
Visualization item for points.
"""
def __init__(self, model_item=None, prefix="", parent=None):
BaseItem.__init__(self, model_item, prefix, parent)
self._radius = 2
self._point = None
self.updatePoint()
def setRadius(self, radius):
self.prepareGeometryChange()
self._radius = radius
self.update()
def radius(self):
return self._radius
def __call__(self, model_item=None, parent=None):
pointitem = PointItem(model_item, parent)
pointitem.setPen(self.pen())
pointitem.setBrush(self.brush())
pointitem.setRadius(self._radius)
return pointitem
def dataChange(self):
self.updatePoint()
def updateModel(self):
self._model_item.update({
self.prefix() + 'x': self.scenePos().x(),
self.prefix() + 'y': self.scenePos().y(),
})
def updatePoint(self):
if self._model_item is None:
return
try:
point
= QPointF(float(self._model_item
[self.
prefix() + 'x']),
float(self._model_item[self.prefix() + 'y']))
except KeyError as e:
LOG.debug("PointItem: Could not find expected key in item: "
+ str(e) + ". Check your config!")
self.setValid(False)
self._point = None
return
if point == self._point:
return
self.prepareGeometryChange()
self._point = point
self.setPos(self._point)
def boundingRect(self):
r = self._radius
return QRectF(-r,
-r,
2 * r,
2 * r
)
def paint(self, painter, option, widget=None):
BaseItem.paint(self, painter, option, widget)
pen = self.pen()
if self.isSelected():
pen.setStyle(Qt.DashLine)
painter.setPen(pen)
painter.drawEllipse(self.boundingRect())
def keyPressEvent(self, event):
BaseItem.keyPressEvent(self, event)
step = 1
if event.modifiers() & Qt.ShiftModifier:
step = 5
ds = {Qt.Key_Left: (-step, 0),
Qt.Key_Right: (step, 0),
Qt.Key_Up: (0, -step),
Qt.Key_Down: (0, step)
}.get(event.key(), None)
if ds is not None:
self.moveBy(*ds)
event.accept()