KD Chart 2  [rev.2.7]
KDChartPolarDiagram.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 ** Copyright (C) 2001-2020 Klaralvdalens Datakonsult AB. All rights reserved.
3 **
4 ** This file is part of the KD Chart library.
5 **
6 ** Licensees holding valid commercial KD Chart licenses may use this file in
7 ** accordance with the KD Chart Commercial License Agreement provided with
8 ** the Software.
9 **
10 **
11 ** This file may be distributed and/or modified under the terms of the
12 ** GNU General Public License version 2 and version 3 as published by the
13 ** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
14 **
15 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17 **
18 ** Contact info@kdab.com if any conditions of this licensing are not
19 ** clear to you.
20 **
21 **********************************************************************/
22 
23 #include "KDChartPolarDiagram.h"
24 #include "KDChartPolarDiagram_p.h"
25 
26 #include <QPainter>
27 #include "KDChartPaintContext.h"
28 #include "KDChartPainterSaver_p.h"
29 
30 #include <KDABLibFakes>
31 
32 using namespace KDChart;
33 
34 PolarDiagram::Private::Private() :
35  rotateCircularLabels( false ),
36  closeDatasets( false )
37 {
38 }
39 
40 PolarDiagram::Private::~Private() {}
41 
42 #define d d_func()
43 
45  AbstractPolarDiagram( new Private( ), parent, plane )
46 {
47  //init();
48 }
49 
51 {
52 }
53 
54 
55 void PolarDiagram::init()
56 {
68 
80 }
81 
86 {
87  PolarDiagram* newDiagram = new PolarDiagram( new Private( *d ) );
88  // This needs to be copied after the fact
89  newDiagram->d->showDelimitersAtPosition = d->showDelimitersAtPosition;
90  newDiagram->d->showLabelsAtPosition = d->showLabelsAtPosition;
91  newDiagram->d->rotateCircularLabels = d->rotateCircularLabels;
92  newDiagram->d->closeDatasets = d->closeDatasets;
93  return newDiagram;
94 }
95 
97 {
98  if ( !checkInvariants(true) ) return QPair<QPointF, QPointF>( QPointF( 0, 0 ), QPointF( 0, 0 ) );
99  const int rowCount = model()->rowCount(rootIndex());
100  const int colCount = model()->columnCount(rootIndex());
101  qreal xMin = 0.0;
102  qreal xMax = colCount;
103  qreal yMin = 0, yMax = 0;
104  for ( int iCol=0; iCol<colCount; ++iCol ) {
105  for ( int iRow=0; iRow< rowCount; ++iRow ) {
106  qreal value = model()->data( model()->index( iRow, iCol, rootIndex() ) ).toReal(); // checked
107  yMax = qMax( yMax, value );
108  yMin = qMin( yMin, value );
109  }
110  }
111  QPointF bottomLeft ( QPointF( xMin, yMin ) );
112  QPointF topRight ( QPointF( xMax, yMax ) );
113  return QPair<QPointF, QPointF> ( bottomLeft, topRight );
114 }
115 
116 
117 
118 void PolarDiagram::paintEvent ( QPaintEvent*)
119 {
120  QPainter painter ( viewport() );
121  PaintContext ctx;
122  ctx.setPainter ( &painter );
123  ctx.setRectangle( QRectF ( 0, 0, width(), height() ) );
124  paint ( &ctx );
125 }
126 
127 void PolarDiagram::resizeEvent ( QResizeEvent*)
128 {
129 }
130 
131 void PolarDiagram::paintPolarMarkers( PaintContext* ctx, const QPolygonF& polygon )
132 {
133  Q_UNUSED(ctx);
134  Q_UNUSED(polygon);
135  // obsolete, since we are using real markers now!
136 }
137 
139 {
140  qreal dummy1, dummy2;
141  paint( ctx, true, dummy1, dummy2 );
142  paint( ctx, false, dummy1, dummy2 );
143 }
144 
146  bool calculateListAndReturnScale,
147  qreal& newZoomX, qreal& newZoomY )
148 {
149  // note: Not having any data model assigned is no bug
150  // but we can not draw a diagram then either.
151  if ( !checkInvariants(true) )
152  return;
153  d->reverseMapper.clear();
154 
155  const int rowCount = model()->rowCount( rootIndex() );
156  const int colCount = model()->columnCount( rootIndex() );
157 
158  if ( calculateListAndReturnScale ) {
159  // Check if all of the data value texts / data comments fit into the available space...
160  d->labelPaintCache.clear();
161 
162  for ( int iCol = 0; iCol < colCount; ++iCol ) {
163  for ( int iRow=0; iRow < rowCount; ++iRow ) {
164  QModelIndex index = model()->index( iRow, iCol, rootIndex() ); // checked
165  const qreal value = model()->data( index ).toReal();
166  QPointF point = coordinatePlane()->translate(
167  QPointF( value, iRow ) ) + ctx->rectangle().topLeft();
168  //qDebug() << point;
169  d->addLabel( &d->labelPaintCache, index, 0, PositionPoints( point ),
171  }
172  }
173 
174  newZoomX = coordinatePlane()->zoomFactorX();
175  newZoomY = coordinatePlane()->zoomFactorY();
176 
177  if ( d->labelPaintCache.paintReplay.count() ) {
178  // ...and zoom out if necessary
179  const qreal oldZoomX = newZoomX;
180  const qreal oldZoomY = newZoomY;
181 
182  QRectF txtRectF;
183  d->paintDataValueTextsAndMarkers( ctx, d->labelPaintCache, true, true, &txtRectF );
184  const QRect txtRect = txtRectF.toRect();
185  const QRect curRect = coordinatePlane()->geometry();
186  const qreal gapX = qMin( txtRect.left() - curRect.left(), curRect.right() - txtRect.right() );
187  const qreal gapY = qMin( txtRect.top() - curRect.top(), curRect.bottom() - txtRect.bottom() );
188  if ( gapX < 0.0 ) {
189  newZoomX = oldZoomX * ( 1.0 + ( gapX - 1.0 ) / curRect.width() );
190  }
191  if ( gapY < 0.0 ) {
192  newZoomY = oldZoomY * ( 1.0 + ( gapY - 1.0 ) / curRect.height() );
193  }
194  }
195  } else {
196  // Paint the data sets
197  for ( int iCol = 0; iCol < colCount; ++iCol ) {
198  //TODO(khz): As of yet PolarDiagram can not show per-segment line attributes
199  // but it draws every polyline in one go - using one color.
200  // This needs to be enhanced to allow for cell-specific settings
201  // in the same way as LineDiagram does it.
202  QBrush brush = d->datasetAttrs( iCol, KDChart::DatasetBrushRole ).value<QBrush>();
203  QPolygonF polygon;
204  for ( int iRow = 0; iRow < rowCount; ++iRow ) {
205  QModelIndex index = model()->index( iRow, iCol, rootIndex() ); // checked
206  const qreal value = model()->data( index ).toReal();
207  QPointF point = coordinatePlane()->translate( QPointF( value, iRow ) )
208  + ctx->rectangle().topLeft();
209  polygon.append( point );
210  //qDebug() << point;
211  }
212  if ( closeDatasets() && !polygon.isEmpty() ) {
213  // close the circle by connecting the last data point to the first
214  polygon.append( polygon.first() );
215  }
216 
217  PainterSaver painterSaver( ctx->painter() );
218  ctx->painter()->setRenderHint ( QPainter::Antialiasing );
219  ctx->painter()->setBrush( brush );
220  QPen p = d->datasetAttrs( iCol, KDChart::DatasetPenRole ).value< QPen >();
221  if ( p.style() != Qt::NoPen )
222  {
223  ctx->painter()->setPen( PrintingParameters::scalePen( p ) );
224  ctx->painter()->drawPolyline( polygon );
225  }
226  }
227  d->paintDataValueTextsAndMarkers( ctx, d->labelPaintCache, true );
228  }
229 }
230 
231 void PolarDiagram::resize ( const QSizeF& )
232 {
233 }
234 
235 /*virtual*/
237 {
238  return model()->rowCount(rootIndex());
239 }
240 
241 /*virtual*/
243 {
244  return model() ? model()->rowCount(rootIndex()) : 0.0;
245 }
246 
247 /*virtual*/
249 {
250  return 5; // FIXME
251 }
252 
254 {
255  Q_UNUSED( degrees );
256  qWarning() << "Deprecated PolarDiagram::setZeroDegreePosition() called, setting ignored.";
257 }
258 
260 {
261  qWarning() << "Deprecated PolarDiagram::zeroDegreePosition() called.";
262  return 0;
263 }
264 
266 {
267  d->rotateCircularLabels = rotateCircularLabels;
268 }
269 
271 {
272  return d->rotateCircularLabels;
273 }
274 
276 {
277  d->closeDatasets = closeDatasets;
278 }
279 
281 {
282  return d->closeDatasets;
283 }
284 
286  bool showDelimiters )
287 {
288  d->showDelimitersAtPosition[position.value()] = showDelimiters;
289 }
290 
292  bool showLabels )
293 {
294  d->showLabelsAtPosition[position.value()] = showLabels;
295 }
296 
298 {
299  return d->showDelimitersAtPosition[position.value()];
300 }
301 
303 {
304  return d->showLabelsAtPosition[position.value()];
305 }
306 
307 
308 
static const Position & East
void setCloseDatasets(bool closeDatasets)
Close each of the data series by connecting the last point to its respective start point...
KDChartEnums::PositionValue value() const
Returns an integer value corresponding to this Position.
const QRectF rectangle() const
void setPainter(QPainter *painter)
virtual bool checkInvariants(bool justReturnTheStatus=false) const
virtual const QPointF translate(const QPointF &diagramPoint) const =0
Translate the given point in value space coordinates to a position in pixel space.
QRect geometry() const override
pure virtual in QLayoutItem
static const Position & South
QPainter * painter() const
static const Position & Center
qreal numberOfGridRings() const override
[reimplemented]
virtual void paintPolarMarkers(PaintContext *ctx, const QPolygonF &polygon)
PolarDiagram defines a common polar diagram.
void setRotateCircularLabels(bool rotateCircularLabels)
AbstractCoordinatePlane * coordinatePlane() const
The coordinate plane associated with the diagram.
void setZeroDegreePosition(int degrees)
PolarDiagram(QWidget *parent=0, PolarCoordinatePlane *plane=0)
const QPair< QPointF, QPointF > calculateDataBoundaries() const override
[reimplemented]
Base class for diagrams based on a polar coordinate system.
#define d
void resizeEvent(QResizeEvent *) override
virtual PolarDiagram * clone() const
Creates an exact copy of this diagram.
QBrush brush() const
Retrieve the brush to be used for painting datapoints globally.
static const Position & Unknown
qreal valueTotals() const override
[reimplemented]
bool showLabelsAtPosition(Position position) const
bool showDelimitersAtPosition(Position position) const
void paint(PaintContext *paintContext) override
[reimplemented]
static const Position & NorthWest
void paintEvent(QPaintEvent *) override
static const Position & West
void setShowDelimitersAtPosition(Position position, bool showDelimiters)
Stores information about painting diagrams.
Stores the absolute target points of a Position.
static const Position & NorthEast
void resize(const QSizeF &area) override
[reimplemented]
static const Position & North
qreal numberOfValuesPerDataset() const override
[reimplemented]
static QPen scalePen(const QPen &pen)
Defines a position, using compass terminology.
static const Position & SouthEast
void setShowLabelsAtPosition(Position position, bool showLabels)
void setRectangle(const QRectF &rect)
Class only listed here to document inheritance of some KDChart classes.
static const Position & Floating
static const Position & SouthWest

Klarälvdalens Datakonsult AB (KDAB)
"The Qt, C++ and OpenGL Experts"
https://www.kdab.com/

https://www.kdab.com/development-resources/qt-tools/kd-chart/