1 /* -*- c++ -*- */
2 /*
3  * Copyright 2008-2011,2014 Free Software Foundation, Inc.
4  *
5  * This file is part of GNU Radio
6  *
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  *
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with GNU Radio; see the file COPYING.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street,
20  * Boston, MA 02110-1301, USA.
21  */
22 
23 #ifndef FREQUENCY_DISPLAY_PLOT_C
24 #define FREQUENCY_DISPLAY_PLOT_C
25 
26 #include <gnuradio/qtgui/FrequencyDisplayPlot.h>
27 
28 #include <gnuradio/qtgui/qtgui_types.h>
29 #include <qwt_scale_draw.h>
30 #include <QColor>
31 #include <iostream>
32 
33 
34 /***********************************************************************
35  * Widget to provide mouse pointer coordinate text
36  **********************************************************************/
37 class FreqDisplayZoomer : public QwtPlotZoomer, public FreqOffsetAndPrecisionClass
38 {
39 public:
40 #if QWT_VERSION < 0x060100
FreqDisplayZoomer(QwtPlotCanvas * canvas,const unsigned int freqPrecision)41     FreqDisplayZoomer(QwtPlotCanvas* canvas, const unsigned int freqPrecision)
42 #else  /* QWT_VERSION < 0x060100 */
43     FreqDisplayZoomer(QWidget* canvas, const unsigned int freqPrecision)
44 #endif /* QWT_VERSION < 0x060100 */
45         : QwtPlotZoomer(canvas), FreqOffsetAndPrecisionClass(freqPrecision)
46     {
47         setTrackerMode(QwtPicker::AlwaysOn);
48     }
49 
updateTrackerText()50     virtual void updateTrackerText() { updateDisplay(); }
51 
setUnitType(const std::string & type)52     void setUnitType(const std::string& type) { d_unitType = type; }
53 
setYUnit(const std::string & unit)54     void setYUnit(const std::string& unit) { d_y_unit = unit; }
55 
56 protected:
57     using QwtPlotZoomer::trackerText;
trackerText(QPoint const & p) const58     virtual QwtText trackerText(QPoint const& p) const
59     {
60         QwtDoublePoint dp = QwtPlotZoomer::invTransform(p);
61         QwtText t(QString("%1 %2, %3 %4")
62                       .arg(dp.x(), 0, 'f', getFrequencyPrecision())
63                       .arg(d_unitType.c_str())
64                       .arg(dp.y(), 0, 'f', 2)
65                       .arg(d_y_unit.c_str()));
66         return t;
67     }
68 
69 private:
70     std::string d_unitType;
71     std::string d_y_unit = "dB";
72 };
73 
74 
75 /***********************************************************************
76  * Main frequency display plotter widget
77  **********************************************************************/
FrequencyDisplayPlot(int nplots,QWidget * parent)78 FrequencyDisplayPlot::FrequencyDisplayPlot(int nplots, QWidget* parent)
79     : DisplayPlot(nplots, parent)
80 {
81     d_start_frequency = -1;
82     d_stop_frequency = 1;
83 
84     d_numPoints = 0;
85     d_min_fft_data = new double[d_numPoints];
86     d_max_fft_data = new double[d_numPoints];
87     d_xdata = new double[d_numPoints];
88     d_half_freq = false;
89     d_autoscale_shot = false;
90 
91     setAxisTitle(QwtPlot::xBottom, "Frequency (Hz)");
92     setAxisScaleDraw(QwtPlot::xBottom, new FreqDisplayScaleDraw(0));
93 
94     d_ymin = -120;
95     d_ymax = 10;
96     setAxisScaleEngine(QwtPlot::yLeft, new QwtLinearScaleEngine);
97     setAxisScale(QwtPlot::yLeft, d_ymin, d_ymax);
98     setAxisTitle(QwtPlot::yLeft, "Relative Gain (dB)");
99 
100     QList<QColor> default_colors;
101     default_colors << QColor(Qt::blue) << QColor(Qt::red) << QColor(Qt::green)
102                    << QColor(Qt::black) << QColor(Qt::cyan) << QColor(Qt::magenta)
103                    << QColor(Qt::yellow) << QColor(Qt::gray) << QColor(Qt::darkRed)
104                    << QColor(Qt::darkGreen) << QColor(Qt::darkBlue)
105                    << QColor(Qt::darkGray);
106 
107     // Create a curve for each input
108     // Automatically deleted when parent is deleted
109     for (unsigned int i = 0; i < d_nplots; ++i) {
110         d_ydata.push_back(new double[d_numPoints]);
111         memset(d_ydata[i], 0x0, d_numPoints * sizeof(double));
112 
113         d_plot_curve.push_back(new QwtPlotCurve(QString("Data %1").arg(i)));
114         d_plot_curve[i]->attach(this);
115 
116         QwtSymbol* symbol = new QwtSymbol(QwtSymbol::NoSymbol,
117                                           QBrush(default_colors[i]),
118                                           QPen(default_colors[i]),
119                                           QSize(7, 7));
120 
121 #if QWT_VERSION < 0x060000
122         d_plot_curve[i]->setRawData(d_xdata, d_ydata[i], d_numPoints);
123         d_plot_curve[i]->setSymbol(*symbol);
124 #else
125         d_plot_curve[i]->setRawSamples(d_xdata, d_ydata[i], d_numPoints);
126         d_plot_curve[i]->setSymbol(symbol);
127 #endif
128         setLineColor(i, default_colors[i]);
129     }
130 
131     // Create min/max plotter curves
132     d_min_fft_plot_curve = new QwtPlotCurve("Min Hold");
133     d_min_fft_plot_curve->attach(this);
134     const QColor default_min_fft_color = Qt::magenta;
135     setMinFFTColor(default_min_fft_color);
136 #if QWT_VERSION < 0x060000
137     d_min_fft_plot_curve->setRawData(d_xdata, d_min_fft_data, d_numPoints);
138 #else
139     d_min_fft_plot_curve->setRawSamples(d_xdata, d_min_fft_data, d_numPoints);
140 #endif
141     d_min_fft_plot_curve->setVisible(false);
142     d_min_fft_plot_curve->setZ(0);
143 
144     d_max_fft_plot_curve = new QwtPlotCurve("Max Hold");
145     d_max_fft_plot_curve->attach(this);
146     QColor default_max_fft_color = Qt::darkYellow;
147     setMaxFFTColor(default_max_fft_color);
148 #if QWT_VERSION < 0x060000
149     d_max_fft_plot_curve->setRawData(d_xdata, d_max_fft_data, d_numPoints);
150 #else
151     d_max_fft_plot_curve->setRawSamples(d_xdata, d_max_fft_data, d_numPoints);
152 #endif
153     d_max_fft_plot_curve->setVisible(false);
154     d_max_fft_plot_curve->setZ(0);
155 
156     d_lower_intensity_marker = new QwtPlotMarker();
157     d_lower_intensity_marker->setLineStyle(QwtPlotMarker::HLine);
158     QColor default_marker_lower_intensity_color = Qt::cyan;
159     setMarkerLowerIntensityColor(default_marker_lower_intensity_color);
160     d_lower_intensity_marker->attach(this);
161 
162     d_upper_intensity_marker = new QwtPlotMarker();
163     d_upper_intensity_marker->setLineStyle(QwtPlotMarker::HLine);
164     QColor default_marker_upper_intensity_color = Qt::green;
165     setMarkerUpperIntensityColor(default_marker_upper_intensity_color);
166     d_upper_intensity_marker->attach(this);
167 
168     memset(d_xdata, 0x0, d_numPoints * sizeof(double));
169 
170     for (int64_t number = 0; number < d_numPoints; number++) {
171         d_min_fft_data[number] = 200.0;
172         d_max_fft_data[number] = -280.0;
173     }
174 
175     d_marker_peak_amplitude = new QwtPlotMarker();
176     QColor default_marker_peak_amplitude_color = Qt::yellow;
177     setMarkerPeakAmplitudeColor(default_marker_peak_amplitude_color);
178     /// THIS CAUSES A PROBLEM!
179     // d_marker_peak_amplitude->attach(this);
180 
181     d_marker_noise_floor_amplitude = new QwtPlotMarker();
182     d_marker_noise_floor_amplitude->setLineStyle(QwtPlotMarker::HLine);
183     QColor default_marker_noise_floor_amplitude_color = Qt::darkRed;
184     setMarkerNoiseFloorAmplitudeColor(default_marker_noise_floor_amplitude_color);
185     d_marker_noise_floor_amplitude->attach(this);
186 
187     d_marker_cf = new QwtPlotMarker();
188     d_marker_cf->setLineStyle(QwtPlotMarker::VLine);
189     QColor default_marker_cf_color = Qt::lightGray;
190     setMarkerCFColor(default_marker_cf_color);
191     d_marker_cf->attach(this);
192     d_marker_cf->hide();
193 
194     d_peak_frequency = 0;
195     d_peak_amplitude = -HUGE_VAL;
196 
197     d_noise_floor_amplitude = -HUGE_VAL;
198 
199     d_zoomer = new FreqDisplayZoomer(canvas(), 0);
200 
201 #if QWT_VERSION < 0x060000
202     d_zoomer->setSelectionFlags(QwtPicker::RectSelection | QwtPicker::DragSelection);
203 #endif
204 
205     d_zoomer->setMousePattern(
206         QwtEventPattern::MouseSelect2, Qt::RightButton, Qt::ControlModifier);
207     d_zoomer->setMousePattern(QwtEventPattern::MouseSelect3, Qt::RightButton);
208 
209 
210     const QColor default_zoomer_color(Qt::darkRed);
211     setZoomerColor(default_zoomer_color);
212 
213     // Do this after the zoomer has been built
214     _resetXAxisPoints();
215 
216     // Turn off min/max hold plots in legend
217 #if QWT_VERSION < 0x060100
218     QWidget* w;
219     w = legend()->find(d_min_fft_plot_curve);
220     ((QwtLegendItem*)w)->setChecked(true);
221     ((QwtLegendItem*)w)->setVisible(false);
222     w = legend()->find(d_max_fft_plot_curve);
223     ((QwtLegendItem*)w)->setChecked(true);
224     ((QwtLegendItem*)w)->setVisible(false);
225     legend()->setVisible(false);
226 #else /* QWT_VERSION < 0x060100 */
227     QWidget* w;
228     w = ((QwtLegend*)legend())->legendWidget(itemToInfo(d_min_fft_plot_curve));
229     ((QwtLegendLabel*)w)->setChecked(true);
230     ((QwtLegendLabel*)w)->setVisible(false);
231 
232     w = ((QwtLegend*)legend())->legendWidget(itemToInfo(d_max_fft_plot_curve));
233     ((QwtLegendLabel*)w)->setChecked(true);
234     ((QwtLegendLabel*)w)->setVisible(false);
235 
236 #endif /* QWT_VERSION < 0x060100 */
237 
238     d_trigger_line = new QwtPlotMarker();
239     d_trigger_line->setLineStyle(QwtPlotMarker::HLine);
240     d_trigger_line->setLinePen(QPen(Qt::red, 0.6, Qt::DashLine));
241     d_trigger_line->setRenderHint(QwtPlotItem::RenderAntialiased);
242     d_trigger_line->setXValue(0.0);
243     d_trigger_line->setYValue(0.0);
244 
245     replot();
246 }
247 
~FrequencyDisplayPlot()248 FrequencyDisplayPlot::~FrequencyDisplayPlot()
249 {
250     for (unsigned int i = 0; i < d_nplots; ++i)
251         delete[] d_ydata[i];
252     delete[] d_max_fft_data;
253     delete[] d_min_fft_data;
254     delete[] d_xdata;
255 }
256 
setYaxis(double min,double max)257 void FrequencyDisplayPlot::setYaxis(double min, double max)
258 {
259     // Get the new max/min values for the plot
260     d_ymin = min;
261     d_ymax = max;
262 
263     // Set the axis max/min to the new values
264     setAxisScale(QwtPlot::yLeft, d_ymin, d_ymax);
265 
266     // Reset the base zoom level to the new axis scale set here.
267     // But don't do it if we set the axis due to auto scaling.
268     if (!d_autoscale_state)
269         d_zoomer->setZoomBase();
270 }
271 
getYMin() const272 double FrequencyDisplayPlot::getYMin() const { return d_ymin; }
273 
getYMax() const274 double FrequencyDisplayPlot::getYMax() const { return d_ymax; }
275 
setFrequencyRange(const double centerfreq,const double bandwidth,const double units,const std::string & strunits)276 void FrequencyDisplayPlot::setFrequencyRange(const double centerfreq,
277                                              const double bandwidth,
278                                              const double units,
279                                              const std::string& strunits)
280 {
281     double startFreq;
282     double stopFreq = (centerfreq + bandwidth / 2.0f) / units;
283     if (d_half_freq)
284         startFreq = centerfreq / units;
285     else
286         startFreq = (centerfreq - bandwidth / 2.0f) / units;
287 
288     d_xdata_multiplier = units;
289 
290     bool reset = false;
291     if ((startFreq != d_start_frequency) || (stopFreq != d_stop_frequency))
292         reset = true;
293 
294     if (stopFreq > startFreq) {
295         d_start_frequency = startFreq;
296         d_stop_frequency = stopFreq;
297         d_center_frequency = centerfreq / units;
298 
299         if ((axisScaleDraw(QwtPlot::xBottom) != NULL) && (d_zoomer != NULL)) {
300             double display_units = ceil(log10(units) / 2.0);
301             setAxisScaleDraw(QwtPlot::xBottom, new FreqDisplayScaleDraw(display_units));
302             setAxisTitle(QwtPlot::xBottom,
303                          QString("Frequency (%1)").arg(strunits.c_str()));
304 
305             if (reset) {
306                 _resetXAxisPoints();
307                 clearMaxData();
308                 clearMinData();
309             }
310 
311             ((FreqDisplayZoomer*)d_zoomer)->setFrequencyPrecision(display_units);
312             ((FreqDisplayZoomer*)d_zoomer)->setUnitType(strunits);
313         }
314     }
315 }
316 
317 
getStartFrequency() const318 double FrequencyDisplayPlot::getStartFrequency() const { return d_start_frequency; }
319 
getStopFrequency() const320 double FrequencyDisplayPlot::getStopFrequency() const { return d_stop_frequency; }
321 
replot()322 void FrequencyDisplayPlot::replot()
323 {
324     d_marker_noise_floor_amplitude->setYValue(d_noise_floor_amplitude);
325     d_marker_peak_amplitude->setXValue(d_peak_frequency + d_start_frequency);
326 
327     // Make sure to take into account the start frequency
328     //  if(d_useCenterFrequencyFlag){
329     //    d_marker_peak_amplitude->setXValue((d_peak_frequency/1000.0) +
330     //    d_start_frequency);
331     //  }
332     //  else{
333     //    _markerPeakAmplitude->setXValue(d_peak_frequency + d_start_frequency);
334     //  }
335     d_marker_peak_amplitude->setYValue(d_peak_amplitude);
336 
337     QwtPlot::replot();
338 }
339 
plotNewData(const std::vector<double * > dataPoints,const int64_t numDataPoints,const double noiseFloorAmplitude,const double peakFrequency,const double peakAmplitude,const double timeInterval)340 void FrequencyDisplayPlot::plotNewData(const std::vector<double*> dataPoints,
341                                        const int64_t numDataPoints,
342                                        const double noiseFloorAmplitude,
343                                        const double peakFrequency,
344                                        const double peakAmplitude,
345                                        const double timeInterval)
346 {
347     int64_t _npoints_in = d_half_freq ? numDataPoints / 2 : numDataPoints;
348     int64_t _in_index = d_half_freq ? _npoints_in : 0;
349 
350     if (!d_stop) {
351         if (numDataPoints > 0) {
352             if (_npoints_in != d_numPoints) {
353                 d_numPoints = _npoints_in;
354 
355                 delete[] d_min_fft_data;
356                 delete[] d_max_fft_data;
357                 delete[] d_xdata;
358                 d_xdata = new double[d_numPoints];
359                 d_min_fft_data = new double[d_numPoints];
360                 d_max_fft_data = new double[d_numPoints];
361 
362                 for (unsigned int i = 0; i < d_nplots; ++i) {
363                     delete[] d_ydata[i];
364                     d_ydata[i] = new double[d_numPoints];
365 
366 #if QWT_VERSION < 0x060000
367                     d_plot_curve[i]->setRawData(d_xdata, d_ydata[i], d_numPoints);
368 #else
369                     d_plot_curve[i]->setRawSamples(d_xdata, d_ydata[i], d_numPoints);
370 #endif
371                 }
372 #if QWT_VERSION < 0x060000
373                 d_min_fft_plot_curve->setRawData(d_xdata, d_min_fft_data, d_numPoints);
374                 d_max_fft_plot_curve->setRawData(d_xdata, d_max_fft_data, d_numPoints);
375 #else
376                 d_min_fft_plot_curve->setRawSamples(d_xdata, d_min_fft_data, d_numPoints);
377                 d_max_fft_plot_curve->setRawSamples(d_xdata, d_max_fft_data, d_numPoints);
378 #endif
379                 _resetXAxisPoints();
380                 clearMaxData();
381                 clearMinData();
382             }
383 
384             double bottom = 1e20, top = -1e20;
385             for (unsigned int n = 0; n < d_nplots; ++n) {
386 
387                 memcpy(d_ydata[n],
388                        &(dataPoints[n][_in_index]),
389                        _npoints_in * sizeof(double));
390 
391                 for (int64_t point = 0; point < _npoints_in; point++) {
392                     if (dataPoints[n][point + _in_index] < d_min_fft_data[point]) {
393                         d_min_fft_data[point] = dataPoints[n][point + _in_index];
394                     }
395                     if (dataPoints[n][point + _in_index] > d_max_fft_data[point]) {
396                         d_max_fft_data[point] = dataPoints[n][point + _in_index];
397                     }
398 
399                     // Find overall top and bottom values in plot.
400                     // Used for autoscaling y-axis.
401                     if (dataPoints[n][point] < bottom) {
402                         bottom = dataPoints[n][point];
403                     }
404                     if (dataPoints[n][point] > top) {
405                         top = dataPoints[n][point];
406                     }
407                 }
408             }
409 
410             if (d_autoscale_state) {
411                 _autoScale(bottom, top);
412                 if (d_autoscale_shot) {
413                     d_autoscale_state = false;
414                     d_autoscale_shot = false;
415                 }
416             }
417 
418             d_noise_floor_amplitude = noiseFloorAmplitude;
419             d_peak_frequency = peakFrequency;
420             d_peak_amplitude = peakAmplitude;
421 
422             setUpperIntensityLevel(d_peak_amplitude);
423 
424             replot();
425         }
426     }
427 }
428 
plotNewData(const double * dataPoints,const int64_t numDataPoints,const double noiseFloorAmplitude,const double peakFrequency,const double peakAmplitude,const double timeInterval)429 void FrequencyDisplayPlot::plotNewData(const double* dataPoints,
430                                        const int64_t numDataPoints,
431                                        const double noiseFloorAmplitude,
432                                        const double peakFrequency,
433                                        const double peakAmplitude,
434                                        const double timeInterval)
435 {
436     std::vector<double*> vecDataPoints;
437     vecDataPoints.push_back((double*)dataPoints);
438     plotNewData(vecDataPoints,
439                 numDataPoints,
440                 noiseFloorAmplitude,
441                 peakFrequency,
442                 peakAmplitude,
443                 timeInterval);
444 }
445 
clearMaxData()446 void FrequencyDisplayPlot::clearMaxData()
447 {
448     for (int64_t number = 0; number < d_numPoints; number++) {
449         d_max_fft_data[number] = d_ymin;
450     }
451 }
452 
clearMinData()453 void FrequencyDisplayPlot::clearMinData()
454 {
455     for (int64_t number = 0; number < d_numPoints; number++) {
456         d_min_fft_data[number] = d_ymax;
457     }
458 }
459 
_autoScale(double bottom,double top)460 void FrequencyDisplayPlot::_autoScale(double bottom, double top)
461 {
462     // Auto scale the y-axis with a margin of 10 dB on either side.
463     d_ymin = bottom - 10;
464     d_ymax = top + 10;
465     setYaxis(d_ymin, d_ymax);
466 }
467 
setAutoScale(bool state)468 void FrequencyDisplayPlot::setAutoScale(bool state) { d_autoscale_state = state; }
469 
setAutoScaleShot()470 void FrequencyDisplayPlot::setAutoScaleShot()
471 {
472     d_autoscale_state = true;
473     d_autoscale_shot = true;
474 }
475 
setPlotPosHalf(bool half)476 void FrequencyDisplayPlot::setPlotPosHalf(bool half)
477 {
478     d_half_freq = half;
479     if (half)
480         d_start_frequency = d_center_frequency;
481 }
482 
483 
setMaxFFTVisible(const bool visibleFlag)484 void FrequencyDisplayPlot::setMaxFFTVisible(const bool visibleFlag)
485 {
486     d_max_fft_visible = visibleFlag;
487     d_max_fft_plot_curve->setVisible(visibleFlag);
488 }
489 
getMaxFFTVisible() const490 const bool FrequencyDisplayPlot::getMaxFFTVisible() const { return d_max_fft_visible; }
491 
setMinFFTVisible(const bool visibleFlag)492 void FrequencyDisplayPlot::setMinFFTVisible(const bool visibleFlag)
493 {
494     d_min_fft_visible = visibleFlag;
495     d_min_fft_plot_curve->setVisible(visibleFlag);
496 }
497 
getMinFFTVisible() const498 const bool FrequencyDisplayPlot::getMinFFTVisible() const { return d_min_fft_visible; }
499 
_resetXAxisPoints()500 void FrequencyDisplayPlot::_resetXAxisPoints()
501 {
502     double fft_bin_size =
503         (d_stop_frequency - d_start_frequency) / static_cast<double>(d_numPoints);
504     double freqValue = d_start_frequency;
505     for (int64_t loc = 0; loc < d_numPoints; loc++) {
506         d_xdata[loc] = freqValue;
507         freqValue += fft_bin_size;
508     }
509 
510     setAxisScale(QwtPlot::xBottom, d_start_frequency, d_stop_frequency);
511 
512     // Set up zoomer base for maximum unzoom x-axis
513     // and reset to maximum unzoom level
514     QwtDoubleRect zbase = d_zoomer->zoomBase();
515     d_zoomer->zoom(zbase);
516     d_zoomer->setZoomBase(zbase);
517     d_zoomer->setZoomBase(true);
518     d_zoomer->zoom(0);
519 }
520 
setLowerIntensityLevel(const double lowerIntensityLevel)521 void FrequencyDisplayPlot::setLowerIntensityLevel(const double lowerIntensityLevel)
522 {
523     d_lower_intensity_marker->setYValue(lowerIntensityLevel);
524 }
525 
setUpperIntensityLevel(const double upperIntensityLevel)526 void FrequencyDisplayPlot::setUpperIntensityLevel(const double upperIntensityLevel)
527 {
528     d_upper_intensity_marker->setYValue(upperIntensityLevel);
529 }
530 
setTraceColour(QColor c)531 void FrequencyDisplayPlot::setTraceColour(QColor c) { d_plot_curve[0]->setPen(QPen(c)); }
532 
setBGColour(QColor c)533 void FrequencyDisplayPlot::setBGColour(QColor c)
534 {
535     QPalette palette;
536     palette.setColor(canvas()->backgroundRole(), c);
537     canvas()->setPalette(palette);
538 }
539 
showCFMarker(const bool show)540 void FrequencyDisplayPlot::showCFMarker(const bool show)
541 {
542     if (show)
543         d_marker_cf->show();
544     else
545         d_marker_cf->hide();
546 }
547 
onPickerPointSelected(const QwtDoublePoint & p)548 void FrequencyDisplayPlot::onPickerPointSelected(const QwtDoublePoint& p)
549 {
550     QPointF point = p;
551     // fprintf(stderr,"onPickerPointSelected %f %f %d\n", point.x(), point.y(),
552     // d_xdata_multiplier);
553     point.setX(point.x() * d_xdata_multiplier);
554     emit plotPointSelected(point);
555 }
556 
onPickerPointSelected6(const QPointF & p)557 void FrequencyDisplayPlot::onPickerPointSelected6(const QPointF& p)
558 {
559     QPointF point = p;
560     // fprintf(stderr,"onPickerPointSelected %f %f %d\n", point.x(), point.y(),
561     // d_xdata_multiplier);
562     point.setX(point.x() * d_xdata_multiplier);
563     emit plotPointSelected(point);
564 }
565 
setYLabel(const std::string & label,const std::string & unit)566 void FrequencyDisplayPlot::setYLabel(const std::string& label, const std::string& unit)
567 {
568     std::string l = label;
569     if (unit.length() > 0)
570         l += " (" + unit + ")";
571     setAxisTitle(QwtPlot::yLeft, QString(l.c_str()));
572     static_cast<FreqDisplayZoomer*>(d_zoomer)->setYUnit(unit);
573 }
574 
setMinFFTColor(QColor c)575 void FrequencyDisplayPlot::setMinFFTColor(QColor c)
576 {
577     d_min_fft_color = c;
578     d_min_fft_plot_curve->setPen(QPen(c));
579 }
getMinFFTColor() const580 const QColor FrequencyDisplayPlot::getMinFFTColor() const { return d_min_fft_color; }
581 
setMaxFFTColor(QColor c)582 void FrequencyDisplayPlot::setMaxFFTColor(QColor c)
583 {
584     d_max_fft_color = c;
585     d_max_fft_plot_curve->setPen(QPen(c));
586 }
587 
getMaxFFTColor() const588 const QColor FrequencyDisplayPlot::getMaxFFTColor() const { return d_max_fft_color; }
589 
setMarkerLowerIntensityColor(QColor c)590 void FrequencyDisplayPlot::setMarkerLowerIntensityColor(QColor c)
591 {
592     d_marker_lower_intensity_color = c;
593     d_lower_intensity_marker->setLinePen(QPen(c));
594 }
getMarkerLowerIntensityColor() const595 const QColor FrequencyDisplayPlot::getMarkerLowerIntensityColor() const
596 {
597     return d_marker_lower_intensity_color;
598 }
599 
setMarkerLowerIntensityVisible(bool visible)600 void FrequencyDisplayPlot::setMarkerLowerIntensityVisible(bool visible)
601 {
602     d_marker_lower_intensity_visible = visible;
603     if (visible)
604         d_lower_intensity_marker->setLineStyle(QwtPlotMarker::HLine);
605     else
606         d_lower_intensity_marker->setLineStyle(QwtPlotMarker::NoLine);
607 }
getMarkerLowerIntensityVisible() const608 const bool FrequencyDisplayPlot::getMarkerLowerIntensityVisible() const
609 {
610     return d_marker_lower_intensity_visible;
611 }
612 
setMarkerUpperIntensityColor(QColor c)613 void FrequencyDisplayPlot::setMarkerUpperIntensityColor(QColor c)
614 {
615     d_marker_upper_intensity_color = c;
616     d_upper_intensity_marker->setLinePen(QPen(c, 0, Qt::DotLine));
617 }
618 
getMarkerUpperIntensityColor() const619 const QColor FrequencyDisplayPlot::getMarkerUpperIntensityColor() const
620 {
621     return d_marker_upper_intensity_color;
622 }
623 
setMarkerUpperIntensityVisible(bool visible)624 void FrequencyDisplayPlot::setMarkerUpperIntensityVisible(bool visible)
625 {
626     d_marker_upper_intensity_visible = visible;
627     if (visible)
628         d_upper_intensity_marker->setLineStyle(QwtPlotMarker::HLine);
629     else
630         d_upper_intensity_marker->setLineStyle(QwtPlotMarker::NoLine);
631 }
632 
getMarkerUpperIntensityVisible() const633 const bool FrequencyDisplayPlot::getMarkerUpperIntensityVisible() const
634 {
635     return d_marker_upper_intensity_visible;
636 }
637 
setMarkerPeakAmplitudeColor(QColor c)638 void FrequencyDisplayPlot::setMarkerPeakAmplitudeColor(QColor c)
639 {
640     d_marker_peak_amplitude_color = c;
641     d_marker_peak_amplitude->setLinePen(QPen(c));
642     QwtSymbol symbol;
643     symbol.setStyle(QwtSymbol::Diamond);
644     symbol.setSize(8);
645     symbol.setPen(QPen(c));
646     symbol.setBrush(QBrush(c));
647 #if QWT_VERSION < 0x060000
648     d_marker_peak_amplitude->setSymbol(symbol);
649 #else
650     d_marker_peak_amplitude->setSymbol(&symbol);
651 #endif
652 }
getMarkerPeakAmplitudeColor() const653 const QColor FrequencyDisplayPlot::getMarkerPeakAmplitudeColor() const
654 {
655     return d_marker_peak_amplitude_color;
656 }
657 
setMarkerNoiseFloorAmplitudeColor(QColor c)658 void FrequencyDisplayPlot::setMarkerNoiseFloorAmplitudeColor(QColor c)
659 {
660     d_marker_noise_floor_amplitude_color = c;
661     d_marker_noise_floor_amplitude->setLinePen(QPen(c, 0, Qt::DotLine));
662 }
663 
getMarkerNoiseFloorAmplitudeColor() const664 const QColor FrequencyDisplayPlot::getMarkerNoiseFloorAmplitudeColor() const
665 {
666     return d_marker_noise_floor_amplitude_color;
667 }
668 
setMarkerNoiseFloorAmplitudeVisible(bool visible)669 void FrequencyDisplayPlot::setMarkerNoiseFloorAmplitudeVisible(bool visible)
670 {
671     d_marker_noise_floor_amplitude_visible = visible;
672     if (visible)
673         d_marker_noise_floor_amplitude->setLineStyle(QwtPlotMarker::HLine);
674     else
675         d_marker_noise_floor_amplitude->setLineStyle(QwtPlotMarker::NoLine);
676 }
677 
getMarkerNoiseFloorAmplitudeVisible() const678 const bool FrequencyDisplayPlot::getMarkerNoiseFloorAmplitudeVisible() const
679 {
680     return d_marker_noise_floor_amplitude_visible;
681 }
682 
setMarkerCFColor(QColor c)683 void FrequencyDisplayPlot::setMarkerCFColor(QColor c)
684 {
685     d_marker_cf_color = c;
686     d_marker_cf->setLinePen(QPen(c, 0, Qt::DotLine));
687 }
688 
getMarkerCFColor() const689 const QColor FrequencyDisplayPlot::getMarkerCFColor() const { return d_marker_cf_color; }
690 
attachTriggerLine(bool en)691 void FrequencyDisplayPlot::attachTriggerLine(bool en)
692 {
693     if (en) {
694         d_trigger_line->attach(this);
695     } else {
696         d_trigger_line->detach();
697     }
698 }
699 
setTriggerLine(double level)700 void FrequencyDisplayPlot::setTriggerLine(double level)
701 {
702     d_trigger_line->setYValue(level);
703 }
704 
705 #endif /* FREQUENCY_DISPLAY_PLOT_C */
706