KD Chart API Documentation  3.1
KDChartPolarDiagram.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** This file is part of the KD Chart library.
4 **
5 ** SPDX-FileCopyrightText: 2001 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
6 **
7 ** SPDX-License-Identifier: MIT
8 **
9 ****************************************************************************/
10 
11 #include "KDChartPolarDiagram.h"
12 #include "KDChartPolarDiagram_p.h"
13 
14 #include "KDChartPaintContext.h"
15 #include "KDChartPainterSaver_p.h"
16 #include <QPainter>
17 
18 #include <KDABLibFakes>
19 
20 using namespace KDChart;
21 
22 PolarDiagram::Private::Private()
23 {
24 }
25 
26 PolarDiagram::Private::~Private()
27 {
28 }
29 
30 #define d d_func()
31 
33  : AbstractPolarDiagram(new Private(), parent, plane)
34 {
35  // init();
36 }
37 
39 {
40 }
41 
42 void PolarDiagram::init()
43 {
55 
67 }
68 
73 {
74  auto *newDiagram = new PolarDiagram(new Private(*d));
75  // This needs to be copied after the fact
76  newDiagram->d->showDelimitersAtPosition = d->showDelimitersAtPosition;
77  newDiagram->d->showLabelsAtPosition = d->showLabelsAtPosition;
78  newDiagram->d->rotateCircularLabels = d->rotateCircularLabels;
79  newDiagram->d->closeDatasets = d->closeDatasets;
80  return newDiagram;
81 }
82 
83 const QPair<QPointF, QPointF> PolarDiagram::calculateDataBoundaries() const
84 {
85  if (!checkInvariants(true))
86  return QPair<QPointF, QPointF>(QPointF(0, 0), QPointF(0, 0));
87  const int rowCount = model()->rowCount(rootIndex());
88  const int colCount = model()->columnCount(rootIndex());
89  qreal xMin = 0.0;
90  qreal xMax = colCount;
91  qreal yMin = 0, yMax = 0;
92  for (int iCol = 0; iCol < colCount; ++iCol) {
93  for (int iRow = 0; iRow < rowCount; ++iRow) {
94  qreal value = model()->data(model()->index(iRow, iCol, rootIndex())).toReal(); // checked
95  yMax = qMax(yMax, value);
96  yMin = qMin(yMin, value);
97  }
98  }
99  QPointF bottomLeft(QPointF(xMin, yMin));
100  QPointF topRight(QPointF(xMax, yMax));
101  return QPair<QPointF, QPointF>(bottomLeft, topRight);
102 }
103 
104 void PolarDiagram::paintEvent(QPaintEvent *)
105 {
106  QPainter painter(viewport());
107  PaintContext ctx;
108  ctx.setPainter(&painter);
109  ctx.setRectangle(QRectF(0, 0, width(), height()));
110  paint(&ctx);
111 }
112 
113 void PolarDiagram::resizeEvent(QResizeEvent *)
114 {
115 }
116 
117 void PolarDiagram::paintPolarMarkers(PaintContext *ctx, const QPolygonF &polygon)
118 {
119  Q_UNUSED(ctx);
120  Q_UNUSED(polygon);
121  // obsolete, since we are using real markers now!
122 }
123 
125 {
126  qreal dummy1, dummy2;
127  paint(ctx, true, dummy1, dummy2);
128  paint(ctx, false, dummy1, dummy2);
129 }
130 
132  bool calculateListAndReturnScale,
133  qreal &newZoomX, qreal &newZoomY)
134 {
135  // note: Not having any data model assigned is no bug
136  // but we can not draw a diagram then either.
137  if (!checkInvariants(true))
138  return;
139  d->reverseMapper.clear();
140 
141  const int rowCount = model()->rowCount(rootIndex());
142  const int colCount = model()->columnCount(rootIndex());
143 
144  if (calculateListAndReturnScale) {
145  // Check if all of the data value texts / data comments fit into the available space...
146  d->labelPaintCache.clear();
147 
148  for (int iCol = 0; iCol < colCount; ++iCol) {
149  for (int iRow = 0; iRow < rowCount; ++iRow) {
150  QModelIndex index = model()->index(iRow, iCol, rootIndex()); // checked
151  const qreal value = model()->data(index).toReal();
152  QPointF point = coordinatePlane()->translate(
153  QPointF(value, iRow))
154  + ctx->rectangle().topLeft();
155  // qDebug() << point;
156  d->addLabel(&d->labelPaintCache, index, nullptr, PositionPoints(point),
158  }
159  }
160 
161  newZoomX = coordinatePlane()->zoomFactorX();
162  newZoomY = coordinatePlane()->zoomFactorY();
163 
164  if (d->labelPaintCache.paintReplay.count()) {
165  // ...and zoom out if necessary
166  const qreal oldZoomX = newZoomX;
167  const qreal oldZoomY = newZoomY;
168 
169  QRectF txtRectF;
170  d->paintDataValueTextsAndMarkers(ctx, d->labelPaintCache, true, true, &txtRectF);
171  const QRect txtRect = txtRectF.toRect();
172  const QRect curRect = coordinatePlane()->geometry();
173  const qreal gapX = qMin(txtRect.left() - curRect.left(), curRect.right() - txtRect.right());
174  const qreal gapY = qMin(txtRect.top() - curRect.top(), curRect.bottom() - txtRect.bottom());
175  if (gapX < 0.0) {
176  newZoomX = oldZoomX * (1.0 + (gapX - 1.0) / curRect.width());
177  }
178  if (gapY < 0.0) {
179  newZoomY = oldZoomY * (1.0 + (gapY - 1.0) / curRect.height());
180  }
181  }
182  } else {
183  // Paint the data sets
184  for (int iCol = 0; iCol < colCount; ++iCol) {
185  // TODO(khz): As of yet PolarDiagram can not show per-segment line attributes
186  // but it draws every polyline in one go - using one color.
187  // This needs to be enhanced to allow for cell-specific settings
188  // in the same way as LineDiagram does it.
189  QBrush brush = d->datasetAttrs(iCol, KDChart::DatasetBrushRole).value<QBrush>();
190  QPolygonF polygon;
191  for (int iRow = 0; iRow < rowCount; ++iRow) {
192  QModelIndex index = model()->index(iRow, iCol, rootIndex()); // checked
193  const qreal value = model()->data(index).toReal();
194  QPointF point = coordinatePlane()->translate(QPointF(value, iRow))
195  + ctx->rectangle().topLeft();
196  polygon.append(point);
197  // qDebug() << point;
198  }
199  if (closeDatasets() && !polygon.isEmpty()) {
200  // close the circle by connecting the last data point to the first
201  polygon.append(polygon.first());
202  }
203 
204  PainterSaver painterSaver(ctx->painter());
205  ctx->painter()->setRenderHint(QPainter::Antialiasing);
206  ctx->painter()->setBrush(brush);
207  QPen p = d->datasetAttrs(iCol, KDChart::DatasetPenRole).value<QPen>();
208  if (p.style() != Qt::NoPen) {
209  ctx->painter()->setPen(PrintingParameters::scalePen(p));
210  ctx->painter()->drawPolyline(polygon);
211  }
212  }
213  d->paintDataValueTextsAndMarkers(ctx, d->labelPaintCache, true);
214  }
215 }
216 
217 void PolarDiagram::resize(const QSizeF &)
218 {
219 }
220 
221 /*virtual*/
223 {
224  return model()->rowCount(rootIndex());
225 }
226 
227 /*virtual*/
229 {
230  return model() ? model()->rowCount(rootIndex()) : 0.0;
231 }
232 
233 /*virtual*/
235 {
236  return 5; // FIXME
237 }
238 
240 {
241  Q_UNUSED(degrees);
242  qWarning() << "Deprecated PolarDiagram::setZeroDegreePosition() called, setting ignored.";
243 }
244 
246 {
247  qWarning() << "Deprecated PolarDiagram::zeroDegreePosition() called.";
248  return 0;
249 }
250 
251 void PolarDiagram::setRotateCircularLabels(bool rotateCircularLabels)
252 {
253  d->rotateCircularLabels = rotateCircularLabels;
254 }
255 
257 {
258  return d->rotateCircularLabels;
259 }
260 
261 void PolarDiagram::setCloseDatasets(bool closeDatasets)
262 {
263  d->closeDatasets = closeDatasets;
264 }
265 
267 {
268  return d->closeDatasets;
269 }
270 
272  bool showDelimiters)
273 {
274  d->showDelimitersAtPosition[position.value()] = showDelimiters;
275 }
276 
278  bool showLabels)
279 {
280  d->showLabelsAtPosition[position.value()] = showLabels;
281 }
282 
284 {
285  return d->showDelimitersAtPosition[position.value()];
286 }
287 
289 {
290  return d->showLabelsAtPosition[position.value()];
291 }
#define d
virtual const QPointF translate(const QPointF &diagramPoint) const =0
virtual bool checkInvariants(bool justReturnTheStatus=false) const
AbstractCoordinatePlane * coordinatePlane() const
Base class for diagrams based on a polar coordinate system.
Stores information about painting diagrams.
void setPainter(QPainter *painter)
void setRectangle(const QRectF &rect)
const QRectF rectangle() const
QPainter * painter() const
PolarDiagram defines a common polar diagram.
PolarDiagram(QWidget *parent=nullptr, PolarCoordinatePlane *plane=nullptr)
void setShowDelimitersAtPosition(Position position, bool showDelimiters)
void setRotateCircularLabels(bool rotateCircularLabels)
Q_DECL_DEPRECATED int zeroDegreePosition() const
void setShowLabelsAtPosition(Position position, bool showLabels)
void paintEvent(QPaintEvent *) override
virtual PolarDiagram * clone() const
void paint(PaintContext *paintContext) override
qreal numberOfValuesPerDataset() const override
Q_DECL_DEPRECATED void setZeroDegreePosition(int degrees)
void resize(const QSizeF &area) override
virtual void paintPolarMarkers(PaintContext *ctx, const QPolygonF &polygon)
void setCloseDatasets(bool closeDatasets)
void resizeEvent(QResizeEvent *) override
qreal valueTotals() const override
const QPair< QPointF, QPointF > calculateDataBoundaries() const override
qreal numberOfGridRings() const override
bool showDelimitersAtPosition(Position position) const
bool showLabelsAtPosition(Position position) const
Stores the absolute target points of a Position.
Defines a position, using compass terminology.
static const Position & West
static const Position & South
static const Position & Floating
static const Position & North
static const Position & SouthWest
static const Position & NorthEast
static const Position & NorthWest
static const Position & SouthEast
static const Position & East
KDChartEnums::PositionValue value() const
static const Position & Center
static const Position & Unknown
static QPen scalePen(const QPen &pen)
@ DatasetBrushRole
@ DatasetPenRole

© 2001 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/
Generated by doxygen 1.9.1