summaryrefslogtreecommitdiff
path: root/silx/gui/plot/actions/control.py
diff options
context:
space:
mode:
Diffstat (limited to 'silx/gui/plot/actions/control.py')
-rw-r--r--silx/gui/plot/actions/control.py607
1 files changed, 0 insertions, 607 deletions
diff --git a/silx/gui/plot/actions/control.py b/silx/gui/plot/actions/control.py
deleted file mode 100644
index ec4a3de..0000000
--- a/silx/gui/plot/actions/control.py
+++ /dev/null
@@ -1,607 +0,0 @@
-# coding: utf-8
-# /*##########################################################################
-#
-# Copyright (c) 2004-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
-# 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.
-#
-# ###########################################################################*/
-"""
-:mod:`silx.gui.plot.actions.control` provides a set of QAction relative to control
-of a :class:`.PlotWidget`.
-
-The following QAction are available:
-
-- :class:`ColormapAction`
-- :class:`CrosshairAction`
-- :class:`CurveStyleAction`
-- :class:`GridAction`
-- :class:`KeepAspectRatioAction`
-- :class:`PanWithArrowKeysAction`
-- :class:`ResetZoomAction`
-- :class:`ShowAxisAction`
-- :class:`XAxisLogarithmicAction`
-- :class:`XAxisAutoScaleAction`
-- :class:`YAxisInvertedAction`
-- :class:`YAxisLogarithmicAction`
-- :class:`YAxisAutoScaleAction`
-- :class:`ZoomBackAction`
-- :class:`ZoomInAction`
-- :class:`ZoomOutAction`
-"""
-
-from __future__ import division
-
-__authors__ = ["V.A. Sole", "T. Vincent", "P. Knobel"]
-__license__ = "MIT"
-__date__ = "24/04/2018"
-
-from . import PlotAction
-import logging
-from silx.gui.plot import items
-from silx.gui.plot._utils import applyZoomToPlot as _applyZoomToPlot
-from silx.gui import qt
-from silx.gui import icons
-
-_logger = logging.getLogger(__name__)
-
-
-class ResetZoomAction(PlotAction):
- """QAction controlling reset zoom on a :class:`.PlotWidget`.
-
- :param plot: :class:`.PlotWidget` instance on which to operate
- :param parent: See :class:`QAction`
- """
-
- def __init__(self, plot, parent=None):
- super(ResetZoomAction, self).__init__(
- plot, icon='zoom-original', text='Reset Zoom',
- tooltip='Auto-scale the graph',
- triggered=self._actionTriggered,
- checkable=False, parent=parent)
- self._autoscaleChanged(True)
- plot.getXAxis().sigAutoScaleChanged.connect(self._autoscaleChanged)
- plot.getYAxis().sigAutoScaleChanged.connect(self._autoscaleChanged)
-
- def _autoscaleChanged(self, enabled):
- xAxis = self.plot.getXAxis()
- yAxis = self.plot.getYAxis()
- self.setEnabled(xAxis.isAutoScale() or yAxis.isAutoScale())
-
- if xAxis.isAutoScale() and yAxis.isAutoScale():
- tooltip = 'Auto-scale the graph'
- elif xAxis.isAutoScale(): # And not Y axis
- tooltip = 'Auto-scale the x-axis of the graph only'
- elif yAxis.isAutoScale(): # And not X axis
- tooltip = 'Auto-scale the y-axis of the graph only'
- else: # no axis in autoscale
- tooltip = 'Auto-scale the graph'
- self.setToolTip(tooltip)
-
- def _actionTriggered(self, checked=False):
- self.plot.resetZoom()
-
-
-class ZoomBackAction(PlotAction):
- """QAction performing a zoom-back in :class:`.PlotWidget` limits history.
-
- :param plot: :class:`.PlotWidget` instance on which to operate
- :param parent: See :class:`QAction`
- """
-
- def __init__(self, plot, parent=None):
- super(ZoomBackAction, self).__init__(
- plot, icon='zoom-back', text='Zoom Back',
- tooltip='Zoom back the plot',
- triggered=self._actionTriggered,
- checkable=False, parent=parent)
- self.setShortcutContext(qt.Qt.WidgetShortcut)
-
- def _actionTriggered(self, checked=False):
- self.plot.getLimitsHistory().pop()
-
-
-class ZoomInAction(PlotAction):
- """QAction performing a zoom-in on a :class:`.PlotWidget`.
-
- :param plot: :class:`.PlotWidget` instance on which to operate
- :param parent: See :class:`QAction`
- """
-
- def __init__(self, plot, parent=None):
- super(ZoomInAction, self).__init__(
- plot, icon='zoom-in', text='Zoom In',
- tooltip='Zoom in the plot',
- triggered=self._actionTriggered,
- checkable=False, parent=parent)
- self.setShortcut(qt.QKeySequence.ZoomIn)
- self.setShortcutContext(qt.Qt.WidgetShortcut)
-
- def _actionTriggered(self, checked=False):
- _applyZoomToPlot(self.plot, 1.1)
-
-
-class ZoomOutAction(PlotAction):
- """QAction performing a zoom-out on a :class:`.PlotWidget`.
-
- :param plot: :class:`.PlotWidget` instance on which to operate
- :param parent: See :class:`QAction`
- """
-
- def __init__(self, plot, parent=None):
- super(ZoomOutAction, self).__init__(
- plot, icon='zoom-out', text='Zoom Out',
- tooltip='Zoom out the plot',
- triggered=self._actionTriggered,
- checkable=False, parent=parent)
- self.setShortcut(qt.QKeySequence.ZoomOut)
- self.setShortcutContext(qt.Qt.WidgetShortcut)
-
- def _actionTriggered(self, checked=False):
- _applyZoomToPlot(self.plot, 1. / 1.1)
-
-
-class XAxisAutoScaleAction(PlotAction):
- """QAction controlling X axis autoscale on a :class:`.PlotWidget`.
-
- :param plot: :class:`.PlotWidget` instance on which to operate
- :param parent: See :class:`QAction`
- """
-
- def __init__(self, plot, parent=None):
- super(XAxisAutoScaleAction, self).__init__(
- plot, icon='plot-xauto', text='X Autoscale',
- tooltip='Enable x-axis auto-scale when checked.\n'
- 'If unchecked, x-axis does not change when reseting zoom.',
- triggered=self._actionTriggered,
- checkable=True, parent=parent)
- self.setChecked(plot.getXAxis().isAutoScale())
- plot.getXAxis().sigAutoScaleChanged.connect(self.setChecked)
-
- def _actionTriggered(self, checked=False):
- self.plot.getXAxis().setAutoScale(checked)
- if checked:
- self.plot.resetZoom()
-
-
-class YAxisAutoScaleAction(PlotAction):
- """QAction controlling Y axis autoscale on a :class:`.PlotWidget`.
-
- :param plot: :class:`.PlotWidget` instance on which to operate
- :param parent: See :class:`QAction`
- """
-
- def __init__(self, plot, parent=None):
- super(YAxisAutoScaleAction, self).__init__(
- plot, icon='plot-yauto', text='Y Autoscale',
- tooltip='Enable y-axis auto-scale when checked.\n'
- 'If unchecked, y-axis does not change when reseting zoom.',
- triggered=self._actionTriggered,
- checkable=True, parent=parent)
- self.setChecked(plot.getYAxis().isAutoScale())
- plot.getYAxis().sigAutoScaleChanged.connect(self.setChecked)
-
- def _actionTriggered(self, checked=False):
- self.plot.getYAxis().setAutoScale(checked)
- if checked:
- self.plot.resetZoom()
-
-
-class XAxisLogarithmicAction(PlotAction):
- """QAction controlling X axis log scale on a :class:`.PlotWidget`.
-
- :param plot: :class:`.PlotWidget` instance on which to operate
- :param parent: See :class:`QAction`
- """
-
- def __init__(self, plot, parent=None):
- super(XAxisLogarithmicAction, self).__init__(
- plot, icon='plot-xlog', text='X Log. scale',
- tooltip='Logarithmic x-axis when checked',
- triggered=self._actionTriggered,
- checkable=True, parent=parent)
- self.axis = plot.getXAxis()
- self.setChecked(self.axis.getScale() == self.axis.LOGARITHMIC)
- self.axis.sigScaleChanged.connect(self._setCheckedIfLogScale)
-
- def _setCheckedIfLogScale(self, scale):
- self.setChecked(scale == self.axis.LOGARITHMIC)
-
- def _actionTriggered(self, checked=False):
- scale = self.axis.LOGARITHMIC if checked else self.axis.LINEAR
- self.axis.setScale(scale)
-
-
-class YAxisLogarithmicAction(PlotAction):
- """QAction controlling Y axis log scale on a :class:`.PlotWidget`.
-
- :param plot: :class:`.PlotWidget` instance on which to operate
- :param parent: See :class:`QAction`
- """
-
- def __init__(self, plot, parent=None):
- super(YAxisLogarithmicAction, self).__init__(
- plot, icon='plot-ylog', text='Y Log. scale',
- tooltip='Logarithmic y-axis when checked',
- triggered=self._actionTriggered,
- checkable=True, parent=parent)
- self.axis = plot.getYAxis()
- self.setChecked(self.axis.getScale() == self.axis.LOGARITHMIC)
- self.axis.sigScaleChanged.connect(self._setCheckedIfLogScale)
-
- def _setCheckedIfLogScale(self, scale):
- self.setChecked(scale == self.axis.LOGARITHMIC)
-
- def _actionTriggered(self, checked=False):
- scale = self.axis.LOGARITHMIC if checked else self.axis.LINEAR
- self.axis.setScale(scale)
-
-
-class GridAction(PlotAction):
- """QAction controlling grid mode on a :class:`.PlotWidget`.
-
- :param plot: :class:`.PlotWidget` instance on which to operate
- :param str gridMode: The grid mode to use in 'both', 'major'.
- See :meth:`.PlotWidget.setGraphGrid`
- :param parent: See :class:`QAction`
- """
-
- def __init__(self, plot, gridMode='both', parent=None):
- assert gridMode in ('both', 'major')
- self._gridMode = gridMode
-
- super(GridAction, self).__init__(
- plot, icon='plot-grid', text='Grid',
- tooltip='Toggle grid (on/off)',
- triggered=self._actionTriggered,
- checkable=True, parent=parent)
- self.setChecked(plot.getGraphGrid() is not None)
- plot.sigSetGraphGrid.connect(self._gridChanged)
-
- def _gridChanged(self, which):
- """Slot listening for PlotWidget grid mode change."""
- self.setChecked(which != 'None')
-
- def _actionTriggered(self, checked=False):
- self.plot.setGraphGrid(self._gridMode if checked else None)
-
-
-class CurveStyleAction(PlotAction):
- """QAction controlling curve style on a :class:`.PlotWidget`.
-
- It changes the default line and markers style which updates all
- curves on the plot.
-
- :param plot: :class:`.PlotWidget` instance on which to operate
- :param parent: See :class:`QAction`
- """
-
- def __init__(self, plot, parent=None):
- super(CurveStyleAction, self).__init__(
- plot, icon='plot-toggle-points', text='Curve style',
- tooltip='Change curve line and markers style',
- triggered=self._actionTriggered,
- checkable=False, parent=parent)
-
- def _actionTriggered(self, checked=False):
- currentState = (self.plot.isDefaultPlotLines(),
- self.plot.isDefaultPlotPoints())
-
- if currentState == (False, False):
- newState = True, False
- else:
- # line only, line and symbol, symbol only
- states = (True, False), (True, True), (False, True)
- newState = states[(states.index(currentState) + 1) % 3]
-
- self.plot.setDefaultPlotLines(newState[0])
- self.plot.setDefaultPlotPoints(newState[1])
-
-
-class ColormapAction(PlotAction):
- """QAction opening a ColormapDialog to update the colormap.
-
- Both the active image colormap and the default colormap are updated.
-
- :param plot: :class:`.PlotWidget` instance on which to operate
- :param parent: See :class:`QAction`
- """
- def __init__(self, plot, parent=None):
- self._dialog = None # To store an instance of ColormapDialog
- super(ColormapAction, self).__init__(
- plot, icon='colormap', text='Colormap',
- tooltip="Change colormap",
- triggered=self._actionTriggered,
- checkable=True, parent=parent)
- self.plot.sigActiveImageChanged.connect(self._updateColormap)
- self.plot.sigActiveScatterChanged.connect(self._updateColormap)
-
- def setColorDialog(self, colorDialog):
- """Set a specific color dialog instead of using the default dialog."""
- assert(colorDialog is not None)
- assert(self._dialog is None)
- self._dialog = colorDialog
- self._dialog.visibleChanged.connect(self._dialogVisibleChanged)
- self.setChecked(self._dialog.isVisible())
-
- @staticmethod
- def _createDialog(parent):
- """Create the dialog if not already existing
-
- :parent QWidget parent: Parent of the new colormap
- :rtype: ColormapDialog
- """
- from silx.gui.dialog.ColormapDialog import ColormapDialog
- dialog = ColormapDialog(parent=parent)
- dialog.setModal(False)
- return dialog
-
- def _actionTriggered(self, checked=False):
- """Create a cmap dialog and update active image and default cmap."""
- if self._dialog is None:
- self._dialog = self._createDialog(self.plot)
- self._dialog.visibleChanged.connect(self._dialogVisibleChanged)
-
- # Run the dialog listening to colormap change
- if checked is True:
- self._dialog.show()
- self._updateColormap()
- else:
- self._dialog.hide()
-
- def _dialogVisibleChanged(self, isVisible):
- self.setChecked(isVisible)
-
- def _updateColormap(self):
- if self._dialog is None:
- return
- image = self.plot.getActiveImage()
-
- if isinstance(image, items.ImageComplexData):
- # Specific init for complex images
- colormap = image.getColormap()
-
- mode = image.getComplexMode()
- if mode in (items.ImageComplexData.ComplexMode.AMPLITUDE_PHASE,
- items.ImageComplexData.ComplexMode.LOG10_AMPLITUDE_PHASE):
- data = image.getData(
- copy=False, mode=items.ImageComplexData.ComplexMode.PHASE)
- else:
- data = image.getData(copy=False)
-
- # Set histogram and range if any
- self._dialog.setData(data)
-
- elif isinstance(image, items.ColormapMixIn):
- # Set dialog from active image
- colormap = image.getColormap()
- data = image.getData(copy=False)
- # Set histogram and range if any
- self._dialog.setData(data)
-
- else:
- # No active image or active image is RGBA,
- # Check for active scatter plot
- scatter = self.plot._getActiveItem(kind='scatter')
- if scatter is not None:
- colormap = scatter.getColormap()
- data = scatter.getValueData(copy=False)
- self._dialog.setData(data)
-
- else:
- # No active data image nor scatter,
- # set dialog from default info
- colormap = self.plot.getDefaultColormap()
- # Reset histogram and range if any
- self._dialog.setData(None)
-
- self._dialog.setColormap(colormap)
-
-
-class ColorBarAction(PlotAction):
- """QAction opening the ColorBarWidget of the specified plot.
-
- :param plot: :class:`.PlotWidget` instance on which to operate
- :param parent: See :class:`QAction`
- """
- def __init__(self, plot, parent=None):
- self._dialog = None # To store an instance of ColorBar
- super(ColorBarAction, self).__init__(
- plot, icon='colorbar', text='Colorbar',
- tooltip="Show/Hide the colorbar",
- triggered=self._actionTriggered,
- checkable=True, parent=parent)
- colorBarWidget = self.plot.getColorBarWidget()
- old = self.blockSignals(True)
- self.setChecked(colorBarWidget.isVisibleTo(self.plot))
- self.blockSignals(old)
- colorBarWidget.sigVisibleChanged.connect(self._widgetVisibleChanged)
-
- def _widgetVisibleChanged(self, isVisible):
- """Callback when the colorbar `visible` property change."""
- if self.isChecked() == isVisible:
- return
- self.setChecked(isVisible)
-
- def _actionTriggered(self, checked=False):
- """Create a cmap dialog and update active image and default cmap."""
- colorBarWidget = self.plot.getColorBarWidget()
- if not colorBarWidget.isHidden() == checked:
- return
- self.plot.getColorBarWidget().setVisible(checked)
-
-
-class KeepAspectRatioAction(PlotAction):
- """QAction controlling aspect ratio on a :class:`.PlotWidget`.
-
- :param plot: :class:`.PlotWidget` instance on which to operate
- :param parent: See :class:`QAction`
- """
-
- def __init__(self, plot, parent=None):
- # Uses two images for checked/unchecked states
- self._states = {
- False: (icons.getQIcon('shape-circle-solid'),
- "Keep data aspect ratio"),
- True: (icons.getQIcon('shape-ellipse-solid'),
- "Do no keep data aspect ratio")
- }
-
- icon, tooltip = self._states[plot.isKeepDataAspectRatio()]
- super(KeepAspectRatioAction, self).__init__(
- plot,
- icon=icon,
- text='Toggle keep aspect ratio',
- tooltip=tooltip,
- triggered=self._actionTriggered,
- checkable=False,
- parent=parent)
- plot.sigSetKeepDataAspectRatio.connect(
- self._keepDataAspectRatioChanged)
-
- def _keepDataAspectRatioChanged(self, aspectRatio):
- """Handle Plot set keep aspect ratio signal"""
- icon, tooltip = self._states[aspectRatio]
- self.setIcon(icon)
- self.setToolTip(tooltip)
-
- def _actionTriggered(self, checked=False):
- # This will trigger _keepDataAspectRatioChanged
- self.plot.setKeepDataAspectRatio(not self.plot.isKeepDataAspectRatio())
-
-
-class YAxisInvertedAction(PlotAction):
- """QAction controlling Y orientation on a :class:`.PlotWidget`.
-
- :param plot: :class:`.PlotWidget` instance on which to operate
- :param parent: See :class:`QAction`
- """
-
- def __init__(self, plot, parent=None):
- # Uses two images for checked/unchecked states
- self._states = {
- False: (icons.getQIcon('plot-ydown'),
- "Orient Y axis downward"),
- True: (icons.getQIcon('plot-yup'),
- "Orient Y axis upward"),
- }
-
- icon, tooltip = self._states[plot.getYAxis().isInverted()]
- super(YAxisInvertedAction, self).__init__(
- plot,
- icon=icon,
- text='Invert Y Axis',
- tooltip=tooltip,
- triggered=self._actionTriggered,
- checkable=False,
- parent=parent)
- plot.getYAxis().sigInvertedChanged.connect(self._yAxisInvertedChanged)
-
- def _yAxisInvertedChanged(self, inverted):
- """Handle Plot set y axis inverted signal"""
- icon, tooltip = self._states[inverted]
- self.setIcon(icon)
- self.setToolTip(tooltip)
-
- def _actionTriggered(self, checked=False):
- # This will trigger _yAxisInvertedChanged
- yAxis = self.plot.getYAxis()
- yAxis.setInverted(not yAxis.isInverted())
-
-
-class CrosshairAction(PlotAction):
- """QAction toggling crosshair cursor on a :class:`.PlotWidget`.
-
- :param plot: :class:`.PlotWidget` instance on which to operate
- :param str color: Color to use to draw the crosshair
- :param int linewidth: Width of the crosshair cursor
- :param str linestyle: Style of line. See :meth:`.Plot.setGraphCursor`
- :param parent: See :class:`QAction`
- """
-
- def __init__(self, plot, color='black', linewidth=1, linestyle='-',
- parent=None):
- self.color = color
- """Color used to draw the crosshair (str)."""
-
- self.linewidth = linewidth
- """Width of the crosshair cursor (int)."""
-
- self.linestyle = linestyle
- """Style of line of the cursor (str)."""
-
- super(CrosshairAction, self).__init__(
- plot, icon='crosshair', text='Crosshair Cursor',
- tooltip='Enable crosshair cursor when checked',
- triggered=self._actionTriggered,
- checkable=True, parent=parent)
- self.setChecked(plot.getGraphCursor() is not None)
- plot.sigSetGraphCursor.connect(self.setChecked)
-
- def _actionTriggered(self, checked=False):
- self.plot.setGraphCursor(checked,
- color=self.color,
- linestyle=self.linestyle,
- linewidth=self.linewidth)
-
-
-class PanWithArrowKeysAction(PlotAction):
- """QAction toggling pan with arrow keys on a :class:`.PlotWidget`.
-
- :param plot: :class:`.PlotWidget` instance on which to operate
- :param parent: See :class:`QAction`
- """
-
- def __init__(self, plot, parent=None):
-
- super(PanWithArrowKeysAction, self).__init__(
- plot, icon='arrow-keys', text='Pan with arrow keys',
- tooltip='Enable pan with arrow keys when checked',
- triggered=self._actionTriggered,
- checkable=True, parent=parent)
- self.setChecked(plot.isPanWithArrowKeys())
- plot.sigSetPanWithArrowKeys.connect(self.setChecked)
-
- def _actionTriggered(self, checked=False):
- self.plot.setPanWithArrowKeys(checked)
-
-
-class ShowAxisAction(PlotAction):
- """QAction controlling axis visibility on a :class:`.PlotWidget`.
-
- :param plot: :class:`.PlotWidget` instance on which to operate
- :param parent: See :class:`QAction`
- """
-
- def __init__(self, plot, parent=None):
- tooltip = 'Show plot axis when checked, otherwise hide them'
- PlotAction.__init__(self,
- plot,
- icon='axis',
- text='show axis',
- tooltip=tooltip,
- triggered=self._actionTriggered,
- checkable=True,
- parent=parent)
- self.setChecked(self.plot._backend.isAxesDisplayed())
- plot._sigAxesVisibilityChanged.connect(self.setChecked)
-
- def _actionTriggered(self, checked=False):
- self.plot.setAxesDisplayed(checked)
-