qwt_plot_tradingcurve.cpp
Go to the documentation of this file.
00001 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
00002  * Qwt Widget Library
00003  * Copyright (C) 1997   Josef Wilgen
00004  * Copyright (C) 2002   Uwe Rathmann
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the Qwt License, Version 1.0
00008  *****************************************************************************/
00009 
00010 #include "qwt_plot_tradingcurve.h"
00011 #include "qwt_scale_map.h"
00012 #include "qwt_clipper.h"
00013 #include "qwt_painter.h"
00014 #include <qpainter.h>
00015 
00016 static inline bool qwtIsSampleInside( const QwtOHLCSample &sample,
00017     double tMin, double tMax, double vMin, double vMax )
00018 {
00019     const double t = sample.time;
00020     const QwtInterval interval = sample.boundingInterval();
00021 
00022     const bool isOffScreen = ( t < tMin ) || ( t > tMax )
00023         || ( interval.maxValue() < vMin ) || ( interval.minValue() > vMax );
00024 
00025     return !isOffScreen;
00026 }
00027 
00028 class QwtPlotTradingCurve::PrivateData
00029 {
00030 public:
00031     PrivateData():
00032         symbolStyle( QwtPlotTradingCurve::CandleStick ),
00033         symbolExtent( 0.6 ),
00034         minSymbolWidth( 2.0 ),
00035         maxSymbolWidth( -1.0 ),
00036         paintAttributes( QwtPlotTradingCurve::ClipSymbols )
00037     {
00038         symbolBrush[0] = QBrush( Qt::white );
00039         symbolBrush[1] = QBrush( Qt::black );
00040     }
00041 
00042     QwtPlotTradingCurve::SymbolStyle symbolStyle;
00043     double symbolExtent;
00044     double minSymbolWidth;
00045     double maxSymbolWidth;
00046 
00047     QPen symbolPen;
00048     QBrush symbolBrush[2]; // Increasing/Decreasing
00049 
00050     QwtPlotTradingCurve::PaintAttributes paintAttributes;
00051 };
00052 
00057 QwtPlotTradingCurve::QwtPlotTradingCurve( const QwtText &title ):
00058     QwtPlotSeriesItem( title )
00059 {
00060     init();
00061 }
00062 
00067 QwtPlotTradingCurve::QwtPlotTradingCurve( const QString &title ):
00068     QwtPlotSeriesItem( QwtText( title ) )
00069 {
00070     init();
00071 }
00072 
00074 QwtPlotTradingCurve::~QwtPlotTradingCurve()
00075 {
00076     delete d_data;
00077 }
00078 
00080 void QwtPlotTradingCurve::init()
00081 {
00082     setItemAttribute( QwtPlotItem::Legend, true );
00083     setItemAttribute( QwtPlotItem::AutoScale, true );
00084 
00085     d_data = new PrivateData;
00086     setData( new QwtTradingChartData() );
00087 
00088     setZ( 19.0 );
00089 }
00090 
00092 int QwtPlotTradingCurve::rtti() const
00093 {
00094     return QwtPlotTradingCurve::Rtti_PlotTradingCurve;
00095 }
00096 
00104 void QwtPlotTradingCurve::setPaintAttribute(
00105     PaintAttribute attribute, bool on )
00106 {
00107     if ( on )
00108         d_data->paintAttributes |= attribute;
00109     else
00110         d_data->paintAttributes &= ~attribute;
00111 }
00112 
00117 bool QwtPlotTradingCurve::testPaintAttribute(
00118     PaintAttribute attribute ) const
00119 {
00120     return ( d_data->paintAttributes & attribute );
00121 }
00122 
00129 void QwtPlotTradingCurve::setSamples(
00130     const QVector<QwtOHLCSample> &samples )
00131 {
00132     setData( new QwtTradingChartData( samples ) );
00133 }
00134 
00145 void QwtPlotTradingCurve::setSamples(
00146     QwtSeriesData<QwtOHLCSample> *data )
00147 {
00148     setData( data );
00149 }   
00150 
00159 void QwtPlotTradingCurve::setSymbolStyle( SymbolStyle style )
00160 {
00161     if ( style != d_data->symbolStyle )
00162     {
00163         d_data->symbolStyle = style;
00164 
00165         legendChanged();
00166         itemChanged();
00167     }
00168 }
00169 
00174 QwtPlotTradingCurve::SymbolStyle QwtPlotTradingCurve::symbolStyle() const
00175 {
00176     return d_data->symbolStyle;
00177 }
00178 
00192 void QwtPlotTradingCurve::setSymbolPen( 
00193     const QColor &color, qreal width, Qt::PenStyle style )
00194 {   
00195     setSymbolPen( QPen( color, width, style ) );
00196 }
00197 
00206 void QwtPlotTradingCurve::setSymbolPen( const QPen &pen )
00207 {
00208     if ( pen != d_data->symbolPen )
00209     {
00210         d_data->symbolPen = pen;
00211 
00212         legendChanged();
00213         itemChanged();
00214     }
00215 }
00216 
00221 QPen QwtPlotTradingCurve::symbolPen() const
00222 {
00223     return d_data->symbolPen;
00224 }
00225 
00235 void QwtPlotTradingCurve::setSymbolBrush(
00236     Direction direction, const QBrush &brush )
00237 {
00238     if ( direction < 0 || direction >= 2 )
00239         return;
00240 
00241     if ( brush != d_data->symbolBrush[ direction ] )
00242     {
00243         d_data->symbolBrush[ direction ] = brush;
00244 
00245         legendChanged();
00246         itemChanged();
00247     }
00248 }
00249 
00257 QBrush QwtPlotTradingCurve::symbolBrush( Direction direction ) const
00258 {
00259     if ( direction < 0 || direction >= 2 )
00260         return QBrush();
00261 
00262     return d_data->symbolBrush[ direction ];
00263 }
00264 
00278 void QwtPlotTradingCurve::setSymbolExtent( double extent )
00279 {
00280     extent = qMax( 0.0, extent );
00281     if ( extent != d_data->symbolExtent )
00282     {
00283         d_data->symbolExtent = extent;
00284 
00285         legendChanged();
00286         itemChanged();
00287     }
00288 }
00289 
00295 double QwtPlotTradingCurve::symbolExtent() const
00296 {
00297     return d_data->symbolExtent;
00298 }
00299 
00306 void QwtPlotTradingCurve::setMinSymbolWidth( double width )
00307 {
00308     width = qMax( width, 0.0 );
00309     if ( width != d_data->minSymbolWidth )
00310     {
00311         d_data->minSymbolWidth = width;
00312 
00313         legendChanged();
00314         itemChanged();
00315     }
00316 }
00317 
00322 double QwtPlotTradingCurve::minSymbolWidth() const
00323 {
00324     return d_data->minSymbolWidth;
00325 }
00326 
00335 void QwtPlotTradingCurve::setMaxSymbolWidth( double width )
00336 {
00337     if ( width != d_data->maxSymbolWidth )
00338     {
00339         d_data->maxSymbolWidth = width;
00340     
00341         legendChanged();
00342         itemChanged();
00343     }
00344 }
00345 
00350 double QwtPlotTradingCurve::maxSymbolWidth() const
00351 {
00352     return d_data->maxSymbolWidth;
00353 }
00354 
00359 QRectF QwtPlotTradingCurve::boundingRect() const
00360 {
00361     QRectF rect = QwtPlotSeriesItem::boundingRect();
00362     if ( rect.isValid() && orientation() == Qt::Vertical )
00363         rect.setRect( rect.y(), rect.x(), rect.height(), rect.width() );
00364 
00365     return rect;
00366 }
00367 
00381 void QwtPlotTradingCurve::drawSeries( QPainter *painter,
00382     const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00383     const QRectF &canvasRect, int from, int to ) const
00384 {
00385     if ( to < 0 )
00386         to = dataSize() - 1;
00387 
00388     if ( from < 0 )
00389         from = 0;
00390 
00391     if ( from > to )
00392         return;
00393 
00394     painter->save();
00395 
00396     if ( d_data->symbolStyle != QwtPlotTradingCurve::NoSymbol )
00397         drawSymbols( painter, xMap, yMap, canvasRect, from, to );
00398 
00399     painter->restore();
00400 }
00401 
00414 void QwtPlotTradingCurve::drawSymbols( QPainter *painter,
00415     const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00416     const QRectF &canvasRect, int from, int to ) const
00417 {
00418     const QRectF tr = QwtScaleMap::invTransform( xMap, yMap, canvasRect );
00419 
00420     const QwtScaleMap *timeMap, *valueMap;
00421     double tMin, tMax, vMin, vMax;
00422 
00423     const Qt::Orientation orient = orientation();
00424     if ( orient == Qt::Vertical )
00425     {
00426         timeMap = &xMap;
00427         valueMap = &yMap;
00428 
00429         tMin = tr.left();
00430         tMax = tr.right();
00431         vMin = tr.top();
00432         vMax = tr.bottom();
00433     }
00434     else
00435     {
00436         timeMap = &yMap;
00437         valueMap = &xMap;
00438 
00439         vMin = tr.left();
00440         vMax = tr.right();
00441         tMin = tr.top();
00442         tMax = tr.bottom();
00443     }
00444 
00445     const bool inverted = timeMap->isInverting();
00446     const bool doClip = d_data->paintAttributes & ClipSymbols;
00447     const bool doAlign = QwtPainter::roundingAlignment( painter );
00448 
00449     double symbolWidth = scaledSymbolWidth( xMap, yMap, canvasRect );
00450     if ( doAlign )
00451         symbolWidth = qFloor( 0.5 * symbolWidth ) * 2.0;
00452 
00453     QPen pen = d_data->symbolPen;
00454     pen.setCapStyle( Qt::FlatCap );
00455 
00456     painter->setPen( pen );
00457 
00458     for ( int i = from; i <= to; i++ )
00459     {
00460         const QwtOHLCSample s = sample( i );
00461 
00462         if ( !doClip || qwtIsSampleInside( s, tMin, tMax, vMin, vMax ) )
00463         {
00464             QwtOHLCSample translatedSample;
00465 
00466             translatedSample.time = timeMap->transform( s.time );
00467             translatedSample.open = valueMap->transform( s.open );
00468             translatedSample.high = valueMap->transform( s.high );
00469             translatedSample.low = valueMap->transform( s.low );
00470             translatedSample.close = valueMap->transform( s.close );
00471 
00472             const int brushIndex = ( s.open < s.close )
00473                 ? QwtPlotTradingCurve::Increasing
00474                 : QwtPlotTradingCurve::Decreasing;
00475 
00476             if ( doAlign )
00477             {
00478                 translatedSample.time = qRound( translatedSample.time );
00479                 translatedSample.open = qRound( translatedSample.open );
00480                 translatedSample.high = qRound( translatedSample.high );
00481                 translatedSample.low = qRound( translatedSample.low );
00482                 translatedSample.close = qRound( translatedSample.close );
00483             }
00484 
00485             switch( d_data->symbolStyle )
00486             {
00487                 case Bar:
00488                 {
00489                     drawBar( painter, translatedSample, 
00490                         orient, inverted, symbolWidth );
00491                     break;
00492                 }
00493                 case CandleStick:
00494                 {
00495                     painter->setBrush( d_data->symbolBrush[ brushIndex ] );
00496                     drawCandleStick( painter, translatedSample, 
00497                         orient, symbolWidth );
00498                     break;
00499                 }
00500                 default:
00501                 {
00502                     if ( d_data->symbolStyle >= UserSymbol )
00503                     {
00504                         painter->setBrush( d_data->symbolBrush[ brushIndex ] );
00505                         drawUserSymbol( painter, d_data->symbolStyle,
00506                             translatedSample, orient, inverted, symbolWidth );
00507                     }
00508                 }
00509             }
00510         }
00511     }
00512 }
00513 
00528 void QwtPlotTradingCurve::drawUserSymbol( QPainter *painter,
00529     SymbolStyle symbolStyle, const QwtOHLCSample &sample,
00530     Qt::Orientation orientation, bool inverted, double symbolWidth ) const
00531 {
00532     Q_UNUSED( painter )
00533     Q_UNUSED( symbolStyle )
00534     Q_UNUSED( orientation )
00535     Q_UNUSED( inverted )
00536     Q_UNUSED( symbolWidth )
00537     Q_UNUSED( sample )
00538 }
00539 
00556 void QwtPlotTradingCurve::drawBar( QPainter *painter,
00557     const QwtOHLCSample &sample, Qt::Orientation orientation, 
00558     bool inverted, double width ) const
00559 {
00560     double w2 = 0.5 * width;
00561     if ( inverted )
00562         w2 *= -1;
00563 
00564     if ( orientation == Qt::Vertical )
00565     {
00566         QwtPainter::drawLine( painter,
00567             sample.time, sample.low, sample.time, sample.high );
00568 
00569         QwtPainter::drawLine( painter,
00570             sample.time - w2, sample.open, sample.time, sample.open );
00571         QwtPainter::drawLine( painter,
00572             sample.time + w2, sample.close, sample.time, sample.close );
00573     }
00574     else
00575     {
00576         QwtPainter::drawLine( painter, sample.low, sample.time,
00577             sample.high, sample.time );
00578         QwtPainter::drawLine( painter,
00579             sample.open, sample.time - w2, sample.open, sample.time );
00580         QwtPainter::drawLine( painter,
00581             sample.close, sample.time + w2, sample.close, sample.time );
00582     }
00583 }
00584 
00595 void QwtPlotTradingCurve::drawCandleStick( QPainter *painter,
00596     const QwtOHLCSample &sample, Qt::Orientation orientation, 
00597     double width ) const
00598 {
00599     const double t = sample.time;
00600     const double v1 = qMin( sample.low, sample.high );
00601     const double v2 = qMin( sample.open, sample.close );
00602     const double v3 = qMax( sample.low, sample.high );
00603     const double v4 = qMax( sample.open, sample.close );
00604 
00605     if ( orientation == Qt::Vertical )
00606     {
00607         QwtPainter::drawLine( painter, t, v1, t, v2 );
00608         QwtPainter::drawLine( painter, t, v3, t, v4 );
00609 
00610         QRectF rect( t - 0.5 * width, sample.open,
00611             width, sample.close - sample.open );
00612 
00613         QwtPainter::drawRect( painter, rect );
00614     }
00615     else
00616     {
00617         QwtPainter::drawLine( painter, v1, t, v2, t );
00618         QwtPainter::drawLine( painter, v3, t, v4, t );
00619 
00620         const QRectF rect( sample.open, t - 0.5 * width,
00621             sample.close - sample.open, width );
00622 
00623         QwtPainter::drawRect( painter, rect );
00624     }
00625 }
00626 
00636 QwtGraphic QwtPlotTradingCurve::legendIcon( int index,
00637     const QSizeF &size ) const
00638 {
00639     Q_UNUSED( index );
00640     return defaultIcon( d_data->symbolPen.color(), size );
00641 }
00642 
00658 double QwtPlotTradingCurve::scaledSymbolWidth(
00659     const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00660     const QRectF &canvasRect ) const
00661 {
00662     Q_UNUSED( canvasRect );
00663 
00664     if ( d_data->maxSymbolWidth > 0.0 &&
00665         d_data->minSymbolWidth >= d_data->maxSymbolWidth )
00666     {
00667         return d_data->minSymbolWidth;
00668     }
00669 
00670     const QwtScaleMap *map =
00671         ( orientation() == Qt::Vertical ) ? &xMap : &yMap;
00672 
00673     const double pos = map->transform( map->s1() + d_data->symbolExtent ); 
00674 
00675     double width = qAbs( pos - map->p1() );
00676 
00677     width = qMax( width,  d_data->minSymbolWidth );
00678     if ( d_data->maxSymbolWidth > 0.0 )
00679         width = qMin( width, d_data->maxSymbolWidth );
00680 
00681     return width;
00682 }


plotjuggler
Author(s): Davide Faconti
autogenerated on Fri Sep 1 2017 02:41:56