KChart

KChartPolarDiagram.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 "KChartPolarDiagram.h"
10#include "KChartPolarDiagram_p.h"
11
12#include "KChartPaintContext.h"
13#include "KChartPainterSaver_p.h"
14#include "KChartMath_p.h"
15
16#include <QPainter>
17
18using namespace KChart;
19
20PolarDiagram::Private::Private() :
21 rotateCircularLabels( false ),
22 closeDatasets( false )
23{
24}
25
26PolarDiagram::Private::~Private() {}
27
28#define d d_func()
29
30PolarDiagram::PolarDiagram( QWidget* parent, PolarCoordinatePlane* plane ) :
31 AbstractPolarDiagram( new Private( ), parent, plane )
32{
33 //init();
34}
35
36PolarDiagram::~PolarDiagram()
37{
38}
39
40
41void PolarDiagram::init()
42{
43 setShowDelimitersAtPosition( Position::Unknown, false );
44 setShowDelimitersAtPosition( Position::Center, false );
45 setShowDelimitersAtPosition( Position::NorthWest, false );
46 setShowDelimitersAtPosition( Position::North, true );
47 setShowDelimitersAtPosition( Position::NorthEast, false );
48 setShowDelimitersAtPosition( Position::West, false );
49 setShowDelimitersAtPosition( Position::East, false );
50 setShowDelimitersAtPosition( Position::SouthWest, false );
51 setShowDelimitersAtPosition( Position::South, true );
52 setShowDelimitersAtPosition( Position::SouthEast, false );
53 setShowDelimitersAtPosition( Position::Floating, false );
54
55 setShowLabelsAtPosition( Position::Unknown, false );
56 setShowLabelsAtPosition( Position::Center, false );
57 setShowLabelsAtPosition( Position::NorthWest, false );
58 setShowLabelsAtPosition( Position::North, true );
59 setShowLabelsAtPosition( Position::NorthEast, false );
60 setShowLabelsAtPosition( Position::West, false );
61 setShowLabelsAtPosition( Position::East, false );
62 setShowLabelsAtPosition( Position::SouthWest, false );
63 setShowLabelsAtPosition( Position::South, true );
64 setShowLabelsAtPosition( Position::SouthEast, false );
65 setShowLabelsAtPosition( Position::Floating, false );
66}
67
69{
70 PolarDiagram* newDiagram = new PolarDiagram( new Private( *d ) );
71 // This needs to be copied after the fact
72 newDiagram->d->showDelimitersAtPosition = d->showDelimitersAtPosition;
73 newDiagram->d->showLabelsAtPosition = d->showLabelsAtPosition;
74 newDiagram->d->rotateCircularLabels = d->rotateCircularLabels;
75 newDiagram->d->closeDatasets = d->closeDatasets;
76 return newDiagram;
77}
78
79const QPair<QPointF, QPointF> PolarDiagram::calculateDataBoundaries () const
80{
81 if ( !checkInvariants(true) ) return QPair<QPointF, QPointF>( QPointF( 0, 0 ), QPointF( 0, 0 ) );
82 const int rowCount = model()->rowCount(rootIndex());
83 const int colCount = model()->columnCount(rootIndex());
84 qreal xMin = 0.0;
85 qreal xMax = colCount;
86 qreal yMin = 0, yMax = 0;
87 for ( int iCol=0; iCol<colCount; ++iCol ) {
88 for ( int iRow=0; iRow< rowCount; ++iRow ) {
89 qreal value = model()->data( model()->index( iRow, iCol, rootIndex() ) ).toReal(); // checked
90 yMax = qMax( yMax, value );
91 yMin = qMin( yMin, value );
92 }
93 }
94 QPointF bottomLeft ( QPointF( xMin, yMin ) );
95 QPointF topRight ( QPointF( xMax, yMax ) );
96 return QPair<QPointF, QPointF> ( bottomLeft, topRight );
97}
98
99
100
101void PolarDiagram::paintEvent ( QPaintEvent*)
102{
103 QPainter painter ( viewport() );
104 PaintContext ctx;
105 ctx.setPainter ( &painter );
106 ctx.setRectangle( QRectF ( 0, 0, width(), height() ) );
107 paint ( &ctx );
108}
109
110void PolarDiagram::resizeEvent ( QResizeEvent*)
111{
112}
113
114void PolarDiagram::paintPolarMarkers( PaintContext* ctx, const QPolygonF& polygon )
115{
116 Q_UNUSED(ctx);
117 Q_UNUSED(polygon);
118 // obsolete, since we are using real markers now!
119}
120
122{
123 qreal dummy1, dummy2;
124 paint( ctx, true, dummy1, dummy2 );
125 paint( ctx, false, dummy1, dummy2 );
126}
127
129 bool calculateListAndReturnScale,
130 qreal& newZoomX, qreal& newZoomY )
131{
132 // note: Not having any data model assigned is no bug
133 // but we can not draw a diagram then either.
134 if ( !checkInvariants(true) )
135 return;
136 d->reverseMapper.clear();
137
138 const int rowCount = model()->rowCount( rootIndex() );
139 const int colCount = model()->columnCount( rootIndex() );
140
141 if ( calculateListAndReturnScale ) {
142 // Check if all of the data value texts / data comments fit into the available space...
143 d->labelPaintCache.clear();
144
145 for ( int iCol = 0; iCol < colCount; ++iCol ) {
146 for ( int iRow=0; iRow < rowCount; ++iRow ) {
147 QModelIndex index = model()->index( iRow, iCol, rootIndex() ); // checked
148 const qreal value = model()->data( index ).toReal();
150 QPointF( value, iRow ) ) + ctx->rectangle().topLeft();
151 //qDebug() << point;
152 d->addLabel( &d->labelPaintCache, index, nullptr, PositionPoints( point ),
153 Position::Center, Position::Center, value );
154 }
155 }
156
157 newZoomX = coordinatePlane()->zoomFactorX();
158 newZoomY = coordinatePlane()->zoomFactorY();
159
160 if ( d->labelPaintCache.paintReplay.count() ) {
161 // ...and zoom out if necessary
162 const qreal oldZoomX = newZoomX;
163 const qreal oldZoomY = newZoomY;
164
165 QRectF txtRectF;
166 d->paintDataValueTextsAndMarkers( ctx, d->labelPaintCache, true, true, &txtRectF );
167 const QRect txtRect = txtRectF.toRect();
168 const QRect curRect = coordinatePlane()->geometry();
169 const qreal gapX = qMin( txtRect.left() - curRect.left(), curRect.right() - txtRect.right() );
170 const qreal gapY = qMin( txtRect.top() - curRect.top(), curRect.bottom() - txtRect.bottom() );
171 if ( gapX < 0.0 ) {
172 newZoomX = oldZoomX * ( 1.0 + ( gapX - 1.0 ) / curRect.width() );
173 }
174 if ( gapY < 0.0 ) {
175 newZoomY = oldZoomY * ( 1.0 + ( gapY - 1.0 ) / curRect.height() );
176 }
177 }
178 } else {
179 // Paint the data sets
180 for ( int iCol = 0; iCol < colCount; ++iCol ) {
181 //TODO(khz): As of yet PolarDiagram can not show per-segment line attributes
182 // but it draws every polyline in one go - using one color.
183 // This needs to be enhanced to allow for cell-specific settings
184 // in the same way as LineDiagram does it.
185 QBrush brush = d->datasetAttrs( iCol, KChart::DatasetBrushRole ).value<QBrush>();
186 QPolygonF polygon;
187 for ( int iRow = 0; iRow < rowCount; ++iRow ) {
188 QModelIndex index = model()->index( iRow, iCol, rootIndex() ); // checked
189 const qreal value = model()->data( index ).toReal();
190 QPointF point = coordinatePlane()->translate( QPointF( value, iRow ) )
191 + ctx->rectangle().topLeft();
192 polygon.append( point );
193 //qDebug() << point;
194 }
195 if ( closeDatasets() && !polygon.isEmpty() ) {
196 // close the circle by connecting the last data point to the first
197 polygon.append( polygon.first() );
198 }
199
200 PainterSaver painterSaver( ctx->painter() );
201 ctx->painter()->setRenderHint ( QPainter::Antialiasing );
202 ctx->painter()->setBrush( brush );
203 QPen p = d->datasetAttrs( iCol, KChart::DatasetPenRole ).value< QPen >();
204 if ( p.style() != Qt::NoPen )
205 {
206 ctx->painter()->setPen( PrintingParameters::scalePen( p ) );
207 ctx->painter()->drawPolyline( polygon );
208 }
209 }
210 d->paintDataValueTextsAndMarkers( ctx, d->labelPaintCache, true );
211 }
212}
213
218
219/*virtual*/
221{
222 return model()->rowCount(rootIndex());
223}
224
225/*virtual*/
227{
228 return model() ? model()->rowCount(rootIndex()) : 0.0;
229}
230
231/*virtual*/
233{
234 return 5; // FIXME
235}
236
238{
239 Q_UNUSED( degrees );
240 qWarning() << "Deprecated PolarDiagram::setZeroDegreePosition() called, setting ignored.";
241}
242
244{
245 qWarning() << "Deprecated PolarDiagram::zeroDegreePosition() called.";
246 return 0;
247}
248
249void PolarDiagram::setRotateCircularLabels( bool rotateCircularLabels )
250{
251 d->rotateCircularLabels = rotateCircularLabels;
252}
253
254bool PolarDiagram::rotateCircularLabels() const
255{
256 return d->rotateCircularLabels;
257}
258
259void PolarDiagram::setCloseDatasets( bool closeDatasets )
260{
261 d->closeDatasets = closeDatasets;
262}
263
264bool PolarDiagram::closeDatasets() const
265{
266 return d->closeDatasets;
267}
268
269void PolarDiagram::setShowDelimitersAtPosition( Position position,
270 bool showDelimiters )
271{
272 d->showDelimitersAtPosition[position.value()] = showDelimiters;
273}
274
275void PolarDiagram::setShowLabelsAtPosition( Position position,
276 bool showLabels )
277{
278 d->showLabelsAtPosition[position.value()] = showLabels;
279}
280
281bool PolarDiagram::showDelimitersAtPosition( Position position ) const
282{
283 return d->showDelimitersAtPosition[position.value()];
284}
285
286bool PolarDiagram::showLabelsAtPosition( Position position ) const
287{
288 return d->showLabelsAtPosition[position.value()];
289}
290
291
292
virtual const QPointF translate(const QPointF &diagramPoint) const =0
Translate the given point in value space coordinates to a position in pixel space.
QRect geometry() const override
pure virtual in QLayoutItem
AbstractCoordinatePlane * coordinatePlane() const
The coordinate plane associated with the diagram.
QBrush brush() const
Retrieve the brush to be used for painting datapoints globally.
Base class for diagrams based on a polar coordinate system.
Stores information about painting diagrams.
PolarDiagram defines a common polar diagram.
virtual PolarDiagram * clone() const
Creates an exact copy of this diagram.
void paint(PaintContext *paintContext) override
\reimpl
qreal numberOfValuesPerDataset() const override
\reimpl
void setZeroDegreePosition(int degrees)
void resize(const QSizeF &area) override
\reimpl
void setCloseDatasets(bool closeDatasets)
Close each of the data series by connecting the last point to its respective start point.
qreal valueTotals() const override
\reimpl
const QPair< QPointF, QPointF > calculateDataBoundaries() const override
\reimpl
qreal numberOfGridRings() const override
\reimpl
Stores the absolute target points of a Position.
Defines a position, using compass terminology.
KChartEnums::PositionValue value() const
Returns an integer value corresponding to this Position.
virtual int columnCount(const QModelIndex &parent) const const=0
virtual QVariant data(const QModelIndex &index, int role) const const=0
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const=0
virtual int rowCount(const QModelIndex &parent) const const=0
QAbstractItemModel * model() const const
QModelIndex rootIndex() const const
QWidget * viewport() const const
void drawPolyline(const QPoint *points, int pointCount)
void setBrush(Qt::BrushStyle style)
void setPen(Qt::PenStyle style)
void setRenderHint(RenderHint hint, bool on)
Qt::PenStyle style() const const
int bottom() const const
int height() const const
int left() const const
int right() const const
int top() const const
int width() const const
QRect toRect() const const
QPointF topLeft() const const
qreal toReal(bool *ok) const const
void resize(const QSize &)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Jul 26 2024 11:51:58 by doxygen 1.11.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.