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