summaryrefslogtreecommitdiff
path: root/silx/gui/plot/PrintPreviewToolButton.py
diff options
context:
space:
mode:
Diffstat (limited to 'silx/gui/plot/PrintPreviewToolButton.py')
-rw-r--r--silx/gui/plot/PrintPreviewToolButton.py392
1 files changed, 0 insertions, 392 deletions
diff --git a/silx/gui/plot/PrintPreviewToolButton.py b/silx/gui/plot/PrintPreviewToolButton.py
deleted file mode 100644
index d857c18..0000000
--- a/silx/gui/plot/PrintPreviewToolButton.py
+++ /dev/null
@@ -1,392 +0,0 @@
-# coding: utf-8
-# /*##########################################################################
-#
-# Copyright (c) 2017-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.
-#
-# ###########################################################################*/
-"""
-This modules provides tool buttons to send the content of a plot to a
-print preview page.
-The plot content can then be moved on the page and resized prior to printing.
-
-Classes
--------
-
-- :class:`PrintPreviewToolButton`
-- :class:`SingletonPrintPreviewToolButton`
-
-Examples
---------
-
-Simple example
-++++++++++++++
-
-.. code-block:: python
-
- from silx.gui import qt
- from silx.gui.plot import PlotWidget
- from silx.gui.plot.PrintPreviewToolButton import PrintPreviewToolButton
- import numpy
-
- app = qt.QApplication([])
-
- pw = PlotWidget()
- toolbar = qt.QToolBar(pw)
- toolbutton = PrintPreviewToolButton(parent=toolbar, plot=pw)
- pw.addToolBar(toolbar)
- toolbar.addWidget(toolbutton)
- pw.show()
-
- x = numpy.arange(1000)
- y = x / numpy.sin(x)
- pw.addCurve(x, y)
-
- app.exec_()
-
-Singleton example
-+++++++++++++++++
-
-This example illustrates how to print the content of several different
-plots on the same page. The plots all instantiate a
-:class:`SingletonPrintPreviewToolButton`, which relies on a singleton widget
-(:class:`silx.gui.widgets.PrintPreview.SingletonPrintPreviewDialog`).
-
-.. image:: img/printPreviewMultiPlot.png
-
-.. code-block:: python
-
- from silx.gui import qt
- from silx.gui.plot import PlotWidget
- from silx.gui.plot.PrintPreviewToolButton import SingletonPrintPreviewToolButton
- import numpy
-
- app = qt.QApplication([])
-
- plot_widgets = []
-
- for i in range(3):
- pw = PlotWidget()
- toolbar = qt.QToolBar(pw)
- toolbutton = SingletonPrintPreviewToolButton(parent=toolbar,
- plot=pw)
- pw.addToolBar(toolbar)
- toolbar.addWidget(toolbutton)
- pw.show()
- plot_widgets.append(pw)
-
- x = numpy.arange(1000)
-
- plot_widgets[0].addCurve(x, numpy.sin(x * 2 * numpy.pi / 1000))
- plot_widgets[1].addCurve(x, numpy.cos(x * 2 * numpy.pi / 1000))
- plot_widgets[2].addCurve(x, numpy.tan(x * 2 * numpy.pi / 1000))
-
- app.exec_()
-
-"""
-from __future__ import absolute_import
-
-import logging
-from io import StringIO
-
-from .. import qt
-from .. import icons
-from . import PlotWidget
-from ..widgets.PrintPreview import PrintPreviewDialog, SingletonPrintPreviewDialog
-from ..widgets.PrintGeometryDialog import PrintGeometryDialog
-from silx.utils.deprecation import deprecated
-
-__authors__ = ["P. Knobel"]
-__license__ = "MIT"
-__date__ = "20/12/2018"
-
-_logger = logging.getLogger(__name__)
-# _logger.setLevel(logging.DEBUG)
-
-
-class PrintPreviewToolButton(qt.QToolButton):
- """QToolButton to open a :class:`PrintPreviewDialog` (if not already open)
- and add the current plot to its page to be printed.
-
- :param parent: See :class:`QAction`
- :param plot: :class:`.PlotWidget` instance on which to operate
- """
- def __init__(self, parent=None, plot=None):
- super(PrintPreviewToolButton, self).__init__(parent)
-
- if not isinstance(plot, PlotWidget):
- raise TypeError("plot parameter must be a PlotWidget")
- self._plot = plot
-
- self.setIcon(icons.getQIcon('document-print'))
-
- printGeomAction = qt.QAction("Print geometry", self)
- printGeomAction.setToolTip("Define a print geometry prior to sending "
- "the plot to the print preview dialog")
- printGeomAction.setIcon(icons.getQIcon('shape-rectangle'))
- printGeomAction.triggered.connect(self._setPrintConfiguration)
-
- printPreviewAction = qt.QAction("Print preview", self)
- printPreviewAction.setToolTip("Send plot to the print preview dialog")
- printPreviewAction.setIcon(icons.getQIcon('document-print'))
- printPreviewAction.triggered.connect(self._plotToPrintPreview)
-
- menu = qt.QMenu(self)
- menu.addAction(printGeomAction)
- menu.addAction(printPreviewAction)
- self.setMenu(menu)
- self.setPopupMode(qt.QToolButton.InstantPopup)
-
- self._printPreviewDialog = None
- self._printConfigurationDialog = None
-
- self._printGeometry = {"xOffset": 0.1,
- "yOffset": 0.1,
- "width": 0.9,
- "height": 0.9,
- "units": "page",
- "keepAspectRatio": True}
-
- @property
- def printPreviewDialog(self):
- """Lazy loaded :class:`PrintPreviewDialog`"""
- # if changes are made here, don't forget making them in
- # SingletonPrintPreviewToolButton.printPreviewDialog as well
- if self._printPreviewDialog is None:
- self._printPreviewDialog = PrintPreviewDialog(self.parent())
- return self._printPreviewDialog
-
- def getTitle(self):
- """Implement this method to fetch the title in the plot.
-
- :return: Title to be printed above the plot, or None (no title added)
- :rtype: str or None
- """
- return None
-
- def getCommentAndPosition(self):
- """Implement this method to fetch the legend to be printed below the
- figure and its position.
-
- :return: Legend to be printed below the figure and its position:
- "CENTER", "LEFT" or "RIGHT"
- :rtype: (str, str) or (None, None)
- """
- return None, None
-
- @property
- @deprecated(since_version="0.10",
- replacement="getPlot()")
- def plot(self):
- return self._plot
-
- def getPlot(self):
- """Return the :class:`.PlotWidget` associated with this tool button.
-
- :rtype: :class:`.PlotWidget`
- """
- return self._plot
-
- def _plotToPrintPreview(self):
- """Grab the plot widget and send it to the print preview dialog.
- Make sure the print preview dialog is shown and raised."""
- if not self.printPreviewDialog.ensurePrinterIsSet():
- return
-
- comment, commentPosition = self.getCommentAndPosition()
-
- if qt.HAS_SVG:
- svgRenderer, viewBox = self._getSvgRendererAndViewbox()
- self.printPreviewDialog.addSvgItem(svgRenderer,
- title=self.getTitle(),
- comment=comment,
- commentPosition=commentPosition,
- viewBox=viewBox,
- keepRatio=self._printGeometry["keepAspectRatio"])
- else:
- _logger.warning("Missing QtSvg library, using a raster image")
- if qt.BINDING in ["PyQt4", "PySide"]:
- pixmap = qt.QPixmap.grabWidget(self._plot.centralWidget())
- else:
- # PyQt5 and hopefully PyQt6+
- pixmap = self._plot.centralWidget().grab()
- self.printPreviewDialog.addPixmap(pixmap,
- title=self.getTitle(),
- comment=comment,
- commentPosition=commentPosition)
- self.printPreviewDialog.show()
- self.printPreviewDialog.raise_()
-
- def _getSvgRendererAndViewbox(self):
- """Return a SVG renderer displaying the plot and its viewbox
- (interactively specified by the user the first time this is called).
-
- The size of the renderer is adjusted to the printer configuration
- and to the geometry configuration (width, height, ratio) specified
- by the user."""
- imgData = StringIO()
- assert self._plot.saveGraph(imgData, fileFormat="svg"), \
- "Unable to save graph"
- imgData.flush()
- imgData.seek(0)
- svgData = imgData.read()
-
- svgRenderer = qt.QSvgRenderer()
-
- viewbox = self._getViewBox()
-
- svgRenderer.setViewBox(viewbox)
-
- xml_stream = qt.QXmlStreamReader(svgData.encode(errors="replace"))
-
- # This is for PyMca compatibility, to share a print preview with PyMca plots
- svgRenderer._viewBox = viewbox
- svgRenderer._svgRawData = svgData.encode(errors="replace")
- svgRenderer._svgRendererData = xml_stream
-
- if not svgRenderer.load(xml_stream):
- raise RuntimeError("Cannot interpret svg data")
-
- return svgRenderer, viewbox
-
- def _getViewBox(self):
- """
- """
- printer = self.printPreviewDialog.printer
- dpix = printer.logicalDpiX()
- dpiy = printer.logicalDpiY()
- availableWidth = printer.width()
- availableHeight = printer.height()
-
- config = self._printGeometry
- width = config['width']
- height = config['height']
- xOffset = config['xOffset']
- yOffset = config['yOffset']
- units = config['units']
- keepAspectRatio = config['keepAspectRatio']
- aspectRatio = self._getPlotAspectRatio()
-
- # convert the offsets to dots
- if units.lower() in ['inch', 'inches']:
- xOffset = xOffset * dpix
- yOffset = yOffset * dpiy
- if width is not None:
- width = width * dpix
- if height is not None:
- height = height * dpiy
- elif units.lower() in ['cm', 'centimeters']:
- xOffset = (xOffset / 2.54) * dpix
- yOffset = (yOffset / 2.54) * dpiy
- if width is not None:
- width = (width / 2.54) * dpix
- if height is not None:
- height = (height / 2.54) * dpiy
- else:
- # page units
- xOffset = availableWidth * xOffset
- yOffset = availableHeight * yOffset
- if width is not None:
- width = availableWidth * width
- if height is not None:
- height = availableHeight * height
-
- availableWidth -= xOffset
- availableHeight -= yOffset
-
- if width is not None:
- if (availableWidth + 0.1) < width:
- txt = "Available width %f is less than requested width %f" % \
- (availableWidth, width)
- raise ValueError(txt)
- if height is not None:
- if (availableHeight + 0.1) < height:
- txt = "Available height %f is less than requested height %f" % \
- (availableHeight, height)
- raise ValueError(txt)
-
- if keepAspectRatio:
- bodyWidth = width or availableWidth
- bodyHeight = bodyWidth * aspectRatio
-
- if bodyHeight > availableHeight:
- bodyHeight = availableHeight
- bodyWidth = bodyHeight / aspectRatio
-
- else:
- bodyWidth = width or availableWidth
- bodyHeight = height or availableHeight
-
- return qt.QRectF(xOffset,
- yOffset,
- bodyWidth,
- bodyHeight)
-
- def _setPrintConfiguration(self):
- """Open a dialog to prompt the user to adjust print
- geometry parameters."""
- self.printPreviewDialog.ensurePrinterIsSet()
- if self._printConfigurationDialog is None:
- self._printConfigurationDialog = PrintGeometryDialog(self.parent())
-
- self._printConfigurationDialog.setPrintGeometry(self._printGeometry)
- if self._printConfigurationDialog.exec_():
- self._printGeometry = self._printConfigurationDialog.getPrintGeometry()
-
- def _getPlotAspectRatio(self):
- widget = self._plot.centralWidget()
- graphWidth = float(widget.width())
- graphHeight = float(widget.height())
- return graphHeight / graphWidth
-
-
-class SingletonPrintPreviewToolButton(PrintPreviewToolButton):
- """This class is similar to its parent class :class:`PrintPreviewToolButton`
- but it uses a singleton print preview widget.
-
- This allows for several plots to send their content to the
- same print page, and for users to arrange them."""
- def __init__(self, parent=None, plot=None):
- PrintPreviewToolButton.__init__(self, parent, plot)
-
- @property
- def printPreviewDialog(self):
- if self._printPreviewDialog is None:
- self._printPreviewDialog = SingletonPrintPreviewDialog(self.parent())
- return self._printPreviewDialog
-
-
-if __name__ == '__main__':
- import numpy
- app = qt.QApplication([])
-
- pw = PlotWidget()
- toolbar = qt.QToolBar(pw)
- toolbutton = PrintPreviewToolButton(parent=toolbar,
- plot=pw)
- pw.addToolBar(toolbar)
- toolbar.addWidget(toolbutton)
- pw.show()
-
- x = numpy.arange(1000)
- y = x / numpy.sin(x)
- pw.addCurve(x, y)
-
- app.exec_()