KD Chart 2  [rev.2.5.1]
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Pages
KDChartPlotter.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 "KDChartPlotter.h"
24 #include "KDChartPlotter_p.h"
25 
26 #include "KDChartAbstractGrid.h"
27 #include "KDChartPainterSaver_p.h"
28 
29 #include <KDABLibFakes>
30 
31 #include "KDChartNormalPlotter_p.h"
32 #include "KDChartPercentPlotter_p.h"
33 
34 using namespace KDChart;
35 
36 Plotter::Private::Private()
37  : implementor( 0 )
38  , normalPlotter( 0 )
39  , percentPlotter( 0 )
40 {
41 }
42 
43 Plotter::Private::~Private()
44 {
45  delete normalPlotter;
46  delete percentPlotter;
47 }
48 
49 
50 #define d d_func()
51 
52 
54  AbstractCartesianDiagram( new Private(), parent, plane )
55 {
56  init();
57 }
58 
59 void Plotter::init()
60 {
61  d->diagram = this;
62  d->normalPlotter = new NormalPlotter( this );
63  d->percentPlotter = new PercentPlotter( this );
64  d->implementor = d->normalPlotter;
65  QObject* test = d->implementor->plotterPrivate();
66  bool connection = connect( this, SIGNAL( boundariesChanged() ), test, SLOT( changedProperties() ) );
67  Q_ASSERT( connection );
68  Q_UNUSED( connection );
69 
71 }
72 
74 {
75 }
76 
81 {
82  Plotter* newDiagram = new Plotter( new Private( *d ) );
83  newDiagram->setType( type() );
84  return newDiagram;
85 }
86 
87 bool Plotter::compare( const Plotter* other ) const
88 {
89  if ( other == this )
90  return true;
91  if ( other == 0 )
92  return false;
93  return // compare the base class
94  ( static_cast< const AbstractCartesianDiagram* >( this )->compare( other ) ) &&
95  // compare own properties
96  ( type() == other->type() );
97 }
98 
99 void Plotter::setModel( QAbstractItemModel *model )
100 {
101  d->plotterCompressor.setModel( NULL );
104  {
105  d->compressor.setModel( NULL );
106  if ( attributesModel() != d->plotterCompressor.model() )
107  {
108  d->plotterCompressor.setModel( attributesModel() );
109  connect( &d->plotterCompressor, SIGNAL( boundariesChanged() ), this, SLOT(setDataBoundariesDirty() ) );
111  {
112  connect( coordinatePlane(), SIGNAL( internal_geometryChanged( QRect,QRect ) ), this, SLOT( setDataBoundariesDirty() ), Qt::QueuedConnection );
113  connect( coordinatePlane(), SIGNAL( geometryChanged( QRect,QRect ) ), this, SLOT( setDataBoundariesDirty() ), Qt::QueuedConnection );
114  calcMergeRadius();
115  }
116  }
117  }
118 }
119 
121 {
122  return d->implementor->useCompression();
123 }
124 
126 {
127  if ( useDataCompression() != value )
128  {
129  d->implementor->setUseCompression( value );
131  {
132  d->compressor.setModel( NULL );
133  if ( attributesModel() != d->plotterCompressor.model() )
134  d->plotterCompressor.setModel( attributesModel() );
135  }
136  }
137 }
138 
140 {
141  return d->plotterCompressor.maxSlopeChange();
142 }
143 
144 void Plotter::setMaxSlopeChange( qreal value )
145 {
146  d->plotterCompressor.setMaxSlopeChange( value );
147 }
148 
149 qreal Plotter::mergeRadiusPercentage() const
150 {
151  return d->mergeRadiusPercentage;
152 }
153 
155 {
156  if ( d->mergeRadiusPercentage != value )
157  {
158  d->mergeRadiusPercentage = value;
159  //d->plotterCompressor.setMergeRadiusPercentage( value );
160  //update();
161  }
162 }
163 
167 void Plotter::setType( const PlotType type )
168 {
169  if ( d->implementor->type() == type ) {
170  return;
171  }
172  if ( datasetDimension() != 2 ) {
173  Q_ASSERT_X ( false, "setType()",
174  "This line chart type can only be used with two-dimensional data." );
175  return;
176  }
177  switch ( type ) {
178  case Normal:
179  d->implementor = d->normalPlotter;
180  break;
181  case Percent:
182  d->implementor = d->percentPlotter;
183  break;
184  default:
185  Q_ASSERT_X( false, "Plotter::setType", "unknown plotter subtype" );
186  }
187  bool connection = connect( this, SIGNAL( boundariesChanged() ),
188  d->implementor->plotterPrivate(), SLOT( changedProperties() ) );
189  Q_ASSERT( connection );
190  Q_UNUSED( connection );
191 
192  // d->lineType = type;
193  Q_ASSERT( d->implementor->type() == type );
194 
196  emit layoutChanged( this );
197  emit propertiesChanged();
198 }
199 
204 {
205  return d->implementor->type();
206 }
207 
212 {
213  d->attributesModel->setModelData( qVariantFromValue( la ), LineAttributesRole );
214  emit propertiesChanged();
215 }
216 
220 void Plotter::setLineAttributes( int column, const LineAttributes& la )
221 {
222  d->setDatasetAttrs( column, qVariantFromValue( la ), LineAttributesRole );
223  emit propertiesChanged();
224 }
225 
230 {
231  d->resetDatasetAttrs( column, LineAttributesRole );
232  emit propertiesChanged();
233 }
234 
238 void Plotter::setLineAttributes( const QModelIndex & index, const LineAttributes& la )
239 {
240  d->attributesModel->setData( d->attributesModel->mapFromSource( index ),
241  qVariantFromValue( la ), LineAttributesRole );
242  emit propertiesChanged();
243 }
244 
248 void Plotter::resetLineAttributes( const QModelIndex & index )
249 {
250  d->attributesModel->resetData(
251  d->attributesModel->mapFromSource(index), LineAttributesRole );
252  emit propertiesChanged();
253 }
254 
259 {
260  return d->attributesModel->data( KDChart::LineAttributesRole ).value<LineAttributes>();
261 }
262 
267 {
268  const QVariant attrs( d->datasetAttrs( column, LineAttributesRole ) );
269  if ( attrs.isValid() )
270  return attrs.value<LineAttributes>();
271  return lineAttributes();
272 }
273 
277 LineAttributes Plotter::lineAttributes( const QModelIndex& index ) const
278 {
279  return d->attributesModel->data(
280  d->attributesModel->mapFromSource( index ), KDChart::LineAttributesRole ).value<LineAttributes>();
281 }
282 
287 {
289  d->attributesModel->setModelData( qVariantFromValue( la ), ThreeDLineAttributesRole );
290  emit propertiesChanged();
291 }
292 
297 {
299  d->setDatasetAttrs( column, qVariantFromValue( la ), ThreeDLineAttributesRole );
300  emit propertiesChanged();
301 }
302 
306 void Plotter::setThreeDLineAttributes( const QModelIndex& index, const ThreeDLineAttributes& la )
307 {
309  d->attributesModel->setData( d->attributesModel->mapFromSource( index ), qVariantFromValue( la ),
311  emit propertiesChanged();
312 }
313 
318 {
319  return d->attributesModel->data( KDChart::ThreeDLineAttributesRole ).value<ThreeDLineAttributes>();
320 }
321 
326 {
327  const QVariant attrs( d->datasetAttrs( column, ThreeDLineAttributesRole ) );
328  if ( attrs.isValid() ) {
329  return attrs.value<ThreeDLineAttributes>();
330  }
331  return threeDLineAttributes();
332 }
333 
337 ThreeDLineAttributes Plotter::threeDLineAttributes( const QModelIndex& index ) const
338 {
339  return d->attributesModel->data(
340  d->attributesModel->mapFromSource( index ), KDChart::ThreeDLineAttributesRole ).value<ThreeDLineAttributes>();
341 }
342 
343 qreal Plotter::threeDItemDepth( const QModelIndex & index ) const
344 {
345  return threeDLineAttributes( index ).validDepth();
346 }
347 
348 qreal Plotter::threeDItemDepth( int column ) const
349 {
350  return threeDLineAttributes( column ).validDepth();
351 }
352 
356 void Plotter::setValueTrackerAttributes( const QModelIndex & index, const ValueTrackerAttributes & va )
357 {
358  d->attributesModel->setData( d->attributesModel->mapFromSource( index ),
359  qVariantFromValue( va ), KDChart::ValueTrackerAttributesRole );
360  emit propertiesChanged();
361 }
362 
366 ValueTrackerAttributes Plotter::valueTrackerAttributes( const QModelIndex & index ) const
367 {
368  return d->attributesModel->data(
369  d->attributesModel->mapFromSource( index ), KDChart::ValueTrackerAttributesRole ).value<ValueTrackerAttributes>();
370 }
371 
372 void Plotter::resizeEvent ( QResizeEvent* )
373 {
374 }
375 
377 {
378  if ( !checkInvariants( true ) )
379  return QPair< QPointF, QPointF >( QPointF( 0, 0 ), QPointF( 0, 0 ) );
380 
381  // note: calculateDataBoundaries() is ignoring the hidden flags.
382  // That's not a bug but a feature: Hiding data does not mean removing them.
383  // For totally removing data from KD Chart's view people can use e.g. a proxy model ...
384 
385  // calculate boundaries for different line types Normal - Stacked - Percent - Default Normal
386  return d->implementor->calculateDataBoundaries();
387 }
388 
389 
390 void Plotter::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 ) ) return;
404 
405  AbstractCoordinatePlane* const plane = ctx->coordinatePlane();
406  if ( ! plane ) return;
407  d->setCompressorResolution( size(), plane );
408 
409  if ( !AbstractGrid::isBoundariesValid(dataBoundaries()) ) return;
410 
411  const PainterSaver p( ctx->painter() );
412  if ( model()->rowCount( rootIndex() ) == 0 || model()->columnCount( rootIndex() ) == 0 )
413  return; // nothing to paint for us
414 
415  ctx->setCoordinatePlane( plane->sharedAxisMasterPlane( ctx->painter() ) );
416 
417  // paint different line types Normal - Stacked - Percent - Default Normal
418  d->implementor->paint( ctx );
419 
420  ctx->setCoordinatePlane( plane );
421 }
422 
423 void Plotter::resize ( const QSizeF& size )
424 {
425  d->setCompressorResolution( size, coordinatePlane() );
427  {
428  d->plotterCompressor.cleanCache();
429  calcMergeRadius();
430  }
432  QAbstractItemView::resize( size.toSize() );
433 }
434 
436 {
439  {
440  calcMergeRadius();
441  //d->plotterCompressor.setMergeRadiusPercentage( d->mergeRadiusPercentage );
442  }
443 }
444 
446 {
448  Q_ASSERT( plane );
449  //Q_ASSERT( plane->translate( plane->translateBack( plane->visibleDiagramArea().topLeft() ) ) == plane->visibleDiagramArea().topLeft() );
450  QRectF range = plane->visibleDataRange();
451  //qDebug() << range;
452  const qreal radius = std::sqrt( ( range.x() + range.width() ) * ( range.y() + range.height() ) );
453  //qDebug() << radius;
454  //qDebug() << radius * d->mergeRadiusPercentage;
455  //qDebug() << d->mergeRadiusPercentage;
456  d->plotterCompressor.setMergeRadius( radius * d->mergeRadiusPercentage );
457 }
458 
459 #if QT_VERSION < 0x040400 || defined(Q_COMPILER_MANGLES_RETURN_TYPE)
460 const
461 #endif
463 {
464  return d->attributesModel->rowCount( attributesModelRootIndex() );
465 }
466 
467 #if QT_VERSION < 0x040400 || defined(Q_COMPILER_MANGLES_RETURN_TYPE)
468 const
469 #endif
471 {
472  return d->attributesModel->columnCount( attributesModelRootIndex() );
473 }

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