KD Chart 2  [rev.2.7]
KDChartLineDiagram.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 "KDChartLineDiagram.h"
24 #include "KDChartLineDiagram_p.h"
25 
26 #include "KDChartBarDiagram.h"
27 #include "KDChartPalette.h"
28 #include "KDChartAttributesModel.h"
29 #include "KDChartAbstractGrid.h"
30 #include "KDChartPainterSaver_p.h"
31 
32 #include <KDABLibFakes>
33 
34 #include "KDChartNormalLineDiagram_p.h"
35 #include "KDChartStackedLineDiagram_p.h"
36 #include "KDChartPercentLineDiagram_p.h"
37 
38 #include <QDebug>
39 #include <QPainter>
40 #include <QString>
41 #include <QPainterPath>
42 #include <QPen>
43 #include <QVector>
44 
45 using namespace KDChart;
46 
47 LineDiagram::Private::Private()
48  : tension(0.0)
49 {
50 }
51 
52 LineDiagram::Private::~Private() {}
53 
54 
55 #define d d_func()
56 
57 
59  AbstractCartesianDiagram( new Private(), parent, plane )
60 {
61  init();
62 }
63 
64 void LineDiagram::init()
65 {
66  d->normalDiagram = new NormalLineDiagram( this );
67  d->stackedDiagram = new StackedLineDiagram( this );
68  d->percentDiagram = new PercentLineDiagram( this );
69  d->implementor = d->normalDiagram;
70  d->centerDataPoints = false;
71  d->reverseDatasetOrder = false;
72 }
73 
75 {
76  delete d->normalDiagram;
77  delete d->stackedDiagram;
78  delete d->percentDiagram;
79 }
80 
85 {
86  LineDiagram* newDiagram = new LineDiagram( new Private( *d ) );
87  newDiagram->setType( type() );
88  return newDiagram;
89 }
90 
91 
92 bool LineDiagram::compare( const LineDiagram* other ) const
93 {
94  if ( other == this ) return true;
95  if ( ! other ) {
96  return false;
97  }
98  return // compare the base class
99  ( static_cast<const AbstractCartesianDiagram*>(this)->compare( other ) ) &&
100  // compare own properties
101  (type() == other->type()) &&
102  (centerDataPoints() == other->centerDataPoints()) &&
104 }
105 
111 {
112  if ( d->implementor->type() == type ) return;
113  if ( type != LineDiagram::Normal && datasetDimension() > 1 ) {
114  Q_ASSERT_X ( false, "setType()",
115  "This line chart type can't be used with multi-dimensional data." );
116  return;
117  }
118  switch ( type ) {
119  case Normal:
120  d->implementor = d->normalDiagram;
121  break;
122  case Stacked:
123  d->implementor = d->stackedDiagram;
124  break;
125  case Percent:
126  d->implementor = d->percentDiagram;
127  break;
128  default:
129  Q_ASSERT_X( false, "LineDiagram::setType", "unknown diagram subtype" );
130  };
131 
132  // d->lineType = type;
133  Q_ASSERT( d->implementor->type() == type );
134 
135  // AbstractAxis settings - see AbstractDiagram and CartesianAxis
138  emit layoutChanged( this );
139  emit propertiesChanged();
140 }
141 
146 {
147  return d->implementor->type();
148 }
149 
151 {
152  if ( d->centerDataPoints == center ) {
153  return;
154  }
155 
156  d->centerDataPoints = center;
157  // The actual data boundaries haven't changed, but the axis will have one more or less tick
158  // A B =\ A B
159  // 1......2 =/ 1......2......3
161  emit layoutChanged( this );
162  emit propertiesChanged();
163 }
164 
166 {
167  return d->centerDataPoints;
168 }
169 
171 {
172  d->reverseDatasetOrder = reverse;
173 }
174 
176 {
177  return d->reverseDatasetOrder;
178 }
179 
184 {
185  d->attributesModel->setModelData(
186  qVariantFromValue( la ),
188  emit propertiesChanged();
189 }
190 
195  int column,
196  const LineAttributes& la )
197 {
198  d->setDatasetAttrs( column, qVariantFromValue( la ), LineAttributesRole );
199  emit propertiesChanged();
200 }
201 
206 {
207  d->resetDatasetAttrs( column, LineAttributesRole );
208  emit propertiesChanged();
209 }
210 
215  const QModelIndex& index,
216  const LineAttributes& la )
217 {
218  d->attributesModel->setData(
219  d->attributesModel->mapFromSource(index),
220  qVariantFromValue( la ),
222  emit propertiesChanged();
223 }
224 
228 void LineDiagram::resetLineAttributes( const QModelIndex & index )
229 {
230  d->attributesModel->resetData(
231  d->attributesModel->mapFromSource(index), LineAttributesRole );
232  emit propertiesChanged();
233 }
234 
239 {
240  return d->attributesModel->data( KDChart::LineAttributesRole ).value<LineAttributes>();
241 }
242 
247 {
248  const QVariant attrs( d->datasetAttrs( column, LineAttributesRole ) );
249  if ( attrs.isValid() )
250  return attrs.value<LineAttributes>();
251  return lineAttributes();
252 }
253 
258  const QModelIndex& index ) const
259 {
260  return d->attributesModel->data(
261  d->attributesModel->mapFromSource(index),
262  KDChart::LineAttributesRole ).value<LineAttributes>();
263 }
264 
269  const ThreeDLineAttributes& la )
270 {
272  d->attributesModel->setModelData(
273  qVariantFromValue( la ),
275  emit propertiesChanged();
276 }
277 
282  int column,
283  const ThreeDLineAttributes& la )
284 {
286  d->setDatasetAttrs( column, qVariantFromValue( la ), ThreeDLineAttributesRole );
287  emit propertiesChanged();
288 }
289 
294  const QModelIndex & index,
295  const ThreeDLineAttributes& la )
296 {
298  d->attributesModel->setData(
299  d->attributesModel->mapFromSource(index),
300  qVariantFromValue( la ),
302  emit propertiesChanged();
303 }
304 
309 {
310  return d->attributesModel->data( KDChart::ThreeDLineAttributesRole ).value<ThreeDLineAttributes>();
311 }
312 
317 {
318  const QVariant attrs( d->datasetAttrs( column, ThreeDLineAttributesRole ) );
319  if ( attrs.isValid() )
320  return attrs.value<ThreeDLineAttributes>();
321  return threeDLineAttributes();
322 }
323 
328 {
329  return d->attributesModel->data(
330  d->attributesModel->mapFromSource( index ),
331  KDChart::ThreeDLineAttributesRole ).value<ThreeDLineAttributes>();
332 }
333 
334 qreal LineDiagram::threeDItemDepth( const QModelIndex& index ) const
335 {
336  return threeDLineAttributes( index ).validDepth();
337 }
338 
339 qreal LineDiagram::threeDItemDepth( int column ) const
340 {
341  return threeDLineAttributes( column ).validDepth();
342 }
343 
347 void LineDiagram::setValueTrackerAttributes( const QModelIndex & index,
348  const ValueTrackerAttributes & va )
349 {
350  d->attributesModel->setData( d->attributesModel->mapFromSource(index),
351  qVariantFromValue( va ),
353  emit propertiesChanged();
354 }
355 
360  const QModelIndex & index ) const
361 {
362  return d->attributesModel->data(
363  d->attributesModel->mapFromSource( index ),
364  KDChart::ValueTrackerAttributesRole ).value<ValueTrackerAttributes>();
365 }
366 
367 
372 {
373  return d->tension;
374 }
375 
376 
377 void LineDiagram::setLineTension( qreal tension )
378 {
379  d->tension = tension;
380  emit propertiesChanged();
381 }
382 
383 
384 
385 void LineDiagram::resizeEvent ( QResizeEvent* )
386 {
387 }
388 
390 {
391  d->compressor.setResolution( static_cast<int>( this->size().width() * coordinatePlane()->zoomFactorX() ),
392  static_cast<int>( this->size().height() * coordinatePlane()->zoomFactorY() ) );
393 
394  if ( !checkInvariants( true ) ) return QPair<QPointF, QPointF>( QPointF( 0, 0 ), QPointF( 0, 0 ) );
395 
396  // note: calculateDataBoundaries() is ignoring the hidden flags.
397  // That's not a bug but a feature: Hiding data does not mean removing them.
398  // For totally removing data from KD Chart's view people can use e.g. a proxy model ...
399 
400  // calculate boundaries for different line types Normal - Stacked - Percent - Default Normal
401  return d->implementor->calculateDataBoundaries();
402 }
403 
404 
405 void LineDiagram::paintEvent ( QPaintEvent*)
406 {
407  QPainter painter ( viewport() );
408  PaintContext ctx;
409  ctx.setPainter ( &painter );
410  ctx.setRectangle ( QRectF ( 0, 0, width(), height() ) );
411  paint ( &ctx );
412 }
413 
415 {
416  // note: Not having any data model assigned is no bug
417  // but we can not draw a diagram then either.
418  if ( !checkInvariants( true ) ) return;
419  if ( !AbstractGrid::isBoundariesValid(dataBoundaries()) ) return;
420  const PainterSaver p( ctx->painter() );
421  if ( model()->rowCount( rootIndex() ) == 0 || model()->columnCount( rootIndex() ) == 0 )
422  return; // nothing to paint for us
423 
424  AbstractCoordinatePlane* const plane = ctx->coordinatePlane();
425  ctx->setCoordinatePlane( plane->sharedAxisMasterPlane( ctx->painter() ) );
426 
427 
428  // paint different line types Normal - Stacked - Percent - Default Normal
429  d->implementor->paint( ctx );
430 
431  ctx->setCoordinatePlane( plane );
432 }
433 
434 void LineDiagram::resize ( const QSizeF& size )
435 {
436  d->compressor.setResolution( static_cast<int>( size.width() * coordinatePlane()->zoomFactorX() ),
437  static_cast<int>( size.height() * coordinatePlane()->zoomFactorY() ) );
439  QAbstractItemView::resize( size.toSize() );
440 }
441 
442 #if QT_VERSION < 0x040400 || defined(Q_COMPILER_MANGLES_RETURN_TYPE)
443 const
444 #endif
446 {
447  return d->attributesModel->rowCount(attributesModelRootIndex());
448 }
449 
450 #if QT_VERSION < 0x040400 || defined(Q_COMPILER_MANGLES_RETURN_TYPE)
451 const
452 #endif
454 {
455  return d->attributesModel->columnCount(attributesModelRootIndex());
456 }
void setLineAttributes(const LineAttributes &a)
Sets the global line attributes to la.
Base class common for all coordinate planes, CartesianCoordinatePlane, PolarCoordinatePlane, TernaryCoordinatePlane.
virtual AbstractCoordinatePlane * sharedAxisMasterPlane(QPainter *p=0)
void setPainter(QPainter *painter)
void setType(const LineType type)
Sets the line diagram&#39;s type to type.
virtual bool checkInvariants(bool justReturnTheStatus=false) const
void resetLineAttributes(int column)
Resets the line attributes of data set column.
AbstractCoordinatePlane * coordinatePlane() const
LineDiagram(QWidget *parent=0, CartesianCoordinatePlane *plane=0)
const int numberOfAbscissaSegments() const
void setPercentMode(bool percent)
Deprecated method that turns the percent mode of this diagram on or off.
QPainter * painter() const
void setReverseDatasetOrder(bool reverse)
With this property set to true, data sets in a normal line diagram are drawn in reversed order...
void paint(PaintContext *paintContext) override
Draw the diagram contents to the rectangle and painter, that are passed in as part of the paint conte...
void resize(const QSizeF &area) override
Called by the widget&#39;s sizeEvent.
AbstractCoordinatePlane * coordinatePlane() const
The coordinate plane associated with the diagram.
void setLineTension(qreal tenson)
This property defines the strength of the line curvature - 0 for straight lines between data points...
qreal lineTension() const
Returns whether the lines are drawn smoothed.
ThreeDLineAttributes threeDLineAttributes() const
Set of attributes for changing the appearance of line charts.
ValueTrackerAttributes valueTrackerAttributes(const QModelIndex &index) const
Returns the value tracker attributes of the model index index.
void resizeEvent(QResizeEvent *) override
const QPair< QPointF, QPointF > dataBoundaries() const
Return the bottom left and top right data point, that the diagram will display (unless the grid adjus...
void paintEvent(QPaintEvent *) override
#define d
void propertiesChanged()
Emitted upon change of a property of the Diagram.
LineDiagram defines a common line diagram.
Cell-specific attributes regarding value tracking.
Base class for diagrams based on a cartesian coordianate system.
Stores information about painting diagrams.
virtual LineDiagram * clone() const
Creates an exact copy of this diagram.
void layoutChanged(AbstractDiagram *)
Diagrams are supposed to emit this signal, when the layout of one of their element changes...
void setThreeDLineAttributes(const ThreeDLineAttributes &a)
Sets the global 3D line attributes to la.
QModelIndex attributesModelRootIndex() const
const QPair< QPointF, QPointF > calculateDataBoundaries() const override
[reimplemented]
LineAttributes lineAttributes() const
void setCenterDataPoints(bool center)
If centerDataPoints() is true, all data points are moved by an offset of 0.5 to the right...
void setCoordinatePlane(AbstractCoordinatePlane *plane)
void setRectangle(const QRectF &rect)
Class only listed here to document inheritance of some KDChart classes.
bool reverseDatasetOrder() const
int datasetDimension() const
The dataset dimension of a diagram determines how many value dimensions it expects each datapoint to ...
const int numberOfOrdinateSegments() const
void setValueTrackerAttributes(const QModelIndex &index, const ValueTrackerAttributes &a)
Sets the value tracker attributes of the model index index to va.
qreal threeDItemDepth(const QModelIndex &index) const override
A set of 3D line attributes.
bool compare(const LineDiagram *other) const
Returns true if both diagrams have the same settings.

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/