summaryrefslogtreecommitdiff
path: root/silx/gui/plot3d/tools
diff options
context:
space:
mode:
authorPicca Frédéric-Emmanuel <picca@debian.org>2018-03-04 10:20:27 +0100
committerPicca Frédéric-Emmanuel <picca@debian.org>2018-03-04 10:20:27 +0100
commit270d5ddc31c26b62379e3caa9044dd75ccc71847 (patch)
tree55c5bfc851dfce7172d335cd2405b214323e3caf /silx/gui/plot3d/tools
parente19c96eff0c310c06c4f268c8b80cb33bd08996f (diff)
New upstream version 0.7.0+dfsg
Diffstat (limited to 'silx/gui/plot3d/tools')
-rw-r--r--silx/gui/plot3d/tools/GroupPropertiesWidget.py200
-rw-r--r--silx/gui/plot3d/tools/ViewpointTools.py119
-rw-r--r--silx/gui/plot3d/tools/__init__.py6
-rw-r--r--silx/gui/plot3d/tools/toolbars.py111
4 files changed, 310 insertions, 126 deletions
diff --git a/silx/gui/plot3d/tools/GroupPropertiesWidget.py b/silx/gui/plot3d/tools/GroupPropertiesWidget.py
new file mode 100644
index 0000000..30e11de
--- /dev/null
+++ b/silx/gui/plot3d/tools/GroupPropertiesWidget.py
@@ -0,0 +1,200 @@
+# coding: utf-8
+# /*##########################################################################
+#
+# Copyright (c) 2018 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
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+# ###########################################################################*/
+""":class:`GroupPropertiesWidget` allows to reset properties in a GroupItem."""
+
+from __future__ import absolute_import
+
+__authors__ = ["T. Vincent"]
+__license__ = "MIT"
+__date__ = "11/01/2018"
+
+from ....gui import qt
+from ....gui.plot.Colormap import Colormap
+from ....gui.plot.ColormapDialog import ColormapDialog
+
+from ..items import SymbolMixIn, ColormapMixIn
+
+
+class GroupPropertiesWidget(qt.QWidget):
+ """Set properties of all items in a :class:`GroupItem`
+
+ :param QWidget parent:
+ """
+
+ MAX_MARKER_SIZE = 20
+ """Maximum value for marker size"""
+
+ MAX_LINE_WIDTH = 10
+ """Maximum value for line width"""
+
+ def __init__(self, parent=None):
+ super(GroupPropertiesWidget, self).__init__(parent)
+ self._group = None
+ self.setEnabled(False)
+
+ # Set widgets
+ layout = qt.QFormLayout(self)
+ self.setLayout(layout)
+
+ # Colormap
+ colormapButton = qt.QPushButton('Set...')
+ colormapButton.setToolTip("Set colormap for all items")
+ colormapButton.clicked.connect(self._colormapButtonClicked)
+ layout.addRow('Colormap', colormapButton)
+
+ self._markerComboBox = qt.QComboBox(self)
+ self._markerComboBox.addItems(SymbolMixIn.getSupportedSymbolNames())
+
+ # Marker
+ markerButton = qt.QPushButton('Set')
+ markerButton.setToolTip("Set marker for all items")
+ markerButton.clicked.connect(self._markerButtonClicked)
+
+ markerLayout = qt.QHBoxLayout()
+ markerLayout.setContentsMargins(0, 0, 0, 0)
+ markerLayout.addWidget(self._markerComboBox, 1)
+ markerLayout.addWidget(markerButton, 0)
+
+ layout.addRow('Marker', markerLayout)
+
+ # Marker size
+ self._markerSizeSlider = qt.QSlider()
+ self._markerSizeSlider.setOrientation(qt.Qt.Horizontal)
+ self._markerSizeSlider.setSingleStep(1)
+ self._markerSizeSlider.setRange(1, self.MAX_MARKER_SIZE)
+ self._markerSizeSlider.setValue(1)
+
+ markerSizeButton = qt.QPushButton('Set')
+ markerSizeButton.setToolTip("Set marker size for all items")
+ markerSizeButton.clicked.connect(self._markerSizeButtonClicked)
+
+ markerSizeLayout = qt.QHBoxLayout()
+ markerSizeLayout.setContentsMargins(0, 0, 0, 0)
+ markerSizeLayout.addWidget(qt.QLabel('1'))
+ markerSizeLayout.addWidget(self._markerSizeSlider, 1)
+ markerSizeLayout.addWidget(qt.QLabel(str(self.MAX_MARKER_SIZE)))
+ markerSizeLayout.addWidget(markerSizeButton, 0)
+
+ layout.addRow('Marker Size', markerSizeLayout)
+
+ # Line width
+ self._lineWidthSlider = qt.QSlider()
+ self._lineWidthSlider.setOrientation(qt.Qt.Horizontal)
+ self._lineWidthSlider.setSingleStep(1)
+ self._lineWidthSlider.setRange(1, self.MAX_LINE_WIDTH)
+ self._lineWidthSlider.setValue(1)
+
+ lineWidthButton = qt.QPushButton('Set')
+ lineWidthButton.setToolTip("Set line width for all items")
+ lineWidthButton.clicked.connect(self._lineWidthButtonClicked)
+
+ lineWidthLayout = qt.QHBoxLayout()
+ lineWidthLayout.setContentsMargins(0, 0, 0, 0)
+ lineWidthLayout.addWidget(qt.QLabel('1'))
+ lineWidthLayout.addWidget(self._lineWidthSlider, 1)
+ lineWidthLayout.addWidget(qt.QLabel(str(self.MAX_LINE_WIDTH)))
+ lineWidthLayout.addWidget(lineWidthButton, 0)
+
+ layout.addRow('Line Width', lineWidthLayout)
+
+ self._colormapDialog = None # To store dialog
+ self._colormap = Colormap()
+
+ def getGroup(self):
+ """Returns the :class:`GroupItem` this widget is attached to.
+
+ :rtype: Union[GroupItem, None]
+ """
+ return self._group
+
+ def setGroup(self, group):
+ """Set the :class:`GroupItem` this widget is attached to.
+
+ :param GroupItem group: GroupItem to control (or None)
+ """
+ self._group = group
+ if group is not None:
+ self.setEnabled(True)
+
+ def _colormapButtonClicked(self, checked=False):
+ """Handle colormap button clicked"""
+ group = self.getGroup()
+ if group is None:
+ return
+
+ if self._colormapDialog is None:
+ self._colormapDialog = ColormapDialog(self)
+ self._colormapDialog.setColormap(self._colormap)
+
+ previousColormap = self._colormapDialog.getColormap()
+ if self._colormapDialog.exec_():
+ colormap = self._colormapDialog.getColormap()
+
+ for item in group.visit():
+ if isinstance(item, ColormapMixIn):
+ itemCmap = item.getColormap()
+ cmapName = colormap.getName()
+ if cmapName is not None:
+ itemCmap.setName(colormap.getName())
+ else:
+ itemCmap.setColormapLUT(colormap.getColormapLUT())
+ itemCmap.setNormalization(colormap.getNormalization())
+ itemCmap.setVRange(colormap.getVMin(), colormap.getVMax())
+ else:
+ # Reset colormap
+ self._colormapDialog.setColormap(previousColormap)
+
+ def _markerButtonClicked(self, checked=False):
+ """Handle marker set button clicked"""
+ group = self.getGroup()
+ if group is None:
+ return
+
+ marker = self._markerComboBox.currentText()
+ for item in group.visit():
+ if isinstance(item, SymbolMixIn):
+ item.setSymbol(marker)
+
+ def _markerSizeButtonClicked(self, checked=False):
+ """Handle marker size set button clicked"""
+ group = self.getGroup()
+ if group is None:
+ return
+
+ markerSize = self._markerSizeSlider.value()
+ for item in group.visit():
+ if isinstance(item, SymbolMixIn):
+ item.setSymbolSize(markerSize)
+
+ def _lineWidthButtonClicked(self, checked=False):
+ """Handle line width set button clicked"""
+ group = self.getGroup()
+ if group is None:
+ return
+
+ lineWidth = self._lineWidthSlider.value()
+ for item in group.visit():
+ if hasattr(item, 'setLineWidth'):
+ item.setLineWidth(lineWidth)
diff --git a/silx/gui/plot3d/tools/ViewpointTools.py b/silx/gui/plot3d/tools/ViewpointTools.py
index 1346c1c..0607382 100644
--- a/silx/gui/plot3d/tools/ViewpointTools.py
+++ b/silx/gui/plot3d/tools/ViewpointTools.py
@@ -1,7 +1,7 @@
# coding: utf-8
# /*##########################################################################
#
-# Copyright (c) 2015-2017 European Synchrotron Radiation Facility
+# Copyright (c) 2015-2018 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
@@ -31,105 +31,54 @@ __license__ = "MIT"
__date__ = "08/09/2017"
+import weakref
+
from silx.gui import qt
from silx.gui.icons import getQIcon
-
-
-class _ViewpointActionGroup(qt.QActionGroup):
- """ActionGroup of actions to reset the viewpoint.
-
- As for QActionGroup, add group's actions to the widget with:
- `widget.addActions(actionGroup.actions())`
-
- :param Plot3DWidget plot3D: The widget for which to control the viewpoint
- :param parent: See :class:`QActionGroup`
- """
-
- # Action information: icon name, text, tooltip
- _RESET_CAMERA_ACTIONS = (
- ('cube-front', 'Front', 'View along the -Z axis'),
- ('cube-back', 'Back', 'View along the +Z axis'),
- ('cube-top', 'Top', 'View along the -Y'),
- ('cube-bottom', 'Bottom', 'View along the +Y'),
- ('cube-right', 'Right', 'View along the -X'),
- ('cube-left', 'Left', 'View along the +X'),
- ('cube', 'Side', 'Side view')
- )
-
- def __init__(self, plot3D, parent=None):
- super(_ViewpointActionGroup, self).__init__(parent)
- self.setExclusive(False)
-
- self._plot3D = plot3D
-
- for actionInfo in self._RESET_CAMERA_ACTIONS:
- iconname, text, tooltip = actionInfo
-
- action = qt.QAction(getQIcon(iconname), text, None)
- action.setIconVisibleInMenu(True)
- action.setCheckable(False)
- action.setToolTip(tooltip)
- self.addAction(action)
-
- self.triggered[qt.QAction].connect(self._actionGroupTriggered)
-
- def _actionGroupTriggered(self, action):
- actionname = action.text().lower()
-
- self._plot3D.viewport.camera.extrinsic.reset(face=actionname)
- self._plot3D.centerScene()
-
-
-class ViewpointToolBar(qt.QToolBar):
- """A toolbar providing icons to reset the viewpoint.
-
- :param parent: See :class:`QToolBar`
- :param Plot3DWidget plot3D: The widget to control
- :param str title: Title of the toolbar
- """
-
- def __init__(self, parent=None, plot3D=None, title='Viewpoint control'):
- super(ViewpointToolBar, self).__init__(title, parent)
-
- self._actionGroup = _ViewpointActionGroup(plot3D)
- assert plot3D is not None
- self._plot3D = plot3D
- self.addActions(self._actionGroup.actions())
-
- # Choosing projection disabled for now
- # Add projection combo box
- # comboBoxProjection = qt.QComboBox()
- # comboBoxProjection.addItem('Perspective')
- # comboBoxProjection.addItem('Parallel')
- # comboBoxProjection.setToolTip(
- # 'Choose the projection:'
- # ' perspective or parallel (i.e., orthographic)')
- # comboBoxProjection.currentIndexChanged[(str)].connect(
- # self._comboBoxProjectionCurrentIndexChanged)
- # self.addWidget(qt.QLabel('Projection:'))
- # self.addWidget(comboBoxProjection)
-
- # def _comboBoxProjectionCurrentIndexChanged(self, text):
- # """Projection combo box listener"""
- # self._plot3D.setProjection(
- # 'perspective' if text == 'Perspective' else 'orthographic')
+from .. import actions
class ViewpointToolButton(qt.QToolButton):
"""A toolbutton with a drop-down list of ways to reset the viewpoint.
:param parent: See :class:`QToolButton`
- :param Plot3DWiddget plot3D: The widget to control
"""
- def __init__(self, parent=None, plot3D=None):
+ def __init__(self, parent=None):
super(ViewpointToolButton, self).__init__(parent)
- self._actionGroup = _ViewpointActionGroup(plot3D)
+ self._plot3DRef = None
menu = qt.QMenu(self)
- menu.addActions(self._actionGroup.actions())
+ menu.addAction(actions.viewpoint.FrontViewpointAction(parent=self))
+ menu.addAction(actions.viewpoint.BackViewpointAction(parent=self))
+ menu.addAction(actions.viewpoint.TopViewpointAction(parent=self))
+ menu.addAction(actions.viewpoint.BottomViewpointAction(parent=self))
+ menu.addAction(actions.viewpoint.RightViewpointAction(parent=self))
+ menu.addAction(actions.viewpoint.LeftViewpointAction(parent=self))
+ menu.addAction(actions.viewpoint.SideViewpointAction(parent=self))
+
self.setMenu(menu)
self.setPopupMode(qt.QToolButton.InstantPopup)
self.setIcon(getQIcon('cube'))
self.setToolTip('Reset the viewpoint to a defined position')
+
+ def setPlot3DWidget(self, widget):
+ """Set the Plot3DWidget this toolbar is associated with
+
+ :param ~silx.gui.plot3d.Plot3DWidget.Plot3DWidget widget:
+ The widget to control
+ """
+ self._plot3DRef = None if widget is None else weakref.ref(widget)
+
+ for action in self.menu().actions():
+ action.setPlot3DWidget(widget)
+
+ def getPlot3DWidget(self):
+ """Return the Plot3DWidget associated to this toolbar.
+
+ If no widget is associated, it returns None.
+
+ :rtype: ~silx.gui.plot3d.Plot3DWidget.Plot3DWidget or None
+ """
+ return None if self._plot3DRef is None else self._plot3DRef()
diff --git a/silx/gui/plot3d/tools/__init__.py b/silx/gui/plot3d/tools/__init__.py
index e14f604..c8b8d21 100644
--- a/silx/gui/plot3d/tools/__init__.py
+++ b/silx/gui/plot3d/tools/__init__.py
@@ -28,5 +28,7 @@ __authors__ = ["T. Vincent"]
__license__ = "MIT"
__date__ = "08/09/2017"
-from .toolbars import InteractiveModeToolBar, OutputToolBar
-from .ViewpointTools import ViewpointToolBar, ViewpointToolButton
+from .toolbars import InteractiveModeToolBar # noqa
+from .toolbars import OutputToolBar # noqa
+from .toolbars import ViewpointToolBar # noqa
+from .ViewpointTools import ViewpointToolButton # noqa
diff --git a/silx/gui/plot3d/tools/toolbars.py b/silx/gui/plot3d/tools/toolbars.py
index c8be226..d4f32db 100644
--- a/silx/gui/plot3d/tools/toolbars.py
+++ b/silx/gui/plot3d/tools/toolbars.py
@@ -1,7 +1,7 @@
# coding: utf-8
# /*##########################################################################
#
-# Copyright (c) 2016-2017 European Synchrotron Radiation Facility
+# Copyright (c) 2016-2018 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
@@ -44,40 +44,44 @@ __license__ = "MIT"
__date__ = "06/09/2017"
import logging
+import weakref
from silx.gui import qt
+from .ViewpointTools import ViewpointToolButton
from .. import actions
_logger = logging.getLogger(__name__)
-class InteractiveModeToolBar(qt.QToolBar):
- """Toolbar providing icons to change the interaction mode
+class Plot3DWidgetToolBar(qt.QToolBar):
+ """Base class for toolbar associated to a Plot3DWidget
:param parent: See :class:`QWidget`
:param str title: Title of the toolbar.
"""
- def __init__(self, parent=None, title='Plot3D Interaction'):
- super(InteractiveModeToolBar, self).__init__(title, parent)
+ def __init__(self, parent=None, title=''):
+ super(Plot3DWidgetToolBar, self).__init__(title, parent)
- self._plot3d = None
+ self._plot3DRef = None
- self._rotateAction = actions.mode.RotateArcballAction(parent=self)
- self.addAction(self._rotateAction)
+ def _plot3DWidgetChanged(self, widget):
+ """Handle change of Plot3DWidget and sync actions
- self._panAction = actions.mode.PanAction(parent=self)
- self.addAction(self._panAction)
+ :param Plot3DWidget widget:
+ """
+ for action in self.actions():
+ if isinstance(action, actions.Plot3DAction):
+ action.setPlot3DWidget(widget)
def setPlot3DWidget(self, widget):
"""Set the Plot3DWidget this toolbar is associated with
- :param Plot3DWidget widget: The widget to copy/save/print
+ :param Plot3DWidget widget: The widget to control
"""
- self._plot3d = widget
- self.getRotateAction().setPlot3DWidget(widget)
- self.getPanAction().setPlot3DWidget(widget)
+ self._plot3DRef = None if widget is None else weakref.ref(widget)
+ self._plot3DWidgetChanged(widget)
def getPlot3DWidget(self):
"""Return the Plot3DWidget associated to this toolbar.
@@ -86,7 +90,24 @@ class InteractiveModeToolBar(qt.QToolBar):
:rtype: qt.QWidget
"""
- return self._plot3d
+ return None if self._plot3DRef is None else self._plot3DRef()
+
+
+class InteractiveModeToolBar(Plot3DWidgetToolBar):
+ """Toolbar providing icons to change the interaction mode
+
+ :param parent: See :class:`QWidget`
+ :param str title: Title of the toolbar.
+ """
+
+ def __init__(self, parent=None, title='Plot3D Interaction'):
+ super(InteractiveModeToolBar, self).__init__(parent, title)
+
+ self._rotateAction = actions.mode.RotateArcballAction(parent=self)
+ self.addAction(self._rotateAction)
+
+ self._panAction = actions.mode.PanAction(parent=self)
+ self.addAction(self._panAction)
def getRotateAction(self):
"""Returns the QAction setting rotate interaction of the Plot3DWidget
@@ -103,7 +124,7 @@ class InteractiveModeToolBar(qt.QToolBar):
return self._panAction
-class OutputToolBar(qt.QToolBar):
+class OutputToolBar(Plot3DWidgetToolBar):
"""Toolbar providing icons to copy, save and print the OpenGL scene
:param parent: See :class:`QWidget`
@@ -111,9 +132,7 @@ class OutputToolBar(qt.QToolBar):
"""
def __init__(self, parent=None, title='Plot3D Output'):
- super(OutputToolBar, self).__init__(title, parent)
-
- self._plot3d = None
+ super(OutputToolBar, self).__init__(parent, title)
self._copyAction = actions.io.CopyAction(parent=self)
self.addAction(self._copyAction)
@@ -127,26 +146,6 @@ class OutputToolBar(qt.QToolBar):
self._printAction = actions.io.PrintAction(parent=self)
self.addAction(self._printAction)
- def setPlot3DWidget(self, widget):
- """Set the Plot3DWidget this toolbar is associated with
-
- :param Plot3DWidget widget: The widget to copy/save/print
- """
- self._plot3d = widget
- self.getCopyAction().setPlot3DWidget(widget)
- self.getSaveAction().setPlot3DWidget(widget)
- self.getVideoRecordAction().setPlot3DWidget(widget)
- self.getPrintAction().setPlot3DWidget(widget)
-
- def getPlot3DWidget(self):
- """Return the Plot3DWidget associated to this toolbar.
-
- If no widget is associated, it returns None.
-
- :rtype: qt.QWidget
- """
- return self._plot3d
-
def getCopyAction(self):
"""Returns the QAction performing copy to clipboard of the Plot3DWidget
@@ -174,3 +173,37 @@ class OutputToolBar(qt.QToolBar):
:rtype: qt.QAction
"""
return self._printAction
+
+
+class ViewpointToolBar(Plot3DWidgetToolBar):
+ """A toolbar providing icons to reset the viewpoint.
+
+ :param parent: See :class:`QToolBar`
+ :param str title: Title of the toolbar
+ """
+
+ def __init__(self, parent=None, title='Viewpoint control'):
+ super(ViewpointToolBar, self).__init__(parent, title)
+
+ self._viewpointToolButton = ViewpointToolButton(parent=self)
+ self.addWidget(self._viewpointToolButton)
+ self._rotateViewpointAction = actions.viewpoint.RotateViewpoint(parent=self)
+ self.addAction(self._rotateViewpointAction)
+
+ def _plot3DWidgetChanged(self, widget):
+ self.getViewpointToolButton().setPlot3DWidget(widget)
+ super(ViewpointToolBar, self)._plot3DWidgetChanged(widget)
+
+ def getViewpointToolButton(self):
+ """Returns the ViewpointToolButton to set viewpoint of the Plot3DWidget
+
+ :rtype: ViewpointToolButton
+ """
+ return self._viewpointToolButton
+
+ def getRotateViewpointAction(self):
+ """Returns the QAction to start/stop rotation of the Plot3DWidget
+
+ :rtype: qt.QAction
+ """
+ return self._rotateViewpointAction