Qwt User's Guide 6.3.0
Loading...
Searching...
No Matches
qwt_plot_tradingcurve.cpp
1/******************************************************************************
2 * Qwt Widget Library
3 * Copyright (C) 1997 Josef Wilgen
4 * Copyright (C) 2002 Uwe Rathmann
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the Qwt License, Version 1.0
8 *****************************************************************************/
9
10#include "qwt_plot_tradingcurve.h"
11#include "qwt_scale_map.h"
12#include "qwt_painter.h"
13#include "qwt_text.h"
14#include "qwt_graphic.h"
15#include "qwt_math.h"
16
17#include <qpainter.h>
18
19static inline bool qwtIsSampleInside( const QwtOHLCSample& sample,
20 double tMin, double tMax, double vMin, double vMax )
21{
22 const double t = sample.time;
23 const QwtInterval interval = sample.boundingInterval();
24
25 const bool isOffScreen = ( t < tMin ) || ( t > tMax )
26 || ( interval.maxValue() < vMin ) || ( interval.minValue() > vMax );
27
28 return !isOffScreen;
29}
30
31class QwtPlotTradingCurve::PrivateData
32{
33 public:
34 PrivateData()
35 : symbolStyle( QwtPlotTradingCurve::CandleStick )
36 , symbolExtent( 0.6 )
37 , minSymbolWidth( 2.0 )
38 , maxSymbolWidth( -1.0 )
39 , paintAttributes( QwtPlotTradingCurve::ClipSymbols )
40 {
41 symbolBrush[0] = QBrush( Qt::white );
42 symbolBrush[1] = QBrush( Qt::black );
43 }
44
46 double symbolExtent;
47 double minSymbolWidth;
48 double maxSymbolWidth;
49
50 QPen symbolPen;
51 QBrush symbolBrush[2]; // Increasing/Decreasing
52
54};
55
61 : QwtPlotSeriesItem( title )
62{
63 init();
64}
65
71 : QwtPlotSeriesItem( QwtText( title ) )
72{
73 init();
74}
75
81
84{
87
88 m_data = new PrivateData;
90
91 setZ( 19.0 );
92}
93
99
108 PaintAttribute attribute, bool on )
109{
110 if ( on )
111 m_data->paintAttributes |= attribute;
112 else
113 m_data->paintAttributes &= ~attribute;
114}
115
121 PaintAttribute attribute ) const
122{
123 return ( m_data->paintAttributes & attribute );
124}
125
133 const QVector< QwtOHLCSample >& samples )
134{
135 setData( new QwtTradingChartData( samples ) );
136}
137
153
163{
164 if ( style != m_data->symbolStyle )
165 {
166 m_data->symbolStyle = style;
167
169 itemChanged();
170 }
171}
172
178{
179 return m_data->symbolStyle;
180}
181
196 const QColor& color, qreal width, Qt::PenStyle style )
197{
198 setSymbolPen( QPen( color, width, style ) );
199}
200
210{
211 if ( pen != m_data->symbolPen )
212 {
213 m_data->symbolPen = pen;
214
216 itemChanged();
217 }
218}
219
225{
226 return m_data->symbolPen;
227}
228
239 Direction direction, const QBrush& brush )
240{
241 // silencing -Wtautological-constant-out-of-range-compare
242 const int index = static_cast< int >( direction );
243 if ( index < 0 || index >= 2 )
244 return;
245
246 if ( brush != m_data->symbolBrush[ index ] )
247 {
248 m_data->symbolBrush[ index ] = brush;
249
251 itemChanged();
252 }
253}
254
263{
264 const int index = static_cast< int >( direction );
265 if ( index < 0 || index >= 2 )
266 return QBrush();
267
268 return m_data->symbolBrush[ index ];
269}
270
285{
286 extent = qwtMaxF( 0.0, extent );
287 if ( extent != m_data->symbolExtent )
288 {
289 m_data->symbolExtent = extent;
290
292 itemChanged();
293 }
294}
295
302{
303 return m_data->symbolExtent;
304}
305
313{
314 width = qwtMaxF( width, 0.0 );
315 if ( width != m_data->minSymbolWidth )
316 {
317 m_data->minSymbolWidth = width;
318
320 itemChanged();
321 }
322}
323
329{
330 return m_data->minSymbolWidth;
331}
332
342{
343 if ( width != m_data->maxSymbolWidth )
344 {
345 m_data->maxSymbolWidth = width;
346
348 itemChanged();
349 }
350}
351
357{
358 return m_data->maxSymbolWidth;
359}
360
366{
367 QRectF rect = QwtPlotSeriesItem::boundingRect();
368 if ( orientation() == Qt::Vertical )
369 rect.setRect( rect.y(), rect.x(), rect.height(), rect.width() );
370
371 return rect;
372}
373
387void QwtPlotTradingCurve::drawSeries( QPainter* painter,
388 const QwtScaleMap& xMap, const QwtScaleMap& yMap,
389 const QRectF& canvasRect, int from, int to ) const
390{
391 if ( to < 0 )
392 to = dataSize() - 1;
393
394 if ( from < 0 )
395 from = 0;
396
397 if ( from > to )
398 return;
399
400 painter->save();
401
402 if ( m_data->symbolStyle != QwtPlotTradingCurve::NoSymbol )
403 drawSymbols( painter, xMap, yMap, canvasRect, from, to );
404
405 painter->restore();
406}
407
420void QwtPlotTradingCurve::drawSymbols( QPainter* painter,
421 const QwtScaleMap& xMap, const QwtScaleMap& yMap,
422 const QRectF& canvasRect, int from, int to ) const
423{
424 const QRectF tr = QwtScaleMap::invTransform( xMap, yMap, canvasRect );
425
426 const QwtScaleMap* timeMap, * valueMap;
427 double tMin, tMax, vMin, vMax;
428
429 const Qt::Orientation orient = orientation();
430 if ( orient == Qt::Vertical )
431 {
432 timeMap = &xMap;
433 valueMap = &yMap;
434
435 tMin = tr.left();
436 tMax = tr.right();
437 vMin = tr.top();
438 vMax = tr.bottom();
439 }
440 else
441 {
442 timeMap = &yMap;
443 valueMap = &xMap;
444
445 vMin = tr.left();
446 vMax = tr.right();
447 tMin = tr.top();
448 tMax = tr.bottom();
449 }
450
451 const bool inverted = timeMap->isInverting();
452 const bool doClip = m_data->paintAttributes & ClipSymbols;
453 const bool doAlign = QwtPainter::roundingAlignment( painter );
454
455 double symbolWidth = scaledSymbolWidth( xMap, yMap, canvasRect );
456 if ( doAlign )
457 symbolWidth = std::floor( 0.5 * symbolWidth ) * 2.0;
458
459 QPen pen = m_data->symbolPen;
460 pen.setCapStyle( Qt::FlatCap );
461
462 painter->setPen( pen );
463
464 for ( int i = from; i <= to; i++ )
465 {
466 const QwtOHLCSample s = sample( i );
467
468 if ( !doClip || qwtIsSampleInside( s, tMin, tMax, vMin, vMax ) )
469 {
470 QwtOHLCSample translatedSample;
471
472 translatedSample.time = timeMap->transform( s.time );
473 translatedSample.open = valueMap->transform( s.open );
474 translatedSample.high = valueMap->transform( s.high );
475 translatedSample.low = valueMap->transform( s.low );
476 translatedSample.close = valueMap->transform( s.close );
477
478 const int brushIndex = ( s.open < s.close )
481
482 if ( doAlign )
483 {
484 translatedSample.time = qRound( translatedSample.time );
485 translatedSample.open = qRound( translatedSample.open );
486 translatedSample.high = qRound( translatedSample.high );
487 translatedSample.low = qRound( translatedSample.low );
488 translatedSample.close = qRound( translatedSample.close );
489 }
490
491 switch( m_data->symbolStyle )
492 {
493 case Bar:
494 {
495 drawBar( painter, translatedSample,
496 orient, inverted, symbolWidth );
497 break;
498 }
499 case CandleStick:
500 {
501 painter->setBrush( m_data->symbolBrush[ brushIndex ] );
502 drawCandleStick( painter, translatedSample,
503 orient, symbolWidth );
504 break;
505 }
506 default:
507 {
508 if ( m_data->symbolStyle >= UserSymbol )
509 {
510 painter->setBrush( m_data->symbolBrush[ brushIndex ] );
511 drawUserSymbol( painter, m_data->symbolStyle,
512 translatedSample, orient, inverted, symbolWidth );
513 }
514 }
515 }
516 }
517 }
518}
519
535 SymbolStyle symbolStyle, const QwtOHLCSample& sample,
536 Qt::Orientation orientation, bool inverted, double symbolWidth ) const
537{
538 Q_UNUSED( painter )
539 Q_UNUSED( symbolStyle )
540 Q_UNUSED( orientation )
541 Q_UNUSED( inverted )
542 Q_UNUSED( symbolWidth )
543 Q_UNUSED( sample )
544}
545
562void QwtPlotTradingCurve::drawBar( QPainter* painter,
563 const QwtOHLCSample& sample, Qt::Orientation orientation,
564 bool inverted, double width ) const
565{
566 double w2 = 0.5 * width;
567 if ( inverted )
568 w2 *= -1;
569
570 if ( orientation == Qt::Vertical )
571 {
572 QwtPainter::drawLine( painter,
574
575 QwtPainter::drawLine( painter,
577 QwtPainter::drawLine( painter,
579 }
580 else
581 {
584 QwtPainter::drawLine( painter,
586 QwtPainter::drawLine( painter,
588 }
589}
590
602 const QwtOHLCSample& sample, Qt::Orientation orientation,
603 double width ) const
604{
605 const double t = sample.time;
606 const double v1 = qwtMinF( sample.low, sample.high );
607 const double v2 = qwtMinF( sample.open, sample.close );
608 const double v3 = qwtMaxF( sample.low, sample.high );
609 const double v4 = qwtMaxF( sample.open, sample.close );
610
611 if ( orientation == Qt::Vertical )
612 {
613 QwtPainter::drawLine( painter, t, v1, t, v2 );
614 QwtPainter::drawLine( painter, t, v3, t, v4 );
615
616 QRectF rect( t - 0.5 * width, sample.open,
617 width, sample.close - sample.open );
618
619 QwtPainter::drawRect( painter, rect );
620 }
621 else
622 {
623 QwtPainter::drawLine( painter, v1, t, v2, t );
624 QwtPainter::drawLine( painter, v3, t, v4, t );
625
626 const QRectF rect( sample.open, t - 0.5 * width,
627 sample.close - sample.open, width );
628
629 QwtPainter::drawRect( painter, rect );
630 }
631}
632
643 const QSizeF& size ) const
644{
645 Q_UNUSED( index );
646 return defaultIcon( m_data->symbolPen.color(), size );
647}
648
665 const QwtScaleMap& xMap, const QwtScaleMap& yMap,
666 const QRectF& canvasRect ) const
667{
668 Q_UNUSED( canvasRect );
669
670 if ( m_data->maxSymbolWidth > 0.0 &&
671 m_data->minSymbolWidth >= m_data->maxSymbolWidth )
672 {
673 return m_data->minSymbolWidth;
674 }
675
676 const QwtScaleMap* map =
677 ( orientation() == Qt::Vertical ) ? &xMap : &yMap;
678
679 const double pos = map->transform( map->s1() + m_data->symbolExtent );
680
681 double width = qAbs( pos - map->p1() );
682
683 width = qwtMaxF( width, m_data->minSymbolWidth );
684 if ( m_data->maxSymbolWidth > 0.0 )
685 width = qwtMinF( width, m_data->maxSymbolWidth );
686
687 return width;
688}
Template class for data, that is organized as QVector.
A paint device for scalable graphics.
Definition qwt_graphic.h:76
A class representing an interval.
double minValue() const
double maxValue() const
Open-High-Low-Close sample used in financial charts.
double high
Highest price.
double open
Opening price.
double close
Closing price.
QwtInterval boundingInterval() const
Calculate the bounding interval of the OHLC values.
double low
Lowest price.
static void drawRect(QPainter *, qreal x, qreal y, qreal w, qreal h)
Wrapper for QPainter::drawRect()
static bool roundingAlignment()
static void drawLine(QPainter *, qreal x1, qreal y1, qreal x2, qreal y2)
Wrapper for QPainter::drawLine()
virtual void legendChanged()
void setZ(double z)
Set the z value.
void setItemAttribute(ItemAttribute, bool on=true)
QwtGraphic defaultIcon(const QBrush &, const QSizeF &) const
Return a default icon from a brush.
@ Rtti_PlotTradingCurve
For QwtPlotTradingCurve.
virtual void itemChanged()
@ Legend
The item is represented on the legend.
Base class for plot items representing a series of samples.
Qt::Orientation orientation() const
virtual QRectF boundingRect() const override
QwtPlotTradingCurve illustrates movements in the price of a financial instrument over time.
void setSymbolStyle(SymbolStyle style)
QBrush symbolBrush(Direction) const
bool testPaintAttribute(PaintAttribute) const
void drawBar(QPainter *, const QwtOHLCSample &, Qt::Orientation, bool inverted, double width) const
Draw a bar.
SymbolStyle symbolStyle() const
void drawCandleStick(QPainter *, const QwtOHLCSample &, Qt::Orientation, double width) const
Draw a candle stick.
QFlags< PaintAttribute > PaintAttributes
virtual void drawUserSymbol(QPainter *, SymbolStyle, const QwtOHLCSample &, Qt::Orientation, bool inverted, double symbolWidth) const
Draw a symbol for a symbol style >= UserSymbol.
void setSamples(const QVector< QwtOHLCSample > &)
virtual QwtGraphic legendIcon(int index, const QSizeF &) const override
virtual QRectF boundingRect() const override
virtual void drawSymbols(QPainter *, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect, int from, int to) const
virtual void drawSeries(QPainter *, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect, int from, int to) const override
virtual ~QwtPlotTradingCurve()
Destructor.
void init()
Initialize internal members.
void setSymbolPen(const QColor &, qreal width=0.0, Qt::PenStyle=Qt::SolidLine)
void setSymbolExtent(double)
Set the extent of the symbol.
Direction
Direction of a price movement.
@ Increasing
The closing price is higher than the opening price.
@ Decreasing
The closing price is lower than the opening price.
void setPaintAttribute(PaintAttribute, bool on=true)
virtual double scaledSymbolWidth(const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect) const
void setSymbolBrush(Direction, const QBrush &)
@ NoSymbol
Nothing is displayed.
virtual int rtti() const override
QwtPlotTradingCurve(const QString &title=QString())
@ ClipSymbols
Check if a symbol is on the plot canvas before painting it.
A scale map.
bool isInverting() const
double p1() const
double transform(double s) const
double s1() const
double invTransform(double p) const
QwtOHLCSample sample(int index) const
virtual size_t dataSize() const override
QwtSeriesData< QwtOHLCSample > * data()
void setData(QwtSeriesData< QwtOHLCSample > *series)
A class representing a text.
Definition qwt_text.h:52