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

Last change on this file since 8495 was 8127, checked in by stoecker, 8 years ago

update qwt and qwtpolar, many QT5 fixes (unfinished)

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