1 #include "plot.h"
2 #include "legend.h"
3 #include "griditem.h"
4 #include "quotefactory.h"
5 #include <qwt_legend.h>
6 #include <qwt_plot_tradingcurve.h>
7 #include <qwt_plot_marker.h>
8 #include <qwt_plot_zoneitem.h>
9 #include <qwt_plot_renderer.h>
10 #include <qwt_plot_zoomer.h>
11 #include <qwt_plot_panner.h>
12 #include <qwt_legend_label.h>
13 #include <qwt_date.h>
14 #include <qwt_date_scale_engine.h>
15 #include <qwt_date_scale_draw.h>
16 
17 class Zoomer: public QwtPlotZoomer
18 {
19 public:
Zoomer(QWidget * canvas)20     Zoomer( QWidget *canvas ):
21         QwtPlotZoomer( canvas )
22     {
23         setRubberBandPen( QColor( Qt::darkGreen ) );
24         setTrackerMode( QwtPlotPicker::AlwaysOn );
25     }
26 
27 protected:
trackerTextF(const QPointF & pos) const28     virtual QwtText trackerTextF( const QPointF &pos ) const
29     {
30         const QDateTime dt = QwtDate::toDateTime( pos.x() );
31 
32         QString s;
33         s += QwtDate::toString( QwtDate::toDateTime( pos.x() ),
34             "MMM dd hh:mm ", QwtDate::FirstThursday );
35 
36         QwtText text( s );
37         text.setColor( Qt::white );
38 
39         QColor c = rubberBandPen().color();
40         text.setBorderPen( QPen( c ) );
41         text.setBorderRadius( 6 );
42         c.setAlpha( 170 );
43         text.setBackgroundBrush( c );
44 
45         return text;
46     }
47 };
48 
49 class DateScaleDraw: public QwtDateScaleDraw
50 {
51 public:
DateScaleDraw(Qt::TimeSpec timeSpec)52     DateScaleDraw( Qt::TimeSpec timeSpec ):
53         QwtDateScaleDraw( timeSpec )
54     {
55         // as we have dates from 2010 only we use
56         // format strings without the year
57 
58         setDateFormat( QwtDate::Millisecond, "hh:mm:ss:zzz\nddd dd MMM" );
59         setDateFormat( QwtDate::Second, "hh:mm:ss\nddd dd MMM" );
60         setDateFormat( QwtDate::Minute, "hh:mm\nddd dd MMM" );
61         setDateFormat( QwtDate::Hour, "hh:mm\nddd dd MMM" );
62         setDateFormat( QwtDate::Day, "ddd dd MMM" );
63         setDateFormat( QwtDate::Week, "Www" );
64         setDateFormat( QwtDate::Month, "MMM" );
65     }
66 };
67 
68 class ZoneItem: public QwtPlotZoneItem
69 {
70 public:
ZoneItem(const QString & title)71     ZoneItem( const QString &title )
72     {
73         setTitle( title );
74         setZ( 11 ); // on top the the grid
75         setOrientation( Qt::Vertical );
76         setItemAttribute( QwtPlotItem::Legend, true );
77     }
78 
setColor(const QColor & color)79     void setColor( const QColor &color )
80     {
81         QColor c = color;
82 
83         c.setAlpha( 100 );
84         setPen( c );
85 
86         c.setAlpha( 20 );
87         setBrush( c );
88     }
89 
setInterval(const QDate & date1,const QDate & date2)90     void setInterval( const QDate &date1, const QDate &date2 )
91     {
92         const QDateTime dt1( date1, QTime(), Qt::UTC );
93         const QDateTime dt2( date2, QTime(), Qt::UTC );
94 
95         QwtPlotZoneItem::setInterval( QwtDate::toDouble( dt1 ),
96             QwtDate::toDouble( dt2 ) );
97     }
98 };
99 
Plot(QWidget * parent)100 Plot::Plot( QWidget *parent ):
101     QwtPlot( parent )
102 {
103     setTitle( "Trading Chart" );
104 
105     QwtDateScaleDraw *scaleDraw = new DateScaleDraw( Qt::UTC );
106     QwtDateScaleEngine *scaleEngine = new QwtDateScaleEngine( Qt::UTC );
107 
108     setAxisTitle( QwtPlot::xBottom, QString( "2010" ) );
109     setAxisScaleDraw( QwtPlot::xBottom, scaleDraw );
110     setAxisScaleEngine( QwtPlot::xBottom, scaleEngine );
111     setAxisLabelRotation( QwtPlot::xBottom, -50.0 );
112     setAxisLabelAlignment( QwtPlot::xBottom, Qt::AlignLeft | Qt::AlignBottom );
113 
114     setAxisTitle( QwtPlot::yLeft, QString( "Price [EUR]" ) );
115 
116 #if 0
117     QwtLegend *legend = new QwtLegend;
118     legend->setDefaultItemMode( QwtLegendData::Checkable );
119     insertLegend( legend, QwtPlot::RightLegend );
120 #else
121     Legend *legend = new Legend;
122     insertLegend( legend, QwtPlot::RightLegend );
123 #endif
124 
125     populate();
126 
127     // LeftButton for the zooming
128     // MidButton for the panning
129     // RightButton: zoom out by 1
130     // Ctrl+RighButton: zoom out to full size
131 
132     Zoomer* zoomer = new Zoomer( canvas() );
133     zoomer->setMousePattern( QwtEventPattern::MouseSelect2,
134         Qt::RightButton, Qt::ControlModifier );
135     zoomer->setMousePattern( QwtEventPattern::MouseSelect3,
136         Qt::RightButton );
137 
138     QwtPlotPanner *panner = new QwtPlotPanner( canvas() );
139     panner->setMouseButton( Qt::MidButton );
140 
141     connect( legend, SIGNAL( checked( QwtPlotItem *, bool, int ) ),
142         SLOT( showItem( QwtPlotItem *, bool ) ) );
143 }
144 
populate()145 void Plot::populate()
146 {
147     GridItem *gridItem = new GridItem();
148 #if 0
149     gridItem->setOrientations( Qt::Horizontal );
150 #endif
151     gridItem->attach( this );
152 
153     const Qt::GlobalColor colors[] =
154     {
155         Qt::red,
156         Qt::blue,
157         Qt::darkCyan,
158         Qt::darkMagenta,
159         Qt::darkYellow
160     };
161 
162     const int numColors = sizeof( colors ) / sizeof( colors[0] );
163 
164     for ( int i = 0; i < QuoteFactory::NumStocks; i++ )
165     {
166         QuoteFactory::Stock stock = static_cast<QuoteFactory::Stock>( i );
167 
168         QwtPlotTradingCurve *curve = new QwtPlotTradingCurve();
169         curve->setTitle( QuoteFactory::title( stock ) );
170         curve->setOrientation( Qt::Vertical );
171         curve->setSamples( QuoteFactory::samples2010( stock ) );
172 
173         // as we have one sample per day a symbol width of
174         // 12h avoids overlapping symbols. We also bound
175         // the width, so that is is not scaled below 3 and
176         // above 15 pixels.
177 
178         curve->setSymbolExtent( 12 * 3600 * 1000.0 );
179         curve->setMinSymbolWidth( 3 );
180         curve->setMaxSymbolWidth( 15 );
181 
182         const Qt::GlobalColor color = colors[ i % numColors ];
183 
184         curve->setSymbolPen( color );
185         curve->setSymbolBrush( QwtPlotTradingCurve::Decreasing, color );
186         curve->setSymbolBrush( QwtPlotTradingCurve::Increasing, Qt::white );
187         curve->attach( this );
188 
189         showItem( curve, true );
190     }
191 
192     for ( int i = 0; i < 2; i++ )
193     {
194         QwtPlotMarker *marker = new QwtPlotMarker();
195 
196         marker->setTitle( QString( "Event %1" ).arg( i + 1 ) );
197         marker->setLineStyle( QwtPlotMarker::VLine );
198         marker->setLinePen( colors[ i % numColors ], 0, Qt::DashLine );
199         marker->setVisible( false );
200 
201         QDateTime dt( QDate( 2010, 1, 1 ) );
202         dt = dt.addDays( 77 * ( i + 1 ) );
203 
204         marker->setValue( QwtDate::toDouble( dt ), 0.0 );
205 
206         marker->setItemAttribute( QwtPlotItem::Legend, true );
207 
208         marker->attach( this );
209     }
210 
211     // to show how QwtPlotZoneItem works
212 
213     ZoneItem *zone1 = new ZoneItem( "Zone 1");
214     zone1->setColor( Qt::darkBlue );
215     zone1->setInterval( QDate( 2010, 3, 10 ), QDate( 2010, 3, 27 ) );
216     zone1->setVisible( false );
217     zone1->attach( this );
218 
219     ZoneItem *zone2 = new ZoneItem( "Zone 2");
220     zone2->setColor( Qt::darkMagenta );
221     zone2->setInterval( QDate( 2010, 8, 1 ), QDate( 2010, 8, 24 ) );
222     zone2->setVisible( false );
223     zone2->attach( this );
224 
225 }
226 
setMode(int style)227 void Plot::setMode( int style )
228 {
229     QwtPlotTradingCurve::SymbolStyle symbolStyle =
230         static_cast<QwtPlotTradingCurve::SymbolStyle>( style );
231 
232     QwtPlotItemList curves = itemList( QwtPlotItem::Rtti_PlotTradingCurve );
233     for ( int i = 0; i < curves.size(); i++ )
234     {
235         QwtPlotTradingCurve *curve =
236             static_cast<QwtPlotTradingCurve *>( curves[i] );
237         curve->setSymbolStyle( symbolStyle );
238     }
239 
240     replot();
241 }
242 
showItem(QwtPlotItem * item,bool on)243 void Plot::showItem( QwtPlotItem *item, bool on )
244 {
245     item->setVisible( on );
246     replot();
247 }
248 
exportPlot()249 void Plot::exportPlot()
250 {
251     QwtPlotRenderer renderer;
252     renderer.exportTo( this, "stockchart.pdf" );
253 }
254