summaryrefslogtreecommitdiff
path: root/silx/gui/plot/items/roi.py
diff options
context:
space:
mode:
Diffstat (limited to 'silx/gui/plot/items/roi.py')
-rw-r--r--silx/gui/plot/items/roi.py200
1 files changed, 121 insertions, 79 deletions
diff --git a/silx/gui/plot/items/roi.py b/silx/gui/plot/items/roi.py
index 65831be..dcad943 100644
--- a/silx/gui/plot/items/roi.py
+++ b/silx/gui/plot/items/roi.py
@@ -1,7 +1,7 @@
# coding: utf-8
# /*##########################################################################
#
-# Copyright (c) 2018 European Synchrotron Radiation Facility
+# Copyright (c) 2018-2019 European Synchrotron Radiation Facility
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@@ -40,12 +40,51 @@ from ....utils.weakref import WeakList
from ... import qt
from .. import items
from ...colors import rgba
+import silx.utils.deprecation
+from silx.utils.proxy import docstring
logger = logging.getLogger(__name__)
-class RegionOfInterest(qt.QObject):
+class _RegionOfInterestBase(qt.QObject):
+ """Base class of 1D and 2D region of interest
+
+ :param QObject parent: See QObject
+ :param str name: The name of the ROI
+ """
+
+ sigItemChanged = qt.Signal(object)
+ """Signal emitted when item has changed.
+
+ It provides a flag describing which property of the item has changed.
+ See :class:`ItemChangedType` for flags description.
+ """
+
+ def __init__(self, parent=None, name=''):
+ qt.QObject.__init__(self)
+ self.__name = str(name)
+
+ def getName(self):
+ """Returns the name of the ROI
+
+ :return: name of the region of interest
+ :rtype: str
+ """
+ return self.__name
+
+ def setName(self, name):
+ """Set the name of the ROI
+
+ :param str name: name of the region of interest
+ """
+ name = str(name)
+ if self.__name != name:
+ self.__name = name
+ self.sigItemChanged.emit(items.ItemChangedType.NAME)
+
+
+class RegionOfInterest(_RegionOfInterestBase):
"""Object describing a region of interest in a plot.
:param QObject parent:
@@ -55,7 +94,7 @@ class RegionOfInterest(qt.QObject):
_kind = None
"""Label for this kind of ROI.
- Should be setted by inherited classes to custom the ROI manager widget.
+ Should be set by inherited classes to custom the ROI manager widget.
"""
sigRegionChanged = qt.Signal()
@@ -65,15 +104,20 @@ class RegionOfInterest(qt.QObject):
# Avoid circular dependancy
from ..tools import roi as roi_tools
assert parent is None or isinstance(parent, roi_tools.RegionOfInterestManager)
- qt.QObject.__init__(self, parent)
+ _RegionOfInterestBase.__init__(self, parent, '')
self._color = rgba('red')
self._items = WeakList()
self._editAnchors = WeakList()
self._points = None
- self._label = ''
self._labelItem = None
self._editable = False
self._visible = True
+ self.sigItemChanged.connect(self.__itemChanged)
+
+ def __itemChanged(self, event):
+ """Handle name change"""
+ if event == items.ItemChangedType.NAME:
+ self._updateLabelItem(self.getName())
def __del__(self):
# Clean-up plot items
@@ -140,22 +184,27 @@ class RegionOfInterest(qt.QObject):
if isinstance(item, items.ColorMixIn):
item.setColor(rgbaColor)
+ self.sigItemChanged.emit(items.ItemChangedType.COLOR)
+
+ @silx.utils.deprecation.deprecated(reason='API modification',
+ replacement='getName()',
+ since_version=0.12)
def getLabel(self):
"""Returns the label displayed for this ROI.
:rtype: str
"""
- return self._label
+ return self.getName()
+ @silx.utils.deprecation.deprecated(reason='API modification',
+ replacement='setName(name)',
+ since_version=0.12)
def setLabel(self, label):
"""Set the label displayed with this ROI.
:param str label: The text label to display
"""
- label = str(label)
- if label != self._label:
- self._label = label
- self._updateLabelItem(label)
+ self.setName(name=label)
def isEditable(self):
"""Returns whether the ROI is editable by the user or not.
@@ -176,6 +225,7 @@ class RegionOfInterest(qt.QObject):
# Recreate plot items
# This can be avoided once marker.setDraggable is public
self._createPlotItems()
+ self.sigItemChanged.emit(items.ItemChangedType.EDITABLE)
def isVisible(self):
"""Returns whether the ROI is visible in the plot.
@@ -197,13 +247,13 @@ class RegionOfInterest(qt.QObject):
hide it.
"""
visible = bool(visible)
- if self._visible == visible:
- return
- self._visible = visible
- if self._labelItem is not None:
- self._labelItem.setVisible(visible)
- for item in self._items + self._editAnchors:
- item.setVisible(visible)
+ if self._visible != visible:
+ self._visible = visible
+ if self._labelItem is not None:
+ self._labelItem.setVisible(visible)
+ for item in self._items + self._editAnchors:
+ item.setVisible(visible)
+ self.sigItemChanged.emit(items.ItemChangedType.VISIBLE)
def _getControlPoints(self):
"""Returns the current ROI control points.
@@ -371,7 +421,7 @@ class RegionOfInterest(qt.QObject):
markerPos = self._getLabelPosition()
marker = items.Marker()
marker.setPosition(*markerPos)
- marker.setText(self.getLabel())
+ marker.setText(self.getName())
marker.setColor(rgba(self.getColor()))
marker.setSymbol('')
marker._setDraggable(False)
@@ -465,6 +515,12 @@ class PointROI(RegionOfInterest, items.SymbolMixIn):
_plotShape = "point"
"""Plot shape which is used for the first interaction"""
+ _DEFAULT_SYMBOL = '+'
+ """Default symbol of the PointROI
+
+ It overwrite the `SymbolMixIn` class attribte.
+ """
+
def __init__(self, parent=None):
items.SymbolMixIn.__init__(self)
RegionOfInterest.__init__(self, parent=parent)
@@ -488,31 +544,31 @@ class PointROI(RegionOfInterest, items.SymbolMixIn):
return None
def _updateLabelItem(self, label):
- if self.isEditable():
- item = self._editAnchors[0]
- else:
+ self._items[0].setText(label)
+
+ def _updateShape(self):
+ if len(self._items) > 0:
+ controlPoints = self._getControlPoints()
item = self._items[0]
- item.setText(label)
+ item.setPosition(*controlPoints[0])
+
+ def __positionChanged(self, event):
+ """Handle position changed events of the marker"""
+ if event is items.ItemChangedType.POSITION:
+ marker = self.sender()
+ if isinstance(marker, items.Marker):
+ self.setPosition(marker.getPosition())
def _createShapeItems(self, points):
- if self.isEditable():
- return []
marker = items.Marker()
marker.setPosition(points[0][0], points[0][1])
- marker.setText(self.getLabel())
- marker.setColor(rgba(self.getColor()))
+ marker.setText(self.getName())
marker.setSymbol(self.getSymbol())
marker.setSymbolSize(self.getSymbolSize())
- marker._setDraggable(False)
- return [marker]
-
- def _createAnchorItems(self, points):
- marker = items.Marker()
- marker.setPosition(points[0][0], points[0][1])
- marker.setText(self.getLabel())
+ marker.setColor(rgba(self.getColor()))
marker._setDraggable(self.isEditable())
- marker.setSymbol(self.getSymbol())
- marker.setSymbolSize(self.getSymbolSize())
+ if self.isEditable():
+ marker.sigItemChanged.connect(self.__positionChanged)
return [marker]
def __str__(self):
@@ -672,38 +728,31 @@ class HorizontalLineROI(RegionOfInterest, items.LineMixIn):
return None
def _updateLabelItem(self, label):
- if self.isEditable():
- item = self._editAnchors[0]
- else:
- item = self._items[0]
- item.setText(label)
+ self._items[0].setText(label)
def _updateShape(self):
- if not self.isEditable():
- if len(self._items) > 0:
- controlPoints = self._getControlPoints()
- item = self._items[0]
- item.setPosition(*controlPoints[0])
+ if len(self._items) > 0:
+ controlPoints = self._getControlPoints()
+ item = self._items[0]
+ item.setPosition(*controlPoints[0])
+
+ def __positionChanged(self, event):
+ """Handle position changed events of the marker"""
+ if event is items.ItemChangedType.POSITION:
+ marker = self.sender()
+ if isinstance(marker, items.YMarker):
+ self.setPosition(marker.getYPosition())
def _createShapeItems(self, points):
- if self.isEditable():
- return []
marker = items.YMarker()
marker.setPosition(points[0][0], points[0][1])
- marker.setText(self.getLabel())
+ marker.setText(self.getName())
marker.setColor(rgba(self.getColor()))
- marker._setDraggable(False)
marker.setLineWidth(self.getLineWidth())
marker.setLineStyle(self.getLineStyle())
- return [marker]
-
- def _createAnchorItems(self, points):
- marker = items.YMarker()
- marker.setPosition(points[0][0], points[0][1])
- marker.setText(self.getLabel())
marker._setDraggable(self.isEditable())
- marker.setLineWidth(self.getLineWidth())
- marker.setLineStyle(self.getLineStyle())
+ if self.isEditable():
+ marker.sigItemChanged.connect(self.__positionChanged)
return [marker]
def __str__(self):
@@ -749,38 +798,31 @@ class VerticalLineROI(RegionOfInterest, items.LineMixIn):
return None
def _updateLabelItem(self, label):
- if self.isEditable():
- item = self._editAnchors[0]
- else:
- item = self._items[0]
- item.setText(label)
+ self._items[0].setText(label)
def _updateShape(self):
- if not self.isEditable():
- if len(self._items) > 0:
- controlPoints = self._getControlPoints()
- item = self._items[0]
- item.setPosition(*controlPoints[0])
+ if len(self._items) > 0:
+ controlPoints = self._getControlPoints()
+ item = self._items[0]
+ item.setPosition(*controlPoints[0])
+
+ def __positionChanged(self, event):
+ """Handle position changed events of the marker"""
+ if event is items.ItemChangedType.POSITION:
+ marker = self.sender()
+ if isinstance(marker, items.XMarker):
+ self.setPosition(marker.getXPosition())
def _createShapeItems(self, points):
- if self.isEditable():
- return []
marker = items.XMarker()
marker.setPosition(points[0][0], points[0][1])
- marker.setText(self.getLabel())
+ marker.setText(self.getName())
marker.setColor(rgba(self.getColor()))
- marker._setDraggable(False)
marker.setLineWidth(self.getLineWidth())
marker.setLineStyle(self.getLineStyle())
- return [marker]
-
- def _createAnchorItems(self, points):
- marker = items.XMarker()
- marker.setPosition(points[0][0], points[0][1])
- marker.setText(self.getLabel())
marker._setDraggable(self.isEditable())
- marker.setLineWidth(self.getLineWidth())
- marker.setLineStyle(self.getLineStyle())
+ if self.isEditable():
+ marker.sigItemChanged.connect(self.__positionChanged)
return [marker]
def __str__(self):