KChart

KChartAbstractDiagram.cpp
1 /*
2  * Copyright (C) 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved.
3  *
4  * This file is part of the KD Chart library.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of
9  * the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <https://www.gnu.org/licenses/>.
18  */
19 
20 #include "KChartAbstractDiagram.h"
21 #include "KChartAbstractDiagram_p.h"
22 
23 #include <QPainter>
24 #include <QPainterPath>
25 #include <QDebug>
26 #include <QApplication>
27 #include <QAbstractProxyModel>
28 #include <QSizeF>
29 #include <QPainterPath>
30 
31 #include "KChartAbstractCoordinatePlane.h"
32 #include "KChartChart.h"
34 #include "KChartTextAttributes.h"
35 #include "KChartMarkerAttributes.h"
36 #include "KChartAbstractThreeDAttributes.h"
37 #include "KChartThreeDLineAttributes.h"
38 #include "KChartPainterSaver_p.h"
39 
40 #include <limits>
41 
42 using namespace KChart;
43 
44 #define d d_func()
45 
46 AbstractDiagram::AbstractDiagram ( QWidget* parent, AbstractCoordinatePlane* plane )
47  : QAbstractItemView ( parent ), _d( new Private() )
48 {
49  _d->init( plane );
50  init();
51 }
52 
53 AbstractDiagram::~AbstractDiagram()
54 {
55  emit aboutToBeDestroyed();
56  delete _d;
57 }
58 
59 void AbstractDiagram::init()
60 {
61  _d->diagram = this;
62  d->reverseMapper.setDiagram( this );
63 }
64 
65 
66 bool AbstractDiagram::compare( const AbstractDiagram* other ) const
67 {
68  if ( other == this ) return true;
69  if ( !other ) {
70  return false;
71  }
72  return // compare QAbstractScrollArea properties
73  (horizontalScrollBarPolicy() == other->horizontalScrollBarPolicy()) &&
74  (verticalScrollBarPolicy() == other->verticalScrollBarPolicy()) &&
75  // compare QFrame properties
76  (frameShadow() == other->frameShadow()) &&
77  (frameShape() == other->frameShape()) &&
78 // frameWidth is a read-only property defined by the style, it should not be in here:
79  // (frameWidth() == other->frameWidth()) &&
80  (lineWidth() == other->lineWidth()) &&
81  (midLineWidth() == other->midLineWidth()) &&
82  // compare QAbstractItemView properties
83  (alternatingRowColors() == other->alternatingRowColors()) &&
84  (hasAutoScroll() == other->hasAutoScroll()) &&
85  (dragDropMode() == other->dragDropMode()) &&
86  (dragDropOverwriteMode() == other->dragDropOverwriteMode()) &&
87  (horizontalScrollMode() == other->horizontalScrollMode ()) &&
88  (verticalScrollMode() == other->verticalScrollMode()) &&
89  (dragEnabled() == other->dragEnabled()) &&
90  (editTriggers() == other->editTriggers()) &&
91  (iconSize() == other->iconSize()) &&
92  (selectionBehavior() == other->selectionBehavior()) &&
93  (selectionMode() == other->selectionMode()) &&
94  (showDropIndicator() == other->showDropIndicator()) &&
95  (tabKeyNavigation() == other->tabKeyNavigation()) &&
96  (textElideMode() == other->textElideMode()) &&
97  // compare all of the properties stored in the attributes model
98  attributesModel()->compare( other->attributesModel() ) &&
99  // compare own properties
100  (rootIndex().column() == other->rootIndex().column()) &&
101  (rootIndex().row() == other->rootIndex().row()) &&
102  (allowOverlappingDataValueTexts() == other->allowOverlappingDataValueTexts()) &&
103  (antiAliasing() == other->antiAliasing()) &&
104  (percentMode() == other->percentMode()) &&
105  (datasetDimension() == other->datasetDimension());
106 }
107 
109 {
110  return d->plane;
111 }
112 
114 {
115  if ( d->databoundariesDirty ) {
116  d->databoundaries = calculateDataBoundaries ();
117  d->databoundariesDirty = false;
118  }
119  return d->databoundaries;
120 }
121 
122 void AbstractDiagram::setDataBoundariesDirty() const
123 {
124  d->databoundariesDirty = true;
125  update();
126 }
127 
129 {
130  d->diagramSize = size;
132 }
133 
135 {
136  if ( newModel == model() ) {
137  return;
138  }
139 
140  AttributesModel* amodel = new PrivateAttributesModel( newModel, this );
141  amodel->initFrom( d->attributesModel );
142  d->setAttributesModel(amodel);
143 
144  QAbstractItemView::setModel( newModel );
145 
146  scheduleDelayedItemsLayout();
147  setDataBoundariesDirty();
148  emit modelsChanged();
149 }
150 
152 {
153  if ( selectionModel() )
154  {
155  disconnect( selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SIGNAL(modelsChanged()) );
156  disconnect( selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SIGNAL(modelsChanged()) );
157  }
158  QAbstractItemView::setSelectionModel( newSelectionModel );
159  if ( selectionModel() )
160  {
161  connect( selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SIGNAL(modelsChanged()) );
162  connect( selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SIGNAL(modelsChanged()) );
163  }
164  emit modelsChanged();
165 }
166 
167 /* Sets an external AttributesModel on this diagram. By default, a diagram has it's
168  own internal set of attributes, but an external one can be set. This can be used to
169  share attributes between several diagrams. The diagram does not take ownership of the
170  attributesmodel.
171 
172  @param amodel The AttributesModel to use for this diagram.
173 */
175 {
176  if ( amodel->sourceModel() != model() ) {
177  qWarning("KChart::AbstractDiagram::setAttributesModel() failed: "
178  "Trying to set an attributesmodel which works on a different "
179  "model than the diagram.");
180  return;
181  }
182  if ( qobject_cast<PrivateAttributesModel*>(amodel) ) {
183  qWarning("KChart::AbstractDiagram::setAttributesModel() failed: "
184  "Trying to set an attributesmodel that is private to another diagram.");
185  return;
186  }
187 
188  d->setAttributesModel( amodel );
189  scheduleDelayedItemsLayout();
190  setDataBoundariesDirty();
191  emit modelsChanged();
192 }
193 
195 {
196  return d->usesExternalAttributesModel();
197 }
198 
200 {
201  return d->attributesModel;
202 }
203 
204 QModelIndex AbstractDiagram::conditionallyMapFromSource( const QModelIndex & index ) const
205 {
206  Q_ASSERT( !index.isValid() || index.model() == attributesModel() || index.model() == attributesModel()->sourceModel() );
207  return index.model() == attributesModel() ? index : attributesModel()->mapFromSource( index );
208 }
209 
210 /* \reimpl */
212 {
214  setAttributesModelRootIndex( d->attributesModel->mapFromSource( idx ) );
215 }
216 
218 {
219  d->attributesModelRootIndex = idx;
220  setDataBoundariesDirty();
221  scheduleDelayedItemsLayout();
222 }
223 
225 {
226  if ( !d->attributesModelRootIndex.isValid() )
227  d->attributesModelRootIndex = d->attributesModel->mapFromSource( rootIndex() );
228  return d->attributesModelRootIndex;
229 }
230 
232 {
233  d->plane = parent;
234 }
235 
237 {
238  if ( d->plane ) {
239  d->plane->layoutDiagrams();
240  update();
241  }
242  QAbstractItemView::doItemsLayout();
243 }
244 
246  const QModelIndex &bottomRight,
247  const QVector<int> & )
248 {
249  Q_UNUSED( topLeft );
250  Q_UNUSED( bottomRight );
251  // We are still too dumb to do intelligent updates...
252  setDataBoundariesDirty();
253  scheduleDelayedItemsLayout();
254 }
255 
256 
257 void AbstractDiagram::setHidden( const QModelIndex & index, bool hidden )
258 {
259  d->attributesModel->setData(
260  conditionallyMapFromSource( index ),
261  QVariant::fromValue( hidden ),
262  DataHiddenRole );
263  emit dataHidden();
264 }
265 
266 void AbstractDiagram::setHidden( int dataset, bool hidden )
267 {
268  d->setDatasetAttrs( dataset, QVariant::fromValue( hidden ), DataHiddenRole );
269  emit dataHidden();
270 }
271 
272 void AbstractDiagram::setHidden( bool hidden )
273 {
274  d->attributesModel->setModelData( QVariant::fromValue( hidden ), DataHiddenRole );
275  emit dataHidden();
276 }
277 
279 {
280  return attributesModel()->modelData( DataHiddenRole ).value< bool >();
281 }
282 
283 bool AbstractDiagram::isHidden( int dataset ) const
284 {
285  const QVariant boolFlag( d->datasetAttrs( dataset, DataHiddenRole ) );
286  if ( boolFlag.isValid() )
287  return boolFlag.value< bool >();
288  return isHidden();
289 }
290 
291 bool AbstractDiagram::isHidden( const QModelIndex & index ) const
292 {
293  const QVariant boolFlag( attributesModel()->data( conditionallyMapFromSource( index ),
294  DataHiddenRole ) );
295  if ( boolFlag.isValid() ) {
296  return boolFlag.value< bool >();
297  }
298  int dataset = index.column() / d->datasetDimension;
299  return isHidden( dataset );
300 }
301 
302 
304  const DataValueAttributes & a )
305 {
306  d->attributesModel->setData( conditionallyMapFromSource( index ), QVariant::fromValue( a ),
307  DataValueLabelAttributesRole );
308  emit propertiesChanged();
309 }
310 
311 
313 {
314  d->setDatasetAttrs( dataset, QVariant::fromValue( a ), DataValueLabelAttributesRole );
315  emit propertiesChanged();
316 }
317 
319 {
320  return attributesModel()->modelData( KChart::DataValueLabelAttributesRole ).value< DataValueAttributes >();
321 }
322 
324 {
325  /*
326  The following did not work!
327  (khz, 2008-01-25)
328  If there was some attrs specified for the 0-th cells of a dataset,
329  then this logic would return the cell's settings instead of the header settings:
330 
331  return qVariantValue<DataValueAttributes>(
332  attributesModel()->data( attributesModel()->mapFromSource(columnToIndex( column )),
333  KChart::DataValueLabelAttributesRole ) );
334  */
335 
336  const QVariant headerAttrs(
337  d->datasetAttrs( dataset, KChart::DataValueLabelAttributesRole ) );
338  if ( headerAttrs.isValid() )
339  return headerAttrs.value< DataValueAttributes >();
340  return dataValueAttributes();
341 }
342 
344 {
345  return attributesModel()->data(
346  conditionallyMapFromSource( index ),
347  KChart::DataValueLabelAttributesRole ).value< DataValueAttributes >();
348 }
349 
351 {
352  d->attributesModel->setModelData( QVariant::fromValue( a ), DataValueLabelAttributesRole );
353  emit propertiesChanged();
354 }
355 
357 {
358  DataValueAttributes attrs = dataValueAttributes();
359  attrs.setShowOverlappingDataLabels( allow );
360  setDataValueAttributes( attrs );
361  d->allowOverlappingDataValueTexts = allow;
362  emit propertiesChanged();
363 }
364 
366 {
367  return d->allowOverlappingDataValueTexts;
368 }
369 
371 {
372  d->antiAliasing = enabled;
373  emit propertiesChanged();
374 }
375 
377 {
378  return d->antiAliasing;
379 }
380 
381 void AbstractDiagram::setPercentMode ( bool percent )
382 {
383  d->percent = percent;
384  emit propertiesChanged();
385 }
386 
388 {
389  return d->percent;
390 }
391 
392 
393 void AbstractDiagram::paintDataValueText( QPainter* painter,
394  const QModelIndex& index,
395  const QPointF& pos,
396  qreal value )
397 {
398  d->paintDataValueText( painter, index, pos, value );
399 }
400 
401 
403 {
404  if ( !checkInvariants() ) {
405  return;
406  }
407 
408  d->forgetAlreadyPaintedDataValues();
409  const int rowCount = model()->rowCount( rootIndex() );
410  const int columnCount = model()->columnCount( rootIndex() );
411  for ( int column = 0; column < columnCount; column += datasetDimension() ) {
412  for ( int row = 0; row < rowCount; ++row ) {
413  QModelIndex index = model()->index( row, column, rootIndex() ); // checked
414  qreal x;
415  qreal y;
416  if ( datasetDimension() == 1 ) {
417  x = row;
418  y = index.data().toReal();
419  } else {
420  x = index.data().toReal();
421  y = model()->index( row, column + 1, rootIndex() ).data().toReal();
422  }
423  paintDataValueText( painter, index, coordinatePlane()->translate( QPointF( x, y ) ), y );
424  }
425  }
426 }
427 
428 
429 void AbstractDiagram::paintMarker( QPainter* painter,
430  const DataValueAttributes& a,
431  const QModelIndex& index,
432  const QPointF& pos )
433 {
434  if ( !checkInvariants() || !a.isVisible() ) return;
435  const MarkerAttributes ma = a.markerAttributes();
436  if ( !ma.isVisible() ) return;
437 
438  const PainterSaver painterSaver( painter );
439 
440  QSizeF maSize = ma.markerSize();
441  const qreal diagramWidth = d->diagramSize.width();
442  const qreal diagramHeight = d->diagramSize.height();
443 
444  switch( ma.markerSizeMode() ) {
446  // Unscaled, i.e. without the painter's "zoom"
447  maSize.rwidth() /= painter->matrix().m11();
448  maSize.rheight() /= painter->matrix().m22();
449  break;
451  // Keep maSize as is. It is specified directly in pixels and desired
452  // to be effected by the painter's "zoom".
453  break;
455  maSize *= qMin( diagramWidth, diagramHeight );
456  break;
457  }
458 
459  QBrush indexBrush( brush( index ) );
460  QPen indexPen( ma.pen() );
461  if ( ma.markerColor().isValid() )
462  indexBrush.setColor( ma.markerColor() );
463 
464  paintMarker( painter, ma, indexBrush, indexPen, pos, maSize );
465 
466  // workaround: BC cannot be changed, otherwise we would pass the
467  // index down to next-lower paintMarker function. So far, we
468  // basically save a circle of radius maSize at pos in the
469  // reverseMapper. This means that ^^^ this version of paintMarker
470  // needs to be called to reverse-map the marker.
471  d->reverseMapper.addCircle( index.row(), index.column(), pos, 2 * maSize );
472 }
473 
474 void AbstractDiagram::paintMarker( QPainter* painter,
475  const QModelIndex& index,
476  const QPointF& pos )
477 {
478  if ( !checkInvariants() ) return;
479  paintMarker( painter, dataValueAttributes( index ), index, pos );
480 }
481 
482 void AbstractDiagram::paintMarker( QPainter* painter,
483  const MarkerAttributes& markerAttributes,
484  const QBrush& brush,
485  const QPen& pen,
486  const QPointF& pos,
487  const QSizeF& maSize )
488 {
489  const QPen oldPen( painter->pen() );
490  // Pen is used to paint 4Pixels - 1 Pixel - Ring and FastCross types.
491  // make sure to use the brush color - see above in those cases.
492  const bool isFourPixels = (markerAttributes.markerStyle() == MarkerAttributes::Marker4Pixels);
493  if ( isFourPixels || (markerAttributes.markerStyle() == MarkerAttributes::Marker1Pixel) ) {
494  // for high-performance point charts with tiny point markers:
495  painter->setPen( PrintingParameters::scalePen( QPen( brush.color().lighter() ) ) );
496  if ( isFourPixels ) {
497  const qreal x = pos.x();
498  const qreal y = pos.y();
499  painter->drawLine( QPointF(x-1.0,y-1.0),
500  QPointF(x+1.0,y-1.0) );
501  painter->drawLine( QPointF(x-1.0,y),
502  QPointF(x+1.0,y) );
503  painter->drawLine( QPointF(x-1.0,y+1.0),
504  QPointF(x+1.0,y+1.0) );
505  }
506  painter->drawPoint( pos );
507  } else {
508  const PainterSaver painterSaver( painter );
509  QPen painterPen( pen );
510  painter->setPen( PrintingParameters::scalePen( painterPen ) );
511  painter->setBrush( brush );
513  painter->translate( pos );
514  switch ( markerAttributes.markerStyle() ) {
515  case MarkerAttributes::MarkerCircle:
516  {
517  if ( markerAttributes.threeD() ) {
518  QRadialGradient grad;
520  QColor drawColor = brush.color();
521  grad.setCenter( 0.5, 0.5 );
522  grad.setRadius( 1.0 );
523  grad.setFocalPoint( 0.35, 0.35 );
524  grad.setColorAt( 0.00, drawColor.lighter( 150 ) );
525  grad.setColorAt( 0.20, drawColor );
526  grad.setColorAt( 0.50, drawColor.darker( 150 ) );
527  grad.setColorAt( 0.75, drawColor.darker( 200 ) );
528  grad.setColorAt( 0.95, drawColor.darker( 250 ) );
529  grad.setColorAt( 1.00, drawColor.darker( 200 ) );
530  QBrush newBrush( grad );
531  newBrush.setMatrix( brush.matrix() );
532  painter->setBrush( newBrush );
533  }
534  painter->drawEllipse( QRectF( 0 - maSize.height()/2, 0 - maSize.width()/2,
535  maSize.height(), maSize.width()) );
536  }
537  break;
538  case MarkerAttributes::MarkerSquare:
539  {
540  QRectF rect( 0 - maSize.width()/2, 0 - maSize.height()/2,
541  maSize.width(), maSize.height() );
542  painter->drawRect( rect );
543  break;
544  }
545  case MarkerAttributes::MarkerDiamond:
546  {
547  QVector <QPointF > diamondPoints;
548  QPointF top, left, bottom, right;
549  top = QPointF( 0, 0 - maSize.height()/2 );
550  left = QPointF( 0 - maSize.width()/2, 0 );
551  bottom = QPointF( 0, maSize.height()/2 );
552  right = QPointF( maSize.width()/2, 0 );
553  diamondPoints << top << left << bottom << right;
554  painter->drawPolygon( diamondPoints );
555  break;
556  }
557  // both handled on top of the method:
558  case MarkerAttributes::Marker1Pixel:
559  case MarkerAttributes::Marker4Pixels:
560  break;
561  case MarkerAttributes::MarkerRing:
562  {
563  painter->setBrush( Qt::NoBrush );
564  painter->setPen( PrintingParameters::scalePen( QPen( brush.color() ) ) );
565  painter->drawEllipse( QRectF( 0 - maSize.height()/2, 0 - maSize.width()/2,
566  maSize.height(), maSize.width()) );
567  break;
568  }
569  case MarkerAttributes::MarkerCross:
570  {
571  // Note: Markers can have outline,
572  // so just drawing two rects is NOT the solution here!
573  const qreal w02 = maSize.width() * 0.2;
574  const qreal w05 = maSize.width() * 0.5;
575  const qreal h02 = maSize.height()* 0.2;
576  const qreal h05 = maSize.height()* 0.5;
577  QVector <QPointF > crossPoints;
578  QPointF p[12];
579  p[ 0] = QPointF( -w02, -h05 );
580  p[ 1] = QPointF( w02, -h05 );
581  p[ 2] = QPointF( w02, -h02 );
582  p[ 3] = QPointF( w05, -h02 );
583  p[ 4] = QPointF( w05, h02 );
584  p[ 5] = QPointF( w02, h02 );
585  p[ 6] = QPointF( w02, h05 );
586  p[ 7] = QPointF( -w02, h05 );
587  p[ 8] = QPointF( -w02, h02 );
588  p[ 9] = QPointF( -w05, h02 );
589  p[10] = QPointF( -w05, -h02 );
590  p[11] = QPointF( -w02, -h02 );
591  for ( int i=0; i<12; ++i )
592  crossPoints << p[i];
593  crossPoints << p[0];
594  painter->drawPolygon( crossPoints );
595  break;
596  }
597  case MarkerAttributes::MarkerFastCross:
598  {
599  QPointF left, right, top, bottom;
600  left = QPointF( -maSize.width()/2, 0 );
601  right = QPointF( maSize.width()/2, 0 );
602  top = QPointF( 0, -maSize.height()/2 );
603  bottom= QPointF( 0, maSize.height()/2 );
604  painter->setPen( PrintingParameters::scalePen( QPen( brush.color() ) ) );
605  painter->drawLine( left, right );
606  painter->drawLine( top, bottom );
607  break;
608  }
609  case MarkerAttributes::MarkerArrowDown:
610  {
611  QVector <QPointF > arrowPoints;
612  QPointF topLeft, topRight, bottom;
613  topLeft = QPointF( 0 - maSize.width()/2, 0 - maSize.height()/2 );
614  topRight = QPointF( maSize.width()/2, 0 - maSize.height()/2 );
615  bottom = QPointF( 0, maSize.height()/2 );
616  arrowPoints << topLeft << bottom << topRight;
617  painter->drawPolygon( arrowPoints );
618  break;
619  }
620  case MarkerAttributes::MarkerArrowUp:
621  {
622  QVector <QPointF > arrowPoints;
623  QPointF top, bottomLeft, bottomRight;
624  top = QPointF( 0, 0 - maSize.height()/2 );
625  bottomLeft = QPointF( 0 - maSize.width()/2, maSize.height()/2 );
626  bottomRight = QPointF( maSize.width()/2, maSize.height()/2 );
627  arrowPoints << top << bottomLeft << bottomRight;
628  painter->drawPolygon( arrowPoints );
629  break;
630  }
631  case MarkerAttributes::MarkerArrowRight:
632  {
633  QVector <QPointF > arrowPoints;
634  QPointF right, topLeft, bottomLeft;
635  right = QPointF( maSize.width()/2, 0 );
636  topLeft = QPointF( 0 - maSize.width()/2, 0 - maSize.height()/2 );
637  bottomLeft = QPointF( 0 - maSize.width()/2, maSize.height()/2 );
638  arrowPoints << topLeft << bottomLeft << right;
639  painter->drawPolygon( arrowPoints );
640  break;
641  }
642  case MarkerAttributes::MarkerArrowLeft:
643  {
644  QVector <QPointF > arrowPoints;
645  QPointF left, topRight, bottomRight;
646  left = QPointF( 0 - maSize.width()/2, 0 );
647  topRight = QPointF( maSize.width()/2, 0 - maSize.height()/2 );
648  bottomRight = QPointF( maSize.width()/2, maSize.height()/2 );
649  arrowPoints << left << bottomRight << topRight;
650  painter->drawPolygon( arrowPoints );
651  break;
652  }
653  case MarkerAttributes::MarkerBowTie:
654  case MarkerAttributes::MarkerHourGlass:
655  {
656  QVector <QPointF > points;
657  QPointF topLeft, topRight, bottomLeft, bottomRight;
658  topLeft = QPointF( 0 - maSize.width()/2, 0 - maSize.height()/2);
659  topRight = QPointF( maSize.width()/2, 0 - maSize.height()/2 );
660  bottomLeft = QPointF( 0 - maSize.width()/2, maSize.height()/2 );
661  bottomRight = QPointF( maSize.width()/2, maSize.height()/2 );
662  if ( markerAttributes.markerStyle() == MarkerAttributes::MarkerBowTie)
663  points << topLeft << bottomLeft << topRight << bottomRight;
664  else
665  points << topLeft << bottomRight << bottomLeft << topRight;
666  painter->drawPolygon( points );
667  break;
668  }
669  case MarkerAttributes::MarkerStar:
670  {
671  const qreal w01 = maSize.width() * 0.1;
672  const qreal w05 = maSize.width() * 0.5;
673  const qreal h01 = maSize.height() * 0.1;
674  const qreal h05 = maSize.height() * 0.5;
675  QVector <QPointF > points;
676  QPointF p1 = QPointF( 0, -h05 );
677  QPointF p2 = QPointF( -w01, -h01 );
678  QPointF p3 = QPointF( -w05, 0 );
679  QPointF p4 = QPointF( -w01, h01 );
680  QPointF p5 = QPointF( 0, h05 );
681  QPointF p6 = QPointF( w01, h01 );
682  QPointF p7 = QPointF( w05, 0 );
683  QPointF p8 = QPointF( w01, -h01 );
684  points << p1 << p2 << p3 << p4 << p5 << p6 << p7 << p8;
685  painter->drawPolygon( points );
686  break;
687  }
688  case MarkerAttributes::MarkerX:
689  {
690  const qreal w01 = maSize.width() * 0.1;
691  const qreal w04 = maSize.width() * 0.4;
692  const qreal w05 = maSize.width() * 0.5;
693  const qreal h01 = maSize.height() * 0.1;
694  const qreal h04 = maSize.height() * 0.4;
695  const qreal h05 = maSize.height() * 0.5;
696  QVector <QPointF > crossPoints;
697  QPointF p1 = QPointF( -w04, -h05 );
698  QPointF p2 = QPointF( -w05, -h04 );
699  QPointF p3 = QPointF( -w01, 0 );
700  QPointF p4 = QPointF( -w05, h04 );
701  QPointF p5 = QPointF( -w04, h05 );
702  QPointF p6 = QPointF( 0, h01 );
703  QPointF p7 = QPointF( w04, h05 );
704  QPointF p8 = QPointF( w05, h04 );
705  QPointF p9 = QPointF( w01, 0 );
706  QPointF p10 = QPointF( w05, -h04 );
707  QPointF p11 = QPointF( w04, -h05 );
708  QPointF p12 = QPointF( 0, -h01 );
709  crossPoints << p1 << p2 << p3 << p4 << p5 << p6
710  << p7 << p8 << p9 << p10 << p11 << p12;
711  painter->drawPolygon( crossPoints );
712  break;
713  }
714  case MarkerAttributes::MarkerAsterisk:
715  {
716  // Note: Markers can have outline,
717  // so just drawing three lines is NOT the solution here!
718  // The idea that we use is to draw 3 lines anyway, but convert their
719  // outlines to QPainterPaths which are then united and filled.
720  const qreal w04 = maSize.width() * 0.4;
721  const qreal h02 = maSize.height() * 0.2;
722  const qreal h05 = maSize.height() * 0.5;
723  //QVector <QPointF > crossPoints;
724  QPointF p1 = QPointF( 0, -h05 );
725  QPointF p2 = QPointF( -w04, -h02 );
726  QPointF p3 = QPointF( -w04, h02 );
727  QPointF p4 = QPointF( 0, h05 );
728  QPointF p5 = QPointF( w04, h02 );
729  QPointF p6 = QPointF( w04, -h02 );
730  QPen pen = painter->pen();
731  QPainterPathStroker stroker;
732  stroker.setWidth( pen.widthF() );
733  stroker.setCapStyle( pen.capStyle() );
734 
735  QPainterPath path;
736  QPainterPath dummyPath;
737  dummyPath.moveTo( p1 );
738  dummyPath.lineTo( p4 );
739  path = stroker.createStroke( dummyPath );
740 
741  dummyPath = QPainterPath();
742  dummyPath.moveTo( p2 );
743  dummyPath.lineTo( p5 );
744  path = path.united( stroker.createStroke( dummyPath ) );
745 
746  dummyPath = QPainterPath();
747  dummyPath.moveTo( p3 );
748  dummyPath.lineTo( p6 );
749  path = path.united( stroker.createStroke( dummyPath ) );
750 
751  painter->drawPath( path );
752  break;
753  }
754  case MarkerAttributes::MarkerHorizontalBar:
755  {
756  const qreal w05 = maSize.width() * 0.5;
757  const qreal h02 = maSize.height()* 0.2;
758  QVector <QPointF > points;
759  QPointF p1 = QPointF( -w05, -h02 );
760  QPointF p2 = QPointF( -w05, h02 );
761  QPointF p3 = QPointF( w05, h02 );
762  QPointF p4 = QPointF( w05, -h02 );
763  points << p1 << p2 << p3 << p4;
764  painter->drawPolygon( points );
765  break;
766  }
767  case MarkerAttributes::MarkerVerticalBar:
768  {
769  const qreal w02 = maSize.width() * 0.2;
770  const qreal h05 = maSize.height()* 0.5;
771  QVector <QPointF > points;
772  QPointF p1 = QPointF( -w02, -h05 );
773  QPointF p2 = QPointF( -w02, h05 );
774  QPointF p3 = QPointF( w02, h05 );
775  QPointF p4 = QPointF( w02, -h05 );
776  points << p1 << p2 << p3 << p4;
777  painter->drawPolygon( points );
778  break;
779  }
780  case MarkerAttributes::NoMarker:
781  break;
782  case MarkerAttributes::PainterPathMarker:
783  {
784  QPainterPath path = markerAttributes.customMarkerPath();
785  const QRectF pathBoundingRect = path.boundingRect();
786  const qreal xScaling = maSize.height() / pathBoundingRect.height();
787  const qreal yScaling = maSize.width() / pathBoundingRect.width();
788  const qreal scaling = qMin( xScaling, yScaling );
789  painter->scale( scaling, scaling );
790  painter->setPen( PrintingParameters::scalePen( QPen( brush.color() ) ) );
791  painter->drawPath(path);
792  break;
793  }
794  default:
795  Q_ASSERT_X ( false, "paintMarkers()",
796  "Type item does not match a defined Marker Type." );
797  }
798  }
799  painter->setPen( oldPen );
800 }
801 
803 {
804  if ( !checkInvariants() ) {
805  return;
806  }
807 
808  const int rowCount = model()->rowCount( rootIndex() );
809  const int columnCount = model()->columnCount( rootIndex() );
810  for ( int column = 0; column < columnCount; column += datasetDimension() ) {
811  for ( int row = 0; row < rowCount; ++row ) {
812  QModelIndex index = model()->index( row, column, rootIndex() ); // checked
813  qreal x;
814  qreal y;
815  if ( datasetDimension() == 1 ) {
816  x = row;
817  y = index.data().toReal();
818  } else {
819  x = index.data().toReal();
820  y = model()->index( row, column + 1, rootIndex() ).data().toReal();
821  }
822  paintMarker( painter, index, coordinatePlane()->translate( QPointF( x, y ) ) );
823  }
824  }
825 }
826 
827 
828 void AbstractDiagram::setPen( const QModelIndex& index, const QPen& pen )
829 {
830  attributesModel()->setData(
831  conditionallyMapFromSource( index ),
832  QVariant::fromValue( pen ), DatasetPenRole );
833  emit propertiesChanged();
834 }
835 
836 void AbstractDiagram::setPen( const QPen& pen )
837 {
838  attributesModel()->setModelData(
839  QVariant::fromValue( pen ), DatasetPenRole );
840  emit propertiesChanged();
841 }
842 
843 void AbstractDiagram::setPen( int dataset, const QPen& pen )
844 {
845  d->setDatasetAttrs( dataset, QVariant::fromValue( pen ), DatasetPenRole );
846  emit propertiesChanged();
847 }
848 
850 {
851  return attributesModel()->data( DatasetPenRole ).value< QPen >();
852 }
853 
854 QPen AbstractDiagram::pen( int dataset ) const
855 {
856  const QVariant penSettings( d->datasetAttrs( dataset, DatasetPenRole ) );
857  if ( penSettings.isValid() )
858  return penSettings.value< QPen >();
859  return pen();
860 }
861 
862 QPen AbstractDiagram::pen( const QModelIndex& index ) const
863 {
864  return attributesModel()->data(
865  conditionallyMapFromSource( index ),
866  DatasetPenRole ).value< QPen >();
867 }
868 
869 void AbstractDiagram::setBrush( const QModelIndex& index, const QBrush& brush )
870 {
871  attributesModel()->setData(
872  conditionallyMapFromSource( index ),
873  QVariant::fromValue( brush ), DatasetBrushRole );
874  emit propertiesChanged();
875 }
876 
877 void AbstractDiagram::setBrush( const QBrush& brush )
878 {
879  attributesModel()->setModelData(
880  QVariant::fromValue( brush ), DatasetBrushRole );
881  emit propertiesChanged();
882 }
883 
884 void AbstractDiagram::setBrush( int dataset, const QBrush& brush )
885 {
886  d->setDatasetAttrs( dataset, QVariant::fromValue( brush ), DatasetBrushRole );
887  emit propertiesChanged();
888 }
889 
891 {
892  return attributesModel()->data( DatasetBrushRole ).value< QBrush >();
893 }
894 
895 QBrush AbstractDiagram::brush( int dataset ) const
896 {
897  const QVariant brushSettings( d->datasetAttrs( dataset, DatasetBrushRole ) );
898  if ( brushSettings.isValid() )
899  return brushSettings.value< QBrush >();
900  return brush();
901 }
902 
904 {
905  return
906  attributesModel()->data( conditionallyMapFromSource( index ), DatasetBrushRole ).value< QBrush >();
907 }
908 
909 /*
910  * Sets the unit prefix for one value
911  * @param prefix the prefix to be set
912  * @param column the value using that prefix
913  * @param orientation the orientantion of the axis to set
914  */
915 void AbstractDiagram::setUnitPrefix( const QString& prefix, int column, Qt::Orientation orientation )
916 {
917  d->unitPrefixMap[ column ][ orientation ]= prefix;
918 }
919 
920 /*
921  * Sets the unit prefix for all values
922  * @param prefix the prefix to be set
923  * @param orientation the orientantion of the axis to set
924  */
925 void AbstractDiagram::setUnitPrefix( const QString& prefix, Qt::Orientation orientation )
926 {
927  d->unitPrefix[ orientation ] = prefix;
928 }
929 
930 /*
931  * Sets the unit suffix for one value
932  * @param suffix the suffix to be set
933  * @param column the value using that suffix
934  * @param orientation the orientantion of the axis to set
935  */
936 void AbstractDiagram::setUnitSuffix( const QString& suffix, int column, Qt::Orientation orientation )
937 {
938  d->unitSuffixMap[ column ][ orientation ]= suffix;
939 }
940 
941 /*
942  * Sets the unit suffix for all values
943  * @param suffix the suffix to be set
944  * @param orientation the orientantion of the axis to set
945  */
946 void AbstractDiagram::setUnitSuffix( const QString& suffix, Qt::Orientation orientation )
947 {
948  d->unitSuffix[ orientation ] = suffix;
949 }
950 
951 /*
952  * Returns the unit prefix for a special value
953  * @param column the value which's prefix is requested
954  * @param orientation the orientation of the axis
955  * @param fallback if true, the global prefix is return when no specific one is set for that value
956  * @return the unit prefix
957  */
958 QString AbstractDiagram::unitPrefix( int column, Qt::Orientation orientation, bool fallback ) const
959 {
960  if ( !fallback || d->unitPrefixMap[ column ].contains( orientation ) )
961  return d->unitPrefixMap[ column ][ orientation ];
962  return d->unitPrefix[ orientation ];
963 }
964 
965 /* Returns the global unit prefix
966  * @param orientation the orientation of the axis
967  * @return the unit prefix
968  */
970 {
971  return d->unitPrefix[ orientation ];
972 }
973 
974 /*
975  * Returns the unit suffix for a special value
976  * @param column the value which's suffix is requested
977  * @param orientation the orientation of the axis
978  * @param fallback if true, the global suffix is return when no specific one is set for that value
979  * @return the unit suffix
980  */
981 QString AbstractDiagram::unitSuffix( int column, Qt::Orientation orientation, bool fallback ) const
982 {
983  if ( !fallback || d->unitSuffixMap[ column ].contains( orientation ) )
984  return d->unitSuffixMap[ column ][ orientation ];
985  return d->unitSuffix[ orientation ];
986 }
987 
988 /* Returns the global unit suffix
989  * @param orientation the orientation of the axis
990  * @return the unit siffix
991  */
993 {
994  return d->unitSuffix[ orientation ];
995 }
996 
997 // implement QAbstractItemView:
999 {
1000  return d->reverseMapper.boundingRect( index.row(), index.column() ).toRect();
1001 }
1002 
1004 {}
1005 
1006 // indexAt ... down below
1007 
1009 { return QModelIndex(); }
1010 
1012 { return 0; }
1013 
1015 { return 0; }
1016 
1018 { return true; }
1019 
1021 {
1022  const QModelIndexList indexes = d->indexesIn( rect );
1023  QItemSelection selection;
1024  for ( const QModelIndex& index : indexes )
1025  {
1026  selection.append( QItemSelectionRange( index ) );
1027  }
1028  selectionModel()->select( selection, command );
1029 }
1030 
1032 {
1033  QPolygonF polygon;
1034  const auto indexes = selection.indexes();
1035  polygon.reserve(indexes.count());
1036  for ( const QModelIndex& index : indexes )
1037  {
1038  polygon << d->reverseMapper.polygon(index.row(), index.column());
1039  }
1040  return polygon.isEmpty() ? QRegion() : QRegion( polygon.toPolygon() );
1041 }
1042 
1043 QRegion AbstractDiagram::visualRegion(const QModelIndex &index) const
1044 {
1045  QPolygonF polygon = d->reverseMapper.polygon(index.row(), index.column());
1046  return polygon.isEmpty() ? QRegion() : QRegion( polygon.toPolygon() );
1047 }
1048 
1050 {
1051  d->attributesModel->setPaletteType( AttributesModel::PaletteTypeDefault );
1052 }
1053 
1055 {
1056  d->attributesModel->setPaletteType( AttributesModel::PaletteTypeSubdued );
1057 }
1058 
1060 {
1061  d->attributesModel->setPaletteType( AttributesModel::PaletteTypeRainbow );
1062 }
1063 
1065 {
1066  QStringList ret;
1067  if ( model() ) {
1068  //qDebug() << "AbstractDiagram::itemRowLabels(): " << attributesModel()->rowCount(attributesModelRootIndex()) << "entries";
1069  const int rowCount = attributesModel()->rowCount(attributesModelRootIndex());
1070  for ( int i = 0; i < rowCount; ++i ) {
1071  //qDebug() << "item row label: " << attributesModel()->headerData( i, Qt::Vertical, Qt::DisplayRole ).toString();
1072  ret << unitPrefix( i, Qt::Horizontal, true ) +
1073  attributesModel()->headerData( i, Qt::Vertical, Qt::DisplayRole ).toString() +
1074  unitSuffix( i, Qt::Horizontal, true );
1075  }
1076  }
1077  return ret;
1078 }
1079 
1081 {
1082  QStringList ret;
1083  if ( !model() ) {
1084  return ret;
1085  }
1086  const int datasetCount = d->datasetCount();
1087  for ( int i = 0; i < datasetCount; ++i ) {
1088  ret << d->datasetAttrs( i, Qt::DisplayRole ).toString();
1089  }
1090  return ret;
1091 }
1092 
1094 {
1095  QList<QBrush> ret;
1096  if ( !model() ) {
1097  return ret;
1098  }
1099  const int datasetCount = d->datasetCount();
1100  for ( int i = 0; i < datasetCount; ++i ) {
1101  ret << brush( i );
1102  }
1103  return ret;
1104 }
1105 
1107 {
1108  QList<QPen> ret;
1109  if ( !model() ) {
1110  return ret;
1111  }
1112  const int datasetCount = d->datasetCount();
1113  for ( int i = 0; i < datasetCount; ++i ) {
1114  ret << pen( i );
1115  }
1116  return ret;
1117 }
1118 
1120 {
1122  if ( !model() ) {
1123  return ret;
1124  }
1125  const int datasetCount = d->datasetCount();
1126  for ( int i = 0; i < datasetCount; ++i ) {
1127  ret << dataValueAttributes( i ).markerAttributes();
1128  }
1129  return ret;
1130 }
1131 
1132 bool AbstractDiagram::checkInvariants( bool justReturnTheStatus ) const
1133 {
1134  if ( ! justReturnTheStatus ) {
1135  Q_ASSERT_X ( model(), "AbstractDiagram::checkInvariants()",
1136  "There is no usable model set, for the diagram." );
1137 
1138  Q_ASSERT_X ( coordinatePlane(), "AbstractDiagram::checkInvariants()",
1139  "There is no usable coordinate plane set, for the diagram." );
1140  }
1141  return model() && coordinatePlane();
1142 }
1143 
1145 {
1146  return d->datasetDimension;
1147 }
1148 
1150 {
1151  Q_UNUSED( dimension );
1152  qDebug() << "Setting the dataset dimension using AbstractDiagram::setDatasetDimension is "
1153  "obsolete. Use the specific diagram types instead.";
1154 }
1155 
1156 void AbstractDiagram::setDatasetDimensionInternal( int dimension )
1157 {
1158  Q_ASSERT( dimension != 0 );
1159  if ( d->datasetDimension == dimension ) {
1160  return;
1161  }
1162  d->datasetDimension = dimension;
1163  d->attributesModel->setDatasetDimension( dimension );
1164  setDataBoundariesDirty();
1165  emit layoutChanged( this );
1166 }
1167 
1168 qreal AbstractDiagram::valueForCell( int row, int column ) const
1169 {
1170  if ( !d->attributesModel->hasIndex( row, column, attributesModelRootIndex() ) ) {
1171  qWarning() << "AbstractDiagram::valueForCell(): Requesting value for invalid index!";
1172  return std::numeric_limits<qreal>::quiet_NaN();
1173  }
1174  return d->attributesModel->data(
1175  d->attributesModel->index( row, column, attributesModelRootIndex() ) ).toReal(); // checked
1176 }
1177 
1178 void AbstractDiagram::update() const
1179 {
1180  if ( d->plane ) {
1181  d->plane->update();
1182  }
1183 }
1184 
1186 {
1187  return d->indexAt( point );
1188 }
1189 
1190 QModelIndexList AbstractDiagram::indexesAt( const QPoint& point ) const
1191 {
1192  return d->indexesAt( point );
1193 }
1194 
1195 QModelIndexList AbstractDiagram::indexesIn( const QRect& rect ) const
1196 {
1197  return d->indexesIn( rect );
1198 }
QList< MarkerAttributes > datasetMarkers() const
The set of dataset markers currently used, for use in legends, etc.
QModelIndexList indexes() const const
QRectF boundingRect() const const
virtual void setRootIndex(const QModelIndex &index)
void resize(int w, int h)
void setWidth(qreal width)
virtual void setSelectionModel(QItemSelectionModel *selectionModel)
void setAntiAliasing(bool enabled)
Set whether anti-aliasing is to be used while rendering this diagram.
void setPercentMode(bool percent)
Deprecated method that turns the percent mode of this diagram on or off.
Class only listed here to document inheritance of some KChart classes.
int verticalOffset() const override
typedef KeyboardModifiers
QPolygon toPolygon() const const
QModelIndexList indexesAt(const QPoint &point) const
This method is added alongside with indexAt from QAIM, since in KChart multiple indexes can be displa...
QColor darker(int factor) const const
AbstractDiagram defines the interface for diagram classes.
Class only listed here to document inheritance of some KChart classes.
void setRenderHint(QPainter::RenderHint hint, bool on)
virtual bool usesExternalAttributesModel() const
Returns whether the diagram is using its own built-in attributes model or an attributes model that wa...
void setColorAt(qreal position, const QColor &color)
A set of attributes controlling the appearance of data set markers.
void initFrom(const AttributesModel *other)
Copies the internal data (maps and palette) of another AttributesModel* into this one...
qreal & rwidth()
virtual void setModel(QAbstractItemModel *model)
void scale(qreal sx, qreal sy)
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector< int > &roles=QVector< int >()) override
QModelIndex attributesModelRootIndex() const
QModelIndex indexAt(const QPoint &point) const override
T value() const const
void drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule)
Diagram attributes dealing with data value labels.
void moveTo(const QPointF &point)
const QPair< QPointF, QPointF > dataBoundaries() const
Return the bottom left and top right data point, that the diagram will display (unless the grid adjus...
QStringList itemRowLabels() const
The set of item row labels currently displayed, for use in Abscissa axes, etc.
QList< QBrush > datasetBrushes() const
The set of dataset brushes currently used, for use in legends, etc.
void drawLine(const QLineF &line)
void setFocalPoint(const QPointF &focalPoint)
the marker size is relative to the diagram&#39;s min(width, height)
Declaring the class KChart::DataValueAttributes.
bool isHidden() const
Retrieve the hidden status specified globally.
QList< QPen > datasetPens() const
The set of dataset pens currently used, for use in legends, etc.
virtual void paintMarkers(QPainter *painter)
bool hasAutoScroll() const const
const QColor & color() const const
virtual AttributesModel * attributesModel() const
Returns the AttributesModel, that is used by this diagram.
qreal m22() const const
qreal m11() const const
void drawRect(const QRectF &rectangle)
void setAttributesModelRootIndex(const QModelIndex &)
bool isValid() const const
virtual void setAttributesModel(AttributesModel *model)
Associate an AttributesModel with this diagram.
qreal x() const const
qreal y() const const
void append(const T &value)
the marker size is directly specified in pixels
void drawPoint(const QPointF &position)
void setAllowOverlappingDataValueTexts(bool allow)
Set whether data value labels are allowed to overlap.
QPainterPath united(const QPainterPath &p) const const
void setPen(const QColor &color)
void lineTo(const QPointF &endPoint)
void drawEllipse(const QRectF &rectangle)
QSize toSize() const const
QPen pen() const
Retrieve the pen to be used for painting datapoints globally.
DisplayRole
Base class common for all coordinate planes, CartesianCoordinatePlane, PolarCoordinatePlane, TernaryCoordinatePlane.
int row() const const
void setBrush(const QBrush &brush)
QPainterPath createStroke(const QPainterPath &path) const const
A proxy model used for decorating data with attributes.
QRect visualRect(const QModelIndex &index) const override
void setRadius(qreal radius)
virtual void setCoordinatePlane(AbstractCoordinatePlane *plane)
Set the coordinate plane associated with the diagram.
bool compare(const AbstractDiagram *other) const
Returns true if both diagrams have the same settings.
the marker size is specified in pixels, but scaled by the painter&#39;s zoom level
Internally used class just adding a special constructor used by AbstractDiagram.
void setCoordinateMode(QGradient::CoordinateMode mode)
MarkerAttributes markerAttributes() const
void setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags command) override
bool allowOverlappingDataValueTexts() const
bool percentMode() const
Returns whether this diagram is drawn in percent mode.
void reserve(int size)
int horizontalOffset() const override
void setCenter(const QPointF &center)
bool isIndexHidden(const QModelIndex &index) const override
QColor lighter(int factor) const const
QVariant fromValue(const T &value)
QCA_EXPORT void init()
QModelIndex rootIndex() const const
void setDatasetDimension(int dimension)
void setSelectionModel(QItemSelectionModel *selectionModel) override
Associate a seleection model with the diagrom.
void setDataValueAttributes(const QModelIndex &index, const DataValueAttributes &a)
Set the DataValueAttributes for the given index.
QBrush brush() const
Retrieve the brush to be used for painting datapoints globally.
void useSubduedColors()
Set the palette to be used, for painting datasets to the subdued palette.
void setHidden(const QModelIndex &index, bool hidden)
Hide (or unhide, resp.) a data cell.
virtual void resize(const QSizeF &area)
Called by the widget&#39;s sizeEvent.
qreal width() const const
const QAbstractItemModel * model() const const
void drawPath(const QPainterPath &path)
QVariant data(int role) const const
DataValueAttributes dataValueAttributes() const
Retrieve the DataValueAttributes specified globally.
QString unitPrefix(int column, Qt::Orientation orientation, bool fallback=false) const
Retrieves the axis unit prefix for a specific column.
const QMatrix & matrix() const const
QRegion visualRegionForSelection(const QItemSelection &selection) const override
bool isEmpty() const const
void setRootIndex(const QModelIndex &idx) override
Set the root index in the model, where the diagram starts referencing data for display.
Qt::PenCapStyle capStyle() const const
qreal valueForCell(int row, int column) const
Helper method, retrieving the data value (DisplayRole) for a given row and column.
void setCapStyle(Qt::PenCapStyle style)
QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers) override
void scrollTo(const QModelIndex &index, ScrollHint hint=EnsureVisible) override
int column() const const
qreal widthF() const const
AbstractCoordinatePlane * coordinatePlane() const
The coordinate plane associated with the diagram.
void translate(const QPointF &offset)
void setModel(QAbstractItemModel *model) override
Associate a model with the diagram.
bool isValid() const const
qreal height() const const
void setMatrix(const QMatrix &matrix)
void setUnitPrefix(const QString &prefix, int column, Qt::Orientation orientation)
Set the unit prefix to be used on axes for one specific column.
Orientation
qreal & rheight()
qreal toReal(bool *ok) const const
virtual void paintDataValueTexts(QPainter *painter)
QString unitSuffix(int column, Qt::Orientation orientation, bool fallback=false) const
Retrieves the axis unit suffix for a specific column.
qreal height() const const
Global namespace.
void useDefaultColors()
Set the palette to be used, for painting datasets to the default palette.
void useRainbowColors()
Set the palette to be used, for painting datasets to the rainbow palette.
void setColor(const QColor &color)
const QPen & pen() const const
QStringList datasetLabels() const
The set of dataset labels currently displayed, for use in legends, etc.
int datasetDimension() const
The dataset dimension of a diagram determines how many value dimensions it expects each datapoint to ...
void setShowOverlappingDataLabels(bool showOverlappingDataLabels)
Set whether data value texts overlapping other data value texts of the same diagram should be drawn...
void setPen(const QModelIndex &index, const QPen &pen)
Set the pen to be used, for painting the datapoint at the given index.
qreal width() const const
const QMatrix & matrix() const const
bool isValid() const const
void setBrush(const QModelIndex &index, const QBrush &brush)
Set the brush to be used, for painting the datapoint at the given index.
void setUnitSuffix(const QString &suffix, int column, Qt::Orientation orientation)
Set the unit prefix to be used on axes for one specific column.
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Fri Nov 27 2020 22:38:02 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.