some cleanup as well as adding a way to pass the Qapplication between sinks that...
[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(QWidget* parent) : QDialog(parent){
9   setupUi(this);
10   
11   _systemSpecifiedFlag = false;
12   _intValidator = new QIntValidator(this);
13   _intValidator->setBottom(0);
14   _frequencyDisplayPlot = new FrequencyDisplayPlot(Tab1PlotDisplayFrame);
15   _waterfallDisplayPlot = new WaterfallDisplayPlot(Tab2PlotDisplayFrame);
16   _waterfall3DDisplayPlot = new Waterfall3DDisplayPlot(Waterfall3DPlotDisplayFrame);
17   _timeDomainDisplayPlot = new TimeDomainDisplayPlot(TimeDomainDisplayFrame);
18   _numRealDataPoints = 1024;
19   _realFFTDataPoints = new double[_numRealDataPoints];
20   _averagedValues = new double[_numRealDataPoints];
21   _historyVector = new std::vector<double*>;
22   
23   AvgLineEdit->setValidator(_intValidator);
24   PowerLineEdit->setValidator(_intValidator);
25   MinHoldCheckBox_toggled( false );
26   MaxHoldCheckBox_toggled( false );
27   
28   WaterfallMaximumIntensityWheel->setRange(-200, 0);
29   WaterfallMaximumIntensityWheel->setTickCnt(50);
30   WaterfallMinimumIntensityWheel->setRange(-200, 0);
31   WaterfallMinimumIntensityWheel->setTickCnt(50);
32   WaterfallMinimumIntensityWheel->setValue(-200);
33   
34   Waterfall3DMaximumIntensityWheel->setRange(-200, 0);
35   Waterfall3DMaximumIntensityWheel->setTickCnt(50);
36   Waterfall3DMinimumIntensityWheel->setRange(-200, 0);
37   Waterfall3DMinimumIntensityWheel->setTickCnt(50);
38   Waterfall3DMinimumIntensityWheel->setValue(-200);
39   
40   _peakFrequency = 0;
41   _peakAmplitude = -HUGE_VAL;
42   
43   _noiseFloorAmplitude = -HUGE_VAL;
44   
45   connect(_waterfallDisplayPlot, SIGNAL(UpdatedLowerIntensityLevel(const double)), _frequencyDisplayPlot, SLOT(SetLowerIntensityLevel(const double)));
46   connect(_waterfallDisplayPlot, SIGNAL(UpdatedUpperIntensityLevel(const double)), _frequencyDisplayPlot, SLOT(SetUpperIntensityLevel(const double)));
47   
48   _frequencyDisplayPlot->SetLowerIntensityLevel(-200);
49   _frequencyDisplayPlot->SetUpperIntensityLevel(-200);
50   
51   // Load up the acceptable FFT sizes...
52   FFTSizeComboBox->clear();
53   for(long fftSize = SpectrumGUIClass::MIN_FFT_SIZE; fftSize <= SpectrumGUIClass::MAX_FFT_SIZE; fftSize *= 2){
54     FFTSizeComboBox->insertItem(FFTSizeComboBox->count(), QString("%1").arg(fftSize));
55   }
56   Reset();
57 }
58
59 SpectrumDisplayForm::~SpectrumDisplayForm(){
60   // Qt deletes children when parent is deleted
61
62   // Don't worry about deleting Display Plots - they are deleted when parents are deleted
63   /*   delete _intValidator; */
64
65   delete[] _realFFTDataPoints;
66   delete[] _averagedValues;
67
68   for(unsigned int count = 0; count < _historyVector->size(); count++){
69     delete[] _historyVector->operator[](count);
70   }
71
72   delete _historyVector;
73 }
74
75 void SpectrumDisplayForm::setSystem( SpectrumGUIClass * newSystem, const uint64_t numFFTDataPoints, const uint64_t numTimeDomainDataPoints )
76 {
77   ResizeBuffers(numFFTDataPoints, numTimeDomainDataPoints);
78   
79   if(newSystem != NULL){
80     _system = newSystem;
81     _systemSpecifiedFlag = true;
82   }
83   else{
84     _systemSpecifiedFlag = false;
85   }
86 }
87
88 void SpectrumDisplayForm::newFrequencyData( const SpectrumUpdateEvent* spectrumUpdateEvent)
89 {
90   const std::complex<float>* complexDataPoints = spectrumUpdateEvent->getFFTPoints();
91   const uint64_t numFFTDataPoints = spectrumUpdateEvent->getNumFFTDataPoints();
92   const double* realTimeDomainDataPoints = spectrumUpdateEvent->getRealTimeDomainPoints();
93   const double* imagTimeDomainDataPoints = spectrumUpdateEvent->getImagTimeDomainPoints();
94   const uint64_t numTimeDomainDataPoints = spectrumUpdateEvent->getNumTimeDomainDataPoints();
95   const double timePerFFT = spectrumUpdateEvent->getTimePerFFT();
96   const timespec dataTimestamp = spectrumUpdateEvent->getDataTimestamp();;
97   const bool repeatDataFlag = spectrumUpdateEvent->getRepeatDataFlag();
98   const bool lastOfMultipleUpdatesFlag = spectrumUpdateEvent->getLastOfMultipleUpdateFlag();
99   const timespec generatedTimestamp = spectrumUpdateEvent->getEventGeneratedTimestamp();
100
101   // REMEMBER: The dataTimestamp is NOT valid when the repeat data flag is true...
102   ResizeBuffers(numFFTDataPoints, numTimeDomainDataPoints);
103
104   // Calculate the Magnitude of the complex point
105   const std::complex<float>* complexDataPointsPtr = complexDataPoints;
106   double* realFFTDataPointsPtr = _realFFTDataPoints;
107   for(uint64_t point = 0; point < numFFTDataPoints; point++){
108     // Calculate dBm
109     // 50 ohm load assumption
110     // 10 * log10 (v^2 / (2 * 50.0 * .001)) = 10 * log10( v^2 * 10)
111     // 75 ohm load assumption
112     // 10 * log10 (v^2 / (2 * 75.0 * .001)) = 10 * log10( v^2 * 15)
113     
114     *realFFTDataPointsPtr = 10.0*log10((((*complexDataPointsPtr).real() * (*complexDataPointsPtr).real()) + ((*complexDataPointsPtr).imag()*(*complexDataPointsPtr).imag())) + 1e-20);
115
116     complexDataPointsPtr++;
117     realFFTDataPointsPtr++;
118   }
119  
120
121   // Don't update the averaging history if this is repeated data
122   if(!repeatDataFlag){
123     _AverageHistory(_realFFTDataPoints);
124
125     double sumMean;
126     const double fft_bin_size = (_stopFrequency-_startFrequency) /
127       static_cast<double>(numFFTDataPoints);
128
129     // find the peak, sum (for mean), etc
130     _peakAmplitude = -HUGE_VAL;
131     sumMean = 0.0;
132     for(uint64_t number = 0; number < numFFTDataPoints; number++){
133       // find peak
134       if(_realFFTDataPoints[number] > _peakAmplitude){
135         _peakFrequency = (static_cast<float>(number) * fft_bin_size);  // Calculate the frequency relative to the local bw, adjust for _startFrequency later
136         _peakAmplitude = _realFFTDataPoints[number];
137         // _peakBin = number;
138       }
139       // sum (for mean)
140       sumMean += _realFFTDataPoints[number];
141     }
142
143     // calculate the spectral mean
144     // +20 because for the comparison below we only want to throw out bins
145     // that are significantly higher (and would, thus, affect the mean more)
146     const double meanAmplitude = (sumMean / numFFTDataPoints) + 20.0;
147
148     // now throw out any bins higher than the mean
149     sumMean = 0.0;
150     uint64_t newNumDataPoints = numFFTDataPoints;
151     for(uint64_t number = 0; number < numFFTDataPoints; number++){
152       if (_realFFTDataPoints[number] <= meanAmplitude)
153         sumMean += _realFFTDataPoints[number];
154       else
155         newNumDataPoints--;
156     }
157
158     if (newNumDataPoints == 0)             // in the odd case that all
159       _noiseFloorAmplitude = meanAmplitude; // amplitudes are equal!
160     else
161       _noiseFloorAmplitude = sumMean / newNumDataPoints;
162   }
163
164   if(lastOfMultipleUpdatesFlag){
165     _frequencyDisplayPlot->PlotNewData(_averagedValues, numFFTDataPoints, 
166                                        _noiseFloorAmplitude, _peakFrequency, 
167                                        _peakAmplitude);
168     _timeDomainDisplayPlot->PlotNewData(realTimeDomainDataPoints, 
169                                         imagTimeDomainDataPoints, 
170                                         numTimeDomainDataPoints);
171   }
172   // Don't update the repeated data for the waterfall
173   if(!repeatDataFlag){
174     _waterfallDisplayPlot->PlotNewData(_realFFTDataPoints, numFFTDataPoints, 
175                                        timePerFFT, dataTimestamp, 
176                                        spectrumUpdateEvent->getDroppedFFTFrames());
177     if( _openGLWaterfall3DFlag == 1 ){
178       _waterfall3DDisplayPlot->PlotNewData(_realFFTDataPoints, numFFTDataPoints, 
179                                            timePerFFT, dataTimestamp, 
180                                            spectrumUpdateEvent->getDroppedFFTFrames());
181     }
182   }
183   
184   // Tell the system the GUI has been updated
185   if(_systemSpecifiedFlag){
186     _system->SetLastGUIUpdateTime(generatedTimestamp);
187     _system->DecrementPendingGUIUpdateEvents();
188   }
189 }
190
191 void SpectrumDisplayForm::resizeEvent( QResizeEvent *e )
192 {
193   // Let the actual window resize its width, but not its height
194   QSize newSize(e->size().width(), e->oldSize().height());
195   QResizeEvent et(newSize, e->oldSize());
196   QWidget::resizeEvent(&et);
197
198   // Tell the Tab Window to Resize
199   SpectrumTypeTab->resize( e->size().width(), SpectrumTypeTab->height());
200
201   // Tell the TabXFreqDisplay to resize
202   Tab1PlotDisplayFrame->resize(e->size().width()-4, 
203                                Tab1PlotDisplayFrame->height());
204   Tab2PlotDisplayFrame->resize(e->size().width()-4,
205                                Tab2PlotDisplayFrame->height());
206   Waterfall3DPlotDisplayFrame->resize(e->size().width()-4, 
207                                       Waterfall3DPlotDisplayFrame->height());
208   TimeDomainDisplayFrame->resize(e->size().width()-4, 
209                                  TimeDomainDisplayFrame->height());
210   _frequencyDisplayPlot->resize( Tab1PlotDisplayFrame->width()-4, 
211                                  Tab1PlotDisplayFrame->height());
212   _waterfallDisplayPlot->resize( Tab2PlotDisplayFrame->width()-4, 
213                                  Tab2PlotDisplayFrame->height());
214   _waterfall3DDisplayPlot->resize( Waterfall3DPlotDisplayFrame->width()-4, 
215                                    Waterfall3DPlotDisplayFrame->height());
216   _timeDomainDisplayPlot->resize( TimeDomainDisplayFrame->width()-4, 
217                                   TimeDomainDisplayFrame->height());
218
219   // Move the IntensityWheels and Labels
220   WaterfallMaximumIntensityLabel->move(width() - 5 - WaterfallMaximumIntensityLabel->width(),
221                                        WaterfallMaximumIntensityLabel->y());
222   WaterfallMinimumIntensityLabel->move(width() - 5 - WaterfallMinimumIntensityLabel->width(),
223                                        WaterfallMinimumIntensityLabel->y());
224   WaterfallMaximumIntensityWheel->resize(WaterfallMaximumIntensityLabel->x() - 5 -
225                                          WaterfallMaximumIntensityWheel->x(),
226                                          WaterfallMaximumIntensityWheel->height());
227   WaterfallMinimumIntensityWheel->resize(WaterfallMinimumIntensityLabel->x() - 5 -
228                                          WaterfallMinimumIntensityWheel->x(),
229                                          WaterfallMinimumIntensityWheel->height());
230
231   Waterfall3DMaximumIntensityLabel->move(width() - 5 -
232                                          Waterfall3DMaximumIntensityLabel->width(),
233                                          Waterfall3DMaximumIntensityLabel->y());
234   Waterfall3DMinimumIntensityLabel->move(width() - 5 -
235                                          Waterfall3DMinimumIntensityLabel->width(),
236                                          Waterfall3DMinimumIntensityLabel->y());
237   Waterfall3DMaximumIntensityWheel->resize(Waterfall3DMaximumIntensityLabel->x() - 5 -
238                                            Waterfall3DMaximumIntensityWheel->x(),
239                                            Waterfall3DMaximumIntensityWheel->height());
240   Waterfall3DMinimumIntensityWheel->resize(Waterfall3DMinimumIntensityLabel->x() - 5 -
241                                            Waterfall3DMinimumIntensityWheel->x(),
242                                            Waterfall3DMinimumIntensityWheel->height());
243
244
245   // Move the Power Lbl
246   PowerLabel->move(e->size().width()-(415-324) - PowerLabel->width(),
247                    PowerLabel->y());
248
249   // Move the Power Line Edit
250   PowerLineEdit->move(e->size().width()-(415-318) - PowerLineEdit->width(),
251                       PowerLineEdit->y());
252
253   // Move the Avg Lbl
254   AvgLabel->move(e->size().width()-(415-406) - AvgLabel->width(),
255                  AvgLabel->y());
256
257   // Move the Avg Line Edit
258   AvgLineEdit->move(e->size().width()-(415-400) - AvgLineEdit->width(),
259                     AvgLineEdit->y());
260   
261   // Move the FFT Size Combobox and label
262   FFTSizeComboBox->move(width() - 5 - FFTSizeComboBox->width(),
263                         FFTSizeComboBox->y());
264   FFTSizeLabel->move(width() - 10 - FFTSizeComboBox->width() - FFTSizeLabel->width(),
265                      FFTSizeLabel->y());
266 }
267
268
269 void SpectrumDisplayForm::customEvent( QEvent * e)
270 {
271   if(e->type() == QEvent::User+3){
272     if(_systemSpecifiedFlag){
273       WindowComboBox->setCurrentIndex(_system->GetWindowType());
274       FFTSizeComboBox->setCurrentIndex(_system->GetFFTSizeIndex());
275       //FFTSizeComboBox->setCurrentIndex(1);
276       PowerLineEdit_textChanged(PowerLineEdit->text());
277     }
278
279     waterfallMinimumIntensityChangedCB(WaterfallMinimumIntensityWheel->value());
280     waterfallMaximumIntensityChangedCB(WaterfallMaximumIntensityWheel->value());
281
282     waterfall3DMinimumIntensityChangedCB(Waterfall3DMinimumIntensityWheel->value());
283     waterfall3DMaximumIntensityChangedCB(Waterfall3DMaximumIntensityWheel->value());
284
285     // If the video card doesn't support OpenGL then don't display the 3D Waterfall
286     if(QGLFormat::hasOpenGL()){
287       // Check for Hardware Acceleration of the OpenGL
288       if(!_waterfall3DDisplayPlot->format().directRendering()){
289         // Only ask this once while the program is running...
290         if(_openGLWaterfall3DFlag == -1){
291           _openGLWaterfall3DFlag = 0;
292           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){
293             _openGLWaterfall3DFlag = 1;
294           }
295         }
296       }
297       else{
298         _openGLWaterfall3DFlag = 1;
299       }
300     }
301
302     if(_openGLWaterfall3DFlag != 1){
303       SpectrumTypeTab->removeTab(SpectrumTypeTab->indexOf(Waterfall3DPage));
304     }
305
306     // Clear any previous display
307     Reset();
308
309     show();
310   }
311   else if(e->type() == 10005){
312     SpectrumUpdateEvent* spectrumUpdateEvent = (SpectrumUpdateEvent*)e;
313     newFrequencyData(spectrumUpdateEvent);
314   }
315   else if(e->type() == 10008){
316     setWindowTitle(((SpectrumWindowCaptionEvent*)e)->getLabel());
317   }
318   else if(e->type() == 10009){
319     Reset();
320     if(_systemSpecifiedFlag){
321       _system->ResetPendingGUIUpdateEvents();
322     }
323   }
324   else if(e->type() == 10010){
325     _startFrequency = ((SpectrumFrequencyRangeEvent*)e)->GetStartFrequency();
326     _stopFrequency = ((SpectrumFrequencyRangeEvent*)e)->GetStopFrequency();
327     _centerFrequency  = ((SpectrumFrequencyRangeEvent*)e)->GetCenterFrequency();
328
329     UseRFFrequenciesCB(UseRFFrequenciesCheckBox->isChecked());
330   }
331 }
332
333 void SpectrumDisplayForm::AvgLineEdit_textChanged( const QString &valueString )
334 {
335   if(!valueString.isEmpty()){
336     int value = valueString.toInt();
337     if(value > 500){
338       value = 500;
339       AvgLineEdit->setText("500");
340     }
341     SetAverageCount(value);
342   }
343 }
344
345
346 void SpectrumDisplayForm::MaxHoldCheckBox_toggled( bool newState )
347 {
348   MaxHoldResetBtn->setEnabled(newState);
349   _frequencyDisplayPlot->SetMaxFFTVisible(newState);
350   MaxHoldResetBtn_clicked();
351 }
352
353
354 void SpectrumDisplayForm::MinHoldCheckBox_toggled( bool newState )
355 {
356   MinHoldResetBtn->setEnabled(newState);
357   _frequencyDisplayPlot->SetMinFFTVisible(newState);
358   MinHoldResetBtn_clicked();
359 }
360
361
362 void SpectrumDisplayForm::MinHoldResetBtn_clicked()
363 {
364   _frequencyDisplayPlot->ClearMinData();
365   _frequencyDisplayPlot->replot();
366 }
367
368
369 void SpectrumDisplayForm::MaxHoldResetBtn_clicked()
370 {
371   _frequencyDisplayPlot->ClearMaxData();
372   _frequencyDisplayPlot->replot();
373 }
374
375
376 void SpectrumDisplayForm::PowerLineEdit_textChanged( const QString &valueString )
377 {
378   if(_systemSpecifiedFlag){
379     if(!valueString.isEmpty()){
380       double value = valueString.toDouble();
381       if(value < 1.0){
382         value = 1.0;
383         PowerLineEdit->setText("1");
384       }
385       _system->SetPowerValue(value);
386     }
387
388     if(_system->GetPowerValue() > 1){
389       UseRFFrequenciesCheckBox->setChecked(false);
390       UseRFFrequenciesCheckBox->setEnabled(false);
391       UseRFFrequenciesCB(false);
392     }
393     else{
394       UseRFFrequenciesCheckBox->setEnabled(true);
395     }
396   }
397 }
398
399 void SpectrumDisplayForm::SetFrequencyRange(const double newStartFrequency, const double newStopFrequency, const double newCenterFrequency){
400   _frequencyDisplayPlot->SetFrequencyRange(newStartFrequency, newStopFrequency, newCenterFrequency, UseRFFrequenciesCheckBox->isChecked());
401   _waterfallDisplayPlot->SetFrequencyRange(newStartFrequency, newStopFrequency, newCenterFrequency, UseRFFrequenciesCheckBox->isChecked());
402   _waterfall3DDisplayPlot->SetFrequencyRange(newStartFrequency, newStopFrequency, newCenterFrequency, UseRFFrequenciesCheckBox->isChecked());
403
404 }
405
406 int SpectrumDisplayForm::GetAverageCount(){
407   return _historyVector->size();
408 }
409
410 void SpectrumDisplayForm::SetAverageCount(const int newCount){
411   if(newCount > -1){
412     if(newCount != static_cast<int>(_historyVector->size())){
413       std::vector<double*>::iterator pos;
414       while(newCount < static_cast<int>(_historyVector->size())){
415         pos = _historyVector->begin();
416         delete[] (*pos);
417         _historyVector->erase(pos);
418       }
419
420       while(newCount > static_cast<int>(_historyVector->size())){
421         _historyVector->push_back(new double[_numRealDataPoints]);
422       }
423       AverageDataReset();
424     }
425   }
426 }
427
428 void SpectrumDisplayForm::_AverageHistory(const double* newBuffer){
429   if(_numRealDataPoints > 0){
430     if(_historyVector->size() > 0){
431       memcpy(_historyVector->operator[](_historyEntry), newBuffer, _numRealDataPoints*sizeof(double));
432
433       // Increment the next location to store data
434       _historyEntryCount++;
435       if(_historyEntryCount > static_cast<int>(_historyVector->size())){
436         _historyEntryCount = _historyVector->size();
437       }
438       _historyEntry = (++_historyEntry)%_historyVector->size();
439
440       // Total up and then average the values
441       double sum;
442       for(uint64_t location = 0; location < _numRealDataPoints; location++){
443         sum = 0;
444         for(int number = 0; number < _historyEntryCount; number++){
445           sum += _historyVector->operator[](number)[location];
446         }
447         _averagedValues[location] = sum/static_cast<double>(_historyEntryCount);
448       }
449     }
450     else{
451       memcpy(_averagedValues, newBuffer, _numRealDataPoints*sizeof(double));
452     }
453   }
454 }
455
456 void SpectrumDisplayForm::ResizeBuffers( const uint64_t numFFTDataPoints, const uint64_t /*numTimeDomainDataPoints*/ ){
457   // Convert from Complex to Real for certain Displays
458   if(_numRealDataPoints != numFFTDataPoints){
459     _numRealDataPoints = numFFTDataPoints;
460     delete[] _realFFTDataPoints;
461     delete[] _averagedValues;
462     
463     _realFFTDataPoints = new double[_numRealDataPoints];
464     _averagedValues = new double[_numRealDataPoints];
465     memset(_realFFTDataPoints, 0x0, _numRealDataPoints*sizeof(double));
466     
467     const int historySize = _historyVector->size();
468     SetAverageCount(0); // Clear the existing history
469     SetAverageCount(historySize);
470     
471     Reset();
472   }
473 }
474
475 void SpectrumDisplayForm::Reset(){
476   AverageDataReset();
477
478   _waterfallDisplayPlot->Reset();
479   _waterfall3DDisplayPlot->Reset();
480 }
481
482
483 void SpectrumDisplayForm::AverageDataReset(){
484   _historyEntry = 0;
485   _historyEntryCount = 0;
486
487   memset(_averagedValues, 0x0, _numRealDataPoints*sizeof(double));
488
489   MaxHoldResetBtn_clicked();
490   MinHoldResetBtn_clicked();
491 }
492
493
494 void SpectrumDisplayForm::closeEvent( QCloseEvent *e )
495 {
496   if(_systemSpecifiedFlag){
497     _system->SetWindowOpenFlag(false);
498   }
499
500   qApp->processEvents();
501
502   QWidget::closeEvent(e);
503 }
504
505
506 void SpectrumDisplayForm::WindowTypeChanged( int newItem )
507 {
508   if(_systemSpecifiedFlag){
509    _system->SetWindowType(newItem);
510   }
511 }
512
513
514 void SpectrumDisplayForm::UseRFFrequenciesCB( bool useRFFlag )
515 {
516   if(useRFFlag){
517     SetFrequencyRange(_startFrequency, _stopFrequency, _centerFrequency);
518   }
519   else{
520     SetFrequencyRange(_startFrequency, _stopFrequency, 0.0 );
521   }
522 }
523
524
525 void SpectrumDisplayForm::waterfallMaximumIntensityChangedCB( double newValue )
526 {
527   if(newValue > WaterfallMinimumIntensityWheel->value()){
528     WaterfallMaximumIntensityLabel->setText(QString("%1 dB").arg(newValue, 0, 'f', 0));
529   }
530   else{
531     WaterfallMaximumIntensityWheel->setValue(WaterfallMinimumIntensityWheel->value());
532   }
533   _waterfallDisplayPlot->SetIntensityRange(WaterfallMinimumIntensityWheel->value(), WaterfallMaximumIntensityWheel->value());
534 }
535
536
537 void SpectrumDisplayForm::waterfallMinimumIntensityChangedCB( double newValue )
538 {
539   if(newValue < WaterfallMaximumIntensityWheel->value()){
540     WaterfallMinimumIntensityLabel->setText(QString("%1 dB").arg(newValue, 0, 'f', 0));
541   }
542   else{
543     WaterfallMinimumIntensityWheel->setValue(WaterfallMaximumIntensityWheel->value());
544   }
545   _waterfallDisplayPlot->SetIntensityRange(WaterfallMinimumIntensityWheel->value(), WaterfallMaximumIntensityWheel->value());
546 }
547
548 void SpectrumDisplayForm::waterfall3DMaximumIntensityChangedCB( double newValue )
549 {
550   if(newValue > Waterfall3DMinimumIntensityWheel->value()){
551     Waterfall3DMaximumIntensityLabel->setText(QString("%1 dB").arg(newValue, 0, 'f', 0));
552   }
553   else{
554     Waterfall3DMaximumIntensityWheel->setValue(Waterfall3DMinimumIntensityWheel->value());
555   }
556   _waterfall3DDisplayPlot->SetIntensityRange(Waterfall3DMinimumIntensityWheel->value(), Waterfall3DMaximumIntensityWheel->value());
557 }
558
559
560 void SpectrumDisplayForm::waterfall3DMinimumIntensityChangedCB( double newValue )
561 {
562   if(newValue < Waterfall3DMaximumIntensityWheel->value()){
563     Waterfall3DMinimumIntensityLabel->setText(QString("%1 dB").arg(newValue, 0, 'f', 0));
564   }
565   else{
566     Waterfall3DMinimumIntensityWheel->setValue(Waterfall3DMaximumIntensityWheel->value());
567   }
568   _waterfall3DDisplayPlot->SetIntensityRange(Waterfall3DMinimumIntensityWheel->value(), Waterfall3DMaximumIntensityWheel->value());
569 }
570
571
572 void SpectrumDisplayForm::FFTComboBoxSelectedCB( const QString &fftSizeString )
573 {
574   if(_systemSpecifiedFlag){
575     _system->SetFFTSize(fftSizeString.toLong());
576   }
577 }
578
579
580 void SpectrumDisplayForm::WaterfallAutoScaleBtnCB()
581 {
582   double minimumIntensity = _noiseFloorAmplitude - 5;
583   if(minimumIntensity < WaterfallMinimumIntensityWheel->minValue()){
584     minimumIntensity = WaterfallMinimumIntensityWheel->minValue();
585   }
586   WaterfallMinimumIntensityWheel->setValue(minimumIntensity);
587   double maximumIntensity = _peakAmplitude + 10;
588   if(maximumIntensity > WaterfallMaximumIntensityWheel->maxValue()){
589     maximumIntensity = WaterfallMaximumIntensityWheel->maxValue();
590   }
591   WaterfallMaximumIntensityWheel->setValue(maximumIntensity);
592   waterfallMaximumIntensityChangedCB(maximumIntensity);
593 }
594
595 void SpectrumDisplayForm::Waterfall3DAutoScaleBtnCB()
596 {
597   double minimumIntensity = _noiseFloorAmplitude - 5;
598   if(minimumIntensity < Waterfall3DMinimumIntensityWheel->minValue()){
599     minimumIntensity = Waterfall3DMinimumIntensityWheel->minValue();
600   }
601   Waterfall3DMinimumIntensityWheel->setValue(minimumIntensity);
602   double maximumIntensity = _peakAmplitude + 10;
603   if(maximumIntensity > Waterfall3DMaximumIntensityWheel->maxValue()){
604     maximumIntensity = Waterfall3DMaximumIntensityWheel->maxValue();
605   }
606   Waterfall3DMaximumIntensityWheel->setValue(maximumIntensity);
607   waterfallMaximumIntensityChangedCB(maximumIntensity);
608 }
609
610 void SpectrumDisplayForm::WaterfallIntensityColorTypeChanged( int newType )
611 {
612   QColor lowIntensityColor;
613   QColor highIntensityColor;
614   if(newType == WaterfallDisplayPlot::INTENSITY_COLOR_MAP_TYPE_USER_DEFINED){
615     // Select the Low Intensity Color
616     lowIntensityColor = _waterfallDisplayPlot->GetUserDefinedLowIntensityColor();
617     if(!lowIntensityColor.isValid()){
618       lowIntensityColor = Qt::black;
619     }
620     QMessageBox::information(this, "Low Intensity Color Selection", "In the next window, select the low intensity color for the waterfall display",  QMessageBox::Ok);
621     lowIntensityColor = QColorDialog::getColor(lowIntensityColor, this);
622
623     // Select the High Intensity Color
624     highIntensityColor = _waterfallDisplayPlot->GetUserDefinedHighIntensityColor();
625     if(!highIntensityColor.isValid()){
626       highIntensityColor = Qt::white;
627     }
628     QMessageBox::information(this, "High Intensity Color Selection", "In the next window, select the high intensity color for the waterfall display",  QMessageBox::Ok);
629     highIntensityColor = QColorDialog::getColor(highIntensityColor, this);
630   }
631   _waterfallDisplayPlot->SetIntensityColorMapType(newType, lowIntensityColor, highIntensityColor);
632 }
633
634 void SpectrumDisplayForm::Waterfall3DIntensityColorTypeChanged( int newType )
635 {
636   QColor lowIntensityColor;
637   QColor highIntensityColor;
638   if(newType == Waterfall3DDisplayPlot::INTENSITY_COLOR_MAP_TYPE_USER_DEFINED){
639     // Select the Low Intensity Color
640     lowIntensityColor = _waterfallDisplayPlot->GetUserDefinedLowIntensityColor();
641     if(!lowIntensityColor.isValid()){
642       lowIntensityColor = Qt::black;
643     }
644     QMessageBox::information(this, "Low Intensity Color Selection", "In the next window, select the low intensity color for the waterfall display",  QMessageBox::Ok);
645     lowIntensityColor = QColorDialog::getColor(lowIntensityColor, this);
646
647     // Select the High Intensity Color
648     highIntensityColor = _waterfallDisplayPlot->GetUserDefinedHighIntensityColor();
649     if(!highIntensityColor.isValid()){
650       highIntensityColor = Qt::white;
651     }
652     QMessageBox::information(this, "High Intensity Color Selection", "In the next window, select the high intensity color for the waterfall display",  QMessageBox::Ok);
653     highIntensityColor = QColorDialog::getColor(highIntensityColor, this);
654   }
655   _waterfall3DDisplayPlot->SetIntensityColorMapType(newType, lowIntensityColor, highIntensityColor);
656 }