KD Chart API Documentation  3.1
KDChartLineDiagram.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 "KDChartLineDiagram.h"
12 #include "KDChartLineDiagram_p.h"
13 
14 #include "KDChartAbstractGrid.h"
15 #include "KDChartAttributesModel.h"
16 #include "KDChartBarDiagram.h"
17 #include "KDChartPainterSaver_p.h"
18 #include "KDChartPalette.h"
19 
20 #include <KDABLibFakes>
21 
22 #include "KDChartNormalLineDiagram_p.h"
23 #include "KDChartPercentLineDiagram_p.h"
24 #include "KDChartStackedLineDiagram_p.h"
25 
26 #include <QDebug>
27 #include <QPainter>
28 #include <QPainterPath>
29 #include <QPen>
30 #include <QString>
31 #include <QVector>
32 
33 using namespace KDChart;
34 
35 LineDiagram::Private::Private()
36 {
37 }
38 
39 LineDiagram::Private::~Private()
40 {
41 }
42 
43 #define d d_func()
44 
46  : AbstractCartesianDiagram(new Private(), parent, plane)
47 {
48  init();
49 }
50 
51 void LineDiagram::init()
52 {
53  d->normalDiagram = new NormalLineDiagram(this);
54  d->stackedDiagram = new StackedLineDiagram(this);
55  d->percentDiagram = new PercentLineDiagram(this);
56  d->implementor = d->normalDiagram;
57  d->centerDataPoints = false;
58  d->reverseDatasetOrder = false;
59 }
60 
62 {
63  delete d->normalDiagram;
64  delete d->stackedDiagram;
65  delete d->percentDiagram;
66 }
67 
72 {
73  auto *newDiagram = new LineDiagram(new Private(*d));
74  newDiagram->setType(type());
75  return newDiagram;
76 }
77 
78 bool LineDiagram::compare(const LineDiagram *other) const
79 {
80  if (other == this)
81  return true;
82  if (!other) {
83  return false;
84  }
85  return // compare the base class
86  (static_cast<const AbstractCartesianDiagram *>(this)->compare(other)) &&
87  // compare own properties
88  (type() == other->type()) && (centerDataPoints() == other->centerDataPoints()) && (reverseDatasetOrder() == other->reverseDatasetOrder());
89 }
90 
96 {
97  if (d->implementor->type() == type)
98  return;
99  if (type != LineDiagram::Normal && datasetDimension() > 1) {
100  Q_ASSERT_X(false, "setType()",
101  "This line chart type can't be used with multi-dimensional data.");
102  return;
103  }
104  switch (type) {
105  case Normal:
106  d->implementor = d->normalDiagram;
107  break;
108  case Stacked:
109  d->implementor = d->stackedDiagram;
110  break;
111  case Percent:
112  d->implementor = d->percentDiagram;
113  break;
114  default:
115  Q_ASSERT_X(false, "LineDiagram::setType", "unknown diagram subtype");
116  };
117 
118  // d->lineType = type;
119  Q_ASSERT(d->implementor->type() == type);
120 
121  // AbstractAxis settings - see AbstractDiagram and CartesianAxis
124  Q_EMIT layoutChanged(this);
125  Q_EMIT propertiesChanged();
126 }
127 
132 {
133  return d->implementor->type();
134 }
135 
137 {
138  if (d->centerDataPoints == center) {
139  return;
140  }
141 
142  d->centerDataPoints = center;
143  // The actual data boundaries haven't changed, but the axis will have one more or less tick
144  // A B =\ A B
145  // 1......2 =/ 1......2......3
147  Q_EMIT layoutChanged(this);
148  Q_EMIT propertiesChanged();
149 }
150 
152 {
153  return d->centerDataPoints;
154 }
155 
157 {
158  d->reverseDatasetOrder = reverse;
159 }
160 
162 {
163  return d->reverseDatasetOrder;
164 }
165 
170 {
171  d->attributesModel->setModelData(
172  QVariant::fromValue(la),
174  Q_EMIT propertiesChanged();
175 }
176 
181  int column,
182  const LineAttributes &la)
183 {
184  d->setDatasetAttrs(column, QVariant::fromValue(la), LineAttributesRole);
185  Q_EMIT propertiesChanged();
186 }
187 
192 {
193  d->resetDatasetAttrs(column, LineAttributesRole);
194  Q_EMIT propertiesChanged();
195 }
196 
201  const QModelIndex &index,
202  const LineAttributes &la)
203 {
204  d->attributesModel->setData(
205  d->attributesModel->mapFromSource(index),
206  QVariant::fromValue(la),
208  Q_EMIT propertiesChanged();
209 }
210 
214 void LineDiagram::resetLineAttributes(const QModelIndex &index)
215 {
216  d->attributesModel->resetData(
217  d->attributesModel->mapFromSource(index), LineAttributesRole);
218  Q_EMIT propertiesChanged();
219 }
220 
225 {
226  return d->attributesModel->data(KDChart::LineAttributesRole).value<LineAttributes>();
227 }
228 
233 {
234  const QVariant attrs(d->datasetAttrs(column, LineAttributesRole));
235  if (attrs.isValid())
236  return attrs.value<LineAttributes>();
237  return lineAttributes();
238 }
239 
244  const QModelIndex &index) const
245 {
246  return d->attributesModel->data(
247  d->attributesModel->mapFromSource(index),
249  .value<LineAttributes>();
250 }
251 
256  const ThreeDLineAttributes &la)
257 {
259  d->attributesModel->setModelData(
260  QVariant::fromValue(la),
262  Q_EMIT propertiesChanged();
263 }
264 
269  int column,
270  const ThreeDLineAttributes &la)
271 {
273  d->setDatasetAttrs(column, QVariant::fromValue(la), ThreeDLineAttributesRole);
274  Q_EMIT propertiesChanged();
275 }
276 
281  const QModelIndex &index,
282  const ThreeDLineAttributes &la)
283 {
285  d->attributesModel->setData(
286  d->attributesModel->mapFromSource(index),
287  QVariant::fromValue(la),
289  Q_EMIT propertiesChanged();
290 }
291 
296 {
297  return d->attributesModel->data(KDChart::ThreeDLineAttributesRole).value<ThreeDLineAttributes>();
298 }
299 
304 {
305  const QVariant attrs(d->datasetAttrs(column, ThreeDLineAttributesRole));
306  if (attrs.isValid())
307  return attrs.value<ThreeDLineAttributes>();
308  return threeDLineAttributes();
309 }
310 
315 {
316  return d->attributesModel->data(
317  d->attributesModel->mapFromSource(index),
319  .value<ThreeDLineAttributes>();
320 }
321 
322 qreal LineDiagram::threeDItemDepth(const QModelIndex &index) const
323 {
324  return threeDLineAttributes(index).validDepth();
325 }
326 
327 qreal LineDiagram::threeDItemDepth(int column) const
328 {
329  return threeDLineAttributes(column).validDepth();
330 }
331 
335 void LineDiagram::setValueTrackerAttributes(const QModelIndex &index,
336  const ValueTrackerAttributes &va)
337 {
338  d->attributesModel->setData(d->attributesModel->mapFromSource(index),
339  QVariant::fromValue(va),
341  Q_EMIT propertiesChanged();
342 }
343 
348  const QModelIndex &index) const
349 {
350  return d->attributesModel->data(
351  d->attributesModel->mapFromSource(index),
353  .value<ValueTrackerAttributes>();
354 }
355 
360 {
361  return d->tension;
362 }
363 
364 void LineDiagram::setLineTension(qreal tension)
365 {
366  d->tension = tension;
367  Q_EMIT propertiesChanged();
368 }
369 
370 void LineDiagram::resizeEvent(QResizeEvent *)
371 {
372 }
373 
374 const QPair<QPointF, QPointF> LineDiagram::calculateDataBoundaries() const
375 {
376  d->compressor.setResolution(static_cast<int>(this->size().width() * coordinatePlane()->zoomFactorX()),
377  static_cast<int>(this->size().height() * coordinatePlane()->zoomFactorY()));
378 
379  if (!checkInvariants(true))
380  return QPair<QPointF, QPointF>(QPointF(0, 0), QPointF(0, 0));
381 
382  // note: calculateDataBoundaries() is ignoring the hidden flags.
383  // That's not a bug but a feature: Hiding data does not mean removing them.
384  // For totally removing data from KD Chart's view people can use e.g. a proxy model ...
385 
386  // calculate boundaries for different line types Normal - Stacked - Percent - Default Normal
387  return d->implementor->calculateDataBoundaries();
388 }
389 
390 void LineDiagram::paintEvent(QPaintEvent *)
391 {
392  QPainter painter(viewport());
393  PaintContext ctx;
394  ctx.setPainter(&painter);
395  ctx.setRectangle(QRectF(0, 0, width(), height()));
396  paint(&ctx);
397 }
398 
400 {
401  // note: Not having any data model assigned is no bug
402  // but we can not draw a diagram then either.
403  if (!checkInvariants(true))
404  return;
406  return;
407  const PainterSaver p(ctx->painter());
408  if (model()->rowCount(rootIndex()) == 0 || model()->columnCount(rootIndex()) == 0)
409  return; // nothing to paint for us
410 
411  AbstractCoordinatePlane *const plane = ctx->coordinatePlane();
412  ctx->setCoordinatePlane(plane->sharedAxisMasterPlane(ctx->painter()));
413 
414  // paint different line types Normal - Stacked - Percent - Default Normal
415  d->implementor->paint(ctx);
416 
417  ctx->setCoordinatePlane(plane);
418 }
419 
420 void LineDiagram::resize(const QSizeF &size)
421 {
422  d->compressor.setResolution(static_cast<int>(size.width() * coordinatePlane()->zoomFactorX()),
423  static_cast<int>(size.height() * coordinatePlane()->zoomFactorY()));
425  QAbstractItemView::resize(size.toSize());
426 }
427 
428 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) && defined(Q_COMPILER_MANGLES_RETURN_TYPE)
429 const
430 #endif
431  int
433 {
434  return d->attributesModel->rowCount(attributesModelRootIndex());
435 }
436 
437 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) && defined(Q_COMPILER_MANGLES_RETURN_TYPE)
438 const
439 #endif
440  int
442 {
443  return d->attributesModel->columnCount(attributesModelRootIndex());
444 }
#define d
Base class for diagrams based on a cartesian coordianate system.
Base class common for all coordinate planes, CartesianCoordinatePlane, PolarCoordinatePlane,...
virtual AbstractCoordinatePlane * sharedAxisMasterPlane(QPainter *p=nullptr)
virtual bool checkInvariants(bool justReturnTheStatus=false) const
void layoutChanged(AbstractDiagram *)
QModelIndex attributesModelRootIndex() const
returns a QModelIndex pointing into the AttributesModel that corresponds to the root index of the dia...
const QPair< QPointF, QPointF > dataBoundaries() const
Return the bottom left and top right data point, that the diagram will display (unless the grid adjus...
AbstractCoordinatePlane * coordinatePlane() const
Q_DECL_DEPRECATED void setPercentMode(bool percent)
Deprecated method that turns the percent mode of this diagram on or off.
static bool isBoundariesValid(const QRectF &r)
Set of attributes for changing the appearance of line charts.
LineDiagram defines a common line diagram.
void setType(const LineType type)
LineAttributes lineAttributes() const
void resizeEvent(QResizeEvent *) override
void setLineAttributes(const LineAttributes &a)
void setLineTension(qreal tenson)
LineDiagram(QWidget *parent=nullptr, CartesianCoordinatePlane *plane=nullptr)
int numberOfAbscissaSegments() const override
void paintEvent(QPaintEvent *) override
void setCenterDataPoints(bool center)
void setValueTrackerAttributes(const QModelIndex &index, const ValueTrackerAttributes &a)
qreal threeDItemDepth(const QModelIndex &index) const override
void setThreeDLineAttributes(const ThreeDLineAttributes &a)
virtual LineDiagram * clone() const
void resize(const QSizeF &area) override
ThreeDLineAttributes threeDLineAttributes() const
const QPair< QPointF, QPointF > calculateDataBoundaries() const override
void resetLineAttributes(int column)
void setReverseDatasetOrder(bool reverse)
void paint(PaintContext *paintContext) override
ValueTrackerAttributes valueTrackerAttributes(const QModelIndex &index) const
int numberOfOrdinateSegments() const override
bool compare(const LineDiagram *other) const
Stores information about painting diagrams.
void setPainter(QPainter *painter)
void setCoordinatePlane(AbstractCoordinatePlane *plane)
void setRectangle(const QRectF &rect)
AbstractCoordinatePlane * coordinatePlane() const
QPainter * painter() const
Cell-specific attributes regarding value tracking.
@ LineAttributesRole
@ ThreeDLineAttributesRole
@ ValueTrackerAttributesRole

© 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