KD Chart 2  [rev.2.8]
KDChartAbstractDiagram_p.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 ** Copyright (C) 2001-2021 Klaralvdalens Datakonsult AB. All rights reserved.
3 **
4 ** This file is part of the KD Chart library.
5 **
6 ** Licensees holding valid commercial KD Chart licenses may use this file in
7 ** accordance with the KD Chart Commercial License Agreement provided with
8 ** the Software.
9 **
10 **
11 ** This file may be distributed and/or modified under the terms of the
12 ** GNU General Public License version 2 and version 3 as published by the
13 ** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
14 **
15 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17 **
18 ** Contact info@kdab.com if any conditions of this licensing are not
19 ** clear to you.
20 **
21 **********************************************************************/
22 
23 //
24 // W A R N I N G
25 // -------------
26 //
27 // This file is not part of the KD Chart API. It exists purely as an
28 // implementation detail. This header file may change from version to
29 // version without notice, or even be removed.
30 //
31 // We mean it.
32 //
33 
34 #include "KDChartAbstractDiagram_p.h"
35 
36 #include "KDChartBarDiagram.h"
37 #include "KDChartFrameAttributes.h"
38 #include "KDChartPainterSaver_p.h"
39 
40 #include <QAbstractTextDocumentLayout>
41 #include <QTextBlock>
42 #include <QApplication>
43 
44 #include <KDABLibFakes>
45 
46 
47 using namespace KDChart;
48 
49 LabelPaintInfo::LabelPaintInfo() :
50  isValuePositive( false )
51 {
52 }
53 
54 LabelPaintInfo::LabelPaintInfo( const QModelIndex& _index, const DataValueAttributes& _attrs,
55  const QPainterPath& _labelArea, const QPointF& _markerPos,
56  bool _isValuePositive, const QString& _value )
57  : index( _index )
58  , attrs( _attrs )
59  , labelArea( _labelArea )
60  , markerPos( _markerPos )
61  , isValuePositive( _isValuePositive )
62  , value( _value )
63 {
64 }
65 
66 LabelPaintInfo::LabelPaintInfo( const LabelPaintInfo& other )
67  : index( other.index )
68  , attrs( other.attrs )
69  , labelArea( other.labelArea )
70  , markerPos( other.markerPos )
71  , isValuePositive( other.isValuePositive )
72  , value( other.value )
73 {
74 }
75 
76 AbstractDiagram::Private::Private()
77  : diagram( 0 )
78  , doDumpPaintTime( false )
79  , plane( 0 )
80  , attributesModel( new PrivateAttributesModel(0,0) )
81  , allowOverlappingDataValueTexts( false )
82  , antiAliasing( true )
83  , percent( false )
84  , datasetDimension( 1 )
85  , databoundariesDirty( true )
86  , mCachedFontMetrics( QFontMetrics( qApp->font() ) )
87 {
88 }
89 
90 AbstractDiagram::Private::~Private()
91 {
92  if ( attributesModel && qobject_cast<PrivateAttributesModel*>(attributesModel) )
93  delete attributesModel;
94 }
95 
96 void AbstractDiagram::Private::init()
97 {
98 }
99 
100 void AbstractDiagram::Private::init( AbstractCoordinatePlane* newPlane )
101 {
102  plane = newPlane;
103 }
104 
105 bool AbstractDiagram::Private::usesExternalAttributesModel() const
106 {
107  return ( ! attributesModel.isNull() ) &&
108  ( ! qobject_cast<PrivateAttributesModel*>(attributesModel) );
109 }
110 
111 void AbstractDiagram::Private::setAttributesModel( AttributesModel* amodel )
112 {
113  if ( attributesModel == amodel ) {
114  return;
115  }
116 
117  if ( !attributesModel.isNull() ) {
118  if ( qobject_cast< PrivateAttributesModel* >( attributesModel ) ) {
119  delete attributesModel;
120  } else {
121  disconnect( attributesModel, SIGNAL( rowsInserted( QModelIndex, int, int ) ),
122  diagram, SLOT( setDataBoundariesDirty() ) );
123  disconnect( attributesModel, SIGNAL( columnsInserted( QModelIndex, int, int ) ),
124  diagram, SLOT( setDataBoundariesDirty() ) );
125  disconnect( attributesModel, SIGNAL( rowsRemoved( QModelIndex, int, int ) ),
126  diagram, SLOT( setDataBoundariesDirty() ) );
127  disconnect( attributesModel, SIGNAL( columnsRemoved( QModelIndex, int, int ) ),
128  diagram, SLOT( setDataBoundariesDirty() ) );
129  disconnect( attributesModel, SIGNAL( modelReset() ),
130  diagram, SLOT( setDataBoundariesDirty() ) );
131  disconnect( attributesModel, SIGNAL( layoutChanged() ),
132  diagram, SLOT( setDataBoundariesDirty() ) );
133  disconnect( attributesModel, SIGNAL( dataChanged( QModelIndex, QModelIndex ) ),
134  diagram, SIGNAL( modelDataChanged() ));
135  }
136  }
137 
138  emit diagram->attributesModelAboutToChange( amodel, attributesModel );
139 
140  connect( amodel, SIGNAL( rowsInserted( QModelIndex, int, int ) ),
141  diagram, SLOT( setDataBoundariesDirty() ) );
142  connect( amodel, SIGNAL( columnsInserted( QModelIndex, int, int ) ),
143  diagram, SLOT( setDataBoundariesDirty() ) );
144  connect( amodel, SIGNAL( rowsRemoved( QModelIndex, int, int ) ),
145  diagram, SLOT( setDataBoundariesDirty() ) );
146  connect( amodel, SIGNAL( columnsRemoved( QModelIndex, int, int ) ),
147  diagram, SLOT( setDataBoundariesDirty() ) );
148  connect( amodel, SIGNAL( modelReset() ),
149  diagram, SLOT( setDataBoundariesDirty() ) );
150  connect( amodel, SIGNAL( layoutChanged() ),
151  diagram, SLOT( setDataBoundariesDirty() ) );
152  connect( amodel, SIGNAL( dataChanged( QModelIndex, QModelIndex ) ),
153  diagram, SIGNAL( modelDataChanged() ));
154 
155  attributesModel = amodel;
156 }
157 
158 AbstractDiagram::Private::Private( const AbstractDiagram::Private& rhs ) :
159  diagram( 0 ),
160  doDumpPaintTime( rhs.doDumpPaintTime ),
161  // Do not copy the plane
162  plane( 0 ),
163  attributesModelRootIndex( QModelIndex() ),
164  attributesModel( rhs.attributesModel ),
165  allowOverlappingDataValueTexts( rhs.allowOverlappingDataValueTexts ),
166  antiAliasing( rhs.antiAliasing ),
167  percent( rhs.percent ),
168  datasetDimension( rhs.datasetDimension ),
169  mCachedFontMetrics( rhs.cachedFontMetrics() )
170 {
171  attributesModel = new PrivateAttributesModel( 0, 0);
172  attributesModel->initFrom( rhs.attributesModel );
173 }
174 
175 // FIXME: Optimize if necessary
176 qreal AbstractDiagram::Private::calcPercentValue( const QModelIndex & index ) const
177 {
178  qreal sum = 0.0;
179  for ( int col = 0; col < attributesModel->columnCount( QModelIndex() ); col++ )
180  sum += attributesModel->data( attributesModel->index( index.row(), col, QModelIndex() ) ).toReal(); // checked
181  if ( sum == 0.0 )
182  return 0.0;
183  return attributesModel->data( attributesModel->mapFromSource( index ) ).toReal() / sum * 100.0;
184 }
185 
186 void AbstractDiagram::Private::addLabel(
187  LabelPaintCache* cache,
188  const QModelIndex& index,
189  const CartesianDiagramDataCompressor::CachePosition* position,
190  const PositionPoints& points,
191  const Position& autoPositionPositive, const Position& autoPositionNegative,
192  const qreal value, qreal favoriteAngle /* = 0.0 */ )
193 {
194  CartesianDiagramDataCompressor::AggregatedDataValueAttributes allAttrs(
195  aggregatedAttrs( index, position ) );
196 
198  for ( it = allAttrs.constBegin(); it != allAttrs.constEnd(); ++it ) {
199  DataValueAttributes dva = it.value();
200  if ( !dva.isVisible() ) {
201  continue;
202  }
203 
204  const bool isPositive = ( value >= 0.0 );
205 
206  RelativePosition relPos( dva.position( isPositive ) );
207  relPos.setReferencePoints( points );
208  if ( relPos.referencePosition().isUnknown() ) {
209  relPos.setReferencePosition( isPositive ? autoPositionPositive : autoPositionNegative );
210  }
211 
212  // Rotate the label position (not the label itself) if the diagram is rotated so that the defaults still work
213  if ( isTransposed() ) {
214  KDChartEnums::PositionValue posValue = relPos.referencePosition().value();
215  if ( posValue >= KDChartEnums::PositionNorthWest && posValue <= KDChartEnums::PositionWest ) {
216  // rotate 90 degrees clockwise
217  posValue = static_cast< KDChartEnums::PositionValue >( posValue + 2 );
218  if ( posValue > KDChartEnums::PositionWest ) {
219  // wraparound
220  posValue = static_cast< KDChartEnums::PositionValue >( posValue -
222  }
223  relPos.setReferencePosition( Position( posValue ) );
224  }
225  }
226 
227  const QPointF referencePoint = relPos.referencePoint();
228  if ( !diagram->coordinatePlane()->isVisiblePoint( referencePoint ) ) {
229  continue;
230  }
231 
232  const qreal fontHeight = cachedFontMetrics( dva.textAttributes().
233  calculatedFont( plane, KDChartEnums::MeasureOrientationMinimum ), diagram )->height();
234 
235  // Note: When printing data value texts and padding's Measure is using automatic reference area
236  // detection, the font height is used as reference size for both horizontal and vertical
237  // padding.
238  QSizeF relativeMeasureSize( fontHeight, fontHeight );
239 
240  if ( !dva.textAttributes().hasRotation() ) {
241  TextAttributes ta = dva.textAttributes();
242  ta.setRotation( favoriteAngle );
243  dva.setTextAttributes( ta );
244  }
245 
246  // get the size of the label text using a subset of the information going into the final layout
247  const QString text = formatDataValueText( dva, index, value );
248  QTextDocument doc;
249  doc.setDocumentMargin( 0 );
250  if ( Qt::mightBeRichText( text ) ) {
251  doc.setHtml( text );
252  } else {
253  doc.setPlainText( text );
254  }
255  const QFont calculatedFont( dva.textAttributes()
257  doc.setDefaultFont( calculatedFont );
258 
259  const QRectF plainRect = doc.documentLayout()->frameBoundingRect( doc.rootFrame() );
260 
296  QTransform transform;
297  {
298  // move to the general area where the label should be
299  QPointF calcPoint = relPos.calculatedPoint( relativeMeasureSize );
300  transform.translate( calcPoint.x(), calcPoint.y() );
301  // align the text rect; find out by how many half-widths / half-heights to move.
302  int dx = -1;
303  if ( relPos.alignment() & Qt::AlignLeft ) {
304  dx -= 1;
305  } else if ( relPos.alignment() & Qt::AlignRight ) {
306  dx += 1;
307  }
308 
309  int dy = -1;
310  if ( relPos.alignment() & Qt::AlignTop ) {
311  dy -= 1;
312  } else if ( relPos.alignment() & Qt::AlignBottom ) {
313  dy += 1;
314  }
315  transform.translate( qreal( dx ) * plainRect.width() * 0.5,
316  qreal( dy ) * plainRect.height() * 0.5 );
317 
318  // rotate the text rect around its center
319  transform.translate( plainRect.center().x(), plainRect.center().y() );
320  int rotation = dva.textAttributes().rotation();
321  if ( !isPositive && dva.mirrorNegativeValueTextRotation() ) {
322  rotation *= -1;
323  }
324  transform.rotate( rotation );
325  transform.translate( -plainRect.center().x(), -plainRect.center().y() );
326  }
327 
328  QPainterPath labelArea;
329  //labelArea.addPolygon( transform.mapToPolygon( plainRect.toRect() ) );
330  //labelArea.closeSubpath();
331  // Not doing that because QTransform has a special case for 180° that gives a different than
332  // usual ordering of the points in the polygon returned by mapToPolygon( const QRect & ).
333  // We expect a particular ordering in paintDataValueTextsAndMarkers() by using elementAt( 0 ),
334  // and similar things might happen elsewhere.
335  labelArea.addPolygon( transform.map( QPolygon( plainRect.toRect(), true ) ) );
336 
337  // store the label geometry and auxiliary data
338  cache->paintReplay.append( LabelPaintInfo( it.key(), dva, labelArea,
339  referencePoint, value >= 0.0, text ) );
340  }
341 }
342 
343 const QFontMetrics* AbstractDiagram::Private::cachedFontMetrics( const QFont& font,
344  const QPaintDevice* paintDevice) const
345 {
346  if ( ( font != mCachedFont ) || ( paintDevice != mCachedPaintDevice ) ) {
347  mCachedFontMetrics = QFontMetrics( font, const_cast<QPaintDevice *>( paintDevice ) );
348  // TODO what about setting mCachedFont and mCachedPaintDevice?
349  }
350  return &mCachedFontMetrics;
351 }
352 
353 const QFontMetrics AbstractDiagram::Private::cachedFontMetrics() const
354 {
355  return mCachedFontMetrics;
356 }
357 
358 QString AbstractDiagram::Private::formatNumber( qreal value, int decimalDigits ) const
359 {
360  const int digits = qMax(decimalDigits, 0);
361  const qreal roundingEpsilon = pow( 0.1, digits ) * ( value >= 0.0 ? 0.5 : -0.5 );
362  QString asString = QString::number( value + roundingEpsilon, 'f' );
363  const int decimalPos = asString.indexOf( QLatin1Char( '.' ) );
364  if ( decimalPos < 0 ) {
365  return asString;
366  }
367 
368  int last = qMin( decimalPos + digits, asString.length() - 1 );
369  // remove trailing zeros (and maybe decimal dot)
370  while ( last > decimalPos && asString[ last ] == QLatin1Char( '0' ) ) {
371  last--;
372  }
373  if ( last == decimalPos ) {
374  last--;
375  }
376  asString.chop( asString.length() - last - 1 );
377  return asString;
378 }
379 
380 void AbstractDiagram::Private::forgetAlreadyPaintedDataValues()
381 {
382  alreadyDrawnDataValueTexts.clear();
383  prevPaintedDataValueText.clear();
384 }
385 
386 void AbstractDiagram::Private::paintDataValueTextsAndMarkers(
387  PaintContext* ctx,
388  const LabelPaintCache &cache,
389  bool paintMarkers,
390  bool justCalculateRect /* = false */,
391  QRectF* cumulatedBoundingRect /* = 0 */ )
392 {
393  if ( justCalculateRect && !cumulatedBoundingRect ) {
394  qWarning() << Q_FUNC_INFO << "Neither painting nor finding the bounding rect, what are we doing?";
395  }
396 
397  const PainterSaver painterSaver( ctx->painter() );
398  ctx->painter()->setClipping( false );
399 
400  if ( paintMarkers && !justCalculateRect ) {
401  KDAB_FOREACH ( const LabelPaintInfo& info, cache.paintReplay ) {
402  diagram->paintMarker( ctx->painter(), info.index, info.markerPos );
403  }
404  }
405 
406  TextAttributes ta;
407  {
410  m.setReferenceArea( ctx->coordinatePlane() );
411  ta.setFontSize( m );
412  m.setAbsoluteValue( 6.0 );
413  ta.setMinimalFontSize( m );
414  }
415 
416  forgetAlreadyPaintedDataValues();
417 
418  KDAB_FOREACH ( const LabelPaintInfo& info, cache.paintReplay ) {
419  const QPointF pos = info.labelArea.elementAt( 0 );
420  paintDataValueText( ctx->painter(), info.attrs, pos, info.isValuePositive,
421  info.value, justCalculateRect, cumulatedBoundingRect );
422 
423  const QString comment = info.index.data( KDChart::CommentRole ).toString();
424  if ( comment.isEmpty() ) {
425  continue;
426  }
427  TextBubbleLayoutItem item( comment, ta, ctx->coordinatePlane()->parent(),
429  Qt::AlignHCenter | Qt::AlignVCenter );
430  const QRect rect( pos.toPoint(), item.sizeHint() );
431 
432  if (cumulatedBoundingRect) {
433  (*cumulatedBoundingRect) |= rect;
434  }
435  if ( !justCalculateRect ) {
436  item.setGeometry( rect );
437  item.paint( ctx->painter() );
438  }
439  }
440  if ( cumulatedBoundingRect ) {
441  *cumulatedBoundingRect = ctx->painter()->transform().inverted().mapRect( *cumulatedBoundingRect );
442  }
443 }
444 
445 QString AbstractDiagram::Private::formatDataValueText( const DataValueAttributes &dva,
446  const QModelIndex& index, qreal value ) const
447 {
448  if ( !dva.isVisible() ) {
449  return QString();
450  }
451  if ( dva.usePercentage() ) {
452  value = calcPercentValue( index );
453  }
454 
455  QString ret;
456  if ( dva.dataLabel().isNull() ) {
457  ret = formatNumber( value, dva.decimalDigits() );
458  } else {
459  ret = dva.dataLabel();
460  }
461 
462  ret.prepend( dva.prefix() );
463  ret.append( dva.suffix() );
464 
465  return ret;
466 }
467 
468 void AbstractDiagram::Private::paintDataValueText(
469  QPainter* painter,
470  const QModelIndex& index,
471  const QPointF& pos,
472  qreal value,
473  bool justCalculateRect /* = false */,
474  QRectF* cumulatedBoundingRect /* = 0 */ )
475 {
476  const DataValueAttributes dva( diagram->dataValueAttributes( index ) );
477  const QString text = formatDataValueText( dva, index, value );
478  paintDataValueText( painter, dva, pos, value >= 0.0, text,
479  justCalculateRect, cumulatedBoundingRect );
480 }
481 
482 void AbstractDiagram::Private::paintDataValueText(
483  QPainter* painter,
484  const DataValueAttributes& attrs,
485  const QPointF& pos,
486  bool valueIsPositive,
487  const QString& text,
488  bool justCalculateRect /* = false */,
489  QRectF* cumulatedBoundingRect /* = 0 */ )
490 {
491  if ( !attrs.isVisible() ) {
492  return;
493  }
494 
495  const TextAttributes ta( attrs.textAttributes() );
496  if ( !ta.isVisible() || ( !attrs.showRepetitiveDataLabels() && prevPaintedDataValueText == text ) ) {
497  return;
498  }
499  prevPaintedDataValueText = text;
500 
501  QTextDocument doc;
502  doc.setDocumentMargin( 0.0 );
503  if ( Qt::mightBeRichText( text ) ) {
504  doc.setHtml( text );
505  } else {
506  doc.setPlainText( text );
507  }
508 
509  const QFont calculatedFont( ta.calculatedFont( plane, KDChartEnums::MeasureOrientationMinimum ) );
510 
511  const PainterSaver painterSaver( painter );
512  painter->setPen( PrintingParameters::scalePen( ta.pen() ) );
513 
514  doc.setDefaultFont( calculatedFont );
515  QAbstractTextDocumentLayout::PaintContext context;
516  context.palette = diagram->palette();
517  context.palette.setColor( QPalette::Text, ta.pen().color() );
518 
519  QAbstractTextDocumentLayout* const layout = doc.documentLayout();
520  layout->setPaintDevice( painter->device() );
521 
522  painter->translate( pos.x(), pos.y() );
523  int rotation = ta.rotation();
524  if ( !valueIsPositive && attrs.mirrorNegativeValueTextRotation() ) {
525  rotation *= -1;
526  }
527  painter->rotate( rotation );
528 
529  // do overlap detection "as seen by the painter"
530  QTransform transform = painter->worldTransform();
531 
532  bool drawIt = true;
533  // note: This flag can be set differently for every label text!
534  // In theory a user could e.g. have some small red text on one of the
535  // values that she wants to have written in any case - so we just
536  // do not test if such texts would cover some of the others.
537  if ( !attrs.showOverlappingDataLabels() ) {
538  const QRectF br( layout->frameBoundingRect( doc.rootFrame() ) );
539  QPolygon pr = transform.mapToPolygon( br.toRect() );
540  // Using QPainterPath allows us to use intersects() (which has many early-exits)
541  // instead of QPolygon::intersected (which calculates a slow and precise intersection polygon)
542  QPainterPath path;
543  path.addPolygon( pr );
544 
545  // iterate backwards because recently added items are more likely to overlap, so we spend
546  // less time checking irrelevant items when there is overlap
547  for ( int i = alreadyDrawnDataValueTexts.count() - 1; i >= 0; i-- ) {
548  if ( alreadyDrawnDataValueTexts.at( i ).intersects( path ) ) {
549  // qDebug() << "not painting this label due to overlap";
550  drawIt = false;
551  break;
552  }
553  }
554  if ( drawIt ) {
555  alreadyDrawnDataValueTexts << path;
556  }
557  }
558 
559  if ( drawIt ) {
560  QRectF rect = layout->frameBoundingRect( doc.rootFrame() );
561  if ( cumulatedBoundingRect ) {
562  (*cumulatedBoundingRect) |= transform.mapRect( rect );
563  }
564  if ( !justCalculateRect ) {
565  bool paintBack = false;
567  if ( back.isVisible() ) {
568  paintBack = true;
569  painter->setBrush( back.brush() );
570  } else {
571  painter->setBrush( QBrush() );
572  }
573 
574  qreal radius = 0.0;
575  FrameAttributes frame( attrs.frameAttributes() );
576  if ( frame.isVisible() ) {
577  paintBack = true;
578  painter->setPen( frame.pen() );
579  radius = frame.cornerRadius();
580  }
581 
582  if ( paintBack ) {
583  QRectF borderRect( QPointF( 0, 0 ), rect.size() );
584  painter->drawRoundedRect( borderRect, radius, radius );
585  }
586  layout->draw( painter, context );
587  }
588  }
589 }
590 
591 QModelIndex AbstractDiagram::Private::indexAt( const QPoint& point ) const
592 {
593  QModelIndexList l = indexesAt( point );
594  qSort( l );
595  if ( !l.isEmpty() )
596  return l.first();
597  else
598  return QModelIndex();
599 }
600 
601 QModelIndexList AbstractDiagram::Private::indexesAt( const QPoint& point ) const
602 {
603  return reverseMapper.indexesAt( point ); // which could be empty
604 }
605 
606 QModelIndexList AbstractDiagram::Private::indexesIn( const QRect& rect ) const
607 {
608  return reverseMapper.indexesIn( rect );
609 }
610 
611 CartesianDiagramDataCompressor::AggregatedDataValueAttributes AbstractDiagram::Private::aggregatedAttrs(
612  const QModelIndex& index,
613  const CartesianDiagramDataCompressor::CachePosition* position ) const
614 {
615  Q_UNUSED( position ); // used by cartesian diagrams only
616  CartesianDiagramDataCompressor::AggregatedDataValueAttributes allAttrs;
617  allAttrs[index] = diagram->dataValueAttributes( index );
618  return allAttrs;
619 }
620 
621 void AbstractDiagram::Private::setDatasetAttrs( int dataset, const QVariant& data, int role )
622 {
623  // To store attributes for a dataset, we use the first column
624  // that's associated with it. (i.e., with a dataset dimension
625  // of two, the column of the keys). In most cases however, there's
626  // only one data dimension, and thus also only one column per data set.
627  int column = dataset * datasetDimension;
628 
629  // For DataHiddenRole, also store the flag in the other data points that belong to this data set,
630  // otherwise it's impossible to hide data points in a plotter diagram because there will always
631  // be one model index that belongs to this data point that is not hidden.
632  // For more details on how hiding works, see the data compressor.
633  // Also see KDCH-503 for which this is a workaround.
634  int columnSpan = role == DataHiddenRole ? datasetDimension : 1;
635 
636  for ( int i = 0; i < columnSpan; i++ ) {
637  attributesModel->setHeaderData( column + i, Qt::Horizontal, data, role );
638  }
639 }
640 
641 QVariant AbstractDiagram::Private::datasetAttrs( int dataset, int role ) const
642 {
643  // See setDataSetAttrs for explanation of column
644  int column = dataset * datasetDimension;
645  return attributesModel->headerData( column, Qt::Horizontal, role );
646 }
647 
648 void AbstractDiagram::Private::resetDatasetAttrs( int dataset, int role )
649 {
650  // See setDataSetAttrs for explanation of column
651  int column = dataset * datasetDimension;
652  attributesModel->resetHeaderData( column, Qt::Horizontal, role );
653 }
654 
655 bool AbstractDiagram::Private::isTransposed() const
656 {
657  // Determine the diagram that specifies the orientation.
658  // That diagram is the reference diagram, if it exists, or otherwise the diagram itself.
659  // Note: In KDChart 2.3 or earlier, only a bar diagram can be transposed.
660  const AbstractCartesianDiagram* refDiagram = qobject_cast< const AbstractCartesianDiagram * >( diagram );
661  if ( !refDiagram ) {
662  return false;
663  }
664  if ( refDiagram->referenceDiagram() ) {
665  refDiagram = refDiagram->referenceDiagram();
666  }
667  const BarDiagram* barDiagram = qobject_cast< const BarDiagram* >( refDiagram );
668  if ( !barDiagram ) {
669  return false;
670  }
671  return barDiagram->orientation() == Qt::Horizontal;
672 }
673 
674 LineAttributesInfo::LineAttributesInfo()
675 {
676 }
677 
678 LineAttributesInfo::LineAttributesInfo( const QModelIndex& _index, const QPointF& _value, const QPointF& _nextValue )
679  : index( _index )
680  , value ( _value )
681  , nextValue ( _nextValue )
682 {
683 }
KDChartEnums::PositionValue
PositionValue
Numerical values of the static KDChart::Position instances, for using a Position::value() with a swit...
Definition: KDChartEnums.h:192
KDChart::Position
Defines a position, using compass terminology.
Definition: KDChartPosition.h:76
KDChart::BarDiagram::orientation
Qt::Orientation orientation() const
Definition: KDChartBarDiagram.cpp:194
KDChart::TextAttributes::hasRotation
bool hasRotation() const
Definition: KDChartTextAttributes.cpp:251
KDChart::DataValueAttributes::showRepetitiveDataLabels
bool showRepetitiveDataLabels() const
Definition: KDChartDataValueAttributes.cpp:269
KDChart::DataValueAttributes::decimalDigits
int decimalDigits() const
Definition: KDChartDataValueAttributes.cpp:234
KDChart::PositionPoints
Stores the absolute target points of a Position.
Definition: KDChartPosition.h:146
KDChart::TextBubbleLayoutItem
Definition: KDChartLayoutItems.h:171
KDChart::TextAttributes::calculatedFont
const QFont calculatedFont(const QObject *autoReferenceArea, KDChartEnums::MeasureOrientation autoReferenceOrientation) const
Returns the font in the size that is used at drawing time.
Definition: KDChartTextAttributes.cpp:185
KDChart::DataValueAttributes::frameAttributes
FrameAttributes frameAttributes() const
Definition: KDChartDataValueAttributes.cpp:184
KDChart::PrivateAttributesModel::PrivateAttributesModel
PrivateAttributesModel(QAbstractItemModel *model, QObject *parent=0)
Definition: KDChartAbstractDiagram.h:733
KDChart::PrintingParameters::scalePen
static QPen scalePen(const QPen &pen)
Definition: KDChartPrintingParameters.cpp:48
KDChart::DataValueAttributes::backgroundAttributes
BackgroundAttributes backgroundAttributes() const
Definition: KDChartDataValueAttributes.cpp:194
KDChart::DataValueAttributes::prefix
QString prefix() const
Returns the string used as a prefix to the data value text.
Definition: KDChartDataValueAttributes.cpp:244
KDChart
Definition: KDChartAbstractCartesianDiagram.h:30
KDChart::PaintContext::coordinatePlane
AbstractCoordinatePlane * coordinatePlane() const
Definition: KDChartPaintContext.cpp:78
KDChart::DataValueAttributes::suffix
QString suffix() const
Returns the string used as a suffix to the data value text.
Definition: KDChartDataValueAttributes.cpp:254
KDChart::DataValueAttributes::usePercentage
bool usePercentage() const
Definition: KDChartDataValueAttributes.cpp:224
KDChart::TextAttributes::pen
QPen pen() const
Definition: KDChartTextAttributes.cpp:261
KDChart::PaintContext
Stores information about painting diagrams.
Definition: KDChartPaintContext.h:42
KDChart::TextAttributes
A set of text attributes.
Definition: KDChartTextAttributes.h:47
KDChart::Measure
Measure is used to specify relative and absolute sizes in KDChart, e.g.
Definition: KDChartMeasure.h:52
KDChart::AbstractCoordinatePlane::parent
Chart * parent()
Definition: KDChartAbstractCoordinatePlane.cpp:198
KDChart::AbstractCartesianDiagram::referenceDiagram
virtual AbstractCartesianDiagram * referenceDiagram() const
Definition: KDChartAbstractCartesianDiagram.cpp:153
KDChart::TextAttributes::isVisible
bool isVisible() const
Definition: KDChartTextAttributes.cpp:123
QTextDocument
Class only listed here to document inheritance of some KDChart classes.
KDChart::PaintContext::painter
QPainter * painter() const
Definition: KDChartPaintContext.cpp:68
QPaintDevice
KDChart::TextAttributes::setMinimalFontSize
void setMinimalFontSize(const Measure &measure)
Set the minimal size of the font used for rendering text.
Definition: KDChartTextAttributes.cpp:150
KDChart::DataValueAttributes::position
const RelativePosition position(bool positive) const
Definition: KDChartDataValueAttributes.h:303
KDChart::AbstractCartesianDiagram
Base class for diagrams based on a cartesian coordianate system.
Definition: KDChartAbstractCartesianDiagram.h:42
KDChart::RelativePosition
Defines relative position information: reference area, position in this area (reference position),...
Definition: KDChartRelativePosition.h:58
KDChart::BackgroundAttributes
Set of attributes usable for background pixmaps.
Definition: KDChartBackgroundAttributes.h:37
KDChart::DataValueAttributes::showOverlappingDataLabels
bool showOverlappingDataLabels() const
Definition: KDChartDataValueAttributes.cpp:279
KDChart::AttributesModel
A proxy model used for decorating data with attributes.
Definition: KDChartAttributesModel.h:47
KDChart::TextAttributes::setFontSize
void setFontSize(const Measure &measure)
Set the size of the font used for rendering text.
Definition: KDChartTextAttributes.cpp:140
KDChartBarDiagram.h
KDChart::FrameAttributes
A set of attributes for frames around items.
Definition: KDChartFrameAttributes.h:37
KDChartFrameAttributes.h
KDChart::DataHiddenRole
@ DataHiddenRole
Definition: KDChartGlobal.h:201
KDChart::DataValueAttributes::textAttributes
TextAttributes textAttributes() const
Definition: KDChartDataValueAttributes.cpp:174
KDChart::DataValueAttributes::isVisible
bool isVisible() const
Definition: KDChartDataValueAttributes.cpp:164
QMap
Definition: KDChartMarkerAttributes.h:35
KDChart::DataValueAttributes::dataLabel
QString dataLabel() const
Returns the string displayed instead of the data value label.
Definition: KDChartDataValueAttributes.cpp:264
KDChart::TextAttributes::setRotation
void setRotation(int rotation)
Set the rotation angle to use for the text.
Definition: KDChartTextAttributes.cpp:234
KDChartEnums::MeasureCalculationModeRelative
@ MeasureCalculationModeRelative
Definition: KDChartEnums.h:223
KDChart::CommentRole
@ CommentRole
Definition: KDChartGlobal.h:203
KDChart::DataValueAttributes
Diagram attributes dealing with data value labels.
Definition: KDChartDataValueAttributes.h:56
KDChart::DataValueAttributes::setTextAttributes
void setTextAttributes(const TextAttributes &a)
Set the text attributes to use for the data value labels.
Definition: KDChartDataValueAttributes.cpp:169
KDChart::PrivateAttributesModel
Internally used class just adding a special constructor used by AbstractDiagram.
Definition: KDChartAbstractDiagram.h:730
KDChartEnums::PositionNorthWest
@ PositionNorthWest
Definition: KDChartEnums.h:195
KDChartEnums::MeasureOrientationMinimum
@ MeasureOrientationMinimum
Definition: KDChartEnums.h:293
KDChart::BarDiagram
BarDiagram defines a common bar diagram.
Definition: KDChartBarDiagram.h:43
KDChart::DataValueAttributes::mirrorNegativeValueTextRotation
bool mirrorNegativeValueTextRotation() const
If true, rotation of negative value labels is negated, so that negative values are rotated in opposit...
Definition: KDChartDataValueAttributes.cpp:214
KDChartEnums::PositionWest
@ PositionWest
Definition: KDChartEnums.h:202
KDChart::AbstractCoordinatePlane
Base class common for all coordinate planes, CartesianCoordinatePlane, PolarCoordinatePlane,...
Definition: KDChartAbstractCoordinatePlane.h:45
KDChart::TextAttributes::rotation
int rotation() const
Definition: KDChartTextAttributes.cpp:240

Klarälvdalens Datakonsult AB (KDAB)
"The Qt, C++ and OpenGL Experts"
https://www.kdab.com/

https://www.kdab.com/development-resources/qt-tools/kd-chart/