KD Chart 2  [rev.2.5.1]
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Pages
KDChartLineDiagram.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 ** Copyright (C) 2001-2013 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 {
49 }
50 
51 LineDiagram::Private::~Private() {}
52 
53 
54 #define d d_func()
55 
56 
58  AbstractCartesianDiagram( new Private(), parent, plane )
59 {
60  init();
61 }
62 
63 void LineDiagram::init()
64 {
65  d->normalDiagram = new NormalLineDiagram( this );
66  d->stackedDiagram = new StackedLineDiagram( this );
67  d->percentDiagram = new PercentLineDiagram( this );
68  d->implementor = d->normalDiagram;
69  d->centerDataPoints = false;
70  d->reverseDatasetOrder = false;
71 }
72 
74 {
75  delete d->normalDiagram;
76  delete d->stackedDiagram;
77  delete d->percentDiagram;
78 }
79 
84 {
85  LineDiagram* newDiagram = new LineDiagram( new Private( *d ) );
86  newDiagram->setType( type() );
87  return newDiagram;
88 }
89 
90 
91 bool LineDiagram::compare( const LineDiagram* other ) const
92 {
93  if ( other == this ) return true;
94  if ( ! other ) {
95  return false;
96  }
97  return // compare the base class
98  ( static_cast<const AbstractCartesianDiagram*>(this)->compare( other ) ) &&
99  // compare own properties
100  (type() == other->type()) &&
101  (centerDataPoints() == other->centerDataPoints()) &&
103 }
104 
109 void LineDiagram::setType( const LineType type )
110 {
111  if ( d->implementor->type() == type ) return;
112  if ( type != LineDiagram::Normal && datasetDimension() > 1 ) {
113  Q_ASSERT_X ( false, "setType()",
114  "This line chart type can't be used with multi-dimensional data." );
115  return;
116  }
117  switch ( type ) {
118  case Normal:
119  d->implementor = d->normalDiagram;
120  break;
121  case Stacked:
122  d->implementor = d->stackedDiagram;
123  break;
124  case Percent:
125  d->implementor = d->percentDiagram;
126  break;
127  default:
128  Q_ASSERT_X( false, "LineDiagram::setType", "unknown diagram subtype" );
129  };
130 
131  // d->lineType = type;
132  Q_ASSERT( d->implementor->type() == type );
133 
134  // AbstractAxis settings - see AbstractDiagram and CartesianAxis
137  emit layoutChanged( this );
138  emit propertiesChanged();
139 }
140 
145 {
146  return d->implementor->type();
147 }
148 
150 {
151  d->centerDataPoints = center;
152  emit propertiesChanged();
153 }
154 
156 {
157  return d->centerDataPoints;
158 }
159 
161 {
162  d->reverseDatasetOrder = reverse;
163 }
164 
166 {
167  return d->reverseDatasetOrder;
168 }
169 
174 {
175  d->attributesModel->setModelData(
176  qVariantFromValue( la ),
178  emit propertiesChanged();
179 }
180 
185  int column,
186  const LineAttributes& la )
187 {
188  d->setDatasetAttrs( column, qVariantFromValue( la ), LineAttributesRole );
189  emit propertiesChanged();
190 }
191 
196 {
197  d->resetDatasetAttrs( column, LineAttributesRole );
198  emit propertiesChanged();
199 }
200 
205  const QModelIndex& index,
206  const LineAttributes& la )
207 {
208  d->attributesModel->setData(
209  d->attributesModel->mapFromSource(index),
210  qVariantFromValue( la ),
212  emit propertiesChanged();
213 }
214 
218 void LineDiagram::resetLineAttributes( const QModelIndex & index )
219 {
220  d->attributesModel->resetData(
221  d->attributesModel->mapFromSource(index), LineAttributesRole );
222  emit propertiesChanged();
223 }
224 
229 {
230  return d->attributesModel->data( KDChart::LineAttributesRole ).value<LineAttributes>();
231 }
232 
237 {
238  const QVariant attrs( d->datasetAttrs( column, LineAttributesRole ) );
239  if ( attrs.isValid() )
240  return attrs.value<LineAttributes>();
241  return lineAttributes();
242 }
243 
248  const QModelIndex& index ) const
249 {
250  return d->attributesModel->data(
251  d->attributesModel->mapFromSource(index),
252  KDChart::LineAttributesRole ).value<LineAttributes>();
253 }
254 
259  const ThreeDLineAttributes& la )
260 {
262  d->attributesModel->setModelData(
263  qVariantFromValue( la ),
265  emit propertiesChanged();
266 }
267 
272  int column,
273  const ThreeDLineAttributes& la )
274 {
276  d->setDatasetAttrs( column, qVariantFromValue( la ), ThreeDLineAttributesRole );
277  emit propertiesChanged();
278 }
279 
284  const QModelIndex & index,
285  const ThreeDLineAttributes& la )
286 {
288  d->attributesModel->setData(
289  d->attributesModel->mapFromSource(index),
290  qVariantFromValue( la ),
292  emit propertiesChanged();
293 }
294 
299 {
300  return d->attributesModel->data( KDChart::ThreeDLineAttributesRole ).value<ThreeDLineAttributes>();
301 }
302 
307 {
308  const QVariant attrs( d->datasetAttrs( column, ThreeDLineAttributesRole ) );
309  if ( attrs.isValid() )
310  return attrs.value<ThreeDLineAttributes>();
311  return threeDLineAttributes();
312 }
313 
318 {
319  return d->attributesModel->data(
320  d->attributesModel->mapFromSource( index ),
321  KDChart::ThreeDLineAttributesRole ).value<ThreeDLineAttributes>();
322 }
323 
324 qreal LineDiagram::threeDItemDepth( const QModelIndex& index ) const
325 {
326  return threeDLineAttributes( index ).validDepth();
327 }
328 
329 qreal LineDiagram::threeDItemDepth( int column ) const
330 {
331  return threeDLineAttributes( column ).validDepth();
332 }
333 
337 void LineDiagram::setValueTrackerAttributes( const QModelIndex & index,
338  const ValueTrackerAttributes & va )
339 {
340  d->attributesModel->setData( d->attributesModel->mapFromSource(index),
341  qVariantFromValue( va ),
343  emit propertiesChanged();
344 }
345 
350  const QModelIndex & index ) const
351 {
352  return d->attributesModel->data(
353  d->attributesModel->mapFromSource( index ),
354  KDChart::ValueTrackerAttributesRole ).value<ValueTrackerAttributes>();
355 }
356 
357 void LineDiagram::resizeEvent ( QResizeEvent* )
358 {
359 }
360 
362 {
363  d->compressor.setResolution( static_cast<int>( this->size().width() * coordinatePlane()->zoomFactorX() ),
364  static_cast<int>( this->size().height() * coordinatePlane()->zoomFactorY() ) );
365 
366  if ( !checkInvariants( true ) ) return QPair<QPointF, QPointF>( QPointF( 0, 0 ), QPointF( 0, 0 ) );
367 
368  // note: calculateDataBoundaries() is ignoring the hidden flags.
369  // That's not a bug but a feature: Hiding data does not mean removing them.
370  // For totally removing data from KD Chart's view people can use e.g. a proxy model ...
371 
372  // calculate boundaries for different line types Normal - Stacked - Percent - Default Normal
373  return d->implementor->calculateDataBoundaries();
374 }
375 
376 
377 void LineDiagram::paintEvent ( QPaintEvent*)
378 {
379  QPainter painter ( viewport() );
380  PaintContext ctx;
381  ctx.setPainter ( &painter );
382  ctx.setRectangle ( QRectF ( 0, 0, width(), height() ) );
383  paint ( &ctx );
384 }
385 
386 
387 qreal LineDiagram::valueForCellTesting( int row, int column,
388  bool& bOK,
389  bool showHiddenCellsAsInvalid ) const
390 {
391  if ( !model()->hasIndex( row, column, rootIndex() ) ) {
392  bOK = false;
393  return 0.0;
394  }
395  qreal value;
396  if ( showHiddenCellsAsInvalid && isHidden( model()->index( row, column, rootIndex() ) ) ) // checked
397  bOK = false;
398  else
399  value = d->attributesModel->data(
400  d->attributesModel->index( row, column, attributesModelRootIndex() ) // checked
401  ).toReal( &bOK );
402  return bOK ? value : 0.0;
403 }
404 
406  int row, int column,
407  bool shiftCountedXValuesByHalfSection,
408  qreal& valueX, qreal& valueY ) const
409 {
411 
412  bool bOK = true;
413  valueX = ( datasetDimension() > 1 && column > 0 )
414  ? valueForCellTesting( row, column-1, bOK, true )
415  : ((shiftCountedXValuesByHalfSection ? 0.5 : 0.0) + row);
416  if ( bOK )
417  valueY = valueForCellTesting( row, column, bOK, true );
418  else if ( model()->hasIndex( row, column, rootIndex() ) ) {
419  // missing value: find out the policy
420  QModelIndex index = model()->index( row, column, rootIndex() ); // checked
421  LineAttributes la = lineAttributes( index );
422  policy = la.missingValuesPolicy();
423  }
424  return policy;
425 }
426 
428 {
429  // note: Not having any data model assigned is no bug
430  // but we can not draw a diagram then either.
431  if ( !checkInvariants( true ) ) return;
432  if ( !AbstractGrid::isBoundariesValid(dataBoundaries()) ) return;
433  const PainterSaver p( ctx->painter() );
434  if ( model()->rowCount( rootIndex() ) == 0 || model()->columnCount( rootIndex() ) == 0 )
435  return; // nothing to paint for us
436 
437  AbstractCoordinatePlane* const plane = ctx->coordinatePlane();
438  ctx->setCoordinatePlane( plane->sharedAxisMasterPlane( ctx->painter() ) );
439 
440 
441  // paint different line types Normal - Stacked - Percent - Default Normal
442  d->implementor->paint( ctx );
443 
444  ctx->setCoordinatePlane( plane );
445 }
446 
447 void LineDiagram::resize ( const QSizeF& size )
448 {
449  d->compressor.setResolution( static_cast<int>( size.width() * coordinatePlane()->zoomFactorX() ),
450  static_cast<int>( size.height() * coordinatePlane()->zoomFactorY() ) );
452  QAbstractItemView::resize( size.toSize() );
453 }
454 
455 #if QT_VERSION < 0x040400 || defined(Q_COMPILER_MANGLES_RETURN_TYPE)
456 const
457 #endif
459 {
460  return d->attributesModel->rowCount(attributesModelRootIndex());
461 }
462 
463 #if QT_VERSION < 0x040400 || defined(Q_COMPILER_MANGLES_RETURN_TYPE)
464 const
465 #endif
467 {
468  return d->attributesModel->columnCount(attributesModelRootIndex());
469 }

Klarälvdalens Datakonsult AB (KDAB)
Qt-related services and products
http://www.kdab.com/
http://www.kdab.com/products/kd-chart/