diff --git a/annotationitem.py b/annotationitem.py deleted file mode 100644 index b5a5b74..0000000 --- a/annotationitem.py +++ /dev/null @@ -1,32 +0,0 @@ -from PyQt4.QtGui import * -from PyQt4.Qt import * - -class AnnotationGraphicsItem(QAbstractGraphicsShapeItem): - def __init__(self,controls_enabled=True, parent=None, **kwargs): - super(AnnotationGraphicsItem, self).__init__(parent) - - self.setFlags(QGraphicsItem.ItemIsSelectable|QGraphicsItem.ItemIsMovable) - - self.text_font_ = QFont() - self.text_font_.setPointSize(4) - self.text_item_ = QGraphicsSimpleTextItem() - self.text_item_.setFont(self.text_font_) - self.updateText() - - def boundingRect(self): - return QRectF(0, 0, 0, 0) - - def updateText(self): - self.text_item_.setText("CLASS") - - def itemChange(self, change, value): - if change == QGraphicsItem.ItemSelectedChange: - self.setControlsVisible(value.toBool()) - return QGraphicsItem.itemChange(self, change, value) - - def setControlsVisible(self, visible=True): - self.controls_visible_ = visible - #for corner in self.corner_items_: - # corner.setVisible(self.controls_enabled_ and self.controls_visible_) - - diff --git a/sceneitems/annotationitem.py b/sceneitems/annotationitem.py new file mode 100644 index 0000000..d992769 --- /dev/null +++ b/sceneitems/annotationitem.py @@ -0,0 +1,218 @@ +from PyQt4.QtGui import * +from PyQt4.Qt import * +from annotationmodel import DataRole + +class ControlItem(QGraphicsItem): + def __init__(self, parent=None): + QGraphicsItem.__init__(self, parent) + + # always have the same size + self.setFlags(QGraphicsItem.ItemIgnoresTransformations) + + def paint(self, painter, option, widget = None): + color = QColor('black') + color.setAlpha(200) + painter.fillRect(self.boundingRect(), color) + +class AnnotationGraphicsItem(QAbstractGraphicsShapeItem): + def __init__(self, index, parent=None): + QAbstractGraphicsShapeItem.__init__(self, parent) + + self.index_ = index + + self.setFlags(QGraphicsItem.ItemIsSelectable | \ + QGraphicsItem.ItemIsMovable | \ + QGraphicsItem.ItemSendsGeometryChanges | \ + QGraphicsItem.ItemSendsScenePositionChanges) + self.setPen(QColor('yellow')) + + self.text_font_ = QFont() + self.text_font_.setPointSize(4) + self.text_item_ = QGraphicsSimpleTextItem() + self.text_item_.setFont(self.text_font_) + self.setText("") + + self._setDelayedDirty(False) + + def _delayedDirty(self): + return self.delayed_dirty_ + def _setDelayedDirty(self, dirty=True): + self.delayed_dirty_ = dirty + + def boundingRect(self): + return QRectF(0, 0, 0, 0) + + def index(self): + return self.index_ + + def setText(self, text, position="upperleft"): + # TODO use different text items for differenct positions + self.text_item_.setText(text) + + def itemChange(self, change, value): + if change == QGraphicsItem.ItemSelectedChange: + self.setControlsVisible(value.toBool()) + return QGraphicsItem.itemChange(self, change, value) + + def dataChanged(self): + pass + + def setControlsVisible(self, visible=True): + self.controls_visible_ = visible + print "Controls visible:", visible + #for corner in self.corner_items_: + # corner.setVisible(self.controls_enabled_ and self.controls_visible_) + + # + # factory methods for creating the graphics items + #_________________________________________________________________________________ + _item_types = {} + + @staticmethod + def addItemType(type, constructor, replace=False): + type = type.lower() + if type in AnnotationGraphicsItem._item_types and not replace: + raise Exception("Type %s already has an constructor" % type) + + AnnotationGraphicsItem._item_types[type.lower()] = constructor + + @staticmethod + def removeItemType(type_str): + type = type.lower() + if type in AnnotationGraphicsItem._item_types: + del AnnotationGraphicsItem._item_types[type] + + @staticmethod + def createItem(index): + """ + Create an AnnotationGraphicsItem based on the type of the annotation. + + E.g. + type == rect --> AnnotationGraphicsRectItem + type == point --> AnnotationGraphicsPointItem + """ + annotation = index.data(DataRole).toPyObject() + print "createItem:", index.row(), index.column(), annotation + + if annotation is not None and 'type' in annotation: + type = annotation['type'] + if type in AnnotationGraphicsItem._item_types: + return AnnotationGraphicsItem._item_types[type](index) + + return None + + +class AnnotationGraphicsRectItem(AnnotationGraphicsItem): + def __init__(self, index, parent=None): + AnnotationGraphicsItem.__init__(self, index, parent) + + self.data_ = self.index().data(DataRole).toPyObject() + self.rect_ = None + self._updateRect(self._dataToRect(self.data_)) + + def _dataToRect(self, data): + return QRectF(float(data['x']), float(data['y']), + float(data.get('width', data.get('w'))), + float(data.get('height', data.get('h')))) + + def _updateRect(self, rect): + if not rect.isValid(): + return + if rect == self.rect_: + return + + self.rect_ = rect + self.prepareGeometryChange() + self.setPos(rect.topLeft()) + #self.layoutChildren() + #self.update() + + def updateModel(self): + if not self._delayedDirty(): + self.rect_ = QRectF(self.scenePos(), self.rect_.size()) + self.data_['x'] = self.rect_.topLeft().x() + self.data_['y'] = self.rect_.topLeft().y() + if 'width' in self.data_: self.data_['width'] = float(self.rect_.width()) + if 'w' in self.data_: self.data_['w'] = float(self.rect_.width()) + if 'height' in self.data_: self.data_['height'] = float(self.rect_.height()) + if 'h' in self.data_: self.data_['h'] = float(self.rect_.height()) + + print "updateModel", self.data_ + self.index().model().setData(self.index(), QVariant(self.data_), DataRole) + + def boundingRect(self): + return QRectF(QPointF(0, 0), self.rect_.size()) + + def paint(self, painter, option, widget = None): + pen = self.pen() + if self.isSelected(): + pen.setStyle(Qt.DashLine) + painter.setPen(pen) + painter.drawRect(self.boundingRect()) + + def itemChange(self, change, value): + print change + if change == QGraphicsItem.ItemScenePositionHasChanged: + self.updateModel() + return AnnotationGraphicsItem.itemChange(self, change, value) + + def dataChanged(self): + self.data_ = self.index().data(DataRole).toPyObject() + rect = self._dataToRect(self.data_) + self._updateRect(rect) + + +class AnnotationGraphicsPointItem(AnnotationGraphicsItem): + def __init__(self, index, parent=None): + AnnotationGraphicsItem.__init__(self, index, parent) + + self.display_size_ = 3 + + self.data_ = self.index().data(DataRole).toPyObject() + self.point_ = None + self.updatePoint() + + def updatePoint(self): + point = QPointF(float(self.data_['x']), + float(self.data_['y'])) + if point == self.point_: + return + + self.point_ = point + self.prepareGeometryChange() + self.setPos(self.point_) + #self.layoutChildren() + #self.update() + + def updateModel(self): + if not self._delayedDirty(): + self.data_['x'] = self.scenePos().x() + self.data_['y'] = self.scenePos().y() + print "updateModel (point)", self.data_ + self.index().model().setData(self.index(), QVariant(self.data_), DataRole) + + def boundingRect(self): + s = self.display_size_ + return QRectF(-s/2, -s/2, s, s) + + def paint(self, painter, option, widget = None): + pen = self.pen() + if self.isSelected(): + pen.setStyle(Qt.DashLine) + painter.setPen(pen) + painter.drawEllipse(self.boundingRect()) + + def itemChange(self, change, value): + if change == QGraphicsItem.ItemPositionHasChanged: + self.updateModel() + return AnnotationGraphicsItem.itemChange(self, change, value) + + def dataChanged(self): + self.data_ = self.index().data(DataRole).toPyObject() + self.updatePoint() + + +# register common item types +AnnotationGraphicsItem.addItemType('rect', AnnotationGraphicsRectItem) +AnnotationGraphicsItem.addItemType('point', AnnotationGraphicsPointItem) +