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