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

KDE's Doxygen guidelines are available online.