KChart

KChartLineDiagram.cpp
1 /*
2  * Copyright (C) 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved.
3  *
4  * This file is part of the KD Chart library.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of
9  * the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <https://www.gnu.org/licenses/>.
18  */
19 
20 #include "KChartLineDiagram.h"
21 #include "KChartLineDiagram_p.h"
22 
23 #include "KChartBarDiagram.h"
24 #include "KChartPalette.h"
25 #include "KChartAttributesModel.h"
26 #include "KChartAbstractGrid.h"
27 #include "KChartPainterSaver_p.h"
28 
29 #include "KChartNormalLineDiagram_p.h"
30 #include "KChartStackedLineDiagram_p.h"
31 #include "KChartPercentLineDiagram_p.h"
32 #include "KChartMath_p.h"
33 
34 #include <QDebug>
35 #include <QPainter>
36 #include <QString>
37 #include <QPainterPath>
38 #include <QPen>
39 #include <QVector>
40 
41 using namespace KChart;
42 
43 LineDiagram::Private::Private()
44 {
45 }
46 
47 LineDiagram::Private::~Private() {}
48 
49 
50 #define d d_func()
51 
52 
53 LineDiagram::LineDiagram( QWidget* parent, CartesianCoordinatePlane* plane ) :
54  AbstractCartesianDiagram( new Private(), parent, plane )
55 {
56  init();
57 }
58 
59 void LineDiagram::init()
60 {
61  d->normalDiagram = new NormalLineDiagram( this );
62  d->stackedDiagram = new StackedLineDiagram( this );
63  d->percentDiagram = new PercentLineDiagram( this );
64  d->implementor = d->normalDiagram;
65  d->centerDataPoints = false;
66  d->reverseDatasetOrder = false;
67 }
68 
69 LineDiagram::~LineDiagram()
70 {
71  delete d->normalDiagram;
72  delete d->stackedDiagram;
73  delete d->percentDiagram;
74 }
75 
77 {
78  LineDiagram* newDiagram = new LineDiagram( new Private( *d ) );
79  newDiagram->setType( type() );
80  return newDiagram;
81 }
82 
83 
84 bool LineDiagram::compare( const LineDiagram* other ) const
85 {
86  if ( other == this ) return true;
87  if ( ! other ) {
88  return false;
89  }
90  return // compare the base class
91  ( static_cast<const AbstractCartesianDiagram*>(this)->compare( other ) ) &&
92  // compare own properties
93  (type() == other->type()) &&
94  (centerDataPoints() == other->centerDataPoints()) &&
95  (reverseDatasetOrder() == other->reverseDatasetOrder());
96 }
97 
98 void LineDiagram::setType( const LineType type )
99 {
100  if ( d->implementor->type() == type ) return;
101  if ( type != LineDiagram::Normal && datasetDimension() > 1 ) {
102  Q_ASSERT_X ( false, "setType()",
103  "This line chart type can't be used with multi-dimensional data." );
104  return;
105  }
106  switch ( type ) {
107  case Normal:
108  d->implementor = d->normalDiagram;
109  break;
110  case Stacked:
111  d->implementor = d->stackedDiagram;
112  break;
113  case Percent:
114  d->implementor = d->percentDiagram;
115  break;
116  default:
117  Q_ASSERT_X( false, "LineDiagram::setType", "unknown diagram subtype" );
118  };
119 
120  // d->lineType = type;
121  Q_ASSERT( d->implementor->type() == type );
122 
123  // AbstractAxis settings - see AbstractDiagram and CartesianAxis
124  setPercentMode( type == LineDiagram::Percent );
125  setDataBoundariesDirty();
126  Q_EMIT layoutChanged( this );
127  Q_EMIT propertiesChanged();
128 }
129 
130 LineDiagram::LineType LineDiagram::type() const
131 {
132  return d->implementor->type();
133 }
134 
136 {
137  if ( d->centerDataPoints == center ) {
138  return;
139  }
140 
141  d->centerDataPoints = center;
142  // The actual data boundaries haven't changed, but the axis will have one more or less tick
143  // A B =\ A B
144  // 1......2 =/ 1......2......3
145  setDataBoundariesDirty();
146  Q_EMIT layoutChanged( this );
147  Q_EMIT propertiesChanged();
148 }
149 
151 {
152  return d->centerDataPoints;
153 }
154 
156 {
157  d->reverseDatasetOrder = reverse;
158 }
159 
161 {
162  return d->reverseDatasetOrder;
163 }
164 
166 {
167  d->attributesModel->setModelData(
168  QVariant::fromValue( la ),
169  LineAttributesRole );
170  Q_EMIT propertiesChanged();
171 }
172 
174  int column,
175  const LineAttributes& la )
176 {
177  d->setDatasetAttrs( column, QVariant::fromValue( la ), LineAttributesRole );
178  Q_EMIT propertiesChanged();
179 }
180 
182 {
183  d->resetDatasetAttrs( column, LineAttributesRole );
184  Q_EMIT propertiesChanged();
185 }
186 
188  const QModelIndex& index,
189  const LineAttributes& la )
190 {
191  d->attributesModel->setData(
192  d->attributesModel->mapFromSource(index),
193  QVariant::fromValue( la ),
194  LineAttributesRole );
195  Q_EMIT propertiesChanged();
196 }
197 
199 {
200  d->attributesModel->resetData(
201  d->attributesModel->mapFromSource(index), LineAttributesRole );
202  Q_EMIT propertiesChanged();
203 }
204 
206 {
207  return d->attributesModel->data( KChart::LineAttributesRole ).value<LineAttributes>();
208 }
209 
211 {
212  const QVariant attrs( d->datasetAttrs( column, LineAttributesRole ) );
213  if ( attrs.isValid() )
214  return attrs.value<LineAttributes>();
215  return lineAttributes();
216 }
217 
219  const QModelIndex& index ) const
220 {
221  return d->attributesModel->data(
222  d->attributesModel->mapFromSource(index),
223  KChart::LineAttributesRole ).value<LineAttributes>();
224 }
225 
227  const ThreeDLineAttributes& la )
228 {
229  setDataBoundariesDirty();
230  d->attributesModel->setModelData(
231  QVariant::fromValue( la ),
232  ThreeDLineAttributesRole );
233  Q_EMIT propertiesChanged();
234 }
235 
237  int column,
238  const ThreeDLineAttributes& la )
239 {
240  setDataBoundariesDirty();
241  d->setDatasetAttrs( column, QVariant::fromValue( la ), ThreeDLineAttributesRole );
242  Q_EMIT propertiesChanged();
243 }
244 
246  const QModelIndex & index,
247  const ThreeDLineAttributes& la )
248 {
249  setDataBoundariesDirty();
250  d->attributesModel->setData(
251  d->attributesModel->mapFromSource(index),
252  QVariant::fromValue( la ),
253  ThreeDLineAttributesRole );
254  Q_EMIT propertiesChanged();
255 }
256 
258 {
259  return d->attributesModel->data( KChart::ThreeDLineAttributesRole ).value<ThreeDLineAttributes>();
260 }
261 
263 {
264  const QVariant attrs( d->datasetAttrs( column, ThreeDLineAttributesRole ) );
265  if ( attrs.isValid() )
266  return attrs.value<ThreeDLineAttributes>();
267  return threeDLineAttributes();
268 }
269 
271 {
272  return d->attributesModel->data(
273  d->attributesModel->mapFromSource( index ),
274  KChart::ThreeDLineAttributesRole ).value<ThreeDLineAttributes>();
275 }
276 
277 qreal LineDiagram::threeDItemDepth( const QModelIndex& index ) const
278 {
279  return threeDLineAttributes( index ).validDepth();
280 }
281 
282 qreal LineDiagram::threeDItemDepth( int column ) const
283 {
284  return threeDLineAttributes( column ).validDepth();
285 }
286 
288  const ValueTrackerAttributes & va )
289 {
290  d->attributesModel->setData( d->attributesModel->mapFromSource(index),
291  QVariant::fromValue( va ),
292  KChart::ValueTrackerAttributesRole );
293  Q_EMIT propertiesChanged();
294 }
295 
297  const QModelIndex & index ) const
298 {
299  return d->attributesModel->data(
300  d->attributesModel->mapFromSource( index ),
301  KChart::ValueTrackerAttributesRole ).value<ValueTrackerAttributes>();
302 }
303 
304 void LineDiagram::resizeEvent ( QResizeEvent* )
305 {
306 }
307 
309 {
310  d->compressor.setResolution( static_cast<int>( this->size().width() * coordinatePlane()->zoomFactorX() ),
311  static_cast<int>( this->size().height() * coordinatePlane()->zoomFactorY() ) );
312 
313  if ( !checkInvariants( true ) ) return QPair<QPointF, QPointF>( QPointF( 0, 0 ), QPointF( 0, 0 ) );
314 
315  // note: calculateDataBoundaries() is ignoring the hidden flags.
316  // That's not a bug but a feature: Hiding data does not mean removing them.
317  // For totally removing data from KD Chart's view people can use e.g. a proxy model ...
318 
319  // calculate boundaries for different line types Normal - Stacked - Percent - Default Normal
320  return d->implementor->calculateDataBoundaries();
321 }
322 
323 
324 void LineDiagram::paintEvent ( QPaintEvent*)
325 {
326  QPainter painter ( viewport() );
327  PaintContext ctx;
328  ctx.setPainter ( &painter );
329  ctx.setRectangle ( QRectF ( 0, 0, width(), height() ) );
330  paint ( &ctx );
331 }
332 
334 {
335  // note: Not having any data model assigned is no bug
336  // but we can not draw a diagram then either.
337  if ( !checkInvariants( true ) ) return;
338  if ( !AbstractGrid::isBoundariesValid(dataBoundaries()) ) return;
339  const PainterSaver p( ctx->painter() );
340  if ( model()->rowCount( rootIndex() ) == 0 || model()->columnCount( rootIndex() ) == 0 )
341  return; // nothing to paint for us
342 
343  AbstractCoordinatePlane* const plane = ctx->coordinatePlane();
344  ctx->setCoordinatePlane( plane->sharedAxisMasterPlane( ctx->painter() ) );
345 
346 
347  // paint different line types Normal - Stacked - Percent - Default Normal
348  d->implementor->paint( ctx );
349 
350  ctx->setCoordinatePlane( plane );
351 }
352 
353 void LineDiagram::resize ( const QSizeF& size )
354 {
355  d->compressor.setResolution( static_cast<int>( size.width() * coordinatePlane()->zoomFactorX() ),
356  static_cast<int>( size.height() * coordinatePlane()->zoomFactorY() ) );
357  setDataBoundariesDirty();
359 }
360 
361 #if defined(Q_COMPILER_MANGLES_RETURN_TYPE)
362 const
363 #endif
364 int LineDiagram::numberOfAbscissaSegments () const
365 {
366  return d->attributesModel->rowCount(attributesModelRootIndex());
367 }
368 
369 #if defined(Q_COMPILER_MANGLES_RETURN_TYPE)
370 const
371 #endif
372 int LineDiagram::numberOfOrdinateSegments () const
373 {
374  return d->attributesModel->columnCount(attributesModelRootIndex());
375 }
bool centerDataPoints() const
Class only listed here to document inheritance of some KChart classes.
A set of 3D line attributes.
bool compare(const LineDiagram *other) const
Returns true if both diagrams have the same settings.
static bool isBoundariesValid(const QRectF &r)
Checks whether both coordinates of r are valid according to isValueValid.
virtual LineDiagram * clone() const
Creates an exact copy of this diagram.
void setType(const LineType type)
Sets the line diagram&#39;s type to type.
qreal threeDItemDepth(const QModelIndex &index) const override
const QPair< QPointF, QPointF > calculateDataBoundaries() const override
T value() const const
void setValueTrackerAttributes(const QModelIndex &index, const ValueTrackerAttributes &a)
Sets the value tracker attributes of the model index index to va.
Set of attributes for changing the appearance of line charts.
void setReverseDatasetOrder(bool reverse)
With this property set to true, data sets in a normal line diagram are drawn in reversed order...
void setCenterDataPoints(bool center)
If centerDataPoints() is true, all data points are moved by an offset of 0.5 to the right...
Stores information about painting diagrams.
Base class for diagrams based on a cartesian coordianate system.
Base class common for all coordinate planes, CartesianCoordinatePlane, PolarCoordinatePlane, TernaryCoordinatePlane.
LineAttributes lineAttributes() const
LineType type() const
Cell-specific attributes regarding value tracking.
QVariant fromValue(const T &value)
QCA_EXPORT void init()
void paint(PaintContext *paintContext) override
Draw the diagram contents to the rectangle and painter, that are passed in as part of the paint conte...
void resetLineAttributes(int column)
Resets the line attributes of data set column.
ValueTrackerAttributes valueTrackerAttributes(const QModelIndex &index) const
Returns the value tracker attributes of the model index index.
virtual void resize(const QSizeF &area)
Called by the widget&#39;s sizeEvent.
void setThreeDLineAttributes(const ThreeDLineAttributes &a)
Sets the global 3D line attributes to la.
ThreeDLineAttributes threeDLineAttributes() const
void resize(const QSizeF &area) override
Called by the widget&#39;s sizeEvent.
bool reverseDatasetOrder() const
LineDiagram defines a common line diagram.
void setLineAttributes(const LineAttributes &a)
Sets the global line attributes to la.
qreal height() const const
Global namespace.
qreal width() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Thu Jan 14 2021 22:38:05 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.