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