diff --git a/conf/default_config.py b/conf/default_config.py index 09b7dea..332d144 100644 --- a/conf/default_config.py +++ b/conf/default_config.py @@ -4,13 +4,15 @@ LABELS = ( HOTKEYS = ( ) -ITEMS = ( - ("rect", "items.RectItem", "items.RectItemInserter"), - ("point", "items.PointItem", "items.PointItemInserter") -) +ITEMS = { + "rect": "items.RectItem", + "point": "items.PointItem", +} -INSERTERS = ( -) +INSERTERS = { + "rect": "items.RectItemInserter", + "point": "items.PointItemInserter", +} LOADERS = ( ) diff --git a/items/__init__.py b/items/__init__.py index 1ec7141..9d6aeaa 100644 --- a/items/__init__.py +++ b/items/__init__.py @@ -1,2 +1,4 @@ -from annotationitem import * +from items import * +from inserters import * +from factory import Factory diff --git a/items/annotationitem.py b/items/annotationitem.py deleted file mode 100644 index 9d78cd8..0000000 --- a/items/annotationitem.py +++ /dev/null @@ -1,401 +0,0 @@ -from PyQt4.QtGui import * -from PyQt4.Qt import * -import math -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(16) - self.text_item_ = QGraphicsSimpleTextItem(self) - self.text_item_.setFont(self.text_font_) - self.text_item_.setPen(Qt.yellow) - self.text_item_.setBrush(Qt.yellow) - 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 different positions - self.text_item_.setText(text) - self.text_item_.setPos(0, 0) - self.text_item_.update() - - 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_) - -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_)) - self._updateText() - - 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 _updateText(self): - if 'id' in self.data_: - self.setText("id: " + str(self.data_['id'])) - - 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): - 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) - self._updateText() - -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() - 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() - -class ItemInserter: - def __init__(self, scene, mode=None): - self.scene_ = scene - self.mode_ = mode - - def setScene(self, scene): - self.scene_ = scene - def scene(self): - return self.scene_ - - def setMode(self, mode): - self.mode_ = mode - def mode(self): - return self.mode - - def mousePressEvent(self, event, index): - event.accept() - - def mouseReleaseEvent(self, event, index): - event.accept() - - def mouseMoveEvent(self, event, index): - event.accept() - - def keyPressEvent(self, event, index): - event.ignore() - -class PointItemInserter(ItemInserter): - def mousePressEvent(self, event, index): - pos = event.scenePos() - ann = {'type': 'point', - 'x': pos.x(), 'y': pos.y()} - index.model().addAnnotation(index, ann) - event.accept() - -class RectItemInserter(ItemInserter): - def __init__(self, scene, mode=None): - ItemInserter.__init__(self, scene, mode) - self.current_item_ = None - self.init_pos_ = None - - def mousePressEvent(self, event, index): - pos = event.scenePos() - item = QGraphicsRectItem(QRectF(pos.x(), pos.y(), 0, 0)) - item.setPen(Qt.red) - self.current_item_ = item - self.init_pos_ = pos - self.scene().addItem(item) - event.accept() - - def mouseMoveEvent(self, event, index): - if self.current_item_ is not None: - assert self.init_pos_ is not None - rect = QRectF(self.init_pos_, event.scenePos()).normalized() - self.current_item_.setRect(rect) - - event.accept() - - def mouseReleaseEvent(self, event, index): - if self.current_item_ is not None: - if self.current_item_.rect().width() > 1 and \ - self.current_item_.rect().height() > 1: - rect = self.current_item_.rect() - ann = {'type': 'rect', - 'x': rect.x(), 'y': rect.y(), - 'width': rect.width(), 'height': rect.height()} - index.model().addAnnotation(index, ann) - self.scene().removeItem(self.current_item_) - self.current_item_ = None - self.init_pos_ = None - - event.accept() - -class FixedRatioRectItemInserter(RectItemInserter): - def __init__(self, scene, mode=None): - RectItemInserter.__init__(self, scene, mode) - self.ratio_ = 1 - if mode is not None: - self.ratio_ = float(mode.get('_ratio', 1)) - - def setMode(self, mode): - if mode is not None: - self.ratio_ = float(mode.get('_ratio', 1)) - RectItemInserter.setMode(self, mode) - - def mouseMoveEvent(self, event, index): - if self.current_item_ is not None: - new_geometry = QRectF(self.current_item_.rect().topLeft(), event.scenePos()) - dx = new_geometry.width() - dy = new_geometry.height() - d = math.sqrt(dx*dx + dy*dy) - r = self.ratio_ - k = math.sqrt(r*r+1) - h = d/k - w = d*r/k - new_geometry.setWidth(w) - new_geometry.setHeight(h) - self.current_item_.setRect(new_geometry.normalized()) - - event.accept() - -class PolygonItemInserter(ItemInserter): - def __init__(self, scene, mode=None): - ItemInserter.__init__(self, scene, mode) - self.current_item_ = None - - def mousePressEvent(self, event, index): - pos = event.scenePos() - if self.current_item_ is None: - item = QGraphicsPolygonItem(QPolygonF([pos])) - self.current_item_ = item - self.scene().addItem(item) - else: - polygon = self.current_item_.polygon() - polygon.append(pos) - self.current_item_.setPolygon(polygon) - - event.accept() - - def mouseMoveEvent(self, event, index): - if self.current_item_ is not None: - pos = event.scenePos() - polygon = self.current_item_.polygon() - assert polygon.size() > 0 - polygon[-1] = pos - self.current_item_.setPolygon(polygon) - - event.accept() - -class Factory: - def __init__(self, items=None): - self.items_ = {} - - print items - if items is not None: - for _type, item in items: - self.register(_type, item, replace=True) - - def register(self, _type, item, replace=False): - _type = _type.lower() - - if _type in self.items_ and not replace: - raise Exception("Type %s already has an item: %s" % \ - (_type, str(self.items_[_type]))) - else: - self.items_[_type] = item - - def clear(self, _type=None): - if _type is None: - self.items_ = {} - else: - _type = _type.lower() - if _type in self.items_: - del self.items_[_type] - - def create(self, _type, *args, **kwargs): - _type = _type.lower() - - if _type not in self.items_: - return None - item = self.items_[_type] - if item is None: - return None - return item(*args, **kwargs) - -### testing -import pytest -class MockupRectItem: pass -class MockupPointItem: pass -class MockupPolygonItem: pass - -def _create_factory(): - itemfactory = Factory((('point', MockupPointItem), - ('polygon', MockupPolygonItem))) - itemfactory.register('rect', MockupRectItem) - - return itemfactory - -def test_register(): - itemfactory = _create_factory() - - item = itemfactory.create('rect') - assert isinstance(item, MockupRectItem) - item = itemfactory.create('point') - assert isinstance(item, MockupPointItem) - item = itemfactory.create('polygon') - assert isinstance(item, MockupPolygonItem) - item = itemfactory.create('polygon2') - assert item is None - -def test_register_fail(): - itemfactory = _create_factory() - with pytest.raises(Exception): - itemfactory.register('rect', MockupRectItem) - -def test_register_replace(): - itemfactory = _create_factory() - - itemfactory.register('rect', MockupPolygonItem, replace=True) - item = itemfactory.create('rect') - assert isinstance(item, MockupPolygonItem) - -def test_clear(): - itemfactory = _create_factory() - - item = itemfactory.create('rect') - assert isinstance(item, MockupRectItem) - itemfactory.clear('rect') - item = itemfactory.create('rect') - assert item is None - - item = itemfactory.create('point') - assert isinstance(item, MockupPointItem) - item = itemfactory.create('polygon') - assert isinstance(item, MockupPolygonItem) - itemfactory.clear() - assert itemfactory.create('point') is None - assert itemfactory.create('polygon') is None - diff --git a/items/factory.py b/items/factory.py new file mode 100644 index 0000000..082cf03 --- /dev/null +++ b/items/factory.py @@ -0,0 +1,135 @@ +class Factory: + """ + A generic factory for both items and inserters. + """ + + def __init__(self, items=None): + """ + Constructor. + + Parameters + ========== + items: dict + Mapping from type to python callable. If not None, all mappings + will be registered with the factory. + """ + self.items_ = {} + + if items is not None: + for _type, item in items.iteritems(): + self.register(_type, item, replace=True) + + def register(self, _type, item, replace=False): + """ + Register a new type-item mapping. + + Parameters + ========== + + + """ + _type = _type.lower() + + if _type in self.items_ and not replace: + raise Exception("Type %s already has an item: %s" % \ + (_type, str(self.items_[_type]))) + else: + self.items_[_type] = item + + def clear(self, _type=None): + """ + Remove a type-item mapping. + + Parameters + ========== + _type: str + Type for which the mapping should be removed. If None, all + mappings will be removed. + """ + if _type is None: + self.items_ = {} + else: + _type = _type.lower() + if _type in self.items_: + del self.items_[_type] + + def create(self, _type, *args, **kwargs): + """ + Create a new objectt. + + Parameters + ========== + _type: str + Type for which a new object should be created. + + All further arguments will be passed to the constructor/creating function + of the mapping. + + Returns + ======= + Newly created object. If for the given type no mapping exists, this + function returns ``None``. + """ + _type = _type.lower() + + if _type not in self.items_: + return None + item = self.items_[_type] + if item is None: + return None + return item(*args, **kwargs) + +### testing +import pytest +class MockupRectItem: pass +class MockupPointItem: pass +class MockupPolygonItem: pass + +def _create_factory(): + itemfactory = Factory({'point': MockupPointItem, + 'polygon': MockupPolygonItem}) + itemfactory.register('rect', MockupRectItem) + + return itemfactory + +def test_register(): + itemfactory = _create_factory() + + item = itemfactory.create('rect') + assert isinstance(item, MockupRectItem) + item = itemfactory.create('point') + assert isinstance(item, MockupPointItem) + item = itemfactory.create('polygon') + assert isinstance(item, MockupPolygonItem) + item = itemfactory.create('polygon2') + assert item is None + +def test_register_fail(): + itemfactory = _create_factory() + with pytest.raises(Exception): + itemfactory.register('rect', MockupRectItem) + +def test_register_replace(): + itemfactory = _create_factory() + + itemfactory.register('rect', MockupPolygonItem, replace=True) + item = itemfactory.create('rect') + assert isinstance(item, MockupPolygonItem) + +def test_clear(): + itemfactory = _create_factory() + + item = itemfactory.create('rect') + assert isinstance(item, MockupRectItem) + itemfactory.clear('rect') + item = itemfactory.create('rect') + assert item is None + + item = itemfactory.create('point') + assert isinstance(item, MockupPointItem) + item = itemfactory.create('polygon') + assert isinstance(item, MockupPolygonItem) + itemfactory.clear() + assert itemfactory.create('point') is None + assert itemfactory.create('polygon') is None + diff --git a/items/inserters.py b/items/inserters.py new file mode 100644 index 0000000..bb023ca --- /dev/null +++ b/items/inserters.py @@ -0,0 +1,133 @@ +from PyQt4.QtGui import * +from PyQt4.Qt import * +import math + +class ItemInserter: + def __init__(self, scene, mode=None): + self.scene_ = scene + self.mode_ = mode + + def setScene(self, scene): + self.scene_ = scene + def scene(self): + return self.scene_ + + def setMode(self, mode): + self.mode_ = mode + def mode(self): + return self.mode + + def mousePressEvent(self, event, index): + event.accept() + + def mouseReleaseEvent(self, event, index): + event.accept() + + def mouseMoveEvent(self, event, index): + event.accept() + + def keyPressEvent(self, event, index): + event.ignore() + +class PointItemInserter(ItemInserter): + def mousePressEvent(self, event, index): + pos = event.scenePos() + ann = {'type': 'point', + 'x': pos.x(), 'y': pos.y()} + index.model().addAnnotation(index, ann) + event.accept() + +class RectItemInserter(ItemInserter): + def __init__(self, scene, mode=None): + ItemInserter.__init__(self, scene, mode) + self.current_item_ = None + self.init_pos_ = None + + def mousePressEvent(self, event, index): + pos = event.scenePos() + item = QGraphicsRectItem(QRectF(pos.x(), pos.y(), 0, 0)) + item.setPen(Qt.red) + self.current_item_ = item + self.init_pos_ = pos + self.scene().addItem(item) + event.accept() + + def mouseMoveEvent(self, event, index): + if self.current_item_ is not None: + assert self.init_pos_ is not None + rect = QRectF(self.init_pos_, event.scenePos()).normalized() + self.current_item_.setRect(rect) + + event.accept() + + def mouseReleaseEvent(self, event, index): + if self.current_item_ is not None: + if self.current_item_.rect().width() > 1 and \ + self.current_item_.rect().height() > 1: + rect = self.current_item_.rect() + ann = {'type': 'rect', + 'x': rect.x(), 'y': rect.y(), + 'width': rect.width(), 'height': rect.height()} + index.model().addAnnotation(index, ann) + self.scene().removeItem(self.current_item_) + self.current_item_ = None + self.init_pos_ = None + + event.accept() + +class FixedRatioRectItemInserter(RectItemInserter): + def __init__(self, scene, mode=None): + RectItemInserter.__init__(self, scene, mode) + self.ratio_ = 1 + if mode is not None: + self.ratio_ = float(mode.get('_ratio', 1)) + + def setMode(self, mode): + if mode is not None: + self.ratio_ = float(mode.get('_ratio', 1)) + RectItemInserter.setMode(self, mode) + + def mouseMoveEvent(self, event, index): + if self.current_item_ is not None: + new_geometry = QRectF(self.current_item_.rect().topLeft(), event.scenePos()) + dx = new_geometry.width() + dy = new_geometry.height() + d = math.sqrt(dx*dx + dy*dy) + r = self.ratio_ + k = math.sqrt(r*r+1) + h = d/k + w = d*r/k + new_geometry.setWidth(w) + new_geometry.setHeight(h) + self.current_item_.setRect(new_geometry.normalized()) + + event.accept() + +class PolygonItemInserter(ItemInserter): + def __init__(self, scene, mode=None): + ItemInserter.__init__(self, scene, mode) + self.current_item_ = None + + def mousePressEvent(self, event, index): + pos = event.scenePos() + if self.current_item_ is None: + item = QGraphicsPolygonItem(QPolygonF([pos])) + self.current_item_ = item + self.scene().addItem(item) + else: + polygon = self.current_item_.polygon() + polygon.append(pos) + self.current_item_.setPolygon(polygon) + + event.accept() + + def mouseMoveEvent(self, event, index): + if self.current_item_ is not None: + pos = event.scenePos() + polygon = self.current_item_.polygon() + assert polygon.size() > 0 + polygon[-1] = pos + self.current_item_.setPolygon(polygon) + + event.accept() + diff --git a/items/items.py b/items/items.py new file mode 100644 index 0000000..6104757 --- /dev/null +++ b/items/items.py @@ -0,0 +1,181 @@ +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(16) + self.text_item_ = QGraphicsSimpleTextItem(self) + self.text_item_.setFont(self.text_font_) + self.text_item_.setPen(Qt.yellow) + self.text_item_.setBrush(Qt.yellow) + 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 different positions + self.text_item_.setText(text) + self.text_item_.setPos(0, 0) + self.text_item_.update() + + 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_) + +class RectItem(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_)) + self._updateText() + + 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 _updateText(self): + if 'id' in self.data_: + self.setText("id: " + str(self.data_['id'])) + + 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): + 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) + self._updateText() + +class PointItem(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() + 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() + diff --git a/items/lineitem.py b/items/lineitem.py index 9d9895c..3dd2af0 100644 --- a/items/lineitem.py +++ b/items/lineitem.py @@ -2,7 +2,7 @@ from PyQt4.QtGui import * from PyQt4.Qt import * from annotationitem import * -class AnnotationGraphicsLineItem(AnnotationGraphicsItem): +class LineItem(AnnotationGraphicsItem): def __init__(self, pos, endPoint, parent=None): AnnotationGraphicsItem.__init__(self, False, parent) diff --git a/std_config.py b/std_config.py index 493f5ad..8d6e86a 100644 --- a/std_config.py +++ b/std_config.py @@ -1,5 +1,4 @@ -from items import AnnotationGraphicsRectItem as RectItem -from items import RectItemInserter, AnnotationGraphicsPointItem +import items from loaders import FeretLoader, RectIdLoader from bboxitem import * @@ -20,16 +19,16 @@ HOTKEYS = ( ("", "BodyBBox", "b") ) -ITEMS = ( - ("rect", RectItem), - ("point", AnnotationGraphicsPointItem), - ("bodybbox", BodyBoundingboxItem), -) +ITEMS = { + "rect": items.RectItem, + "point": items.PointItem, + "bodybbox": BodyBoundingboxItem, +} -INSERTERS = ( - ("rect", RectItemInserter), - ("bodybbox", BodyBoundingboxItemInserter), -) +INSERTERS = { + "rect": items.RectItemInserter, + "bodybbox": BodyBoundingboxItemInserter, +} LOADERS = ( ('txt', RectIdLoader), @@ -38,14 +37,3 @@ LOADERS = ( PLUGINS = ( ) -#labeltool.buttonarea.add_label("Rect", {"type": "rect"}) -#labeltool.buttonarea.add_label("FixedRatioRect", {"type": "ratiorect", "_ratio": RATIOS}) -#labeltool.buttonarea.add_label("Point", {"type": "point"}) -#labeltool.buttonarea.add_label("Polygon", {"type": "polygon"}) -#labeltool.buttonarea.add_label("BodyBBox", {"type": "bodybbox"}) -# -#Labeltool.buttonarea.add_hotkey("", "Rect", "r") -#Labeltool.buttonarea.add_hotkey("", "Point", "p") -#Labeltool.buttonarea.add_hotkey("", "Polygon", "o") -#Labeltool.buttonarea.add_hotkey("", "BodyBBox", "b") -