Skip to content

Commit 6a1c67c

Browse files
committed
Added docstrings for plot_renderer and plot_seriesitem modules
1 parent 2af0ac6 commit 6a1c67c

File tree

5 files changed

+273
-0
lines changed

5 files changed

+273
-0
lines changed

doc/reference/index.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,5 @@ Main `python-qwt` classes:
2020
plot_histogram
2121
plot_layout
2222
plot_marker
23+
plot_renderer
24+
plot_seriesitem

doc/reference/plot_renderer.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.. automodule:: qwt.plot_renderer
2+
:members:

doc/reference/plot_seriesitem.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.. automodule:: qwt.plot_seriesitem
2+
:members:

qwt/plot_renderer.py

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@
55
# Copyright (c) 2015 Pierre Raybaut, for the Python translation/optimization
66
# (see LICENSE file for more details)
77

8+
"""
9+
QwtPlotRenderer
10+
---------------
11+
12+
.. autoclass:: QwtPlotRenderer
13+
:members:
14+
"""
15+
816
from __future__ import division
917

1018
from qwt.painter import QwtPainter
@@ -25,6 +33,11 @@
2533

2634

2735
def qwtCanvasClip(canvas, canvasRect):
36+
"""
37+
The clip region is calculated in integers
38+
To avoid too much rounding errors better
39+
calculate it in target device resolution
40+
"""
2841
x1 = np.ceil(canvasRect.left())
2942
x2 = np.floor(canvasRect.right())
3043
y1 = np.ceil(canvasRect.top())
@@ -39,6 +52,30 @@ def __init__(self):
3952
self.layoutFlags = QwtPlotRenderer.DefaultLayout
4053

4154
class QwtPlotRenderer(QObject):
55+
"""
56+
Renderer for exporting a plot to a document, a printer
57+
or anything else, that is supported by QPainter/QPaintDevice
58+
59+
Discard flags:
60+
61+
* `QwtPlotRenderer.DiscardNone`: Render all components of the plot
62+
* `QwtPlotRenderer.DiscardBackground`: Don't render the background of the plot
63+
* `QwtPlotRenderer.DiscardTitle`: Don't render the title of the plot
64+
* `QwtPlotRenderer.DiscardLegend`: Don't render the legend of the plot
65+
* `QwtPlotRenderer.DiscardCanvasBackground`: Don't render the background of the canvas
66+
* `QwtPlotRenderer.DiscardFooter`: Don't render the footer of the plot
67+
* `QwtPlotRenderer.DiscardCanvasFrame`: Don't render the frame of the canvas
68+
69+
.. note::
70+
71+
The `QwtPlotRenderer.DiscardCanvasFrame` flag has no effect when using
72+
style sheets, where the frame is part of the background
73+
74+
Layout flags:
75+
76+
* `QwtPlotRenderer.DefaultLayout`: Use the default layout as on screen
77+
* `QwtPlotRenderer.FrameWithScales`: Instead of the scales a box is painted around the plot canvas, where the scale ticks are aligned to.
78+
"""
4279

4380
# enum DiscardFlag
4481
DiscardNone = 0x00
@@ -58,37 +95,123 @@ def __init__(self, parent=None):
5895
self.__data = QwtPlotRenderer_PrivateData()
5996

6097
def setDiscardFlag(self, flag, on):
98+
"""
99+
Change a flag, indicating what to discard from rendering
100+
101+
:param int flag: Flag to change
102+
:param bool on: On/Off
103+
104+
.. seealso::
105+
106+
:py:meth:`testDiscardFlag()`, :py:meth:`setDiscardFlags()`,
107+
:py:meth:`discardFlags()`
108+
"""
61109
if on:
62110
self.__data.discardFlags |= flag
63111
else:
64112
self.__data.discardFlags &= ~flag
65113

66114
def testDiscardFlag(self, flag):
115+
"""
116+
:param int flag: Flag to be tested
117+
:return: True, if flag is enabled.
118+
119+
.. seealso::
120+
121+
:py:meth:`setDiscardFlag()`, :py:meth:`setDiscardFlags()`,
122+
:py:meth:`discardFlags()`
123+
"""
67124
return self.__data.discardFlags & flag
68125

69126
def setDiscardFlags(self, flags):
127+
"""
128+
Set the flags, indicating what to discard from rendering
129+
130+
:param int flags: Flags
131+
132+
.. seealso::
133+
134+
:py:meth:`testDiscardFlag()`, :py:meth:`setDiscardFlag()`,
135+
:py:meth:`discardFlags()`
136+
"""
70137
self.__data.discardFlags = flags
71138

72139
def discardFlags(self):
140+
"""
141+
:return: Flags, indicating what to discard from rendering
142+
143+
.. seealso::
144+
145+
:py:meth:`setDiscardFlag()`, :py:meth:`setDiscardFlags()`,
146+
:py:meth:`testDiscardFlag()`
147+
"""
73148
return self.__data.discardFlags
74149

75150
def setLayoutFlag(self, flag, on):
151+
"""
152+
Change a layout flag
153+
154+
:param int flag: Flag to change
155+
156+
.. seealso::
157+
158+
:py:meth:`testLayoutFlag()`, :py:meth:`setLayoutFlags()`,
159+
:py:meth:`layoutFlags()`
160+
"""
76161
if on:
77162
self.__data.layoutFlags |= flag
78163
else:
79164
self.__data.layoutFlags &= ~flag
80165

81166
def testLayoutFlag(self, flag):
167+
"""
168+
:param int flag: Flag to be tested
169+
:return: True, if flag is enabled.
170+
171+
.. seealso::
172+
173+
:py:meth:`setLayoutFlag()`, :py:meth:`setLayoutFlags()`,
174+
:py:meth:`layoutFlags()`
175+
"""
82176
return self.__data.layoutFlags & flag
83177

84178
def setLayoutFlags(self, flags):
179+
"""
180+
Set the layout flags
181+
182+
:param int flags: Flags
183+
184+
.. seealso::
185+
186+
:py:meth:`setLayoutFlag()`, :py:meth:`testLayoutFlag()`,
187+
:py:meth:`layoutFlags()`
188+
"""
85189
self.__data.layoutFlags = flags
86190

87191
def layoutFlags(self):
192+
"""
193+
:return: Layout flags
194+
195+
.. seealso::
196+
197+
:py:meth:`setLayoutFlags()`, :py:meth:`setLayoutFlag()`,
198+
:py:meth:`testLayoutFlag()`
199+
"""
88200
return self.__data.layoutFlags
89201

90202
def renderDocument(self, plot, filename, sizeMM=(300, 200), resolution=85,
91203
format_=None):
204+
"""
205+
Render a plot to a file
206+
207+
The format of the document will be auto-detected from the
208+
suffix of the file name.
209+
210+
:param qwt.plot.QwtPlot plot: Plot widget
211+
:param str fileName: Path of the file, where the document will be stored
212+
:param QSizeF sizeMM: Size for the document in millimeters
213+
:param int resolution: Resolution in dots per Inch (dpi)
214+
"""
92215
if isinstance(sizeMM, tuple):
93216
sizeMM = QSizeF(*sizeMM)
94217
if format_ is None:
@@ -144,6 +267,30 @@ def renderDocument(self, plot, filename, sizeMM=(300, 200), resolution=85,
144267
raise TypeError("Unsupported file format '%s'" % fmt)
145268

146269
def renderTo(self, plot, dest):
270+
"""
271+
Render a plot to a file
272+
273+
Supported formats are:
274+
275+
- pdf: Portable Document Format PDF
276+
- ps: Postcript
277+
- svg: Scalable Vector Graphics SVG
278+
- all image formats supported by Qt, see QImageWriter.supportedImageFormats()
279+
280+
Scalable vector graphic formats like PDF or SVG are superior to
281+
raster graphics formats.
282+
283+
:param qwt.plot.QwtPlot plot: Plot widget
284+
:param str fileName: Path of the file, where the document will be stored
285+
:param str format: Format for the document
286+
:param QSizeF sizeMM: Size for the document in millimeters.
287+
:param int resolution: Resolution in dots per Inch (dpi)
288+
289+
.. seealso::
290+
291+
:py:meth:`renderTo()`, :py:meth:`render()`,
292+
:py:meth:`qwt.painter.QwtPainter.setRoundingAlignment()`
293+
"""
147294
if isinstance(dest, QPaintDevice):
148295
w = dest.width()
149296
h = dest.height()
@@ -165,12 +312,28 @@ def renderTo(self, plot, dest):
165312
self.render(plot, p, rect)
166313

167314
def render(self, plot, painter, plotRect):
315+
"""
316+
Paint the contents of a QwtPlot instance into a given rectangle.
317+
318+
:param qwt.plot.QwtPlot plot: Plot to be rendered
319+
:param QPainter painter: Painter
320+
:param str format: Format for the document
321+
:param QRectF plotRect: Bounding rectangle
322+
323+
.. seealso::
324+
325+
:py:meth:`renderDocument()`, :py:meth:`renderTo()`,
326+
:py:meth:`qwt.painter.QwtPainter.setRoundingAlignment()`
327+
"""
168328
if painter == 0 or not painter.isActive() or not plotRect.isValid()\
169329
or plot.size().isNull():
170330
return
171331
if not self.__data.discardFlags & self.DiscardBackground:
172332
QwtPainter.drawBackground(painter, plotRect, plot)
173333

334+
# The layout engine uses the same methods as they are used
335+
# by the Qt layout system. Therefore we need to calculate the
336+
# layout in screen coordinates and paint with a scaled painter.
174337
transform = QTransform()
175338
transform.scale(float(painter.device().logicalDpiX())/plot.logicalDpiX(),
176339
float(painter.device().logicalDpiY())/plot.logicalDpiY())
@@ -194,6 +357,9 @@ def render(self, plot, painter, plotRect):
194357
scaleWidget.setMargin(0)
195358
if not plot.axisEnabled(axisId):
196359
left, right, top, bottom = 0, 0, 0, 0
360+
# When we have a scale the frame is painted on
361+
# the position of the backbone - otherwise we
362+
# need to introduce a margin around the canvas
197363
if axisId == QwtPlot.yLeft:
198364
layoutRect.adjust(1, 0, 0, 0)
199365
elif axisId == QwtPlot.yRight:
@@ -204,6 +370,7 @@ def render(self, plot, painter, plotRect):
204370
layoutRect.adjust(0, 0, 0, -1)
205371
layoutRect.adjust(left, top, right, bottom)
206372

373+
# Calculate the layout for the document.
207374
layoutOptions = QwtPlotLayout.IgnoreScrollbars
208375

209376
if self.__data.layoutFlags & self.FrameWithScales or\
@@ -221,6 +388,8 @@ def render(self, plot, painter, plotRect):
221388

222389
maps = self.buildCanvasMaps(plot, layout.canvasRect())
223390
if self.updateCanvasMargins(plot, layout.canvasRect(), maps):
391+
# recalculate maps and layout, when the margins
392+
# have been changed
224393
layout.activate(plot, layoutRect, layoutOptions)
225394
maps = self.buildCanvasMaps(plot, layout.canvasRect())
226395

@@ -261,24 +430,57 @@ def render(self, plot, painter, plotRect):
261430
layout.invalidate()
262431

263432
def renderTitle(self, plot, painter, rect):
433+
"""
434+
Render the title into a given rectangle.
435+
436+
:param qwt.plot.QwtPlot plot: Plot widget
437+
:param QPainter painter: Painter
438+
:param QRectF rect: Bounding rectangle
439+
"""
264440
painter.setFont(plot.titleLabel().font())
265441
color = plot.titleLabel().palette().color(QPalette.Active, QPalette.Text)
266442
painter.setPen(color)
267443
plot.titleLabel().text().draw(painter, rect)
268444

269445
def renderFooter(self, plot, painter, rect):
446+
"""
447+
Render the footer into a given rectangle.
448+
449+
:param qwt.plot.QwtPlot plot: Plot widget
450+
:param QPainter painter: Painter
451+
:param QRectF rect: Bounding rectangle
452+
"""
270453
painter.setFont(plot.footerLabel().font())
271454
color = plot.footerLabel().palette().color(QPalette.Active, QPalette.Text)
272455
painter.setPen(color)
273456
plot.footerLabel().text().draw(painter, rect)
274457

275458
def renderLegend(self, plot, painter, rect):
459+
"""
460+
Render the legend into a given rectangle.
461+
462+
:param qwt.plot.QwtPlot plot: Plot widget
463+
:param QPainter painter: Painter
464+
:param QRectF rect: Bounding rectangle
465+
"""
276466
if plot.legend():
277467
fillBackground = not self.__data.discardFlags & self.DiscardBackground
278468
plot.legend().renderLegend(painter, rect, fillBackground)
279469

280470
def renderScale(self, plot, painter, axisId, startDist, endDist,
281471
baseDist, rect):
472+
"""
473+
Paint a scale into a given rectangle.
474+
Paint the scale into a given rectangle.
475+
476+
:param qwt.plot.QwtPlot plot: Plot widget
477+
:param QPainter painter: Painter
478+
:param int axisId: Axis
479+
:param int startDist: Start border distance
480+
:param int endDist: End border distance
481+
:param int baseDist: Base distance
482+
:param QRectF rect: Bounding rectangle
483+
"""
282484
if not plot.axisEnabled(axisId):
283485
return
284486
scaleWidget = plot.axisWidget(axisId)
@@ -322,6 +524,14 @@ def renderScale(self, plot, painter, axisId, startDist, endDist,
322524
painter.restore()
323525

324526
def renderCanvas(self, plot, painter, canvasRect, maps):
527+
"""
528+
Render the canvas into a given rectangle.
529+
530+
:param qwt.plot.QwtPlot plot: Plot widget
531+
:param QPainter painter: Painter
532+
:param qwt.scale_map.QwtScaleMap maps: mapping between plot and paint device coordinates
533+
:param QRectF rect: Bounding rectangle
534+
"""
325535
canvas = plot.canvas()
326536
r = canvasRect.adjusted(0., 0., -1., 1.)
327537
if self.__data.layoutFlags & self.FrameWithScales:
@@ -385,6 +595,13 @@ def renderCanvas(self, plot, painter, canvasRect, maps):
385595
painter.restore()
386596

387597
def buildCanvasMaps(self, plot, canvasRect):
598+
"""
599+
Calculated the scale maps for rendering the canvas
600+
601+
:param qwt.plot.QwtPlot plot: Plot widget
602+
:param QRectF canvasRect: Target rectangle
603+
:return: Calculated scale maps
604+
"""
388605
maps = []
389606
for axisId in range(QwtPlot.axisCnt):
390607
map_ = QwtScaleMap()
@@ -426,6 +643,19 @@ def updateCanvasMargins(self, plot, canvasRect, maps):
426643
return marginsChanged
427644

428645
def exportTo(self, plot, documentname, sizeMM=None, resolution=85):
646+
"""
647+
Execute a file dialog and render the plot to the selected file
648+
649+
:param qwt.plot.QwtPlot plot: Plot widget
650+
:param str documentName: Default document name
651+
:param QSizeF sizeMM: Size for the document in millimeters
652+
:param int resolution: Resolution in dots per Inch (dpi)
653+
:return: True, when exporting was successful
654+
655+
.. seealso::
656+
657+
:py:meth:`renderDocument()`
658+
"""
429659
if plot is None:
430660
return
431661
if sizeMM is None:

0 commit comments

Comments
 (0)