Fixes segfault on close. Using the right objective (d_main_gui) instead of d_object...
[debian/gnuradio] / gr-qtgui / src / lib / spectrumdisplayform.cc
1 #include <cmath>
2 #include <QColorDialog>
3 #include <QMessageBox>
4 #include <spectrumdisplayform.h>
5
6 int SpectrumDisplayForm::_openGLWaterfall3DFlag = -1;
7
8 SpectrumDisplayForm::SpectrumDisplayForm(bool useOpenGL, QWidget* parent)
9   : QWidget(parent)
10 {
11   setupUi(this);
12
13   _useOpenGL = useOpenGL;
14   _systemSpecifiedFlag = false;
15   _intValidator = new QIntValidator(this);
16   _intValidator->setBottom(0);
17   _frequencyDisplayPlot = new FrequencyDisplayPlot(FrequencyPlotDisplayFrame);
18   _waterfallDisplayPlot = new WaterfallDisplayPlot(WaterfallPlotDisplayFrame);
19
20   if((QGLFormat::hasOpenGL()) && (_useOpenGL)) {
21     //_waterfall3DDisplayPlot = new Waterfall3DDisplayPlot(Waterfall3DPlotDisplayFrame);
22   }
23
24   _timeDomainDisplayPlot = new TimeDomainDisplayPlot(TimeDomainDisplayFrame);
25   _constellationDisplayPlot = new ConstellationDisplayPlot(ConstellationDisplayFrame);
26   _numRealDataPoints = 1024;
27   _realFFTDataPoints = new double[_numRealDataPoints];
28   _averagedValues = new double[_numRealDataPoints];
29   _historyVector = new std::vector<double*>;
30   
31   AvgLineEdit->setRange(0, 500);                 // Set range of Average box value from 0 to 500
32   MinHoldCheckBox_toggled( false );
33   MaxHoldCheckBox_toggled( false );
34   
35   WaterfallMaximumIntensityWheel->setRange(-200, 0);
36   WaterfallMaximumIntensityWheel->setTickCnt(50);
37   WaterfallMinimumIntensityWheel->setRange(-200, 0);
38   WaterfallMinimumIntensityWheel->setTickCnt(50);
39   WaterfallMinimumIntensityWheel->setValue(-200);
40   
41   if((QGLFormat::hasOpenGL()) && (_useOpenGL)) {
42     Waterfall3DMaximumIntensityWheel->setRange(-200, 0);
43     Waterfall3DMaximumIntensityWheel->setTickCnt(50);
44     Waterfall3DMinimumIntensityWheel->setRange(-200, 0);
45     Waterfall3DMinimumIntensityWheel->setTickCnt(50);
46     Waterfall3DMinimumIntensityWheel->setValue(-200);
47   }
48
49   _peakFrequency = 0;
50   _peakAmplitude = -HUGE_VAL;
51   
52   _noiseFloorAmplitude = -HUGE_VAL;
53
54   connect(_waterfallDisplayPlot, SIGNAL(UpdatedLowerIntensityLevel(const double)), 
55           _frequencyDisplayPlot, SLOT(SetLowerIntensityLevel(const double)));
56   connect(_waterfallDisplayPlot, SIGNAL(UpdatedUpperIntensityLevel(const double)), 
57           _frequencyDisplayPlot, SLOT(SetUpperIntensityLevel(const double)));
58   
59   _frequencyDisplayPlot->SetLowerIntensityLevel(-200);
60   _frequencyDisplayPlot->SetUpperIntensityLevel(-200);
61
62   // Load up the acceptable FFT sizes...
63   FFTSizeComboBox->clear();
64   for(long fftSize = SpectrumGUIClass::MIN_FFT_SIZE; fftSize <= SpectrumGUIClass::MAX_FFT_SIZE; fftSize *= 2){
65     FFTSizeComboBox->insertItem(FFTSizeComboBox->count(), QString("%1").arg(fftSize));
66   }
67   Reset();
68
69   ToggleTabFrequency(false);
70   ToggleTabWaterfall(false);
71   ToggleTabWaterfall3D(false);
72   ToggleTabTime(false);
73   ToggleTabConstellation(false);
74
75   // Create a timer to update plots at the specified rate
76   displayTimer = new QTimer(this);
77   connect(displayTimer, SIGNAL(timeout()), this, SLOT(UpdateGuiTimer()));
78 }
79
80 SpectrumDisplayForm::~SpectrumDisplayForm()
81 {
82   // Qt deletes children when parent is deleted
83
84   // Don't worry about deleting Display Plots - they are deleted when parents are deleted
85   delete _intValidator;
86
87   delete[] _realFFTDataPoints;
88   delete[] _averagedValues;
89
90   for(unsigned int count = 0; count < _historyVector->size(); count++){
91     delete[] _historyVector->operator[](count);
92   }
93
94   delete _historyVector;
95
96   displayTimer->stop();
97   delete displayTimer;
98 }
99
100 void
101 SpectrumDisplayForm::setSystem( SpectrumGUIClass * newSystem, 
102                                 const uint64_t numFFTDataPoints, 
103                                 const uint64_t numTimeDomainDataPoints )
104 {
105   ResizeBuffers(numFFTDataPoints, numTimeDomainDataPoints);
106   
107   if(newSystem != NULL){
108     _system = newSystem;
109     _systemSpecifiedFlag = true;
110   }
111   else{
112     _systemSpecifiedFlag = false;
113   }
114 }
115
116 void
117 SpectrumDisplayForm::newFrequencyData( const SpectrumUpdateEvent* spectrumUpdateEvent)
118 {
119   //_lastSpectrumEvent = (SpectrumUpdateEvent)(*spectrumUpdateEvent);
120   const std::complex<float>* complexDataPoints = spectrumUpdateEvent->getFFTPoints();
121   const uint64_t numFFTDataPoints = spectrumUpdateEvent->getNumFFTDataPoints();
122   const double* realTimeDomainDataPoints = spectrumUpdateEvent->getRealTimeDomainPoints();
123   const double* imagTimeDomainDataPoints = spectrumUpdateEvent->getImagTimeDomainPoints();
124   const uint64_t numTimeDomainDataPoints = spectrumUpdateEvent->getNumTimeDomainDataPoints();
125   const timespec dataTimestamp = spectrumUpdateEvent->getDataTimestamp();;
126   const bool repeatDataFlag = spectrumUpdateEvent->getRepeatDataFlag();
127   const bool lastOfMultipleUpdatesFlag = spectrumUpdateEvent->getLastOfMultipleUpdateFlag();
128   const timespec generatedTimestamp = spectrumUpdateEvent->getEventGeneratedTimestamp();
129
130   // REMEMBER: The dataTimestamp is NOT valid when the repeat data flag is true...
131   ResizeBuffers(numFFTDataPoints, numTimeDomainDataPoints);
132
133   // Calculate the Magnitude of the complex point
134   const std::complex<float>* complexDataPointsPtr = complexDataPoints+numFFTDataPoints/2;
135   double* realFFTDataPointsPtr = _realFFTDataPoints;
136
137   // Run this twice to perform the fftshift operation on the data here as well
138   for(uint64_t point = 0; point < numFFTDataPoints/2; point++){
139     // Calculate dBm
140     // 50 ohm load assumption
141     // 10 * log10 (v^2 / (2 * 50.0 * .001)) = 10 * log10( v^2 * 10)
142     // 75 ohm load assumption
143     // 10 * log10 (v^2 / (2 * 75.0 * .001)) = 10 * log10( v^2 * 15)
144
145     // perform scaling here
146     std::complex<float> pt = (*complexDataPointsPtr) / std::complex<float>((float)numFFTDataPoints);
147     *realFFTDataPointsPtr = 10.0*log10((pt.real() * pt.real() + pt.imag()*pt.imag()) + 1e-20);
148
149     complexDataPointsPtr++;
150     realFFTDataPointsPtr++;
151   }
152   
153   // This loop takes the first half of the input data and puts it in the 
154   // second half of the plotted data
155   complexDataPointsPtr = complexDataPoints;
156   for(uint64_t point = 0; point < numFFTDataPoints/2; point++){
157     std::complex<float> pt = (*complexDataPointsPtr) / std::complex<float>((float)numFFTDataPoints);
158     *realFFTDataPointsPtr = 10.0*log10((pt.real() * pt.real() + pt.imag()*pt.imag()) + 1e-20);
159
160     complexDataPointsPtr++;
161     realFFTDataPointsPtr++;
162   }
163
164   // Don't update the averaging history if this is repeated data
165   if(!repeatDataFlag){
166     _AverageHistory(_realFFTDataPoints);
167
168     double sumMean;
169     const double fft_bin_size = (_stopFrequency-_startFrequency) /
170       static_cast<double>(numFFTDataPoints);
171
172     // find the peak, sum (for mean), etc
173     _peakAmplitude = -HUGE_VAL;
174     sumMean = 0.0;
175     for(uint64_t number = 0; number < numFFTDataPoints; number++){
176       // find peak
177       if(_realFFTDataPoints[number] > _peakAmplitude){
178         // Calculate the frequency relative to the local bw, adjust for _startFrequency later
179         _peakFrequency = (static_cast<float>(number) * fft_bin_size);
180         _peakAmplitude = _realFFTDataPoints[number];
181         // _peakBin = number;
182       }
183       // sum (for mean)
184       sumMean += _realFFTDataPoints[number];
185     }
186
187     // calculate the spectral mean
188     // +20 because for the comparison below we only want to throw out bins
189     // that are significantly higher (and would, thus, affect the mean more)
190     const double meanAmplitude = (sumMean / numFFTDataPoints) + 20.0;
191
192     // now throw out any bins higher than the mean
193     sumMean = 0.0;
194     uint64_t newNumDataPoints = numFFTDataPoints;
195     for(uint64_t number = 0; number < numFFTDataPoints; number++){
196       if (_realFFTDataPoints[number] <= meanAmplitude)
197         sumMean += _realFFTDataPoints[number];
198       else
199         newNumDataPoints--;
200     }
201
202     if (newNumDataPoints == 0)             // in the odd case that all
203       _noiseFloorAmplitude = meanAmplitude; // amplitudes are equal!
204     else
205       _noiseFloorAmplitude = sumMean / newNumDataPoints;
206   }
207
208   if(lastOfMultipleUpdatesFlag){
209     int tabindex = SpectrumTypeTab->currentIndex();
210     if(tabindex == d_plot_fft) {
211       _frequencyDisplayPlot->PlotNewData(_averagedValues, numFFTDataPoints, 
212                                          _noiseFloorAmplitude, _peakFrequency, 
213                                          _peakAmplitude, d_update_time);
214     }
215     if(tabindex == d_plot_time) {
216       _timeDomainDisplayPlot->PlotNewData(realTimeDomainDataPoints, 
217                                           imagTimeDomainDataPoints, 
218                                           numTimeDomainDataPoints,
219                                           d_update_time);
220     }
221     if(tabindex == d_plot_constellation) {
222       _constellationDisplayPlot->PlotNewData(realTimeDomainDataPoints, 
223                                              imagTimeDomainDataPoints, 
224                                              numTimeDomainDataPoints,
225                                              d_update_time);
226     }
227
228     // Don't update the repeated data for the waterfall
229     if(!repeatDataFlag){
230       if(tabindex == d_plot_waterfall) {
231         _waterfallDisplayPlot->PlotNewData(_realFFTDataPoints, numFFTDataPoints, 
232                                            d_update_time, dataTimestamp, 
233                                            spectrumUpdateEvent->getDroppedFFTFrames());
234       }
235       if((QGLFormat::hasOpenGL()) && (_useOpenGL)) {
236         if( _openGLWaterfall3DFlag == 1 && (tabindex == d_plot_waterfall3d)) {
237           /*
238           _waterfall3DDisplayPlot->PlotNewData(_realFFTDataPoints, numFFTDataPoints, 
239                                                d_update_time, dataTimestamp, 
240                                                spectrumUpdateEvent->getDroppedFFTFrames());
241           */
242         }
243       }
244     }
245
246     
247     // Tell the system the GUI has been updated
248     if(_systemSpecifiedFlag){
249       _system->SetLastGUIUpdateTime(generatedTimestamp);
250       _system->DecrementPendingGUIUpdateEvents();
251     }
252   }
253 }
254
255 void
256 SpectrumDisplayForm::resizeEvent( QResizeEvent *e )
257 {
258   QSize s;
259   s.setWidth(FrequencyPlotDisplayFrame->width());
260   s.setHeight(FrequencyPlotDisplayFrame->height());
261   emit _frequencyDisplayPlot->resizeSlot(&s);
262
263   s.setWidth(TimeDomainDisplayFrame->width());
264   s.setHeight(TimeDomainDisplayFrame->height());
265   emit _timeDomainDisplayPlot->resizeSlot(&s);
266
267   s.setWidth(WaterfallPlotDisplayFrame->width());
268   s.setHeight(WaterfallPlotDisplayFrame->height());
269   emit _waterfallDisplayPlot->resizeSlot(&s);
270
271   if((QGLFormat::hasOpenGL()) && (_useOpenGL)) {
272     s.setWidth(Waterfall3DPlotDisplayFrame->width());
273     s.setHeight(Waterfall3DPlotDisplayFrame->height());
274     //emit _waterfall3DDisplayPlot->resizeSlot(&s);
275   }
276
277   s.setWidth(ConstellationDisplayFrame->width());
278   s.setHeight(ConstellationDisplayFrame->height());
279   emit _constellationDisplayPlot->resizeSlot(&s);
280 }
281
282 void
283 SpectrumDisplayForm::customEvent( QEvent * e)
284 {
285   if(e->type() == QEvent::User+3){
286     if(_systemSpecifiedFlag){
287       WindowComboBox->setCurrentIndex(_system->GetWindowType());
288       FFTSizeComboBox->setCurrentIndex(_system->GetFFTSizeIndex());
289       //FFTSizeComboBox->setCurrentIndex(1);
290     }
291
292     waterfallMinimumIntensityChangedCB(WaterfallMinimumIntensityWheel->value());
293     waterfallMaximumIntensityChangedCB(WaterfallMaximumIntensityWheel->value());
294
295     // If the video card doesn't support OpenGL then don't display the 3D Waterfall
296     if((QGLFormat::hasOpenGL()) && (_useOpenGL)) {
297       waterfall3DMinimumIntensityChangedCB(Waterfall3DMinimumIntensityWheel->value());
298       waterfall3DMaximumIntensityChangedCB(Waterfall3DMaximumIntensityWheel->value());
299       
300       // Check for Hardware Acceleration of the OpenGL
301       /*
302       if(!_waterfall3DDisplayPlot->format().directRendering()){
303         // Only ask this once while the program is running...
304         if(_openGLWaterfall3DFlag == -1){
305           _openGLWaterfall3DFlag = 0;
306           if(QMessageBox::warning(this, "OpenGL Direct Rendering NOT Supported", "<center>The system's video card hardware or current drivers do not support direct hardware rendering of the OpenGL modules.</center><br><center>Software rendering is VERY processor intensive.</center><br><center>Do you want to use software rendering?</center>", QMessageBox::Yes, QMessageBox::No | QMessageBox::Default | QMessageBox::Escape) == QMessageBox::Yes){
307             _openGLWaterfall3DFlag = 1;
308           }
309         }
310       }
311       else{
312         _openGLWaterfall3DFlag = 1;
313       }
314       */
315     }
316     
317     if(_openGLWaterfall3DFlag != 1){
318       ToggleTabWaterfall3D(false);
319     }
320
321     // Clear any previous display
322     Reset();
323   }
324   else if(e->type() == 10005){
325     SpectrumUpdateEvent* spectrumUpdateEvent = (SpectrumUpdateEvent*)e;
326     newFrequencyData(spectrumUpdateEvent);
327   }
328   else if(e->type() == 10008){
329     setWindowTitle(((SpectrumWindowCaptionEvent*)e)->getLabel());
330   }
331   else if(e->type() == 10009){
332     Reset();
333     if(_systemSpecifiedFlag){
334       _system->ResetPendingGUIUpdateEvents();
335     }
336   }
337   else if(e->type() == 10010){
338     _startFrequency = ((SpectrumFrequencyRangeEvent*)e)->GetStartFrequency();
339     _stopFrequency = ((SpectrumFrequencyRangeEvent*)e)->GetStopFrequency();
340     _centerFrequency  = ((SpectrumFrequencyRangeEvent*)e)->GetCenterFrequency();
341
342     UseRFFrequenciesCB(UseRFFrequenciesCheckBox->isChecked());
343   }
344 }
345
346 void
347 SpectrumDisplayForm::UpdateGuiTimer()
348 {
349   // This is called by the displayTimer and redraws the canvases of
350   // all of the plots.
351   _frequencyDisplayPlot->canvas()->update();
352   _waterfallDisplayPlot->canvas()->update();
353   //if((QGLFormat::hasOpenGL()) && (_useOpenGL))
354   //_waterfall3DDisplayPlot->canvas()->update();
355   _timeDomainDisplayPlot->canvas()->update();
356   _constellationDisplayPlot->canvas()->update();
357 }
358
359
360 void
361 SpectrumDisplayForm::AvgLineEdit_valueChanged( int value )
362 {
363   SetAverageCount(value);
364 }
365
366
367 void
368 SpectrumDisplayForm::MaxHoldCheckBox_toggled( bool newState )
369 {
370   MaxHoldResetBtn->setEnabled(newState);
371   _frequencyDisplayPlot->SetMaxFFTVisible(newState);
372   MaxHoldResetBtn_clicked();
373 }
374
375
376 void
377 SpectrumDisplayForm::MinHoldCheckBox_toggled( bool newState )
378 {
379   MinHoldResetBtn->setEnabled(newState);
380   _frequencyDisplayPlot->SetMinFFTVisible(newState);
381   MinHoldResetBtn_clicked();
382 }
383
384
385 void
386 SpectrumDisplayForm::MinHoldResetBtn_clicked()
387 {
388   _frequencyDisplayPlot->ClearMinData();
389   _frequencyDisplayPlot->replot();
390 }
391
392
393 void
394 SpectrumDisplayForm::MaxHoldResetBtn_clicked()
395 {
396   _frequencyDisplayPlot->ClearMaxData();
397   _frequencyDisplayPlot->replot();
398 }
399
400
401 void
402 SpectrumDisplayForm::TabChanged(int index)
403 {
404   // This might be dangerous to call this with NULL
405   resizeEvent(NULL);  
406 }
407
408 void
409 SpectrumDisplayForm::SetFrequencyRange(const double newCenterFrequency,
410                                        const double newStartFrequency, 
411                                        const double newStopFrequency)
412 {
413   double fdiff;
414   if(UseRFFrequenciesCheckBox->isChecked()) {
415     fdiff = newCenterFrequency;
416   }
417   else {
418     fdiff = std::max(fabs(newStartFrequency), fabs(newStopFrequency));
419   }
420
421   if(fdiff > 0) {
422     std::string strunits[4] = {"Hz", "kHz", "MHz", "GHz"};
423     std::string strtime[4] = {"sec", "ms", "us", "ns"};
424     double units10 = floor(log10(fdiff));
425     double units3  = std::max(floor(units10 / 3.0), 0.0);
426     double units = pow(10, (units10-fmod(units10, 3.0)));
427     int iunit = static_cast<int>(units3);
428     
429     _startFrequency = newStartFrequency;
430     _stopFrequency = newStopFrequency;
431     _centerFrequency = newCenterFrequency;
432
433     _frequencyDisplayPlot->SetFrequencyRange(_startFrequency,
434                                              _stopFrequency,
435                                              _centerFrequency,
436                                              UseRFFrequenciesCheckBox->isChecked(),
437                                              units, strunits[iunit]);
438     _waterfallDisplayPlot->SetFrequencyRange(_startFrequency,
439                                              _stopFrequency,
440                                              _centerFrequency,
441                                              UseRFFrequenciesCheckBox->isChecked(),
442                                              units, strunits[iunit]);
443     if((QGLFormat::hasOpenGL()) && (_useOpenGL)) {
444       /*
445       _waterfall3DDisplayPlot->SetFrequencyRange(_startFrequency,
446                                                  _stopFrequency,
447                                                  _centerFrequency,
448                                                  UseRFFrequenciesCheckBox->isChecked(),
449                                                  units, strunits[iunit]);
450       */
451     }
452     _timeDomainDisplayPlot->SetSampleRate(_stopFrequency - _startFrequency,
453                                           units, strtime[iunit]);
454   }
455 }
456
457 int
458 SpectrumDisplayForm::GetAverageCount()
459 {
460   return _historyVector->size();
461 }
462
463 void
464 SpectrumDisplayForm::SetAverageCount(const int newCount)
465 {
466   if(newCount > -1){
467     if(newCount != static_cast<int>(_historyVector->size())){
468       std::vector<double*>::iterator pos;
469       while(newCount < static_cast<int>(_historyVector->size())){
470         pos = _historyVector->begin();
471         delete[] (*pos);
472         _historyVector->erase(pos);
473       }
474
475       while(newCount > static_cast<int>(_historyVector->size())){
476         _historyVector->push_back(new double[_numRealDataPoints]);
477       }
478       AverageDataReset();
479     }
480   }
481 }
482
483 void
484 SpectrumDisplayForm::_AverageHistory(const double* newBuffer)
485 {
486   if(_numRealDataPoints > 0){
487     if(_historyVector->size() > 0){
488       memcpy(_historyVector->operator[](_historyEntry), newBuffer,
489              _numRealDataPoints*sizeof(double));
490
491       // Increment the next location to store data
492       _historyEntryCount++;
493       if(_historyEntryCount > static_cast<int>(_historyVector->size())){
494         _historyEntryCount = _historyVector->size();
495       }
496       _historyEntry = (++_historyEntry)%_historyVector->size();
497
498       // Total up and then average the values
499       double sum;
500       for(uint64_t location = 0; location < _numRealDataPoints; location++){
501         sum = 0;
502         for(int number = 0; number < _historyEntryCount; number++){
503           sum += _historyVector->operator[](number)[location];
504         }
505         _averagedValues[location] = sum/static_cast<double>(_historyEntryCount);
506       }
507     }
508     else{
509       memcpy(_averagedValues, newBuffer, _numRealDataPoints*sizeof(double));
510     }
511   }
512 }
513
514 void
515 SpectrumDisplayForm::ResizeBuffers( const uint64_t numFFTDataPoints,
516                                     const uint64_t /*numTimeDomainDataPoints*/ )
517 {
518   // Convert from Complex to Real for certain Displays
519   if(_numRealDataPoints != numFFTDataPoints){
520     _numRealDataPoints = numFFTDataPoints;
521     delete[] _realFFTDataPoints;
522     delete[] _averagedValues;
523     
524     _realFFTDataPoints = new double[_numRealDataPoints];
525     _averagedValues = new double[_numRealDataPoints];
526     memset(_realFFTDataPoints, 0x0, _numRealDataPoints*sizeof(double));
527     
528     const int historySize = _historyVector->size();
529     SetAverageCount(0); // Clear the existing history
530     SetAverageCount(historySize);
531     
532     Reset();
533   }
534 }
535
536 void
537 SpectrumDisplayForm::Reset()
538 {
539   AverageDataReset();
540
541   _waterfallDisplayPlot->Reset();
542   if((QGLFormat::hasOpenGL()) && (_useOpenGL)) {
543     //_waterfall3DDisplayPlot->Reset();
544   }
545 }
546
547
548 void
549 SpectrumDisplayForm::AverageDataReset()
550 {
551   _historyEntry = 0;
552   _historyEntryCount = 0;
553
554   memset(_averagedValues, 0x0, _numRealDataPoints*sizeof(double));
555
556   MaxHoldResetBtn_clicked();
557   MinHoldResetBtn_clicked();
558 }
559
560
561 void
562 SpectrumDisplayForm::closeEvent( QCloseEvent *e )
563 {
564   if(_systemSpecifiedFlag){
565     _system->SetWindowOpenFlag(false);
566   }
567
568   qApp->processEvents();
569
570   QWidget::closeEvent(e);
571 }
572
573
574 void
575 SpectrumDisplayForm::WindowTypeChanged( int newItem )
576 {
577   if(_systemSpecifiedFlag){
578    _system->SetWindowType(newItem);
579   }
580 }
581
582
583 void
584 SpectrumDisplayForm::UseRFFrequenciesCB( bool useRFFlag )
585 {
586   SetFrequencyRange(_centerFrequency, _startFrequency, _stopFrequency);
587 }
588
589
590 void
591 SpectrumDisplayForm::waterfallMaximumIntensityChangedCB( double newValue )
592 {
593   if(newValue > WaterfallMinimumIntensityWheel->value()){
594     WaterfallMaximumIntensityLabel->setText(QString("%1 dB").arg(newValue, 0, 'f', 0));
595   }
596   else{
597     WaterfallMaximumIntensityWheel->setValue(WaterfallMinimumIntensityWheel->value());
598   }
599
600   _waterfallDisplayPlot->SetIntensityRange(WaterfallMinimumIntensityWheel->value(),
601                                            WaterfallMaximumIntensityWheel->value());
602 }
603
604
605 void
606 SpectrumDisplayForm::waterfallMinimumIntensityChangedCB( double newValue )
607 {
608   if(newValue < WaterfallMaximumIntensityWheel->value()){
609     WaterfallMinimumIntensityLabel->setText(QString("%1 dB").arg(newValue, 0, 'f', 0));
610   }
611   else{
612     WaterfallMinimumIntensityWheel->setValue(WaterfallMaximumIntensityWheel->value());
613   }
614
615   _waterfallDisplayPlot->SetIntensityRange(WaterfallMinimumIntensityWheel->value(),
616                                            WaterfallMaximumIntensityWheel->value());
617 }
618
619 void
620 SpectrumDisplayForm::waterfall3DMaximumIntensityChangedCB( double newValue )
621 {
622   if((QGLFormat::hasOpenGL()) && (_useOpenGL)) {
623     if(newValue > Waterfall3DMinimumIntensityWheel->value()){
624       Waterfall3DMaximumIntensityLabel->setText(QString("%1 dB").arg(newValue, 0, 'f', 0));
625     }
626     else{
627       Waterfall3DMaximumIntensityWheel->setValue(Waterfall3DMinimumIntensityWheel->value());
628     }
629
630     /*
631     _waterfall3DDisplayPlot->SetIntensityRange(Waterfall3DMinimumIntensityWheel->value(),
632                                                Waterfall3DMaximumIntensityWheel->value());
633     */
634   }
635 }
636
637
638 void
639 SpectrumDisplayForm::waterfall3DMinimumIntensityChangedCB( double newValue )
640 {
641   if((QGLFormat::hasOpenGL()) && (_useOpenGL)) {
642     if(newValue < Waterfall3DMaximumIntensityWheel->value()){
643       Waterfall3DMinimumIntensityLabel->setText(QString("%1 dB").arg(newValue, 0, 'f', 0));
644     }
645     else{
646       Waterfall3DMinimumIntensityWheel->setValue(Waterfall3DMaximumIntensityWheel->value());
647     }
648
649     /*
650     _waterfall3DDisplayPlot->SetIntensityRange(Waterfall3DMinimumIntensityWheel->value(),
651                                                Waterfall3DMaximumIntensityWheel->value());
652     */
653   }
654 }
655
656
657 void
658 SpectrumDisplayForm::FFTComboBoxSelectedCB( const QString &fftSizeString )
659 {
660   if(_systemSpecifiedFlag){
661     _system->SetFFTSize(fftSizeString.toLong());
662   }
663 }
664
665
666 void
667 SpectrumDisplayForm::WaterfallAutoScaleBtnCB()
668 {
669   double minimumIntensity = _noiseFloorAmplitude - 5;
670   if(minimumIntensity < WaterfallMinimumIntensityWheel->minValue()){
671     minimumIntensity = WaterfallMinimumIntensityWheel->minValue();
672   }
673   WaterfallMinimumIntensityWheel->setValue(minimumIntensity);
674   double maximumIntensity = _peakAmplitude + 10;
675   if(maximumIntensity > WaterfallMaximumIntensityWheel->maxValue()){
676     maximumIntensity = WaterfallMaximumIntensityWheel->maxValue();
677   }
678   WaterfallMaximumIntensityWheel->setValue(maximumIntensity);
679   waterfallMaximumIntensityChangedCB(maximumIntensity);
680 }
681
682 void
683 SpectrumDisplayForm::Waterfall3DAutoScaleBtnCB()
684 {
685   if((QGLFormat::hasOpenGL()) && (_useOpenGL)) {
686     double minimumIntensity = _noiseFloorAmplitude - 5;
687     if(minimumIntensity < Waterfall3DMinimumIntensityWheel->minValue()){
688       minimumIntensity = Waterfall3DMinimumIntensityWheel->minValue();
689     }
690     Waterfall3DMinimumIntensityWheel->setValue(minimumIntensity);
691     double maximumIntensity = _peakAmplitude + 10;
692     if(maximumIntensity > Waterfall3DMaximumIntensityWheel->maxValue()){
693       maximumIntensity = Waterfall3DMaximumIntensityWheel->maxValue();
694     }
695     Waterfall3DMaximumIntensityWheel->setValue(maximumIntensity);
696     waterfallMaximumIntensityChangedCB(maximumIntensity);
697   }
698 }
699
700 void
701 SpectrumDisplayForm::WaterfallIntensityColorTypeChanged( int newType )
702 {
703   QColor lowIntensityColor;
704   QColor highIntensityColor;
705   if(newType == WaterfallDisplayPlot::INTENSITY_COLOR_MAP_TYPE_USER_DEFINED){
706     // Select the Low Intensity Color
707     lowIntensityColor = _waterfallDisplayPlot->GetUserDefinedLowIntensityColor();
708     if(!lowIntensityColor.isValid()){
709       lowIntensityColor = Qt::black;
710     }
711     QMessageBox::information(this, "Low Intensity Color Selection", "In the next window, select the low intensity color for the waterfall display",  QMessageBox::Ok);
712     lowIntensityColor = QColorDialog::getColor(lowIntensityColor, this);
713     
714     // Select the High Intensity Color
715     highIntensityColor = _waterfallDisplayPlot->GetUserDefinedHighIntensityColor();
716     if(!highIntensityColor.isValid()){
717       highIntensityColor = Qt::white;
718     }
719     QMessageBox::information(this, "High Intensity Color Selection", "In the next window, select the high intensity color for the waterfall display",  QMessageBox::Ok);
720     highIntensityColor = QColorDialog::getColor(highIntensityColor, this);
721   }
722   
723   _waterfallDisplayPlot->SetIntensityColorMapType(newType, lowIntensityColor, highIntensityColor);
724 }
725
726 void
727 SpectrumDisplayForm::Waterfall3DIntensityColorTypeChanged( int newType )
728 {
729   if((QGLFormat::hasOpenGL()) && (_useOpenGL)) {
730     QColor lowIntensityColor;
731     QColor highIntensityColor;
732     if(newType == Waterfall3DDisplayPlot::INTENSITY_COLOR_MAP_TYPE_USER_DEFINED){
733       // Select the Low Intensity Color
734       lowIntensityColor = _waterfallDisplayPlot->GetUserDefinedLowIntensityColor();
735       if(!lowIntensityColor.isValid()){
736         lowIntensityColor = Qt::black;
737       }
738       QMessageBox::information(this, "Low Intensity Color Selection", "In the next window, select the low intensity color for the waterfall display",  QMessageBox::Ok);
739       lowIntensityColor = QColorDialog::getColor(lowIntensityColor, this);
740       
741       // Select the High Intensity Color
742       highIntensityColor = _waterfallDisplayPlot->GetUserDefinedHighIntensityColor();
743       if(!highIntensityColor.isValid()){
744         highIntensityColor = Qt::white;
745       }
746       QMessageBox::information(this, "High Intensity Color Selection", "In the next window, select the high intensity color for the waterfall display",  QMessageBox::Ok);
747       highIntensityColor = QColorDialog::getColor(highIntensityColor, this);
748     }
749     /*
750     _waterfall3DDisplayPlot->SetIntensityColorMapType(newType, lowIntensityColor,
751                                                       highIntensityColor);
752     */
753   }
754 }
755
756
757 void
758 SpectrumDisplayForm::ToggleTabFrequency(const bool state)
759 {
760   if(state == true) {
761     if(d_plot_fft == -1) {
762       SpectrumTypeTab->addTab(FrequencyPage, "Frequency Display");
763       d_plot_fft = SpectrumTypeTab->count()-1;
764     }
765   }
766   else {
767     SpectrumTypeTab->removeTab(SpectrumTypeTab->indexOf(FrequencyPage));
768     d_plot_fft = -1;
769   }
770 }
771
772 void
773 SpectrumDisplayForm::ToggleTabWaterfall(const bool state)
774 {
775   if(state == true) {
776     if(d_plot_waterfall == -1) {
777       SpectrumTypeTab->addTab(WaterfallPage, "Waterfall Display");
778       d_plot_waterfall = SpectrumTypeTab->count()-1;
779     }
780   }
781   else {
782     SpectrumTypeTab->removeTab(SpectrumTypeTab->indexOf(WaterfallPage));
783     d_plot_waterfall = -1;
784   }
785 }
786
787 void
788 SpectrumDisplayForm::ToggleTabWaterfall3D(const bool state)
789 {
790   if(state == true) {
791     /*
792     if((QGLFormat::hasOpenGL()) && (_useOpenGL)) {
793       if(d_plot_waterfall3d == -1) {
794         SpectrumTypeTab->addTab(Waterfall3DPage, "3D Waterfall Display");
795         d_plot_waterfall3d = SpectrumTypeTab->count()-1;
796       }
797     }
798     */
799     SpectrumTypeTab->removeTab(SpectrumTypeTab->indexOf(Waterfall3DPage));
800     d_plot_waterfall3d = -1;
801     fprintf(stderr, "\nWARNING: The Waterfall3D plot has been disabled until we get it working.\n\n");
802   }
803   else {
804     SpectrumTypeTab->removeTab(SpectrumTypeTab->indexOf(Waterfall3DPage));
805     d_plot_waterfall3d = -1;
806   }
807 }
808
809 void
810 SpectrumDisplayForm::ToggleTabTime(const bool state)
811 {
812   if(state == true) {
813     if(d_plot_time == -1) {
814       SpectrumTypeTab->addTab(TimeDomainPage, "Time Domain Display");
815       d_plot_time = SpectrumTypeTab->count()-1;
816     }
817   }
818   else {
819     SpectrumTypeTab->removeTab(SpectrumTypeTab->indexOf(TimeDomainPage));
820     d_plot_time = -1;
821   }
822 }
823
824 void
825 SpectrumDisplayForm::ToggleTabConstellation(const bool state)
826 {
827   if(state == true) {
828     if(d_plot_constellation == -1) {
829       SpectrumTypeTab->addTab(ConstellationPage, "Constellation Display");
830       d_plot_constellation = SpectrumTypeTab->count()-1;
831     }
832   }
833   else {
834     SpectrumTypeTab->removeTab(SpectrumTypeTab->indexOf(ConstellationPage));
835     d_plot_constellation = -1;
836   }
837 }
838
839
840 void
841 SpectrumDisplayForm::SetTimeDomainAxis(double min, double max)
842 {
843   _timeDomainDisplayPlot->set_yaxis(min, max);
844 }
845
846 void
847 SpectrumDisplayForm::SetConstellationAxis(double xmin, double xmax,
848                                                 double ymin, double ymax)
849 {
850   _constellationDisplayPlot->set_axis(xmin, xmax, ymin, ymax);
851 }
852
853 void
854 SpectrumDisplayForm::SetConstellationPenSize(int size)
855 {
856   _constellationDisplayPlot->set_pen_size( size );
857 }
858
859 void
860 SpectrumDisplayForm::SetFrequencyAxis(double min, double max)
861 {
862   _frequencyDisplayPlot->set_yaxis(min, max);
863 }
864
865 void
866 SpectrumDisplayForm::SetUpdateTime(double t)
867 {
868   d_update_time = t;
869   // QTimer class takes millisecond input
870   displayTimer->start(d_update_time*1000);
871 }