KChart

KChartPolarDiagram.cpp
1 /*
2  * SPDX-FileCopyrightText: 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved.
3  *
4  * This file is part of the KD Chart library.
5  *
6  * SPDX-License-Identifier: GPL-2.0-or-later
7  */
8 
9 #include "KChartPolarDiagram.h"
10 #include "KChartPolarDiagram_p.h"
11 
12 #include "KChartPaintContext.h"
13 #include "KChartPainterSaver_p.h"
14 #include "KChartMath_p.h"
15 
16 #include <QPainter>
17 
18 using namespace KChart;
19 
20 PolarDiagram::Private::Private() :
21  rotateCircularLabels( false ),
22  closeDatasets( false )
23 {
24 }
25 
26 PolarDiagram::Private::~Private() {}
27 
28 #define d d_func()
29 
30 PolarDiagram::PolarDiagram( QWidget* parent, PolarCoordinatePlane* plane ) :
31  AbstractPolarDiagram( new Private( ), parent, plane )
32 {
33  //init();
34 }
35 
36 PolarDiagram::~PolarDiagram()
37 {
38 }
39 
40 
41 void PolarDiagram::init()
42 {
43  setShowDelimitersAtPosition( Position::Unknown, false );
44  setShowDelimitersAtPosition( Position::Center, false );
45  setShowDelimitersAtPosition( Position::NorthWest, false );
46  setShowDelimitersAtPosition( Position::North, true );
47  setShowDelimitersAtPosition( Position::NorthEast, false );
48  setShowDelimitersAtPosition( Position::West, false );
49  setShowDelimitersAtPosition( Position::East, false );
50  setShowDelimitersAtPosition( Position::SouthWest, false );
51  setShowDelimitersAtPosition( Position::South, true );
52  setShowDelimitersAtPosition( Position::SouthEast, false );
53  setShowDelimitersAtPosition( Position::Floating, false );
54 
55  setShowLabelsAtPosition( Position::Unknown, false );
56  setShowLabelsAtPosition( Position::Center, false );
57  setShowLabelsAtPosition( Position::NorthWest, false );
58  setShowLabelsAtPosition( Position::North, true );
59  setShowLabelsAtPosition( Position::NorthEast, false );
60  setShowLabelsAtPosition( Position::West, false );
61  setShowLabelsAtPosition( Position::East, false );
62  setShowLabelsAtPosition( Position::SouthWest, false );
63  setShowLabelsAtPosition( Position::South, true );
64  setShowLabelsAtPosition( Position::SouthEast, false );
65  setShowLabelsAtPosition( Position::Floating, false );
66 }
67 
69 {
70  PolarDiagram* newDiagram = new PolarDiagram( new Private( *d ) );
71  // This needs to be copied after the fact
72  newDiagram->d->showDelimitersAtPosition = d->showDelimitersAtPosition;
73  newDiagram->d->showLabelsAtPosition = d->showLabelsAtPosition;
74  newDiagram->d->rotateCircularLabels = d->rotateCircularLabels;
75  newDiagram->d->closeDatasets = d->closeDatasets;
76  return newDiagram;
77 }
78 
80 {
81  if ( !checkInvariants(true) ) return QPair<QPointF, QPointF>( QPointF( 0, 0 ), QPointF( 0, 0 ) );
82  const int rowCount = model()->rowCount(rootIndex());
83  const int colCount = model()->columnCount(rootIndex());
84  qreal xMin = 0.0;
85  qreal xMax = colCount;
86  qreal yMin = 0, yMax = 0;
87  for ( int iCol=0; iCol<colCount; ++iCol ) {
88  for ( int iRow=0; iRow< rowCount; ++iRow ) {
89  qreal value = model()->data( model()->index( iRow, iCol, rootIndex() ) ).toReal(); // checked
90  yMax = qMax( yMax, value );
91  yMin = qMin( yMin, value );
92  }
93  }
94  QPointF bottomLeft ( QPointF( xMin, yMin ) );
95  QPointF topRight ( QPointF( xMax, yMax ) );
96  return QPair<QPointF, QPointF> ( bottomLeft, topRight );
97 }
98 
99 
100 
101 void PolarDiagram::paintEvent ( QPaintEvent*)
102 {
103  QPainter painter ( viewport() );
104  PaintContext ctx;
105  ctx.setPainter ( &painter );
106  ctx.setRectangle( QRectF ( 0, 0, width(), height() ) );
107  paint ( &ctx );
108 }
109 
110 void PolarDiagram::resizeEvent ( QResizeEvent*)
111 {
112 }
113 
114 void PolarDiagram::paintPolarMarkers( PaintContext* ctx, const QPolygonF& polygon )
115 {
116  Q_UNUSED(ctx);
117  Q_UNUSED(polygon);
118  // obsolete, since we are using real markers now!
119 }
120 
122 {
123  qreal dummy1, dummy2;
124  paint( ctx, true, dummy1, dummy2 );
125  paint( ctx, false, dummy1, dummy2 );
126 }
127 
129  bool calculateListAndReturnScale,
130  qreal& newZoomX, qreal& newZoomY )
131 {
132  // note: Not having any data model assigned is no bug
133  // but we can not draw a diagram then either.
134  if ( !checkInvariants(true) )
135  return;
136  d->reverseMapper.clear();
137 
138  const int rowCount = model()->rowCount( rootIndex() );
139  const int colCount = model()->columnCount( rootIndex() );
140 
141  if ( calculateListAndReturnScale ) {
142  // Check if all of the data value texts / data comments fit into the available space...
143  d->labelPaintCache.clear();
144 
145  for ( int iCol = 0; iCol < colCount; ++iCol ) {
146  for ( int iRow=0; iRow < rowCount; ++iRow ) {
147  QModelIndex index = model()->index( iRow, iCol, rootIndex() ); // checked
148  const qreal value = model()->data( index ).toReal();
149  QPointF point = coordinatePlane()->translate(
150  QPointF( value, iRow ) ) + ctx->rectangle().topLeft();
151  //qDebug() << point;
152  d->addLabel( &d->labelPaintCache, index, nullptr, PositionPoints( point ),
153  Position::Center, Position::Center, value );
154  }
155  }
156 
157  newZoomX = coordinatePlane()->zoomFactorX();
158  newZoomY = coordinatePlane()->zoomFactorY();
159 
160  if ( d->labelPaintCache.paintReplay.count() ) {
161  // ...and zoom out if necessary
162  const qreal oldZoomX = newZoomX;
163  const qreal oldZoomY = newZoomY;
164 
165  QRectF txtRectF;
166  d->paintDataValueTextsAndMarkers( ctx, d->labelPaintCache, true, true, &txtRectF );
167  const QRect txtRect = txtRectF.toRect();
168  const QRect curRect = coordinatePlane()->geometry();
169  const qreal gapX = qMin( txtRect.left() - curRect.left(), curRect.right() - txtRect.right() );
170  const qreal gapY = qMin( txtRect.top() - curRect.top(), curRect.bottom() - txtRect.bottom() );
171  if ( gapX < 0.0 ) {
172  newZoomX = oldZoomX * ( 1.0 + ( gapX - 1.0 ) / curRect.width() );
173  }
174  if ( gapY < 0.0 ) {
175  newZoomY = oldZoomY * ( 1.0 + ( gapY - 1.0 ) / curRect.height() );
176  }
177  }
178  } else {
179  // Paint the data sets
180  for ( int iCol = 0; iCol < colCount; ++iCol ) {
181  //TODO(khz): As of yet PolarDiagram can not show per-segment line attributes
182  // but it draws every polyline in one go - using one color.
183  // This needs to be enhanced to allow for cell-specific settings
184  // in the same way as LineDiagram does it.
185  QBrush brush = d->datasetAttrs( iCol, KChart::DatasetBrushRole ).value<QBrush>();
186  QPolygonF polygon;
187  for ( int iRow = 0; iRow < rowCount; ++iRow ) {
188  QModelIndex index = model()->index( iRow, iCol, rootIndex() ); // checked
189  const qreal value = model()->data( index ).toReal();
190  QPointF point = coordinatePlane()->translate( QPointF( value, iRow ) )
191  + ctx->rectangle().topLeft();
192  polygon.append( point );
193  //qDebug() << point;
194  }
195  if ( closeDatasets() && !polygon.isEmpty() ) {
196  // close the circle by connecting the last data point to the first
197  polygon.append( polygon.first() );
198  }
199 
200  PainterSaver painterSaver( ctx->painter() );
201  ctx->painter()->setRenderHint ( QPainter::Antialiasing );
202  ctx->painter()->setBrush( brush );
203  QPen p = d->datasetAttrs( iCol, KChart::DatasetPenRole ).value< QPen >();
204  if ( p.style() != Qt::NoPen )
205  {
206  ctx->painter()->setPen( PrintingParameters::scalePen( p ) );
207  ctx->painter()->drawPolyline( polygon );
208  }
209  }
210  d->paintDataValueTextsAndMarkers( ctx, d->labelPaintCache, true );
211  }
212 }
213 
214 void PolarDiagram::resize ( const QSizeF& size )
215 {
217 }
218 
219 /*virtual*/
221 {
222  return model()->rowCount(rootIndex());
223 }
224 
225 /*virtual*/
227 {
228  return model() ? model()->rowCount(rootIndex()) : 0.0;
229 }
230 
231 /*virtual*/
233 {
234  return 5; // FIXME
235 }
236 
238 {
239  Q_UNUSED( degrees );
240  qWarning() << "Deprecated PolarDiagram::setZeroDegreePosition() called, setting ignored.";
241 }
242 
244 {
245  qWarning() << "Deprecated PolarDiagram::zeroDegreePosition() called.";
246  return 0;
247 }
248 
249 void PolarDiagram::setRotateCircularLabels( bool rotateCircularLabels )
250 {
251  d->rotateCircularLabels = rotateCircularLabels;
252 }
253 
254 bool PolarDiagram::rotateCircularLabels() const
255 {
256  return d->rotateCircularLabels;
257 }
258 
259 void PolarDiagram::setCloseDatasets( bool closeDatasets )
260 {
261  d->closeDatasets = closeDatasets;
262 }
263 
264 bool PolarDiagram::closeDatasets() const
265 {
266  return d->closeDatasets;
267 }
268 
269 void PolarDiagram::setShowDelimitersAtPosition( Position position,
270  bool showDelimiters )
271 {
272  d->showDelimitersAtPosition[position.value()] = showDelimiters;
273 }
274 
275 void PolarDiagram::setShowLabelsAtPosition( Position position,
276  bool showLabels )
277 {
278  d->showLabelsAtPosition[position.value()] = showLabels;
279 }
280 
281 bool PolarDiagram::showDelimitersAtPosition( Position position ) const
282 {
283  return d->showDelimitersAtPosition[position.value()];
284 }
285 
286 bool PolarDiagram::showLabelsAtPosition( Position position ) const
287 {
288  return d->showLabelsAtPosition[position.value()];
289 }
290 
291 
292 
KChartEnums::PositionValue value() const
Returns an integer value corresponding to this Position.
Class only listed here to document inheritance of some KChart classes.
Qt::PenStyle style() const const
QRect toRect() const const
void resize(const QSizeF &area) override
void paint(PaintContext *paintContext) override
void setRenderHint(QPainter::RenderHint hint, bool on)
int right() const const
void drawPolyline(const QPointF *points, int pointCount)
Defines a position, using compass terminology.
void setCloseDatasets(bool closeDatasets)
Close each of the data series by connecting the last point to its respective start point...
qreal valueTotals() const override
int height() const const
void paint(QPainter *) override
reimpl
void setZeroDegreePosition(int degrees)
Stores the absolute target points of a Position.
Stores information about painting diagrams.
int top() const const
void setPen(const QColor &color)
int left() const const
QPointF topLeft() const const
void setBrush(const QBrush &brush)
qreal numberOfValuesPerDataset() const override
qreal numberOfGridRings() const override
virtual void resize(const QSizeF &area)
Called by the widget&#39;s sizeEvent.
int width() const const
QVariant data(int role) const const
const QPair< QPointF, QPointF > calculateDataBoundaries() const override
int bottom() const const
Base class for diagrams based on a polar coordinate system.
qreal toReal(bool *ok) const const
Global namespace.
virtual PolarDiagram * clone() const
Creates an exact copy of this diagram.
PolarDiagram defines a common polar diagram.
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Thu Oct 21 2021 22:37:38 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.