KDChartStockDiagram.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 ** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB.  All rights reserved.
00003 **
00004 ** This file is part of the KD Chart library.
00005 **
00006 ** Licensees holding valid commercial KD Chart licenses may use this file in
00007 ** accordance with the KD Chart Commercial License Agreement provided with
00008 ** the Software.
00009 **
00010 **
00011 ** This file may be distributed and/or modified under the terms of the
00012 ** GNU General Public License version 2 and version 3 as published by the
00013 ** Free Software Foundation and appearing in the file LICENSE.GPL included.
00014 **
00015 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00016 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00017 **
00018 ** Contact info@kdab.com if any conditions of this licensing are not
00019 ** clear to you.
00020 **
00021 **********************************************************************/
00022 
00023 #include "KDChartStockDiagram.h"
00024 #include "KDChartStockDiagram_p.h"
00025 
00026 #include "KDChartPaintContext.h"
00027 
00028 using namespace KDChart;
00029 
00030 #define d d_func()
00031 
00032 StockDiagram::StockDiagram( QWidget *parent, CartesianCoordinatePlane *plane )
00033     : AbstractCartesianDiagram( new Private(), parent, plane )
00034 {
00035     init();
00036 }
00037 
00038 StockDiagram::~StockDiagram()
00039 {
00040 }
00041 
00045 void StockDiagram::init()
00046 {
00047     d->diagram = this;
00048     d->compressor.setModel( attributesModel() );
00049 
00050     // Set properties to defaults
00051     d->type = HighLowClose;
00052     d->upTrendCandlestickBrush = QBrush( Qt::white );
00053     d->downTrendCandlestickBrush = QBrush( Qt::black );
00054     d->upTrendCandlestickPen = QPen( Qt::black );
00055     d->downTrendCandlestickPen = QPen( Qt::black );
00056 
00057     d->lowHighLinePen = QPen( Qt::black );
00058 
00059     setPen( QPen( Qt::black ) );
00060 }
00061 
00066 void StockDiagram::setType( Type type )
00067 {
00068     d->type = type;
00069     emit propertiesChanged();
00070 }
00071 
00075 StockDiagram::Type StockDiagram::type() const
00076 {
00077    return d->type;
00078 }
00079 
00080 void StockDiagram::setStockBarAttributes( const StockBarAttributes &attr )
00081 {
00082     attributesModel()->setModelData(
00083             qVariantFromValue( attr ),
00084             StockBarAttributesRole );
00085     emit propertiesChanged();
00086 }
00087 
00088 StockBarAttributes StockDiagram::stockBarAttributes() const
00089 {
00090     return qVariantValue<StockBarAttributes>(
00091         attributesModel()->modelData( StockBarAttributesRole ) );
00092 }
00093 
00094 void StockDiagram::setStockBarAttributes( int column, const StockBarAttributes &attr )
00095 {
00096     d->setDatasetAttrs( column, qVariantFromValue( attr ), StockBarAttributesRole );
00097     emit propertiesChanged();
00098 }
00099 
00100 StockBarAttributes StockDiagram::stockBarAttributes( int column ) const
00101 {
00102     const QVariant attr( d->datasetAttrs( column, StockBarAttributesRole ) );
00103     if ( attr.isValid() )
00104         return qVariantValue<StockBarAttributes>( attr );
00105     return stockBarAttributes();
00106 }
00107 
00113 void StockDiagram::setThreeDBarAttributes( const ThreeDBarAttributes &attr )
00114 {
00115     attributesModel()->setModelData(
00116             qVariantFromValue( attr ),
00117             ThreeDBarAttributesRole );
00118     emit propertiesChanged();
00119 }
00120 
00126 ThreeDBarAttributes StockDiagram::threeDBarAttributes() const
00127 {
00128         return qVariantValue<ThreeDBarAttributes>(
00129                         attributesModel()->modelData( ThreeDBarAttributesRole ) );
00130 }
00131 
00141 void StockDiagram::setThreeDBarAttributes( int column, const ThreeDBarAttributes &attr )
00142 {
00143     d->setDatasetAttrs( column, qVariantFromValue( attr ), StockBarAttributesRole );
00144     emit propertiesChanged();
00145 }
00146 
00156 ThreeDBarAttributes StockDiagram::threeDBarAttributes( int column ) const
00157 {
00158     const QVariant attr( d->datasetAttrs( column, ThreeDBarAttributesRole ) );
00159     if ( attr.isValid() )
00160         return qVariantValue<ThreeDBarAttributes>( attr );
00161     return threeDBarAttributes();
00162 }
00163 
00164 
00165 void StockDiagram::setLowHighLinePen( const QPen &pen )
00166 {
00167     d->lowHighLinePen = pen;
00168 }
00169 
00170 QPen StockDiagram::lowHighLinePen() const
00171 {
00172     return d->lowHighLinePen;
00173 }
00174 
00175 void StockDiagram::setLowHighLinePen( int column, const QPen &pen )
00176 {
00177     d->lowHighLinePens[column] = pen;
00178 }
00179 
00180 QPen StockDiagram::lowHighLinePen( int column ) const
00181 {
00182     if ( d->lowHighLinePens.contains( column ) )
00183         return d->lowHighLinePens[column];
00184     return d->lowHighLinePen;
00185 }
00186 
00187 void StockDiagram::setUpTrendCandlestickBrush( const QBrush &brush )
00188 {
00189     d->upTrendCandlestickBrush = brush;
00190 }
00191 
00192 QBrush StockDiagram::upTrendCandlestickBrush() const
00193 {
00194     return d->upTrendCandlestickBrush;
00195 }
00196 
00197 void StockDiagram::setDownTrendCandlestickBrush( const QBrush &brush )
00198 {
00199     d->downTrendCandlestickBrush = brush;
00200 }
00201 
00202 QBrush StockDiagram::downTrendCandlestickBrush() const
00203 {
00204     return d->downTrendCandlestickBrush;
00205 }
00206 
00207 void StockDiagram::setUpTrendCandlestickBrush( int column, const QBrush &brush )
00208 {
00209     d->upTrendCandlestickBrushes[column] = brush;
00210 }
00211 
00212 QBrush StockDiagram::upTrendCandlestickBrush( int column ) const
00213 {
00214     if ( d->upTrendCandlestickBrushes.contains( column ) )
00215         return d->upTrendCandlestickBrushes[column];
00216     return d->upTrendCandlestickBrush;
00217 }
00218 
00219 void StockDiagram::setDownTrendCandlestickBrush( int column, const QBrush &brush )
00220 {
00221     d->downTrendCandlestickBrushes[column] = brush;
00222 }
00223 
00224 QBrush StockDiagram::downTrendCandlestickBrush( int column ) const
00225 {
00226     if ( d->downTrendCandlestickBrushes.contains( column ) )
00227         return d->downTrendCandlestickBrushes[column];
00228     return d->downTrendCandlestickBrush;
00229 }
00230 
00231 
00232 void StockDiagram::setUpTrendCandlestickPen( const QPen &pen )
00233 {
00234     d->upTrendCandlestickPen = pen;
00235 }
00236 
00237 QPen StockDiagram::upTrendCandlestickPen() const
00238 {
00239     return d->upTrendCandlestickPen;
00240 }
00241 
00242 void StockDiagram::setDownTrendCandlestickPen( const QPen &pen )
00243 {
00244     d->downTrendCandlestickPen = pen;
00245 }
00246 
00247 QPen StockDiagram::downTrendCandlestickPen() const
00248 {
00249     return d->downTrendCandlestickPen;
00250 }
00251 
00252 void StockDiagram::setUpTrendCandlestickPen( int column, const QPen &pen )
00253 {
00254     d->upTrendCandlestickPens[column] = pen;
00255 }
00256 
00257 QPen StockDiagram::upTrendCandlestickPen( int column ) const
00258 {
00259     if ( d->upTrendCandlestickPens.contains( column ) )
00260         return d->upTrendCandlestickPens[column];
00261     return d->upTrendCandlestickPen;
00262 }
00263 
00264 void StockDiagram::setDownTrendCandlestickPen( int column, const QPen &pen )
00265 {
00266     d->downTrendCandlestickPens[column] = pen;
00267 }
00268 
00269 QPen StockDiagram::downTrendCandlestickPen( int column ) const
00270 {
00271     if ( d->downTrendCandlestickPens.contains( column ) )
00272         return d->downTrendCandlestickPens[column];
00273     return d->downTrendCandlestickPen;
00274 }
00275 
00276 #if QT_VERSION < 0x040400 || defined(Q_COMPILER_MANGLES_RETURN_TYPE)
00277 const
00278 #endif
00279 int StockDiagram::numberOfAbscissaSegments() const { return 1; }
00280 
00281 #if QT_VERSION < 0x040400 || defined(Q_COMPILER_MANGLES_RETURN_TYPE)
00282 const
00283 #endif
00284 int StockDiagram::numberOfOrdinateSegments() const { return 1; }
00285 
00286 void StockDiagram::paint( PaintContext *context )
00287 {
00288     // Clear old reverse mapping data and create new
00289     // reverse mapping scene
00290     d->reverseMapper.clear();
00291 
00292     PainterSaver painterSaver( context->painter() );
00293     int rowCount = attributesModel()->rowCount( attributesModelRootIndex() );
00294     for ( int row = 0; row < rowCount; row++ ) {
00295         CartesianDiagramDataCompressor::DataPoint low;
00296         CartesianDiagramDataCompressor::DataPoint high;
00297         CartesianDiagramDataCompressor::DataPoint open;
00298         CartesianDiagramDataCompressor::DataPoint close;
00299         CartesianDiagramDataCompressor::DataPoint volume;
00300 
00301         if ( d->type == HighLowClose ) {
00302             const CartesianDiagramDataCompressor::CachePosition highPos( row, 0 );
00303             const CartesianDiagramDataCompressor::CachePosition lowPos( row, 1 );
00304             const CartesianDiagramDataCompressor::CachePosition closePos( row, 2 );
00305             low = d->compressor.data( lowPos );
00306             high = d->compressor.data( highPos );
00307             close = d->compressor.data( closePos );
00308         } else if ( d->type == OpenHighLowClose || d->type == Candlestick ) {
00309             const CartesianDiagramDataCompressor::CachePosition openPos( row, 0 );
00310             const CartesianDiagramDataCompressor::CachePosition highPos( row, 1 );
00311             const CartesianDiagramDataCompressor::CachePosition lowPos( row, 2 );
00312             const CartesianDiagramDataCompressor::CachePosition closePos( row, 3 );
00313             open = d->compressor.data( openPos );
00314             low = d->compressor.data( lowPos );
00315             high = d->compressor.data( highPos );
00316             close = d->compressor.data( closePos );
00317         }
00318 
00319         switch( d->type ) {
00320         case HighLowClose:
00321             open.hidden = true;
00322             // Fall-through intended!
00323         case OpenHighLowClose:
00324             d->drawOHLCBar( open, high, low, close, context );
00325             break;
00326         case Candlestick:
00327             d->drawCandlestick( open, high, low, close, context );
00328             break;
00329         }
00330     }
00331 }
00332 
00333 void StockDiagram::resize( const QSizeF &size )
00334 {
00335     d->compressor.setResolution( static_cast< int >( size.width() * coordinatePlane()->zoomFactorX() ),
00336                                  static_cast< int >( size.height() * coordinatePlane()->zoomFactorY() ) );
00337     setDataBoundariesDirty();
00338 }
00339 
00340 double StockDiagram::threeDItemDepth( int column ) const
00341 {
00342     Q_UNUSED( column );
00343     //FIXME: Implement threeD functionality
00344     return 1.0;
00345 }
00346 
00347 double StockDiagram::threeDItemDepth( const QModelIndex &index ) const
00348 {
00349     Q_UNUSED( index );
00350     //FIXME: Implement threeD functionality
00351     return 1.0;
00352 }
00353 
00354 const QPair<QPointF, QPointF> StockDiagram::calculateDataBoundaries() const
00355 {
00356     const int rowCount = attributesModel()->rowCount( attributesModelRootIndex() );
00357     const int colCount = attributesModel()->columnCount( attributesModelRootIndex() );
00358     qreal xMin = 0.0;
00359     qreal xMax = rowCount;
00360     qreal yMin = 0.0;
00361     qreal yMax = 0.0;
00362     for ( int row = 0; row < rowCount; row++ ) {
00363         for ( int col = 0; col < colCount; col++ ) {
00364             const CartesianDiagramDataCompressor::CachePosition pos( row, col );
00365             const CartesianDiagramDataCompressor::DataPoint point = d->compressor.data( pos );
00366             yMax = qMax( yMax, point.value );
00367             yMin = qMin( yMin, point.value ); // FIXME: Can stock charts really have negative values?
00368         }
00369     }
00370     return QPair<QPointF, QPointF>( QPointF( xMin, yMin ), QPointF( xMax, yMax ) );
00371 }
00372