KChart

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

KDE's Doxygen guidelines are available online.