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 ( brush != d_data->symbolBrush[ direction ] )
00239     {
00240         d_data->symbolBrush[ direction ] = brush;
00241 
00242         legendChanged();
00243         itemChanged();
00244     }
00245 }
00246 
00254 QBrush QwtPlotTradingCurve::symbolBrush( Direction direction ) const
00255 {
00256     return d_data->symbolBrush[ direction ];
00257 }
00258 
00272 void QwtPlotTradingCurve::setSymbolExtent( double extent )
00273 {
00274     extent = qMax( 0.0, extent );
00275     if ( extent != d_data->symbolExtent )
00276     {
00277         d_data->symbolExtent = extent;
00278 
00279         legendChanged();
00280         itemChanged();
00281     }
00282 }
00283 
00289 double QwtPlotTradingCurve::symbolExtent() const
00290 {
00291     return d_data->symbolExtent;
00292 }
00293 
00300 void QwtPlotTradingCurve::setMinSymbolWidth( double width )
00301 {
00302     width = qMax( width, 0.0 );
00303     if ( width != d_data->minSymbolWidth )
00304     {
00305         d_data->minSymbolWidth = width;
00306 
00307         legendChanged();
00308         itemChanged();
00309     }
00310 }
00311 
00316 double QwtPlotTradingCurve::minSymbolWidth() const
00317 {
00318     return d_data->minSymbolWidth;
00319 }
00320 
00329 void QwtPlotTradingCurve::setMaxSymbolWidth( double width )
00330 {
00331     if ( width != d_data->maxSymbolWidth )
00332     {
00333         d_data->maxSymbolWidth = width;
00334     
00335         legendChanged();
00336         itemChanged();
00337     }
00338 }
00339 
00344 double QwtPlotTradingCurve::maxSymbolWidth() const
00345 {
00346     return d_data->maxSymbolWidth;
00347 }
00348 
00353 QRectF QwtPlotTradingCurve::boundingRect() const
00354 {
00355     QRectF rect = QwtPlotSeriesItem::boundingRect();
00356     if ( rect.isValid() && orientation() == Qt::Vertical )
00357         rect.setRect( rect.y(), rect.x(), rect.height(), rect.width() );
00358 
00359     return rect;
00360 }
00361 
00375 void QwtPlotTradingCurve::drawSeries( QPainter *painter,
00376     const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00377     const QRectF &canvasRect, int from, int to ) const
00378 {
00379     if ( to < 0 )
00380         to = dataSize() - 1;
00381 
00382     if ( from < 0 )
00383         from = 0;
00384 
00385     if ( from > to )
00386         return;
00387 
00388     painter->save();
00389 
00390     if ( d_data->symbolStyle != QwtPlotTradingCurve::NoSymbol )
00391         drawSymbols( painter, xMap, yMap, canvasRect, from, to );
00392 
00393     painter->restore();
00394 }
00395 
00408 void QwtPlotTradingCurve::drawSymbols( QPainter *painter,
00409     const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00410     const QRectF &canvasRect, int from, int to ) const
00411 {
00412     const QRectF tr = QwtScaleMap::invTransform( xMap, yMap, canvasRect );
00413 
00414     const QwtScaleMap *timeMap, *valueMap;
00415     double tMin, tMax, vMin, vMax;
00416 
00417     const Qt::Orientation orient = orientation();
00418     if ( orient == Qt::Vertical )
00419     {
00420         timeMap = &xMap;
00421         valueMap = &yMap;
00422 
00423         tMin = tr.left();
00424         tMax = tr.right();
00425         vMin = tr.top();
00426         vMax = tr.bottom();
00427     }
00428     else
00429     {
00430         timeMap = &yMap;
00431         valueMap = &xMap;
00432 
00433         vMin = tr.left();
00434         vMax = tr.right();
00435         tMin = tr.top();
00436         tMax = tr.bottom();
00437     }
00438 
00439     const bool inverted = timeMap->isInverting();
00440     const bool doClip = d_data->paintAttributes & ClipSymbols;
00441     const bool doAlign = QwtPainter::roundingAlignment( painter );
00442 
00443     double symbolWidth = scaledSymbolWidth( xMap, yMap, canvasRect );
00444     if ( doAlign )
00445         symbolWidth = qFloor( 0.5 * symbolWidth ) * 2.0;
00446 
00447     QPen pen = d_data->symbolPen;
00448     pen.setCapStyle( Qt::FlatCap );
00449 
00450     painter->setPen( pen );
00451 
00452     for ( int i = from; i <= to; i++ )
00453     {
00454         const QwtOHLCSample s = sample( i );
00455 
00456         if ( !doClip || qwtIsSampleInside( s, tMin, tMax, vMin, vMax ) )
00457         {
00458             QwtOHLCSample translatedSample;
00459 
00460             translatedSample.time = timeMap->transform( s.time );
00461             translatedSample.open = valueMap->transform( s.open );
00462             translatedSample.high = valueMap->transform( s.high );
00463             translatedSample.low = valueMap->transform( s.low );
00464             translatedSample.close = valueMap->transform( s.close );
00465 
00466             const int brushIndex = ( s.open < s.close )
00467                 ? QwtPlotTradingCurve::Increasing
00468                 : QwtPlotTradingCurve::Decreasing;
00469 
00470             if ( doAlign )
00471             {
00472                 translatedSample.time = qRound( translatedSample.time );
00473                 translatedSample.open = qRound( translatedSample.open );
00474                 translatedSample.high = qRound( translatedSample.high );
00475                 translatedSample.low = qRound( translatedSample.low );
00476                 translatedSample.close = qRound( translatedSample.close );
00477             }
00478 
00479             switch( d_data->symbolStyle )
00480             {
00481                 case Bar:
00482                 {
00483                     drawBar( painter, translatedSample, 
00484                         orient, inverted, symbolWidth );
00485                     break;
00486                 }
00487                 case CandleStick:
00488                 {
00489                     painter->setBrush( d_data->symbolBrush[ brushIndex ] );
00490                     drawCandleStick( painter, translatedSample, 
00491                         orient, symbolWidth );
00492                     break;
00493                 }
00494                 default:
00495                 {
00496                     if ( d_data->symbolStyle >= UserSymbol )
00497                     {
00498                         painter->setBrush( d_data->symbolBrush[ brushIndex ] );
00499                         drawUserSymbol( painter, d_data->symbolStyle,
00500                             translatedSample, orient, inverted, symbolWidth );
00501                     }
00502                 }
00503             }
00504         }
00505     }
00506 }
00507 
00522 void QwtPlotTradingCurve::drawUserSymbol( QPainter *painter,
00523     SymbolStyle symbolStyle, const QwtOHLCSample &sample,
00524     Qt::Orientation orientation, bool inverted, double symbolWidth ) const
00525 {
00526     Q_UNUSED( painter )
00527     Q_UNUSED( symbolStyle )
00528     Q_UNUSED( orientation )
00529     Q_UNUSED( inverted )
00530     Q_UNUSED( symbolWidth )
00531     Q_UNUSED( sample )
00532 }
00533 
00550 void QwtPlotTradingCurve::drawBar( QPainter *painter,
00551     const QwtOHLCSample &sample, Qt::Orientation orientation, 
00552     bool inverted, double width ) const
00553 {
00554     double w2 = 0.5 * width;
00555     if ( inverted )
00556         w2 *= -1;
00557 
00558     if ( orientation == Qt::Vertical )
00559     {
00560         QwtPainter::drawLine( painter,
00561             sample.time, sample.low, sample.time, sample.high );
00562 
00563         QwtPainter::drawLine( painter,
00564             sample.time - w2, sample.open, sample.time, sample.open );
00565         QwtPainter::drawLine( painter,
00566             sample.time + w2, sample.close, sample.time, sample.close );
00567     }
00568     else
00569     {
00570         QwtPainter::drawLine( painter, sample.low, sample.time,
00571             sample.high, sample.time );
00572         QwtPainter::drawLine( painter,
00573             sample.open, sample.time - w2, sample.open, sample.time );
00574         QwtPainter::drawLine( painter,
00575             sample.close, sample.time + w2, sample.close, sample.time );
00576     }
00577 }
00578 
00589 void QwtPlotTradingCurve::drawCandleStick( QPainter *painter,
00590     const QwtOHLCSample &sample, Qt::Orientation orientation, 
00591     double width ) const
00592 {
00593     const double t = sample.time;
00594     const double v1 = qMin( sample.low, sample.high );
00595     const double v2 = qMin( sample.open, sample.close );
00596     const double v3 = qMax( sample.low, sample.high );
00597     const double v4 = qMax( sample.open, sample.close );
00598 
00599     if ( orientation == Qt::Vertical )
00600     {
00601         QwtPainter::drawLine( painter, t, v1, t, v2 );
00602         QwtPainter::drawLine( painter, t, v3, t, v4 );
00603 
00604         QRectF rect( t - 0.5 * width, sample.open,
00605             width, sample.close - sample.open );
00606 
00607         QwtPainter::drawRect( painter, rect );
00608     }
00609     else
00610     {
00611         QwtPainter::drawLine( painter, v1, t, v2, t );
00612         QwtPainter::drawLine( painter, v3, t, v4, t );
00613 
00614         const QRectF rect( sample.open, t - 0.5 * width,
00615             sample.close - sample.open, width );
00616 
00617         QwtPainter::drawRect( painter, rect );
00618     }
00619 }
00620 
00630 QwtGraphic QwtPlotTradingCurve::legendIcon( int index,
00631     const QSizeF &size ) const
00632 {
00633     Q_UNUSED( index );
00634     return defaultIcon( d_data->symbolPen.color(), size );
00635 }
00636 
00652 double QwtPlotTradingCurve::scaledSymbolWidth(
00653     const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00654     const QRectF &canvasRect ) const
00655 {
00656     Q_UNUSED( canvasRect );
00657 
00658     if ( d_data->maxSymbolWidth > 0.0 &&
00659         d_data->minSymbolWidth >= d_data->maxSymbolWidth )
00660     {
00661         return d_data->minSymbolWidth;
00662     }
00663 
00664     const QwtScaleMap *map =
00665         ( orientation() == Qt::Vertical ) ? &xMap : &yMap;
00666 
00667     const double pos = map->transform( map->s1() + d_data->symbolExtent ); 
00668 
00669     double width = qAbs( pos - map->p1() );
00670 
00671     width = qMax( width,  d_data->minSymbolWidth );
00672     if ( d_data->maxSymbolWidth > 0.0 )
00673         width = qMin( width, d_data->maxSymbolWidth );
00674 
00675     return width;
00676 }


plotjuggler
Author(s): Davide Faconti
autogenerated on Wed Jul 3 2019 19:28:05