Merge branch 'upstream' into dfsg-orig
[debian/gnuradio] / gr-qtgui / src / lib / TimeDomainDisplayPlot.cc
index 42f827d9ab920a414d5f3adb288713678bf37861..c299f83a4a09ea56f6b39df9d039cbfc1c96c794 100644 (file)
@@ -7,10 +7,37 @@
 #include <qwt_legend.h>
 
 
-class TimeDomainDisplayZoomer: public QwtPlotZoomer
+class TimePrecisionClass
 {
 public:
-  TimeDomainDisplayZoomer(QwtPlotCanvas* canvas):QwtPlotZoomer(canvas)
+  TimePrecisionClass(const int timePrecision)
+  {
+    _timePrecision = timePrecision;
+  }
+
+  virtual ~TimePrecisionClass()
+  {
+  }
+
+  virtual unsigned int GetTimePrecision() const
+  {
+    return _timePrecision;
+  }
+
+  virtual void SetTimePrecision(const unsigned int newPrecision)
+  {
+    _timePrecision = newPrecision;
+  }
+protected:
+  unsigned int _timePrecision;
+};
+
+
+class TimeDomainDisplayZoomer: public QwtPlotZoomer, public TimePrecisionClass
+{
+public:
+  TimeDomainDisplayZoomer(QwtPlotCanvas* canvas, const unsigned int timePrecision)
+    : QwtPlotZoomer(canvas),TimePrecisionClass(timePrecision)
   {
     setTrackerMode(QwtPicker::AlwaysOn);
   }
@@ -23,27 +50,38 @@ public:
     updateDisplay();
   }
 
+  void SetUnitType(const std::string &type)
+  {
+    _unitType = type;
+  }
+
 protected:
   virtual QwtText trackerText( const QwtDoublePoint& p ) const 
   {
-    QwtText t(QString("Sample %1, %2 V").arg(p.x(), 0, 'f', 0).arg(p.y(), 0, 'f', 4));
+    QwtText t(QString("%1 %2, %3 V").arg(p.x(), 0, 'f', GetTimePrecision()).
+             arg(_unitType.c_str()).
+             arg(p.y(), 0, 'f', 4));
 
     return t;
   }
+
+private:
+  std::string _unitType;
 };
 
-TimeDomainDisplayPlot::TimeDomainDisplayPlot(QWidget* parent):QwtPlot(parent){
+TimeDomainDisplayPlot::TimeDomainDisplayPlot(QWidget* parent):QwtPlot(parent)
+{
   timespec_reset(&_lastReplot);
 
   resize(parent->width(), parent->height());
 
-  _displayIntervalTime = (1.0/10.0); // 1/10 of a second between updates
-
   _numPoints = 1024;
   _realDataPoints = new double[_numPoints];
   _imagDataPoints = new double[_numPoints];
   _xAxisPoints = new double[_numPoints];
 
+  _zoomer = new TimeDomainDisplayZoomer(canvas(), 0);
+
   // Disable polygon clipping
   QwtPainter::setDeviceClipping(false);
   
@@ -56,8 +94,8 @@ TimeDomainDisplayPlot::TimeDomainDisplayPlot(QWidget* parent):QwtPlot(parent){
   canvas()->setPalette(palette);  
 
   setAxisScaleEngine(QwtPlot::xBottom, new QwtLinearScaleEngine);
-  setAxisScale(QwtPlot::xBottom, 0, _numPoints);
-  setAxisTitle(QwtPlot::xBottom, "Sample Number");
+  set_xaxis(0, _numPoints);
+  setAxisTitle(QwtPlot::xBottom, "Time (sec)");
 
   setAxisScaleEngine(QwtPlot::yLeft, new QwtLinearScaleEngine);
   set_yaxis(-2.0, 2.0);
@@ -79,11 +117,11 @@ TimeDomainDisplayPlot::TimeDomainDisplayPlot(QWidget* parent):QwtPlot(parent){
   memset(_imagDataPoints, 0x0, _numPoints*sizeof(double));
   memset(_xAxisPoints, 0x0, _numPoints*sizeof(double));
 
+  _sampleRate = 1;
   _resetXAxisPoints();
 
   replot();
 
-  _zoomer = new TimeDomainDisplayZoomer(canvas());
 #if QT_VERSION < 0x040000
   _zoomer->setMousePattern(QwtEventPattern::MouseSelect2,
                          Qt::RightButton, Qt::ControlModifier);
@@ -113,7 +151,8 @@ TimeDomainDisplayPlot::TimeDomainDisplayPlot(QWidget* parent):QwtPlot(parent){
   legendDisplay->setItemMode(QwtLegend::CheckableItem);
   insertLegend(legendDisplay);
 
-  connect(this, SIGNAL( legendChecked(QwtPlotItem *, bool ) ), this, SLOT( LegendEntryChecked(QwtPlotItem *, bool ) ));
+  connect(this, SIGNAL( legendChecked(QwtPlotItem *, bool ) ), 
+         this, SLOT( LegendEntryChecked(QwtPlotItem *, bool ) ));
 }
 
 TimeDomainDisplayPlot::~TimeDomainDisplayPlot(){
@@ -129,26 +168,36 @@ void
 TimeDomainDisplayPlot::set_yaxis(double min, double max)
 {
   setAxisScale(QwtPlot::yLeft, min, max);
+  _zoomer->setZoomBase();
 }
 
-void TimeDomainDisplayPlot::replot(){
-
-  const timespec startTime = get_highres_clock();
-  
-  QwtPlot::replot();
+void
+TimeDomainDisplayPlot::set_xaxis(double min, double max)
+{
+  setAxisScale(QwtPlot::xBottom, min, max);
+  _zoomer->setZoomBase();
+}
 
-  double differenceTime = (diff_timespec(get_highres_clock(), startTime));
 
-  differenceTime *= 99.0;
-  // Require at least a 10% duty cycle
-  if(differenceTime > (1.0/10.0)){
-    _displayIntervalTime = differenceTime;
-  }
+void TimeDomainDisplayPlot::replot()
+{
+  QwtPlot::replot();
 }
 
-void TimeDomainDisplayPlot::PlotNewData(const double* realDataPoints, const double* imagDataPoints, const int64_t numDataPoints){
-  if(numDataPoints > 0){
+void
+TimeDomainDisplayPlot::resizeSlot( QSize *s )
+{
+  resize(s->width(), s->height());
+}
 
+void TimeDomainDisplayPlot::PlotNewData(const double* realDataPoints,
+                                       const double* imagDataPoints,
+                                       const int64_t numDataPoints,
+                                       const double timeInterval)
+{
+  if((numDataPoints > 0) && 
+     (diff_timespec(get_highres_clock(), _lastReplot) > timeInterval)) {
+  
     if(numDataPoints != _numPoints){
       _numPoints = numDataPoints;
 
@@ -162,36 +211,65 @@ void TimeDomainDisplayPlot::PlotNewData(const double* realDataPoints, const doub
       _real_plot_curve->setRawData(_xAxisPoints, _realDataPoints, _numPoints);
       _imag_plot_curve->setRawData(_xAxisPoints, _imagDataPoints, _numPoints);
 
+      set_xaxis(0, numDataPoints);
+
       _resetXAxisPoints();
     }
+
     memcpy(_realDataPoints, realDataPoints, numDataPoints*sizeof(double));
     memcpy(_imagDataPoints, imagDataPoints, numDataPoints*sizeof(double));
 
-  }
+    replot();
 
-  // Allow at least a 50% duty cycle
-  if(diff_timespec(get_highres_clock(), _lastReplot) > _displayIntervalTime){
-    // Only replot the screen if it is visible
-    if(isVisible()){
-      replot();
-    }
     _lastReplot = get_highres_clock();
   }
 }
 
-void TimeDomainDisplayPlot::SetImaginaryDataVisible(const bool visibleFlag){
+void TimeDomainDisplayPlot::SetImaginaryDataVisible(const bool visibleFlag)
+{
   _imag_plot_curve->setVisible(visibleFlag);
 }
 
-void TimeDomainDisplayPlot::_resetXAxisPoints(){
+void TimeDomainDisplayPlot::_resetXAxisPoints()
+{
+  double delt = 1.0/_sampleRate;
   for(long loc = 0; loc < _numPoints; loc++){
-    _xAxisPoints[loc] = loc;
+    _xAxisPoints[loc] = loc*delt;
   }
-  setAxisScale(QwtPlot::xBottom, 0, _numPoints);
+  setAxisScale(QwtPlot::xBottom, 0, _numPoints*delt);
+
+  // Set up zoomer base for maximum unzoom x-axis
+  // and reset to maximum unzoom level
+  QwtDoubleRect zbase = _zoomer->zoomBase();
+  zbase.setLeft(0);
+  zbase.setRight(_numPoints*delt);
+  _zoomer->zoom(zbase);
+  _zoomer->setZoomBase(zbase);
+  _zoomer->zoom(0);
 }
 
-void TimeDomainDisplayPlot::LegendEntryChecked(QwtPlotItem* plotItem, bool on){
+void TimeDomainDisplayPlot::LegendEntryChecked(QwtPlotItem* plotItem, bool on)
+{
   plotItem->setVisible(!on);
 }
 
+void
+TimeDomainDisplayPlot::SetSampleRate(double sr, double units,
+                                    const std::string &strunits)
+{
+  double newsr = sr/units;
+  if(newsr != _sampleRate) {
+    _sampleRate = sr/units;
+    _resetXAxisPoints();
+    
+    // While we could change the displayed sigfigs based on the unit being
+    // displayed, I think it looks better by just setting it to 4 regardless.
+    //double display_units = ceil(log10(units)/2.0);
+    double display_units = 4;
+    setAxisTitle(QwtPlot::xBottom, QString("Time (%1)").arg(strunits.c_str()));
+    ((TimeDomainDisplayZoomer*)_zoomer)->SetTimePrecision(display_units);
+    ((TimeDomainDisplayZoomer*)_zoomer)->SetUnitType(strunits);
+  }
+}
+
 #endif /* TIME_DOMAIN_DISPLAY_PLOT_C */