KD Chart 2  [rev.2.7]
KDChartStockDiagram.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 "KDChartStockDiagram.h"
24 #include "KDChartStockDiagram_p.h"
25 
26 #include "KDChartPaintContext.h"
27 #include "KDChartPainterSaver_p.h"
28 
29 using namespace KDChart;
30 
31 #define d d_func()
32 
34  : AbstractCartesianDiagram( new Private(), parent, plane )
35 {
36  init();
37 }
38 
39 StockDiagram::~StockDiagram()
40 {
41 }
42 
46 void StockDiagram::init()
47 {
48  d->diagram = this;
49  d->compressor.setModel( attributesModel() );
50 
51  // Set properties to defaults
52  d->type = HighLowClose;
53  d->upTrendCandlestickBrush = QBrush( Qt::white );
54  d->downTrendCandlestickBrush = QBrush( Qt::black );
55  d->upTrendCandlestickPen = QPen( Qt::black );
56  d->downTrendCandlestickPen = QPen( Qt::black );
57 
58  d->lowHighLinePen = QPen( Qt::black );
60  //setDatasetDimension( 3 );
61 
62  setPen( QPen( Qt::black ) );
63 }
64 
70 {
71  d->type = type;
72  emit propertiesChanged();
73 }
74 
79 {
80  return d->type;
81 }
82 
84 {
86  qVariantFromValue( attr ),
88  emit propertiesChanged();
89 }
90 
92 {
94 }
95 
96 void StockDiagram::setStockBarAttributes( int column, const StockBarAttributes &attr )
97 {
98  d->setDatasetAttrs( column, qVariantFromValue( attr ), StockBarAttributesRole );
99  emit propertiesChanged();
100 }
101 
103 {
104  const QVariant attr( d->datasetAttrs( column, StockBarAttributesRole ) );
105  if ( attr.isValid() )
106  return attr.value<StockBarAttributes>();
107  return stockBarAttributes();
108 }
109 
116 {
118  qVariantFromValue( attr ),
120  emit propertiesChanged();
121 }
122 
129 {
131 }
132 
142 void StockDiagram::setThreeDBarAttributes( int column, const ThreeDBarAttributes &attr )
143 {
144  d->setDatasetAttrs( column, qVariantFromValue( attr ), StockBarAttributesRole );
145  emit propertiesChanged();
146 }
147 
158 {
159  const QVariant attr( d->datasetAttrs( column, ThreeDBarAttributesRole ) );
160  if ( attr.isValid() )
161  return attr.value<ThreeDBarAttributes>();
162  return threeDBarAttributes();
163 }
164 
165 
166 void StockDiagram::setLowHighLinePen( const QPen &pen )
167 {
168  d->lowHighLinePen = pen;
169 }
170 
171 QPen StockDiagram::lowHighLinePen() const
172 {
173  return d->lowHighLinePen;
174 }
175 
176 void StockDiagram::setLowHighLinePen( int column, const QPen &pen )
177 {
178  d->lowHighLinePens[column] = pen;
179 }
180 
181 QPen StockDiagram::lowHighLinePen( int column ) const
182 {
183  if ( d->lowHighLinePens.contains( column ) )
184  return d->lowHighLinePens[column];
185  return d->lowHighLinePen;
186 }
187 
189 {
190  d->upTrendCandlestickBrush = brush;
191 }
192 
194 {
195  return d->upTrendCandlestickBrush;
196 }
197 
199 {
200  d->downTrendCandlestickBrush = brush;
201 }
202 
204 {
205  return d->downTrendCandlestickBrush;
206 }
207 
208 void StockDiagram::setUpTrendCandlestickBrush( int column, const QBrush &brush )
209 {
210  d->upTrendCandlestickBrushes[column] = brush;
211 }
212 
213 QBrush StockDiagram::upTrendCandlestickBrush( int column ) const
214 {
215  if ( d->upTrendCandlestickBrushes.contains( column ) )
216  return d->upTrendCandlestickBrushes[column];
217  return d->upTrendCandlestickBrush;
218 }
219 
220 void StockDiagram::setDownTrendCandlestickBrush( int column, const QBrush &brush )
221 {
222  d->downTrendCandlestickBrushes[column] = brush;
223 }
224 
225 QBrush StockDiagram::downTrendCandlestickBrush( int column ) const
226 {
227  if ( d->downTrendCandlestickBrushes.contains( column ) )
228  return d->downTrendCandlestickBrushes[column];
229  return d->downTrendCandlestickBrush;
230 }
231 
232 
234 {
235  d->upTrendCandlestickPen = pen;
236 }
237 
239 {
240  return d->upTrendCandlestickPen;
241 }
242 
244 {
245  d->downTrendCandlestickPen = pen;
246 }
247 
249 {
250  return d->downTrendCandlestickPen;
251 }
252 
253 void StockDiagram::setUpTrendCandlestickPen( int column, const QPen &pen )
254 {
255  d->upTrendCandlestickPens[column] = pen;
256 }
257 
258 QPen StockDiagram::upTrendCandlestickPen( int column ) const
259 {
260  if ( d->upTrendCandlestickPens.contains( column ) )
261  return d->upTrendCandlestickPens[column];
262  return d->upTrendCandlestickPen;
263 }
264 
265 void StockDiagram::setDownTrendCandlestickPen( int column, const QPen &pen )
266 {
267  d->downTrendCandlestickPens[column] = pen;
268 }
269 
270 QPen StockDiagram::downTrendCandlestickPen( int column ) const
271 {
272  if ( d->downTrendCandlestickPens.contains( column ) )
273  return d->downTrendCandlestickPens[column];
274  return d->downTrendCandlestickPen;
275 }
276 
277 #if QT_VERSION < 0x040400 || defined(Q_COMPILER_MANGLES_RETURN_TYPE)
278 const
279 #endif
280 int StockDiagram::numberOfAbscissaSegments() const { return 1; }
281 
282 #if QT_VERSION < 0x040400 || defined(Q_COMPILER_MANGLES_RETURN_TYPE)
283 const
284 #endif
285 int StockDiagram::numberOfOrdinateSegments() const { return 1; }
286 
287 void StockDiagram::paint( PaintContext *context )
288 {
289  // Clear old reverse mapping data and create new
290  // reverse mapping scene
291  d->reverseMapper.clear();
292 
293  PainterSaver painterSaver( context->painter() );
294  const int rowCount = attributesModel()->rowCount( attributesModelRootIndex() );
295  const int divisor = ( d->type == OpenHighLowClose || d->type == Candlestick ) ? 4 : 3;
296  const int colCount = attributesModel()->columnCount( attributesModelRootIndex() ) / divisor;
297  for ( int col = 0; col < colCount; ++col )
298  {
299  for ( int row = 0; row < rowCount; row++ ) {
300  CartesianDiagramDataCompressor::DataPoint low;
301  CartesianDiagramDataCompressor::DataPoint high;
302  CartesianDiagramDataCompressor::DataPoint open;
303  CartesianDiagramDataCompressor::DataPoint close;
304  CartesianDiagramDataCompressor::DataPoint volume;
305 
306  if ( d->type == HighLowClose ) {
307  const CartesianDiagramDataCompressor::CachePosition highPos( row, col * divisor );
308  const CartesianDiagramDataCompressor::CachePosition lowPos( row, col * divisor + 1 );
309  const CartesianDiagramDataCompressor::CachePosition closePos( row, col * divisor + 2 );
310  low = d->compressor.data( lowPos );
311  high = d->compressor.data( highPos );
312  close = d->compressor.data( closePos );
313  } else if ( d->type == OpenHighLowClose || d->type == Candlestick ) {
314  const CartesianDiagramDataCompressor::CachePosition openPos( row, col * divisor );
315  const CartesianDiagramDataCompressor::CachePosition highPos( row, col * divisor + 1 );
316  const CartesianDiagramDataCompressor::CachePosition lowPos( row, col * divisor + 2 );
317  const CartesianDiagramDataCompressor::CachePosition closePos( row, col * divisor + 3 );
318  open = d->compressor.data( openPos );
319  low = d->compressor.data( lowPos );
320  high = d->compressor.data( highPos );
321  close = d->compressor.data( closePos );
322  }
323 
324 
325  switch ( d->type ) {
326  case HighLowClose:
327  open.hidden = true;
328  // Fall-through intended!
329  case OpenHighLowClose:
330  if ( close.index.isValid() && low.index.isValid() && high.index.isValid() )
331  d->drawOHLCBar( col, open, high, low, close, context );
332  break;
333  case Candlestick:
334  d->drawCandlestick( col, open, high, low, close, context );
335  break;
336  }
337  }
338  }
339 }
340 
341 void StockDiagram::resize( const QSizeF &size )
342 {
343  d->compressor.setResolution( static_cast< int >( size.width() * coordinatePlane()->zoomFactorX() ),
344  static_cast< int >( size.height() * coordinatePlane()->zoomFactorY() ) );
346  QAbstractItemView::resize( size.toSize() );
347 }
348 
349 qreal StockDiagram::threeDItemDepth( int column ) const
350 {
351  Q_UNUSED( column );
352  //FIXME: Implement threeD functionality
353  return 1.0;
354 }
355 
356 qreal StockDiagram::threeDItemDepth( const QModelIndex &index ) const
357 {
358  Q_UNUSED( index );
359  //FIXME: Implement threeD functionality
360  return 1.0;
361 }
362 
364 {
365  const int rowCount = attributesModel()->rowCount( attributesModelRootIndex() );
366  const int colCount = attributesModel()->columnCount( attributesModelRootIndex() );
367  qreal xMin = 0.0;
368  qreal xMax = rowCount;
369  qreal yMin = 0.0;
370  qreal yMax = 0.0;
371  for ( int row = 0; row < rowCount; row++ ) {
372  for ( int col = 0; col < colCount; col++ ) {
373  const CartesianDiagramDataCompressor::CachePosition pos( row, col );
374  const CartesianDiagramDataCompressor::DataPoint point = d->compressor.data( pos );
375  yMax = qMax( yMax, point.value );
376  yMin = qMin( yMin, point.value ); // FIXME: Can stock charts really have negative values?
377  }
378  }
379  return QPair<QPointF, QPointF>( QPointF( xMin, yMin ), QPointF( xMax, yMax ) );
380 }
381 
void setThreeDBarAttributes(const ThreeDBarAttributes &attr)
QPen downTrendCandlestickPen() const
int rowCount(const QModelIndex &) const override
[reimplemented]
qreal threeDItemDepth(int column) const override
QPen lowHighLinePen() const
QPainter * painter() const
virtual AttributesModel * attributesModel() const
Returns the AttributesModel, that is used by this diagram.
int columnCount(const QModelIndex &) const override
[reimplemented]
QPen upTrendCandlestickPen() const
StockDiagram(QWidget *parent=0, CartesianCoordinatePlane *plane=0)
AbstractCoordinatePlane * coordinatePlane() const
The coordinate plane associated with the diagram.
QVariant modelData(int role) const
void setDatasetDimensionInternal(int dimension)
void setDownTrendCandlestickBrush(const QBrush &brush)
StockBarAttributes stockBarAttributes() const
virtual const int numberOfOrdinateSegments() const
QBrush brush() const
Retrieve the brush to be used for painting datapoints globally.
void setPen(const QModelIndex &index, const QPen &pen)
Set the pen to be used, for painting the datapoint at the given index.
void setStockBarAttributes(const StockBarAttributes &attr)
Type type() const
void setDownTrendCandlestickPen(const QPen &pen)
#define d
void propertiesChanged()
Emitted upon change of a property of the Diagram.
void setType(Type type)
Base class for diagrams based on a cartesian coordianate system.
QBrush downTrendCandlestickBrush() const
Stores information about painting diagrams.
A set of 3D bar attributes.
void setUpTrendCandlestickBrush(const QBrush &brush)
QPen pen() const
Retrieve the pen to be used for painting datapoints globally.
virtual const int numberOfAbscissaSegments() const
QModelIndex attributesModelRootIndex() const
QBrush upTrendCandlestickBrush() const
void setLowHighLinePen(const QPen &pen)
void setUpTrendCandlestickPen(const QPen &pen)
ThreeDBarAttributes threeDBarAttributes() const
void paint(PaintContext *paintContext) override
Draw the diagram contents to the rectangle and painter, that are passed in as part of the paint conte...
Class only listed here to document inheritance of some KDChart classes.
bool setModelData(const QVariant value, int role)
const QPair< QPointF, QPointF > calculateDataBoundaries() const override
void resize(const QSizeF &size) override
Called by the widget&#39;s sizeEvent.
Attributes to customize the appearance of a column in a stock chart.

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/