source: ntrip/trunk/BNC/qwt/qwt_plot_renderer.cpp@ 10110

Last change on this file since 10110 was 9383, checked in by stoecker, 4 years ago

update to qwt verion 6.1.1 to fix build with newer Qt5

File size: 28.4 KB
RevLine 
[4271]1/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
2 * Qwt Widget Library
3 * Copyright (C) 1997 Josef Wilgen
4 * Copyright (C) 2002 Uwe Rathmann
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the Qwt License, Version 1.0
8 *****************************************************************************/
9
10#include "qwt_plot_renderer.h"
11#include "qwt_plot.h"
12#include "qwt_painter.h"
13#include "qwt_plot_layout.h"
[8127]14#include "qwt_abstract_legend.h"
[4271]15#include "qwt_scale_widget.h"
16#include "qwt_scale_engine.h"
[9383]17#include "qwt_scale_map.h"
[4271]18#include "qwt_text.h"
19#include "qwt_text_label.h"
20#include "qwt_math.h"
[9383]21
[4271]22#include <qpainter.h>
[9383]23#include <qpainterpath.h>
[4271]24#include <qtransform.h>
25#include <qprinter.h>
[8127]26#include <qfiledialog.h>
27#include <qfileinfo.h>
[4271]28#include <qimagewriter.h>
[9383]29#include <qvariant.h>
30
[4271]31#ifndef QWT_NO_SVG
32#ifdef QT_SVG_LIB
[9383]33#if QT_VERSION >= 0x040500
34#define QWT_FORMAT_SVG 1
35#endif
36#endif
37#endif
38
39#ifndef QT_NO_PRINTER
40#define QWT_FORMAT_PDF 1
41#endif
42
43#ifndef QT_NO_PDF
44
45// QPdfWriter::setResolution() has been introduced with
46// Qt 5.3. Guess it is o.k. to stay with QPrinter for older
47// versions.
48
49#if QT_VERSION >= 0x050300
50
51#ifndef QWT_FORMAT_PDF
52#define QWT_FORMAT_PDF 1
53#endif
54
55#define QWT_PDF_WRITER 1
56
57#endif
58#endif
59
60#ifndef QT_NO_PRINTER
61// postscript support has been dropped in Qt5
62#if QT_VERSION < 0x050000
63#define QWT_FORMAT_POSTSCRIPT 1
64#endif
65#endif
66
67#if QWT_FORMAT_SVG
[4271]68#include <qsvggenerator.h>
69#endif
[9383]70
71#if QWT_PDF_WRITER
72#include <qpdfwriter.h>
[4271]73#endif
74
[9383]75static QPainterPath qwtCanvasClip(
[8127]76 const QWidget* canvas, const QRectF &canvasRect )
77{
78 // The clip region is calculated in integers
79 // To avoid too much rounding errors better
80 // calculate it in target device resolution
81
82 int x1 = qCeil( canvasRect.left() );
83 int x2 = qFloor( canvasRect.right() );
84 int y1 = qCeil( canvasRect.top() );
85 int y2 = qFloor( canvasRect.bottom() );
86
87 const QRect r( x1, y1, x2 - x1 - 1, y2 - y1 - 1 );
88
89 QPainterPath clipPath;
90
91 ( void ) QMetaObject::invokeMethod(
92 const_cast< QWidget *>( canvas ), "borderPath",
93 Qt::DirectConnection,
94 Q_RETURN_ARG( QPainterPath, clipPath ), Q_ARG( QRect, r ) );
95
96 return clipPath;
97}
98
[9383]99static inline QFont qwtResolvedFont( const QWidget *widget )
100{
101 QFont font = widget->font();
102 font.resolve( QFont::AllPropertiesResolved );
103
104 return font;
105}
106
[4271]107class QwtPlotRenderer::PrivateData
108{
109public:
110 PrivateData():
[8127]111 discardFlags( QwtPlotRenderer::DiscardNone ),
[4271]112 layoutFlags( QwtPlotRenderer::DefaultLayout )
113 {
114 }
115
116 QwtPlotRenderer::DiscardFlags discardFlags;
117 QwtPlotRenderer::LayoutFlags layoutFlags;
118};
119
[9383]120/*!
[4271]121 Constructor
122 \param parent Parent object
123*/
124QwtPlotRenderer::QwtPlotRenderer( QObject *parent ):
125 QObject( parent )
126{
127 d_data = new PrivateData;
128}
129
130//! Destructor
131QwtPlotRenderer::~QwtPlotRenderer()
132{
133 delete d_data;
134}
135
136/*!
137 Change a flag, indicating what to discard from rendering
138
139 \param flag Flag to change
140 \param on On/Off
141
142 \sa DiscardFlag, testDiscardFlag(), setDiscardFlags(), discardFlags()
143*/
144void QwtPlotRenderer::setDiscardFlag( DiscardFlag flag, bool on )
145{
146 if ( on )
147 d_data->discardFlags |= flag;
148 else
149 d_data->discardFlags &= ~flag;
150}
151
152/*!
[8127]153 \return True, if flag is enabled.
[4271]154 \param flag Flag to be tested
155 \sa DiscardFlag, setDiscardFlag(), setDiscardFlags(), discardFlags()
156*/
157bool QwtPlotRenderer::testDiscardFlag( DiscardFlag flag ) const
158{
159 return d_data->discardFlags & flag;
160}
161
162/*!
163 Set the flags, indicating what to discard from rendering
164
165 \param flags Flags
166 \sa DiscardFlag, setDiscardFlag(), testDiscardFlag(), discardFlags()
167*/
168void QwtPlotRenderer::setDiscardFlags( DiscardFlags flags )
169{
170 d_data->discardFlags = flags;
171}
172
173/*!
174 \return Flags, indicating what to discard from rendering
175 \sa DiscardFlag, setDiscardFlags(), setDiscardFlag(), testDiscardFlag()
176*/
177QwtPlotRenderer::DiscardFlags QwtPlotRenderer::discardFlags() const
178{
179 return d_data->discardFlags;
180}
181
182/*!
183 Change a layout flag
184
185 \param flag Flag to change
186 \param on On/Off
187
188 \sa LayoutFlag, testLayoutFlag(), setLayoutFlags(), layoutFlags()
189*/
190void QwtPlotRenderer::setLayoutFlag( LayoutFlag flag, bool on )
191{
192 if ( on )
193 d_data->layoutFlags |= flag;
194 else
195 d_data->layoutFlags &= ~flag;
196}
197
198/*!
[8127]199 \return True, if flag is enabled.
[4271]200 \param flag Flag to be tested
201 \sa LayoutFlag, setLayoutFlag(), setLayoutFlags(), layoutFlags()
202*/
203bool QwtPlotRenderer::testLayoutFlag( LayoutFlag flag ) const
204{
205 return d_data->layoutFlags & flag;
206}
207
208/*!
209 Set the layout flags
210
211 \param flags Flags
212 \sa LayoutFlag, setLayoutFlag(), testLayoutFlag(), layoutFlags()
213*/
214void QwtPlotRenderer::setLayoutFlags( LayoutFlags flags )
215{
216 d_data->layoutFlags = flags;
217}
218
219/*!
220 \return Layout flags
221 \sa LayoutFlag, setLayoutFlags(), setLayoutFlag(), testLayoutFlag()
222*/
223QwtPlotRenderer::LayoutFlags QwtPlotRenderer::layoutFlags() const
224{
225 return d_data->layoutFlags;
226}
227
228/*!
229 Render a plot to a file
230
[8127]231 The format of the document will be auto-detected from the
232 suffix of the file name.
[4271]233
234 \param plot Plot widget
235 \param fileName Path of the file, where the document will be stored
236 \param sizeMM Size for the document in millimeters.
237 \param resolution Resolution in dots per Inch (dpi)
238*/
239void QwtPlotRenderer::renderDocument( QwtPlot *plot,
240 const QString &fileName, const QSizeF &sizeMM, int resolution )
241{
242 renderDocument( plot, fileName,
243 QFileInfo( fileName ).suffix(), sizeMM, resolution );
244}
245
246/*!
247 Render a plot to a file
248
249 Supported formats are:
250
251 - pdf\n
252 Portable Document Format PDF
253 - ps\n
254 Postcript
255 - svg\n
256 Scalable Vector Graphics SVG
257 - all image formats supported by Qt\n
258 see QImageWriter::supportedImageFormats()
259
260 Scalable vector graphic formats like PDF or SVG are superior to
261 raster graphics formats.
262
263 \param plot Plot widget
264 \param fileName Path of the file, where the document will be stored
265 \param format Format for the document
266 \param sizeMM Size for the document in millimeters.
267 \param resolution Resolution in dots per Inch (dpi)
268
269 \sa renderTo(), render(), QwtPainter::setRoundingAlignment()
270*/
271void QwtPlotRenderer::renderDocument( QwtPlot *plot,
272 const QString &fileName, const QString &format,
273 const QSizeF &sizeMM, int resolution )
274{
275 if ( plot == NULL || sizeMM.isEmpty() || resolution <= 0 )
276 return;
277
278 QString title = plot->title().text();
279 if ( title.isEmpty() )
280 title = "Plot Document";
281
282 const double mmToInch = 1.0 / 25.4;
283 const QSizeF size = sizeMM * mmToInch * resolution;
284
285 const QRectF documentRect( 0.0, 0.0, size.width(), size.height() );
286
287 const QString fmt = format.toLower();
[9383]288 if ( fmt == QLatin1String( "pdf" ) )
[4271]289 {
[9383]290#if QWT_FORMAT_PDF
291
292#if QWT_PDF_WRITER
293 QPdfWriter pdfWriter( fileName );
294 pdfWriter.setPageSizeMM( sizeMM );
295 pdfWriter.setTitle( title );
296 pdfWriter.setPageMargins( QMarginsF() );
297 pdfWriter.setResolution( resolution );
298
299 QPainter painter( &pdfWriter );
300 render( plot, &painter, documentRect );
301#else
[4271]302 QPrinter printer;
[8127]303 printer.setOutputFormat( QPrinter::PdfFormat );
304 printer.setColorMode( QPrinter::Color );
[4271]305 printer.setFullPage( true );
306 printer.setPaperSize( sizeMM, QPrinter::Millimeter );
307 printer.setDocName( title );
308 printer.setOutputFileName( fileName );
309 printer.setResolution( resolution );
310
311 QPainter painter( &printer );
312 render( plot, &painter, documentRect );
313#endif
[9383]314#endif
[4271]315 }
[9383]316 else if ( fmt == QLatin1String( "ps" ) )
[8127]317 {
[9383]318#if QWT_FORMAT_POSTSCRIPT
[8127]319 QPrinter printer;
320 printer.setOutputFormat( QPrinter::PostScriptFormat );
321 printer.setColorMode( QPrinter::Color );
322 printer.setFullPage( true );
323 printer.setPaperSize( sizeMM, QPrinter::Millimeter );
324 printer.setDocName( title );
325 printer.setOutputFileName( fileName );
326 printer.setResolution( resolution );
327
328 QPainter painter( &printer );
329 render( plot, &painter, documentRect );
330#endif
331 }
[9383]332 else if ( fmt == QLatin1String( "svg" ) )
[4271]333 {
[9383]334#if QWT_FORMAT_SVG
[4271]335 QSvgGenerator generator;
336 generator.setTitle( title );
337 generator.setFileName( fileName );
338 generator.setResolution( resolution );
339 generator.setViewBox( documentRect );
340
341 QPainter painter( &generator );
342 render( plot, &painter, documentRect );
343#endif
344 }
345 else
346 {
347 if ( QImageWriter::supportedImageFormats().indexOf(
348 format.toLatin1() ) >= 0 )
349 {
350 const QRect imageRect = documentRect.toRect();
351 const int dotsPerMeter = qRound( resolution * mmToInch * 1000.0 );
352
353 QImage image( imageRect.size(), QImage::Format_ARGB32 );
354 image.setDotsPerMeterX( dotsPerMeter );
355 image.setDotsPerMeterY( dotsPerMeter );
356 image.fill( QColor( Qt::white ).rgb() );
357
358 QPainter painter( &image );
359 render( plot, &painter, imageRect );
360 painter.end();
361
362 image.save( fileName, format.toLatin1() );
363 }
364 }
365}
366
367/*!
368 \brief Render the plot to a \c QPaintDevice
369
370 This function renders the contents of a QwtPlot instance to
371 \c QPaintDevice object. The target rectangle is derived from
372 its device metrics.
373
374 \param plot Plot to be rendered
375 \param paintDevice device to paint on, f.e a QImage
376
377 \sa renderDocument(), render(), QwtPainter::setRoundingAlignment()
378*/
379
380void QwtPlotRenderer::renderTo(
381 QwtPlot *plot, QPaintDevice &paintDevice ) const
382{
383 int w = paintDevice.width();
384 int h = paintDevice.height();
385
386 QPainter p( &paintDevice );
387 render( plot, &p, QRectF( 0, 0, w, h ) );
388}
389
390/*!
391 \brief Render the plot to a QPrinter
392
393 This function renders the contents of a QwtPlot instance to
394 \c QPaintDevice object. The size is derived from the printer
395 metrics.
396
397 \param plot Plot to be rendered
398 \param printer Printer to paint on
399
400 \sa renderDocument(), render(), QwtPainter::setRoundingAlignment()
401*/
402
403#ifndef QT_NO_PRINTER
404
405void QwtPlotRenderer::renderTo(
406 QwtPlot *plot, QPrinter &printer ) const
407{
408 int w = printer.width();
409 int h = printer.height();
410
411 QRectF rect( 0, 0, w, h );
412 double aspect = rect.width() / rect.height();
413 if ( ( aspect < 1.0 ) )
414 rect.setHeight( aspect * rect.width() );
415
416 QPainter p( &printer );
417 render( plot, &p, rect );
418}
419
420#endif
421
[9383]422#if QWT_FORMAT_SVG
[4271]423
424/*!
425 \brief Render the plot to a QSvgGenerator
426
427 If the generator has a view box, the plot will be rendered into it.
428 If it has no viewBox but a valid size the target coordinates
429 will be (0, 0, generator.width(), generator.height()). Otherwise
430 the target rectangle will be QRectF(0, 0, 800, 600);
431
432 \param plot Plot to be rendered
433 \param generator SVG generator
434*/
435void QwtPlotRenderer::renderTo(
436 QwtPlot *plot, QSvgGenerator &generator ) const
437{
438 QRectF rect = generator.viewBoxF();
439 if ( rect.isEmpty() )
440 rect.setRect( 0, 0, generator.width(), generator.height() );
441
442 if ( rect.isEmpty() )
443 rect.setRect( 0, 0, 800, 600 ); // something
444
445 QPainter p( &generator );
446 render( plot, &p, rect );
447}
[9383]448
[4271]449#endif
450
451/*!
452 Paint the contents of a QwtPlot instance into a given rectangle.
453
454 \param plot Plot to be rendered
455 \param painter Painter
456 \param plotRect Bounding rectangle
457
458 \sa renderDocument(), renderTo(), QwtPainter::setRoundingAlignment()
459*/
460void QwtPlotRenderer::render( QwtPlot *plot,
461 QPainter *painter, const QRectF &plotRect ) const
462{
463 if ( painter == 0 || !painter->isActive() ||
464 !plotRect.isValid() || plot->size().isNull() )
[8127]465 {
[4271]466 return;
[8127]467 }
[4271]468
469 if ( !( d_data->discardFlags & DiscardBackground ) )
[8127]470 QwtPainter::drawBackgound( painter, plotRect, plot );
[4271]471
472 /*
473 The layout engine uses the same methods as they are used
474 by the Qt layout system. Therefore we need to calculate the
475 layout in screen coordinates and paint with a scaled painter.
476 */
477 QTransform transform;
478 transform.scale(
479 double( painter->device()->logicalDpiX() ) / plot->logicalDpiX(),
480 double( painter->device()->logicalDpiY() ) / plot->logicalDpiY() );
481
[8127]482 QRectF layoutRect = transform.inverted().mapRect( plotRect );
[4271]483
[8127]484 if ( !( d_data->discardFlags & DiscardBackground ) )
485 {
486 // subtract the contents margins
487
488 int left, top, right, bottom;
489 plot->getContentsMargins( &left, &top, &right, &bottom );
490 layoutRect.adjust( left, top, -right, -bottom );
491 }
492
493 QwtPlotLayout *layout = plot->plotLayout();
494
[4271]495 int baseLineDists[QwtPlot::axisCnt];
[8127]496 int canvasMargins[QwtPlot::axisCnt];
497
498 for ( int axisId = 0; axisId < QwtPlot::axisCnt; axisId++ )
[4271]499 {
[8127]500 canvasMargins[ axisId ] = layout->canvasMargin( axisId );
501
502 if ( d_data->layoutFlags & FrameWithScales )
[4271]503 {
504 QwtScaleWidget *scaleWidget = plot->axisWidget( axisId );
505 if ( scaleWidget )
506 {
507 baseLineDists[axisId] = scaleWidget->margin();
508 scaleWidget->setMargin( 0 );
509 }
[8127]510
511 if ( !plot->axisEnabled( axisId ) )
512 {
513 // When we have a scale the frame is painted on
514 // the position of the backbone - otherwise we
515 // need to introduce a margin around the canvas
516
517 switch( axisId )
518 {
519 case QwtPlot::yLeft:
520 layoutRect.adjust( 1, 0, 0, 0 );
521 break;
522 case QwtPlot::yRight:
523 layoutRect.adjust( 0, 0, -1, 0 );
524 break;
525 case QwtPlot::xTop:
526 layoutRect.adjust( 0, 1, 0, 0 );
527 break;
528 case QwtPlot::xBottom:
529 layoutRect.adjust( 0, 0, 0, -1 );
530 break;
531 default:
532 break;
533 }
534 }
[4271]535 }
536 }
537
[8127]538 // Calculate the layout for the document.
539
540 QwtPlotLayout::Options layoutOptions = QwtPlotLayout::IgnoreScrollbars;
541
542 if ( ( d_data->layoutFlags & FrameWithScales ) ||
543 ( d_data->discardFlags & DiscardCanvasFrame ) )
544 {
545 layoutOptions |= QwtPlotLayout::IgnoreFrames;
[9383]546 }
[8127]547
[4271]548 if ( d_data->discardFlags & DiscardLegend )
549 layoutOptions |= QwtPlotLayout::IgnoreLegend;
550
[8127]551 if ( d_data->discardFlags & DiscardTitle )
552 layoutOptions |= QwtPlotLayout::IgnoreTitle;
[4271]553
[8127]554 if ( d_data->discardFlags & DiscardFooter )
555 layoutOptions |= QwtPlotLayout::IgnoreFooter;
[4271]556
[8127]557 layout->activate( plot, layoutRect, layoutOptions );
558
[4271]559 // canvas
560
561 QwtScaleMap maps[QwtPlot::axisCnt];
[8127]562 buildCanvasMaps( plot, layout->canvasRect(), maps );
563 if ( updateCanvasMargins( plot, layout->canvasRect(), maps ) )
564 {
565 // recalculate maps and layout, when the margins
566 // have been changed
[4271]567
[8127]568 layout->activate( plot, layoutRect, layoutOptions );
569 buildCanvasMaps( plot, layout->canvasRect(), maps );
570 }
571
572 // now start painting
573
574 painter->save();
575 painter->setWorldTransform( transform, true );
576
577 renderCanvas( plot, painter, layout->canvasRect(), maps );
578
[4271]579 if ( !( d_data->discardFlags & DiscardTitle )
580 && ( !plot->titleLabel()->text().isEmpty() ) )
581 {
[8127]582 renderTitle( plot, painter, layout->titleRect() );
[4271]583 }
584
[8127]585 if ( !( d_data->discardFlags & DiscardFooter )
586 && ( !plot->footerLabel()->text().isEmpty() ) )
587 {
588 renderFooter( plot, painter, layout->footerRect() );
589 }
590
[4271]591 if ( !( d_data->discardFlags & DiscardLegend )
592 && plot->legend() && !plot->legend()->isEmpty() )
593 {
[8127]594 renderLegend( plot, painter, layout->legendRect() );
[4271]595 }
596
[8127]597 for ( int axisId = 0; axisId < QwtPlot::axisCnt; axisId++ )
[4271]598 {
599 QwtScaleWidget *scaleWidget = plot->axisWidget( axisId );
600 if ( scaleWidget )
601 {
602 int baseDist = scaleWidget->margin();
603
604 int startDist, endDist;
605 scaleWidget->getBorderDistHint( startDist, endDist );
606
607 renderScale( plot, painter, axisId, startDist, endDist,
[8127]608 baseDist, layout->scaleRect( axisId ) );
[4271]609 }
610 }
611
[8127]612 painter->restore();
[4271]613
[8127]614 // restore all setting to their original attributes.
615 for ( int axisId = 0; axisId < QwtPlot::axisCnt; axisId++ )
[4271]616 {
[8127]617 if ( d_data->layoutFlags & FrameWithScales )
[4271]618 {
619 QwtScaleWidget *scaleWidget = plot->axisWidget( axisId );
620 if ( scaleWidget )
621 scaleWidget->setMargin( baseLineDists[axisId] );
622 }
[8127]623
624 layout->setCanvasMargin( canvasMargins[axisId] );
[4271]625 }
626
[8127]627 layout->invalidate();
628
[4271]629}
630
631/*!
632 Render the title into a given rectangle.
633
634 \param plot Plot widget
635 \param painter Painter
[9383]636 \param titleRect Bounding rectangle for the title
[4271]637*/
638void QwtPlotRenderer::renderTitle( const QwtPlot *plot,
[9383]639 QPainter *painter, const QRectF &titleRect ) const
[4271]640{
[9383]641 painter->setFont( qwtResolvedFont( plot->titleLabel() ) );
[4271]642
643 const QColor color = plot->titleLabel()->palette().color(
644 QPalette::Active, QPalette::Text );
645
646 painter->setPen( color );
[9383]647 plot->titleLabel()->text().draw( painter, titleRect );
[4271]648}
649
650/*!
[8127]651 Render the footer into a given rectangle.
[4271]652
653 \param plot Plot widget
654 \param painter Painter
[9383]655 \param footerRect Bounding rectangle for the footer
[4271]656*/
[8127]657void QwtPlotRenderer::renderFooter( const QwtPlot *plot,
[9383]658 QPainter *painter, const QRectF &footerRect ) const
[4271]659{
[9383]660 painter->setFont( qwtResolvedFont( plot->footerLabel() ) );
[4271]661
[8127]662 const QColor color = plot->footerLabel()->palette().color(
663 QPalette::Active, QPalette::Text );
[4271]664
[8127]665 painter->setPen( color );
[9383]666 plot->footerLabel()->text().draw( painter, footerRect );
[8127]667}
[4271]668
669/*!
[8127]670 Render the legend into a given rectangle.
[4271]671
672 \param plot Plot widget
673 \param painter Painter
[9383]674 \param legendRect Bounding rectangle for the legend
[4271]675*/
[8127]676void QwtPlotRenderer::renderLegend( const QwtPlot *plot,
[9383]677 QPainter *painter, const QRectF &legendRect ) const
[4271]678{
[8127]679 if ( plot->legend() )
[4271]680 {
[8127]681 bool fillBackground = !( d_data->discardFlags & DiscardBackground );
[9383]682 plot->legend()->renderLegend( painter, legendRect, fillBackground );
[4271]683 }
684}
685
686/*!
687 \brief Paint a scale into a given rectangle.
688 Paint the scale into a given rectangle.
689
690 \param plot Plot widget
691 \param painter Painter
692 \param axisId Axis
693 \param startDist Start border distance
694 \param endDist End border distance
695 \param baseDist Base distance
[9383]696 \param scaleRect Bounding rectangle for the scale
[4271]697*/
698void QwtPlotRenderer::renderScale( const QwtPlot *plot,
699 QPainter *painter,
700 int axisId, int startDist, int endDist, int baseDist,
[9383]701 const QRectF &scaleRect ) const
[4271]702{
703 if ( !plot->axisEnabled( axisId ) )
704 return;
705
706 const QwtScaleWidget *scaleWidget = plot->axisWidget( axisId );
707 if ( scaleWidget->isColorBarEnabled()
708 && scaleWidget->colorBarWidth() > 0 )
709 {
[9383]710 scaleWidget->drawColorBar( painter, scaleWidget->colorBarRect( scaleRect ) );
[8127]711 baseDist += scaleWidget->colorBarWidth() + scaleWidget->spacing();
[4271]712 }
713
714 painter->save();
715
716 QwtScaleDraw::Alignment align;
717 double x, y, w;
718
719 switch ( axisId )
720 {
721 case QwtPlot::yLeft:
722 {
[9383]723 x = scaleRect.right() - 1.0 - baseDist;
724 y = scaleRect.y() + startDist;
725 w = scaleRect.height() - startDist - endDist;
[4271]726 align = QwtScaleDraw::LeftScale;
727 break;
728 }
729 case QwtPlot::yRight:
730 {
[9383]731 x = scaleRect.left() + baseDist;
732 y = scaleRect.y() + startDist;
733 w = scaleRect.height() - startDist - endDist;
[4271]734 align = QwtScaleDraw::RightScale;
735 break;
736 }
737 case QwtPlot::xTop:
738 {
[9383]739 x = scaleRect.left() + startDist;
740 y = scaleRect.bottom() - 1.0 - baseDist;
741 w = scaleRect.width() - startDist - endDist;
[4271]742 align = QwtScaleDraw::TopScale;
743 break;
744 }
745 case QwtPlot::xBottom:
746 {
[9383]747 x = scaleRect.left() + startDist;
748 y = scaleRect.top() + baseDist;
749 w = scaleRect.width() - startDist - endDist;
[4271]750 align = QwtScaleDraw::BottomScale;
751 break;
752 }
753 default:
754 return;
755 }
756
[9383]757 scaleWidget->drawTitle( painter, align, scaleRect );
[4271]758
[9383]759 painter->setFont( qwtResolvedFont( scaleWidget ) );
[4271]760
761 QwtScaleDraw *sd = const_cast<QwtScaleDraw *>( scaleWidget->scaleDraw() );
762 const QPointF sdPos = sd->pos();
763 const double sdLength = sd->length();
764
765 sd->move( x, y );
766 sd->setLength( w );
767
768 QPalette palette = scaleWidget->palette();
769 palette.setCurrentColorGroup( QPalette::Active );
770 sd->draw( painter, palette );
771
772 // reset previous values
773 sd->move( sdPos );
774 sd->setLength( sdLength );
775
776 painter->restore();
777}
778
779/*!
780 Render the canvas into a given rectangle.
781
782 \param plot Plot widget
783 \param painter Painter
[9383]784 \param maps Maps mapping between plot and paint device coordinates
[4271]785 \param canvasRect Canvas rectangle
786*/
787void QwtPlotRenderer::renderCanvas( const QwtPlot *plot,
[9383]788 QPainter *painter, const QRectF &canvasRect,
789 const QwtScaleMap *maps ) const
[4271]790{
[8127]791 const QWidget *canvas = plot->canvas();
[4271]792
793 QRectF r = canvasRect.adjusted( 0.0, 0.0, -1.0, -1.0 );
794
795 if ( d_data->layoutFlags & FrameWithScales )
796 {
[8127]797 painter->save();
798
[4271]799 r.adjust( -1.0, -1.0, 1.0, 1.0 );
800 painter->setPen( QPen( Qt::black ) );
801
802 if ( !( d_data->discardFlags & DiscardCanvasBackground ) )
803 {
804 const QBrush bgBrush =
[8127]805 canvas->palette().brush( plot->backgroundRole() );
[4271]806 painter->setBrush( bgBrush );
807 }
808
809 QwtPainter::drawRect( painter, r );
[8127]810
811 painter->restore();
812 painter->save();
813
814 painter->setClipRect( canvasRect );
[9383]815 plot->drawItems( painter, canvasRect, maps );
[8127]816
817 painter->restore();
[4271]818 }
[8127]819 else if ( canvas->testAttribute( Qt::WA_StyledBackground ) )
[4271]820 {
[8127]821 QPainterPath clipPath;
822
823 painter->save();
824
[4271]825 if ( !( d_data->discardFlags & DiscardCanvasBackground ) )
826 {
[8127]827 QwtPainter::drawBackgound( painter, r, canvas );
828 clipPath = qwtCanvasClip( canvas, canvasRect );
829 }
[4271]830
[8127]831 painter->restore();
832 painter->save();
[4271]833
[8127]834 if ( clipPath.isEmpty() )
835 painter->setClipRect( canvasRect );
836 else
837 painter->setClipPath( clipPath );
[4271]838
[9383]839 plot->drawItems( painter, canvasRect, maps );
[8127]840
841 painter->restore();
[4271]842 }
[8127]843 else
844 {
845 QPainterPath clipPath;
[4271]846
[8127]847 int frameWidth = 0;
[4271]848
[8127]849 if ( !( d_data->discardFlags & DiscardCanvasFrame ) )
850 {
851 const QVariant fw = canvas->property( "frameWidth" );
852 if ( fw.type() == QVariant::Int )
853 frameWidth = fw.toInt();
[4271]854
[8127]855 clipPath = qwtCanvasClip( canvas, canvasRect );
856 }
[4271]857
[9383]858 QRectF innerRect = canvasRect.adjusted(
[8127]859 frameWidth, frameWidth, -frameWidth, -frameWidth );
[4271]860
[8127]861 painter->save();
862
863 if ( clipPath.isEmpty() )
864 {
865 painter->setClipRect( innerRect );
866 }
867 else
868 {
869 painter->setClipPath( clipPath );
870 }
871
872 if ( !( d_data->discardFlags & DiscardCanvasBackground ) )
873 {
874 QwtPainter::drawBackgound( painter, innerRect, canvas );
875 }
876
[9383]877 plot->drawItems( painter, innerRect, maps );
[8127]878
879 painter->restore();
880
881 if ( frameWidth > 0 )
882 {
883 painter->save();
884
885 const int frameStyle =
886 canvas->property( "frameShadow" ).toInt() |
887 canvas->property( "frameShape" ).toInt();
888
889 const QVariant borderRadius = canvas->property( "borderRadius" );
[9383]890 if ( borderRadius.type() == QVariant::Double
[8127]891 && borderRadius.toDouble() > 0.0 )
892 {
[9383]893 const double radius = borderRadius.toDouble();
[8127]894
895 QwtPainter::drawRoundedFrame( painter, canvasRect,
[9383]896 radius, radius, canvas->palette(), frameWidth, frameStyle );
[8127]897 }
898 else
899 {
900 const int midLineWidth = canvas->property( "midLineWidth" ).toInt();
901
902 QwtPainter::drawFrame( painter, canvasRect,
903 canvas->palette(), canvas->foregroundRole(),
904 frameWidth, midLineWidth, frameStyle );
905 }
906 painter->restore();
907 }
908 }
[4271]909}
910
911/*!
912 Calculated the scale maps for rendering the canvas
913
914 \param plot Plot widget
915 \param canvasRect Target rectangle
916 \param maps Scale maps to be calculated
917*/
918void QwtPlotRenderer::buildCanvasMaps( const QwtPlot *plot,
919 const QRectF &canvasRect, QwtScaleMap maps[] ) const
920{
921 for ( int axisId = 0; axisId < QwtPlot::axisCnt; axisId++ )
922 {
923 maps[axisId].setTransformation(
924 plot->axisScaleEngine( axisId )->transformation() );
925
[8127]926 const QwtScaleDiv &scaleDiv = plot->axisScaleDiv( axisId );
[4271]927 maps[axisId].setScaleInterval(
928 scaleDiv.lowerBound(), scaleDiv.upperBound() );
929
930 double from, to;
931 if ( plot->axisEnabled( axisId ) )
932 {
933 const int sDist = plot->axisWidget( axisId )->startBorderDist();
934 const int eDist = plot->axisWidget( axisId )->endBorderDist();
[8127]935 const QRectF scaleRect = plot->plotLayout()->scaleRect( axisId );
[4271]936
937 if ( axisId == QwtPlot::xTop || axisId == QwtPlot::xBottom )
938 {
939 from = scaleRect.left() + sDist;
940 to = scaleRect.right() - eDist;
941 }
942 else
943 {
944 from = scaleRect.bottom() - eDist;
945 to = scaleRect.top() + sDist;
946 }
947 }
948 else
949 {
[8127]950 int margin = 0;
951 if ( !plot->plotLayout()->alignCanvasToScale( axisId ) )
952 margin = plot->plotLayout()->canvasMargin( axisId );
953
[4271]954 if ( axisId == QwtPlot::yLeft || axisId == QwtPlot::yRight )
955 {
956 from = canvasRect.bottom() - margin;
957 to = canvasRect.top() + margin;
958 }
959 else
960 {
961 from = canvasRect.left() + margin;
962 to = canvasRect.right() - margin;
963 }
964 }
965 maps[axisId].setPaintInterval( from, to );
966 }
967}
[8127]968
969bool QwtPlotRenderer::updateCanvasMargins( QwtPlot *plot,
970 const QRectF &canvasRect, const QwtScaleMap maps[] ) const
971{
972 double margins[QwtPlot::axisCnt];
973 plot->getCanvasMarginsHint( maps, canvasRect,
[9383]974 margins[QwtPlot::yLeft], margins[QwtPlot::xTop],
[8127]975 margins[QwtPlot::yRight], margins[QwtPlot::xBottom] );
976
977 bool marginsChanged = false;
978 for ( int axisId = 0; axisId < QwtPlot::axisCnt; axisId++ )
979 {
980 if ( margins[axisId] >= 0.0 )
981 {
982 const int m = qCeil( margins[axisId] );
983 plot->plotLayout()->setCanvasMargin( m, axisId);
984 marginsChanged = true;
985 }
986 }
987
988 return marginsChanged;
989}
990
991/*!
992 \brief Execute a file dialog and render the plot to the selected file
993
994 \param plot Plot widget
995 \param documentName Default document name
996 \param sizeMM Size for the document in millimeters.
997 \param resolution Resolution in dots per Inch (dpi)
998
999 \return True, when exporting was successful
1000 \sa renderDocument()
1001*/
1002bool QwtPlotRenderer::exportTo( QwtPlot *plot, const QString &documentName,
1003 const QSizeF &sizeMM, int resolution )
[9383]1004{
[8127]1005 if ( plot == NULL )
1006 return false;
[9383]1007
[8127]1008 QString fileName = documentName;
1009
[9383]1010 // What about translation
[8127]1011
1012#ifndef QT_NO_FILEDIALOG
1013 const QList<QByteArray> imageFormats =
1014 QImageWriter::supportedImageFormats();
[9383]1015
[8127]1016 QStringList filter;
[9383]1017#if QWT_FORMAT_PDF
[8127]1018 filter += QString( "PDF " ) + tr( "Documents" ) + " (*.pdf)";
1019#endif
[9383]1020#if QWT_FORMAT_SVG
[8127]1021 filter += QString( "SVG " ) + tr( "Documents" ) + " (*.svg)";
1022#endif
[9383]1023#if QWT_FORMAT_POSTSCRIPT
[8127]1024 filter += QString( "Postscript " ) + tr( "Documents" ) + " (*.ps)";
1025#endif
[9383]1026
[8127]1027 if ( imageFormats.size() > 0 )
1028 {
1029 QString imageFilter( tr( "Images" ) );
1030 imageFilter += " (";
1031 for ( int i = 0; i < imageFormats.size(); i++ )
1032 {
1033 if ( i > 0 )
1034 imageFilter += " ";
[9383]1035 imageFilter += "*.";
[8127]1036 imageFilter += imageFormats[i];
[9383]1037 }
[8127]1038 imageFilter += ")";
[9383]1039
[8127]1040 filter += imageFilter;
[9383]1041 }
1042
[8127]1043 fileName = QFileDialog::getSaveFileName(
1044 NULL, tr( "Export File Name" ), fileName,
1045 filter.join( ";;" ), NULL, QFileDialog::DontConfirmOverwrite );
[9383]1046#endif
[8127]1047 if ( fileName.isEmpty() )
1048 return false;
1049
1050 renderDocument( plot, fileName, sizeMM, resolution );
1051
1052 return true;
[9383]1053}
Note: See TracBrowser for help on using the repository browser.