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