KChart

KChartLineDiagram.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 "KChartLineDiagram.h"
10#include "KChartLineDiagram_p.h"
11
12#include "KChartBarDiagram.h"
13#include "KChartPalette.h"
14#include "KChartAttributesModel.h"
15#include "KChartAbstractGrid.h"
16#include "KChartPainterSaver_p.h"
17
18#include "KChartNormalLineDiagram_p.h"
19#include "KChartStackedLineDiagram_p.h"
20#include "KChartPercentLineDiagram_p.h"
21#include "KChartMath_p.h"
22
23#include <QDebug>
24#include <QPainter>
25#include <QString>
26#include <QPainterPath>
27#include <QPen>
28#include <QVector>
29
30using namespace KChart;
31
32LineDiagram::Private::Private()
33{
34}
35
36LineDiagram::Private::~Private() {}
37
38
39#define d d_func()
40
41
42LineDiagram::LineDiagram( QWidget* parent, CartesianCoordinatePlane* plane ) :
43 AbstractCartesianDiagram( new Private(), parent, plane )
44{
45 init();
46}
47
48void LineDiagram::init()
49{
50 d->normalDiagram = new NormalLineDiagram( this );
51 d->stackedDiagram = new StackedLineDiagram( this );
52 d->percentDiagram = new PercentLineDiagram( this );
53 d->implementor = d->normalDiagram;
54 d->centerDataPoints = false;
55 d->reverseDatasetOrder = false;
56}
57
58LineDiagram::~LineDiagram()
59{
60 delete d->normalDiagram;
61 delete d->stackedDiagram;
62 delete d->percentDiagram;
63}
64
66{
67 LineDiagram* newDiagram = new LineDiagram( new Private( *d ) );
68 newDiagram->setType( type() );
69 return newDiagram;
70}
71
72
73bool LineDiagram::compare( const LineDiagram* other ) const
74{
75 if ( other == this ) return true;
76 if ( ! other ) {
77 return false;
78 }
79 return // compare the base class
80 ( static_cast<const AbstractCartesianDiagram*>(this)->compare( other ) ) &&
81 // compare own properties
82 (type() == other->type()) &&
83 (centerDataPoints() == other->centerDataPoints()) &&
84 (reverseDatasetOrder() == other->reverseDatasetOrder());
85}
86
87void LineDiagram::setType( const LineType type )
88{
89 if ( d->implementor->type() == type ) return;
90 if ( type != LineDiagram::Normal && datasetDimension() > 1 ) {
91 Q_ASSERT_X ( false, "setType()",
92 "This line chart type can't be used with multi-dimensional data." );
93 return;
94 }
95 switch ( type ) {
96 case Normal:
97 d->implementor = d->normalDiagram;
98 break;
99 case Stacked:
100 d->implementor = d->stackedDiagram;
101 break;
102 case Percent:
103 d->implementor = d->percentDiagram;
104 break;
105 default:
106 Q_ASSERT_X( false, "LineDiagram::setType", "unknown diagram subtype" );
107 };
108
109 // d->lineType = type;
110 Q_ASSERT( d->implementor->type() == type );
111
112 // AbstractAxis settings - see AbstractDiagram and CartesianAxis
113 setPercentMode( type == LineDiagram::Percent );
114 setDataBoundariesDirty();
115 Q_EMIT layoutChanged( this );
117}
118
119LineDiagram::LineType LineDiagram::type() const
120{
121 return d->implementor->type();
122}
123
125{
126 if ( d->centerDataPoints == center ) {
127 return;
128 }
129
130 d->centerDataPoints = center;
131 // The actual data boundaries haven't changed, but the axis will have one more or less tick
132 // A B =\ A B
133 // 1......2 =/ 1......2......3
134 setDataBoundariesDirty();
135 Q_EMIT layoutChanged( this );
137}
138
140{
141 return d->centerDataPoints;
142}
143
145{
146 d->reverseDatasetOrder = reverse;
147}
148
150{
151 return d->reverseDatasetOrder;
152}
153
155{
156 d->attributesModel->setModelData(
158 LineAttributesRole );
160}
161
163 int column,
164 const LineAttributes& la )
165{
166 d->setDatasetAttrs( column, QVariant::fromValue( la ), LineAttributesRole );
168}
169
171{
172 d->resetDatasetAttrs( column, LineAttributesRole );
174}
175
177 const QModelIndex& index,
178 const LineAttributes& la )
179{
180 d->attributesModel->setData(
181 d->attributesModel->mapFromSource(index),
183 LineAttributesRole );
185}
186
188{
189 d->attributesModel->resetData(
190 d->attributesModel->mapFromSource(index), LineAttributesRole );
192}
193
195{
196 return d->attributesModel->data( KChart::LineAttributesRole ).value<LineAttributes>();
197}
198
200{
201 const QVariant attrs( d->datasetAttrs( column, LineAttributesRole ) );
202 if ( attrs.isValid() )
203 return attrs.value<LineAttributes>();
204 return lineAttributes();
205}
206
208 const QModelIndex& index ) const
209{
210 return d->attributesModel->data(
211 d->attributesModel->mapFromSource(index),
212 KChart::LineAttributesRole ).value<LineAttributes>();
213}
214
216 const ThreeDLineAttributes& la )
217{
218 setDataBoundariesDirty();
219 d->attributesModel->setModelData(
221 ThreeDLineAttributesRole );
223}
224
226 int column,
227 const ThreeDLineAttributes& la )
228{
229 setDataBoundariesDirty();
230 d->setDatasetAttrs( column, QVariant::fromValue( la ), ThreeDLineAttributesRole );
232}
233
235 const QModelIndex & index,
236 const ThreeDLineAttributes& la )
237{
238 setDataBoundariesDirty();
239 d->attributesModel->setData(
240 d->attributesModel->mapFromSource(index),
242 ThreeDLineAttributesRole );
244}
245
247{
248 return d->attributesModel->data( KChart::ThreeDLineAttributesRole ).value<ThreeDLineAttributes>();
249}
250
252{
253 const QVariant attrs( d->datasetAttrs( column, ThreeDLineAttributesRole ) );
254 if ( attrs.isValid() )
255 return attrs.value<ThreeDLineAttributes>();
256 return threeDLineAttributes();
257}
258
260{
261 return d->attributesModel->data(
262 d->attributesModel->mapFromSource( index ),
263 KChart::ThreeDLineAttributesRole ).value<ThreeDLineAttributes>();
264}
265
266qreal LineDiagram::threeDItemDepth( const QModelIndex& index ) const
267{
268 return threeDLineAttributes( index ).validDepth();
269}
270
271qreal LineDiagram::threeDItemDepth( int column ) const
272{
273 return threeDLineAttributes( column ).validDepth();
274}
275
277 const ValueTrackerAttributes & va )
278{
279 d->attributesModel->setData( d->attributesModel->mapFromSource(index),
281 KChart::ValueTrackerAttributesRole );
283}
284
286 const QModelIndex & index ) const
287{
288 return d->attributesModel->data(
289 d->attributesModel->mapFromSource( index ),
290 KChart::ValueTrackerAttributesRole ).value<ValueTrackerAttributes>();
291}
292
293void LineDiagram::resizeEvent ( QResizeEvent* )
294{
295}
296
297const QPair<QPointF, QPointF> LineDiagram::calculateDataBoundaries() const
298{
299 d->compressor.setResolution( static_cast<int>( this->size().width() * coordinatePlane()->zoomFactorX() ),
300 static_cast<int>( this->size().height() * coordinatePlane()->zoomFactorY() ) );
301
302 if ( !checkInvariants( true ) ) return QPair<QPointF, QPointF>( QPointF( 0, 0 ), QPointF( 0, 0 ) );
303
304 // note: calculateDataBoundaries() is ignoring the hidden flags.
305 // That's not a bug but a feature: Hiding data does not mean removing them.
306 // For totally removing data from KD Chart's view people can use e.g. a proxy model ...
307
308 // calculate boundaries for different line types Normal - Stacked - Percent - Default Normal
309 return d->implementor->calculateDataBoundaries();
310}
311
312
313void LineDiagram::paintEvent ( QPaintEvent*)
314{
315 QPainter painter ( viewport() );
317 ctx.setPainter ( &painter );
318 ctx.setRectangle ( QRectF ( 0, 0, width(), height() ) );
319 paint ( &ctx );
320}
321
323{
324 // note: Not having any data model assigned is no bug
325 // but we can not draw a diagram then either.
326 if ( !checkInvariants( true ) ) return;
328 const PainterSaver p( ctx->painter() );
329 if ( model()->rowCount( rootIndex() ) == 0 || model()->columnCount( rootIndex() ) == 0 )
330 return; // nothing to paint for us
331
332 AbstractCoordinatePlane* const plane = ctx->coordinatePlane();
333 ctx->setCoordinatePlane( plane->sharedAxisMasterPlane( ctx->painter() ) );
334
335
336 // paint different line types Normal - Stacked - Percent - Default Normal
337 d->implementor->paint( ctx );
338
339 ctx->setCoordinatePlane( plane );
340}
341
342void LineDiagram::resize ( const QSizeF& size )
343{
344 d->compressor.setResolution( static_cast<int>( size.width() * coordinatePlane()->zoomFactorX() ),
345 static_cast<int>( size.height() * coordinatePlane()->zoomFactorY() ) );
346 setDataBoundariesDirty();
348}
349
350#if defined(Q_COMPILER_MANGLES_RETURN_TYPE)
351const
352#endif
353int LineDiagram::numberOfAbscissaSegments () const
354{
355 return d->attributesModel->rowCount(attributesModelRootIndex());
356}
357
358#if defined(Q_COMPILER_MANGLES_RETURN_TYPE)
359const
360#endif
361int LineDiagram::numberOfOrdinateSegments () const
362{
363 return d->attributesModel->columnCount(attributesModelRootIndex());
364}
Base class for diagrams based on a cartesian coordianate system.
Base class common for all coordinate planes, CartesianCoordinatePlane, PolarCoordinatePlane,...
QModelIndex attributesModelRootIndex() const
const QPair< QPointF, QPointF > dataBoundaries() const
Return the bottom left and top right data point, that the diagram will display (unless the grid adjus...
void propertiesChanged()
Emitted upon change of a property of the Diagram.
void layoutChanged(KChart::AbstractDiagram *)
Diagrams are supposed to emit this signal, when the layout of one of their element changes.
AbstractCoordinatePlane * coordinatePlane() const
The coordinate plane associated with the diagram.
void setPercentMode(bool percent)
Deprecated method that turns the percent mode of this diagram on or off.
int datasetDimension() const
The dataset dimension of a diagram determines how many value dimensions it expects each datapoint to ...
static bool isBoundariesValid(const QRectF &r)
Checks whether both coordinates of r are valid according to isValueValid.
Set of attributes for changing the appearance of line charts.
LineDiagram defines a common line diagram.
void setType(const LineType type)
Sets the line diagram's type to type.
LineAttributes lineAttributes() const
void setLineAttributes(const LineAttributes &a)
Sets the global line attributes to la.
void setCenterDataPoints(bool center)
If centerDataPoints() is true, all data points are moved by an offset of 0.5 to the right.
void setValueTrackerAttributes(const QModelIndex &index, const ValueTrackerAttributes &a)
Sets the value tracker attributes of the model index index to va.
qreal threeDItemDepth(const QModelIndex &index) const override
void setThreeDLineAttributes(const ThreeDLineAttributes &a)
Sets the global 3D line attributes to la.
virtual LineDiagram * clone() const
Creates an exact copy of this diagram.
void resize(const QSizeF &area) override
Called by the widget's sizeEvent.
ThreeDLineAttributes threeDLineAttributes() const
const QPair< QPointF, QPointF > calculateDataBoundaries() const override
\reimpl
void resetLineAttributes(int column)
Resets the line attributes of data set column.
void setReverseDatasetOrder(bool reverse)
With this property set to true, data sets in a normal line diagram are drawn in reversed order.
void paint(PaintContext *paintContext) override
Draw the diagram contents to the rectangle and painter, that are passed in as part of the paint conte...
ValueTrackerAttributes valueTrackerAttributes(const QModelIndex &index) const
Returns the value tracker attributes of the model index index.
bool compare(const LineDiagram *other) const
Returns true if both diagrams have the same settings.
Stores information about painting diagrams.
Cell-specific attributes regarding value tracking.
QCA_EXPORT void init()
QAbstractItemModel * model() const const
QModelIndex rootIndex() const const
QWidget * viewport() const const
Q_EMITQ_EMIT
T qobject_cast(QObject *object)
QVariant fromValue(T &&value)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:14:24 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.