KD Chart 2  [rev.2.7]
KDChartBarDiagram_p.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 ** Copyright (C) 2001-2020 Klaralvdalens Datakonsult AB. All rights reserved.
3 **
4 ** This file is part of the KD Chart library.
5 **
6 ** Licensees holding valid commercial KD Chart licenses may use this file in
7 ** accordance with the KD Chart Commercial License Agreement provided with
8 ** the Software.
9 **
10 **
11 ** This file may be distributed and/or modified under the terms of the
12 ** GNU General Public License version 2 and version 3 as published by the
13 ** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
14 **
15 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17 **
18 ** Contact info@kdab.com if any conditions of this licensing are not
19 ** clear to you.
20 **
21 **********************************************************************/
22 
23 #include "KDChartBarDiagram.h"
24 #include "KDChartBarDiagram_p.h"
25 
27 #include "KDChartPainterSaver_p.h"
28 
29 using namespace KDChart;
30 
31 BarDiagram::Private::Private( const Private& rhs )
32  : AbstractCartesianDiagram::Private( rhs )
33 {
34 }
35 
36 void BarDiagram::BarDiagramType::paintBars( PaintContext* ctx, const QModelIndex& index, const QRectF& bar, qreal maxDepth )
37 {
38  PainterSaver painterSaver( ctx->painter() );
39 
40  //Pending Michel: configure threeDBrush settings - shadowColor etc...
41  QBrush indexBrush( diagram()->brush( index ) );
42  QPen indexPen( diagram()->pen( index ) );
43 
44  ctx->painter()->setRenderHint( QPainter::Antialiasing, diagram()->antiAliasing() );
45  ThreeDBarAttributes threeDAttrs = diagram()->threeDBarAttributes( index );
46  if ( threeDAttrs.isEnabled() ) {
47  indexBrush = threeDAttrs.threeDBrush( indexBrush, bar );
48  }
49  ctx->painter()->setBrush( indexBrush );
50  ctx->painter()->setPen( PrintingParameters::scalePen( indexPen ) );
51 
52  if ( threeDAttrs.isEnabled() ) {
53  if ( maxDepth ) {
54  threeDAttrs.setDepth( -maxDepth );
55  }
56  //fixme adjust the painting to reasonable depth value
57  const qreal usedDepth = threeDAttrs.depth() * ( type() == BarDiagram::Normal ? 0.25 : 1.0 );
58 
59  const QRectF isoRect = bar.translated( usedDepth, -usedDepth );
60  // we need to find out if the height is negative
61  // and in this case paint it up and down
62  QPolygonF topPoints;
63  if ( isoRect.height() < 0 ) {
64  if ( !( type() == BarDiagram::Stacked && index.column() != 0 ) ) {
65  // fix it when several negative stacked values
66  topPoints << isoRect.bottomLeft() << isoRect.bottomRight()
67  << bar.bottomRight() << bar.bottomLeft();
68  }
69  } else {
70  reverseMapper().addRect( index.row(), index.column(), isoRect );
71  ctx->painter()->drawRect( isoRect );
72  if ( !( type() == BarDiagram::Percent && isoRect.height() == 0 ) ) {
73  topPoints << bar.topLeft() << bar.topRight() << isoRect.topRight() << isoRect.topLeft();
74  }
75  }
76 
77  bool noClippingForTop = false;
78  if ( !topPoints.isEmpty() ) {
79  // Draw the top, if at least one of the top's points is
80  // either inside or near at the edge of the coordinate plane:
81  bool drawIt = false;
82  bool hasPointOutside = false;
83  const QRectF r( ctx->rectangle().adjusted( 0, -1, 1, 0 ) );
84  KDAB_FOREACH( QPointF pt, topPoints ) {
85  if ( r.contains( pt ) ) {
86  drawIt = true;
87  } else {
88  hasPointOutside = true;
89  }
90  }
91  if ( drawIt ) {
92  const PainterSaver p( ctx->painter() );
93  noClippingForTop = hasPointOutside && ctx->painter()->hasClipping();
94  if ( noClippingForTop ) {
95  ctx->painter()->setClipping( false );
96  }
97  reverseMapper().addPolygon( index.row(), index.column(), topPoints );
98  ctx->painter()->drawPolygon( topPoints );
99  }
100  }
101 
102  if ( bar.height() != 0 ) {
103  const PainterSaver p( ctx->painter() );
104  if ( noClippingForTop ) {
105  ctx->painter()->setClipping( false );
106  }
107  QPolygonF sidePoints;
108  sidePoints << bar.topRight() << isoRect.topRight()
109  << isoRect.bottomRight() << bar.bottomRight();
110  reverseMapper().addPolygon( index.row(), index.column(), sidePoints );
111  ctx->painter()->drawPolygon( sidePoints );
112  }
113  }
114 
115  if ( bar.height() != 0 ) {
116  reverseMapper().addRect( index.row(), index.column(), bar );
117  ctx->painter()->drawRect( bar );
118  }
119 }
120 
121 AttributesModel* BarDiagram::BarDiagramType::attributesModel() const
122 {
123  return m_private->attributesModel;
124 }
125 
126 QModelIndex BarDiagram::BarDiagramType::attributesModelRootIndex() const
127 {
128  return diagram()->attributesModelRootIndex();
129 }
130 
131 BarDiagram* BarDiagram::BarDiagramType::diagram() const
132 {
133  return static_cast< BarDiagram* >( m_private->diagram );
134 }
135 
136 void BarDiagram::BarDiagramType::calculateValueAndGapWidths( int rowCount, int colCount,
137  qreal groupWidth,
138  qreal& outBarWidth,
139  qreal& outSpaceBetweenBars,
140  qreal& outSpaceBetweenGroups )
141 {
142 
143  Q_UNUSED( rowCount );
144  BarAttributes ba = diagram()->barAttributes();
145 
146  // Pending Michel Fixme
147  /* We are colCount groups to paint. Each group is centered around the
148  * horizontal point position on the grid. The full area covers the
149  * values -1 to colCount + 1. A bar has a relative width of one unit,
150  * the gaps between bars are 0.5 wide, and the gap between groups is
151  * also one unit, by default. */
152 
153  qreal units;
154  if ( type() == Normal ) {
155  units = colCount // number of bars in group * 1.0
156  + (colCount-1) * ba.barGapFactor() // number of bar gaps
157  + 1 * ba.groupGapFactor(); // number of group gaps
158  } else {
159  units = 1 + 1 * ba.groupGapFactor();
160  }
161 
162  qreal unitWidth = groupWidth / units;
163 
164  if ( !ba.useFixedBarWidth() ) {
165  outBarWidth = unitWidth;
166  }
167 
168  outSpaceBetweenBars += unitWidth * ba.barGapFactor();
169 
170  // Pending Michel - minLimit: allow space between bars to be reduced until the bars are displayed next to each other.
171  // is that what we want?
172  // sebsauer; in the case e.g. CartesianCoordinatePlane::setHorizontalRangeReversed(true) was
173  // used to reverse the values, we deal with negative outSpaceBetweenBars and unitWidth here
174  // and since that's correct we don't like to lose e.g. the spacing here.
175  //if ( outSpaceBetweenBars < 0 )
176  // outSpaceBetweenBars = 0;
177 
178  outSpaceBetweenGroups += unitWidth * ba.groupGapFactor();
179 }
180 
181 ReverseMapper& BarDiagram::BarDiagramType::reverseMapper()
182 {
183  return m_private->reverseMapper;
184 }
185 
186 CartesianDiagramDataCompressor& BarDiagram::BarDiagramType::compressor() const
187 {
188  return m_private->compressor;
189 }
const QRectF rectangle() const
Set of attributes for changing the appearance of bar charts.
Declaring the class KDChart::DataValueAttributes.
QPainter * painter() const
BarDiagram defines a common bar diagram.
QBrush brush() const
Retrieve the brush to be used for painting datapoints globally.
The ReverseMapper stores information about objects on a chart and their respective model indexes...
Definition: ReverseMapper.h:44
A proxy model used for decorating data with attributes.
Base class for diagrams based on a cartesian coordianate system.
Stores information about painting diagrams.
A set of 3D bar attributes.
QPen pen() const
Retrieve the pen to be used for painting datapoints globally.
virtual QBrush threeDBrush(const QBrush &brush, const QRectF &rect) const
static QPen scalePen(const QPen &pen)

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/