cb18b44184db14dfdb1f2e4301bf56cfff112908
[debian/gnuradio] / gr-qtgui / src / lib / TimeDomainDisplayPlot.cc
1 #ifndef TIME_DOMAIN_DISPLAY_PLOT_C
2 #define TIME_DOMAIN_DISPLAY_PLOT_C
3
4 #include <TimeDomainDisplayPlot.h>
5
6 #include <qwt_scale_draw.h>
7 #include <qwt_legend.h>
8
9
10 class TimeDomainDisplayZoomer: public QwtPlotZoomer
11 {
12 public:
13   TimeDomainDisplayZoomer(QwtPlotCanvas* canvas):QwtPlotZoomer(canvas)
14   {
15     setTrackerMode(QwtPicker::AlwaysOn);
16   }
17
18   virtual ~TimeDomainDisplayZoomer(){
19
20   }
21   
22   virtual void updateTrackerText(){
23     updateDisplay();
24   }
25
26 protected:
27   virtual QwtText trackerText( const QwtDoublePoint& p ) const 
28   {
29     QwtText t(QString("Sample %1, %2 V").arg(p.x(), 0, 'f', 0).arg(p.y(), 0, 'f', 4));
30
31     return t;
32   }
33 };
34
35 TimeDomainDisplayPlot::TimeDomainDisplayPlot(QWidget* parent):QwtPlot(parent){
36   timespec_reset(&_lastReplot);
37
38   resize(parent->width(), parent->height());
39
40   _displayIntervalTime = (1.0/10.0); // 1/10 of a second between updates
41
42   _numPoints = 1024;
43   _realDataPoints = new double[_numPoints];
44   _imagDataPoints = new double[_numPoints];
45   _xAxisPoints = new double[_numPoints];
46
47   _zoomer = new TimeDomainDisplayZoomer(canvas());
48
49   // Disable polygon clipping
50   QwtPainter::setDeviceClipping(false);
51   
52   // We don't need the cache here
53   canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached, false);
54   canvas()->setPaintAttribute(QwtPlotCanvas::PaintPacked, false);
55
56   QPalette palette;
57   palette.setColor(canvas()->backgroundRole(), QColor("white"));
58   canvas()->setPalette(palette);  
59
60   setAxisScaleEngine(QwtPlot::xBottom, new QwtLinearScaleEngine);
61   set_xaxis(0, _numPoints);
62   setAxisTitle(QwtPlot::xBottom, "Sample Number");
63
64   setAxisScaleEngine(QwtPlot::yLeft, new QwtLinearScaleEngine);
65   set_yaxis(-2.0, 2.0);
66   setAxisTitle(QwtPlot::yLeft, "Normalized Voltage");
67
68   // Automatically deleted when parent is deleted
69   _real_plot_curve = new QwtPlotCurve("Real Data");
70   _real_plot_curve->attach(this);
71   _real_plot_curve->setPen(QPen(Qt::blue));
72   _real_plot_curve->setRawData(_xAxisPoints, _realDataPoints, _numPoints);
73
74   _imag_plot_curve = new QwtPlotCurve("Imaginary Data");
75   _imag_plot_curve->attach(this);
76   _imag_plot_curve->setPen(QPen(Qt::magenta));
77   _imag_plot_curve->setRawData(_xAxisPoints, _imagDataPoints, _numPoints);
78   // _imag_plot_curve->setVisible(false);
79
80   memset(_realDataPoints, 0x0, _numPoints*sizeof(double));
81   memset(_imagDataPoints, 0x0, _numPoints*sizeof(double));
82   memset(_xAxisPoints, 0x0, _numPoints*sizeof(double));
83
84   _resetXAxisPoints();
85
86   replot();
87
88 #if QT_VERSION < 0x040000
89   _zoomer->setMousePattern(QwtEventPattern::MouseSelect2,
90                           Qt::RightButton, Qt::ControlModifier);
91 #else
92   _zoomer->setMousePattern(QwtEventPattern::MouseSelect2,
93                           Qt::RightButton, Qt::ControlModifier);
94 #endif
95   _zoomer->setMousePattern(QwtEventPattern::MouseSelect3,
96                           Qt::RightButton);
97
98   _panner = new QwtPlotPanner(canvas());
99   _panner->setAxisEnabled(QwtPlot::yRight, false);
100   _panner->setMouseButton(Qt::MidButton);
101
102   // Avoid jumping when labels with more/less digits
103   // appear/disappear when scrolling vertically
104
105   const QFontMetrics fm(axisWidget(QwtPlot::yLeft)->font());
106   QwtScaleDraw *sd = axisScaleDraw(QwtPlot::yLeft);
107   sd->setMinimumExtent( fm.width("100.00") );
108
109   const QColor c(Qt::darkRed);
110   _zoomer->setRubberBandPen(c);
111   _zoomer->setTrackerPen(c);
112
113   QwtLegend* legendDisplay = new QwtLegend(this);
114   legendDisplay->setItemMode(QwtLegend::CheckableItem);
115   insertLegend(legendDisplay);
116
117   connect(this, SIGNAL( legendChecked(QwtPlotItem *, bool ) ), this, SLOT( LegendEntryChecked(QwtPlotItem *, bool ) ));
118 }
119
120 TimeDomainDisplayPlot::~TimeDomainDisplayPlot(){
121   delete[] _realDataPoints;
122   delete[] _imagDataPoints;
123   delete[] _xAxisPoints;
124
125   // _fft_plot_curves deleted when parent deleted
126   // _zoomer and _panner deleted when parent deleted
127 }
128
129 void
130 TimeDomainDisplayPlot::set_yaxis(double min, double max)
131 {
132   setAxisScale(QwtPlot::yLeft, min, max);
133   _zoomer->setZoomBase();
134 }
135
136 void
137 TimeDomainDisplayPlot::set_xaxis(double min, double max)
138 {
139   setAxisScale(QwtPlot::xBottom, min, max);
140   _zoomer->setZoomBase();
141 }
142
143
144 void TimeDomainDisplayPlot::replot()
145 {
146   const timespec startTime = get_highres_clock();
147   
148   QwtPlot::replot();
149
150   double differenceTime = (diff_timespec(get_highres_clock(), startTime));
151
152   differenceTime *= 99.0;
153   // Require at least a 10% duty cycle
154   if(differenceTime > (1.0/10.0)){
155     _displayIntervalTime = differenceTime;
156   }
157 }
158
159 void
160 TimeDomainDisplayPlot::resizeSlot( QSize *s )
161 {
162   resize(s->width(), s->height());
163 }
164
165 void TimeDomainDisplayPlot::PlotNewData(const double* realDataPoints,
166                                         const double* imagDataPoints,
167                                         const int64_t numDataPoints)
168 {
169   if(numDataPoints > 0){
170
171     if(numDataPoints != _numPoints){
172       _numPoints = numDataPoints;
173
174       delete[] _realDataPoints;
175       delete[] _imagDataPoints;
176       delete[] _xAxisPoints;
177       _realDataPoints = new double[_numPoints];
178       _imagDataPoints = new double[_numPoints];
179       _xAxisPoints = new double[_numPoints];
180       
181       _real_plot_curve->setRawData(_xAxisPoints, _realDataPoints, _numPoints);
182       _imag_plot_curve->setRawData(_xAxisPoints, _imagDataPoints, _numPoints);
183
184       set_xaxis(0, numDataPoints);
185
186       _resetXAxisPoints();
187     }
188     memcpy(_realDataPoints, realDataPoints, numDataPoints*sizeof(double));
189     memcpy(_imagDataPoints, imagDataPoints, numDataPoints*sizeof(double));
190
191   }
192
193   // Allow at least a 50% duty cycle
194   if(diff_timespec(get_highres_clock(), _lastReplot) > _displayIntervalTime){
195     // Only replot the screen if it is visible
196     if(isVisible()){
197       replot();
198     }
199     _lastReplot = get_highres_clock();
200   }
201 }
202
203 void TimeDomainDisplayPlot::SetImaginaryDataVisible(const bool visibleFlag){
204   _imag_plot_curve->setVisible(visibleFlag);
205 }
206
207 void TimeDomainDisplayPlot::_resetXAxisPoints(){
208   for(long loc = 0; loc < _numPoints; loc++){
209     _xAxisPoints[loc] = loc;
210   }
211   setAxisScale(QwtPlot::xBottom, 0, _numPoints);
212 }
213
214 void TimeDomainDisplayPlot::LegendEntryChecked(QwtPlotItem* plotItem, bool on){
215   plotItem->setVisible(!on);
216 }
217
218 #endif /* TIME_DOMAIN_DISPLAY_PLOT_C */