[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Commit-gnuradio] [gnuradio] 01/08: qtgui: adds control panel to frequen
From: |
git |
Subject: |
[Commit-gnuradio] [gnuradio] 01/08: qtgui: adds control panel to frequency sinks. |
Date: |
Mon, 6 Apr 2015 06:03:45 +0000 (UTC) |
This is an automated email from the git hooks/post-receive script.
jcorgan pushed a commit to branch master
in repository gnuradio.
commit 8cdc041e1aaf8771de0fd9e7327720dc5b383464
Author: Tom Rondeau <address@hidden>
Date: Sat Apr 4 16:57:29 2015 -0400
qtgui: adds control panel to frequency sinks.
Also adds ability to disable the legend. Currently, only exposed in
GRC for the freq sinks.
---
gr-qtgui/grc/qtgui_freq_sink_x.xml | 38 +++
gr-qtgui/include/gnuradio/qtgui/CMakeLists.txt | 1 +
gr-qtgui/include/gnuradio/qtgui/DisplayPlot.h | 12 +
.../include/gnuradio/qtgui/FrequencyDisplayPlot.h | 9 +-
gr-qtgui/include/gnuradio/qtgui/displayform.h | 2 +
gr-qtgui/include/gnuradio/qtgui/freq_sink_c.h | 4 +
gr-qtgui/include/gnuradio/qtgui/freq_sink_f.h | 4 +
gr-qtgui/include/gnuradio/qtgui/freqcontrolpanel.h | 94 ++++++++
gr-qtgui/include/gnuradio/qtgui/freqdisplayform.h | 30 ++-
gr-qtgui/lib/CMakeLists.txt | 2 +
gr-qtgui/lib/DisplayPlot.cc | 6 +
gr-qtgui/lib/FrequencyDisplayPlot.cc | 34 ++-
gr-qtgui/lib/displayform.cc | 6 +
gr-qtgui/lib/freq_sink_c_impl.cc | 27 +++
gr-qtgui/lib/freq_sink_c_impl.h | 4 +
gr-qtgui/lib/freq_sink_f_impl.cc | 27 +++
gr-qtgui/lib/freq_sink_f_impl.h | 4 +
gr-qtgui/lib/freqcontrolpanel.cc | 219 ++++++++++++++++++
gr-qtgui/lib/freqdisplayform.cc | 256 +++++++++++++++++++--
19 files changed, 751 insertions(+), 28 deletions(-)
diff --git a/gr-qtgui/grc/qtgui_freq_sink_x.xml
b/gr-qtgui/grc/qtgui_freq_sink_x.xml
index aea46ab..96a9fd0 100644
--- a/gr-qtgui/grc/qtgui_freq_sink_x.xml
+++ b/gr-qtgui/grc/qtgui_freq_sink_x.xml
@@ -26,6 +26,10 @@ self.$(id).set_trigger_mode($tr_mode, $tr_level, $tr_chan,
$tr_tag)
self.$(id).enable_autoscale($autoscale)
self.$(id).enable_grid($grid)
self.$(id).set_fft_average($average)
+self.$(id).enable_control_panel($ctrlpanel)
+
+if not $legend:
+ self.$(id).disable_legend()
if $type == type(float()):
self.$(id).set_plot_pos_half(not $freqhalf)
@@ -319,6 +323,40 @@ $(gui_hint()($win))</make>
<!-- Begin Config Tab items -->
<param>
+ <name>Control Panel</name>
+ <key>ctrlpanel</key>
+ <value>False</value>
+ <type>enum</type>
+ <hide>part</hide>
+ <option>
+ <name>Yes</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>No</name>
+ <key>False</key>
+ </option>
+ <tab>Config</tab>
+ </param>
+
+ <param>
+ <name>Legend</name>
+ <key>legend</key>
+ <value>True</value>
+ <type>enum</type>
+ <hide>part</hide>
+ <option>
+ <name>Yes</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>No</name>
+ <key>False</key>
+ </option>
+ <tab>Config</tab>
+ </param>
+
+ <param>
<name>Line 1 Label</name>
<key>label1</key>
<type>string</type>
diff --git a/gr-qtgui/include/gnuradio/qtgui/CMakeLists.txt
b/gr-qtgui/include/gnuradio/qtgui/CMakeLists.txt
index 6ba9923..1e0c9f3 100644
--- a/gr-qtgui/include/gnuradio/qtgui/CMakeLists.txt
+++ b/gr-qtgui/include/gnuradio/qtgui/CMakeLists.txt
@@ -31,6 +31,7 @@ install(FILES
DisplayPlot.h
form_menus.h
freqdisplayform.h
+ freqcontrolpanel.h
freq_sink_c.h
freq_sink_f.h
FrequencyDisplayPlot.h
diff --git a/gr-qtgui/include/gnuradio/qtgui/DisplayPlot.h
b/gr-qtgui/include/gnuradio/qtgui/DisplayPlot.h
index 73c7440..19b1182 100644
--- a/gr-qtgui/include/gnuradio/qtgui/DisplayPlot.h
+++ b/gr-qtgui/include/gnuradio/qtgui/DisplayPlot.h
@@ -37,6 +37,7 @@
#include <qwt_plot_magnifier.h>
#include <qwt_plot_marker.h>
#include <qwt_symbol.h>
+#include <qwt_legend.h>
#include <gnuradio/qtgui/utils.h>
#if QWT_VERSION >= 0x060000
@@ -46,6 +47,13 @@
typedef QList<QColor> QColorList;
Q_DECLARE_METATYPE ( QColorList )
+#if QWT_VERSION < 0x060100
+#include <qwt_legend_item.h>
+#else /* QWT_VERSION < 0x060100 */
+#include <qwt_legend_data.h>
+#include <qwt_legend_label.h>
+#endif /* QWT_VERSION < 0x060100 */
+
/*!
* \brief QWidget base plot to build QTGUI plotting tools.
* \ingroup qtgui_blk
@@ -117,6 +125,8 @@ public:
DisplayPlot(int nplots, QWidget*);
virtual ~DisplayPlot();
+ void disableLegend();
+
virtual void replot() = 0;
const QColor getLineColor1 () const;
@@ -289,6 +299,8 @@ protected:
QList<QColor> d_trace_colors;
bool d_autoscale_state;
+
+ QwtLegend d_legend;
};
#endif /* DOMAIN_DISPLAY_PLOT_H */
diff --git a/gr-qtgui/include/gnuradio/qtgui/FrequencyDisplayPlot.h
b/gr-qtgui/include/gnuradio/qtgui/FrequencyDisplayPlot.h
index cb44fbe..3a8f1f3 100644
--- a/gr-qtgui/include/gnuradio/qtgui/FrequencyDisplayPlot.h
+++ b/gr-qtgui/include/gnuradio/qtgui/FrequencyDisplayPlot.h
@@ -70,9 +70,6 @@ public:
const double noiseFloorAmplitude, const double peakFrequency,
const double peakAmplitude, const double timeInterval);
- void clearMaxData();
- void clearMinData();
-
void replot();
void setYaxis(double min, double max);
@@ -117,9 +114,13 @@ public slots:
void onPickerPointSelected6(const QPointF & p);
void setAutoScale(bool state);
+ void setAutoScaleShot();
void setPlotPosHalf(bool half);
+ void clearMaxData();
+ void clearMinData();
+
private:
void _resetXAxisPoints();
void _autoScale(double bottom, double top);
@@ -164,6 +165,8 @@ private:
double d_peak_amplitude;
double d_noise_floor_amplitude;
+
+ bool d_autoscale_shot;
};
#endif /* FREQUENCY_DISPLAY_PLOT_HPP */
diff --git a/gr-qtgui/include/gnuradio/qtgui/displayform.h
b/gr-qtgui/include/gnuradio/qtgui/displayform.h
index 02d2cf8..2ef4b80 100644
--- a/gr-qtgui/include/gnuradio/qtgui/displayform.h
+++ b/gr-qtgui/include/gnuradio/qtgui/displayform.h
@@ -86,6 +86,8 @@ public slots:
void saveFigure();
+ void disableLegend();
+
private slots:
virtual void newData(const QEvent*) = 0;
virtual void autoScale(bool) = 0;
diff --git a/gr-qtgui/include/gnuradio/qtgui/freq_sink_c.h
b/gr-qtgui/include/gnuradio/qtgui/freq_sink_c.h
index f49e7b0..8869afc 100644
--- a/gr-qtgui/include/gnuradio/qtgui/freq_sink_c.h
+++ b/gr-qtgui/include/gnuradio/qtgui/freq_sink_c.h
@@ -159,8 +159,12 @@ namespace gr {
virtual void enable_menu(bool en=true) = 0;
virtual void enable_grid(bool en=true) = 0;
virtual void enable_autoscale(bool en=true) = 0;
+ virtual void enable_control_panel(bool en=true) = 0;
+ virtual void enable_max_hold(bool en) = 0;
+ virtual void enable_min_hold(bool en) = 0;
virtual void clear_max_hold() = 0;
virtual void clear_min_hold() = 0;
+ virtual void disable_legend() = 0;
virtual void reset() = 0;
QApplication *d_qApplication;
diff --git a/gr-qtgui/include/gnuradio/qtgui/freq_sink_f.h
b/gr-qtgui/include/gnuradio/qtgui/freq_sink_f.h
index ed65d31..552e1e4 100644
--- a/gr-qtgui/include/gnuradio/qtgui/freq_sink_f.h
+++ b/gr-qtgui/include/gnuradio/qtgui/freq_sink_f.h
@@ -165,8 +165,12 @@ namespace gr {
virtual void enable_menu(bool en=true) = 0;
virtual void enable_grid(bool en=true) = 0;
virtual void enable_autoscale(bool en=true) = 0;
+ virtual void enable_control_panel(bool en=true) = 0;
+ virtual void enable_max_hold(bool en) = 0;
+ virtual void enable_min_hold(bool en) = 0;
virtual void clear_max_hold() = 0;
virtual void clear_min_hold() = 0;
+ virtual void disable_legend() = 0;
virtual void reset() = 0;
QApplication *d_qApplication;
diff --git a/gr-qtgui/include/gnuradio/qtgui/freqcontrolpanel.h
b/gr-qtgui/include/gnuradio/qtgui/freqcontrolpanel.h
new file mode 100644
index 0000000..fe7636f
--- /dev/null
+++ b/gr-qtgui/include/gnuradio/qtgui/freqcontrolpanel.h
@@ -0,0 +1,94 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef FREQ_CONTROL_PANEL_H
+#define FREQ_CONTROL_PANEL_H
+
+#include <QtGui/QtGui>
+#include <vector>
+#include <QSlider>
+#include <QComboBox>
+#include <QCheckBox>
+#include <QPushButton>
+#include <QLabel>
+#include <QHBoxLayout>
+#include <gnuradio/qtgui/displayform.h>
+#include <gnuradio/qtgui/freqdisplayform.h>
+
+class FreqControlPanel : public QVBoxLayout
+{
+ Q_OBJECT
+
+public:
+ FreqControlPanel(FreqDisplayForm *form);
+ ~FreqControlPanel();
+
+public slots:
+ void notifyAvgSlider(int val);
+ void toggleGrid(bool en);
+ void toggleMaxHold(bool en);
+ void toggleMinHold(bool en);
+
+ void toggleFFTSize(int val);
+ void toggleFFTWindow(const gr::filter::firdes::win_type win);
+
+signals:
+ void signalAvgSlider(float val);
+ void signalAvg(bool en);
+
+private:
+ FreqDisplayForm *d_parent;
+
+ QGroupBox *d_trace_box;
+ QVBoxLayout *d_trace_layout;
+ QCheckBox *d_maxhold_check;
+ QCheckBox *d_minhold_check;
+
+ QHBoxLayout *d_avg_layout;
+ QLabel *d_avg_label;
+ QSlider *d_avg_slider;
+
+ QGroupBox *d_axes_box;
+ QVBoxLayout *d_axes_layout;
+
+ QCheckBox *d_grid_check;
+ QHBoxLayout *d_yrange_layout;
+ QLabel *d_yrange_label;
+ QPushButton *d_yrange_plus;
+ QPushButton *d_yrange_minus;
+
+ QHBoxLayout *d_ymin_layout;
+ QLabel *d_ymin_label;
+ QPushButton *d_ymin_plus;
+ QPushButton *d_ymin_minus;
+
+ QPushButton *d_autoscale_button;
+
+ QGroupBox *d_fft_box;
+ QVBoxLayout *d_fft_layout;
+ QComboBox *d_fft_size_combo;
+ QComboBox *d_fft_win_combo;
+
+ int d_slider_max, d_slider_min, d_slider_step;
+};
+
+#endif /* FREQ_CONTROL_PANEL_H */
diff --git a/gr-qtgui/include/gnuradio/qtgui/freqdisplayform.h
b/gr-qtgui/include/gnuradio/qtgui/freqdisplayform.h
index 744ac3e..1f866ba 100644
--- a/gr-qtgui/include/gnuradio/qtgui/freqdisplayform.h
+++ b/gr-qtgui/include/gnuradio/qtgui/freqdisplayform.h
@@ -31,6 +31,8 @@
#include <gnuradio/qtgui/displayform.h>
+class FreqControlPanel;
+
/*!
* \brief DisplayForm child for managing frequency (PSD) plots.
* \ingroup qtgui_blk
@@ -76,6 +78,7 @@ public slots:
void setYMax(const QString &m);
void setYMin(const QString &m);
void autoScale(bool en);
+ void autoScaleShot();
void setPlotPosHalf(bool half);
void clearMaxHold();
void clearMinHold();
@@ -89,6 +92,28 @@ public slots:
void setTriggerTagKey(QString s);
void setTriggerTagKey(const std::string &s);
+ void setupControlPanel(bool en);
+ void setupControlPanel();
+ void teardownControlPanel();
+
+ void notifyYAxisPlus();
+ void notifyYAxisMinus();
+ void notifyYRangePlus();
+ void notifyYRangeMinus();
+ void notifyFFTSize(const QString &s);
+ void notifyFFTWindow(const QString &s);
+ void notifyMaxHold(bool en);
+ void notifyMinHold(bool en);
+
+signals:
+ void signalFFTSize(int size);
+ void signalFFTWindow(gr::filter::firdes::win_type win);
+ void signalReplot();
+ void signalClearMaxData();
+ void signalClearMinData();
+ void signalSetMaxFFTVisible(bool en);
+ void signalSetMinFFTVisible(bool en);
+
private slots:
void newData(const QEvent *updateEvent);
void onPlotPointSelected(const QPointF p);
@@ -109,7 +134,7 @@ private:
FFTSizeMenu *d_sizemenu;
FFTAverageMenu *d_avgmenu;
FFTWindowMenu *d_winmenu;
- QAction *d_clearmin_act, *d_clearmax_act;
+ QAction *d_minhold_act, *d_maxhold_act;
QMenu *d_triggermenu;
TriggerModeMenu *d_tr_mode_menu;
@@ -121,6 +146,9 @@ private:
float d_trig_level;
int d_trig_channel;
std::string d_trig_tag_key;
+
+ QAction *d_controlpanelmenu;
+ FreqControlPanel *d_controlpanel;
};
#endif /* FREQ_DISPLAY_FORM_H */
diff --git a/gr-qtgui/lib/CMakeLists.txt b/gr-qtgui/lib/CMakeLists.txt
index 64e47f4..a0af95b 100644
--- a/gr-qtgui/lib/CMakeLists.txt
+++ b/gr-qtgui/lib/CMakeLists.txt
@@ -28,6 +28,7 @@ set(qtgui_moc_hdrs
${qtgui_mod_includedir}/timecontrolpanel.h
${qtgui_mod_includedir}/timerasterdisplayform.h
${qtgui_mod_includedir}/freqdisplayform.h
+ ${qtgui_mod_includedir}/freqcontrolpanel.h
${qtgui_mod_includedir}/constellationdisplayform.h
${qtgui_mod_includedir}/waterfalldisplayform.h
${qtgui_mod_includedir}/histogramdisplayform.h
@@ -72,6 +73,7 @@ set(qtgui_sources
timecontrolpanel.cc
timerasterdisplayform.cc
freqdisplayform.cc
+ freqcontrolpanel.cc
constellationdisplayform.cc
histogramdisplayform.cc
numberdisplayform.cc
diff --git a/gr-qtgui/lib/DisplayPlot.cc b/gr-qtgui/lib/DisplayPlot.cc
index dcf5461..30fd837 100644
--- a/gr-qtgui/lib/DisplayPlot.cc
+++ b/gr-qtgui/lib/DisplayPlot.cc
@@ -102,6 +102,12 @@ DisplayPlot::~DisplayPlot()
// d_zoomer and d_panner deleted when parent deleted
}
+void
+DisplayPlot::disableLegend()
+{
+ // Haven't found a good way to toggle it on/off
+ insertLegend(NULL);
+}
void
DisplayPlot::setYaxis(double min, double max)
diff --git a/gr-qtgui/lib/FrequencyDisplayPlot.cc
b/gr-qtgui/lib/FrequencyDisplayPlot.cc
index 8005be1..2c7f3ef 100644
--- a/gr-qtgui/lib/FrequencyDisplayPlot.cc
+++ b/gr-qtgui/lib/FrequencyDisplayPlot.cc
@@ -27,16 +27,9 @@
#include <gnuradio/qtgui/qtgui_types.h>
#include <qwt_scale_draw.h>
-#include <qwt_legend.h>
#include <QColor>
#include <iostream>
-#if QWT_VERSION < 0x060100
-#include <qwt_legend_item.h>
-#else /* QWT_VERSION < 0x060100 */
-#include <qwt_legend_data.h>
-#include <qwt_legend_label.h>
-#endif /* QWT_VERSION < 0x060100 */
/***********************************************************************
* Widget to provide mouse pointer coordinate text
@@ -95,6 +88,7 @@ FrequencyDisplayPlot::FrequencyDisplayPlot(int nplots,
QWidget* parent)
d_max_fft_data = new double[d_numPoints];
d_xdata = new double[d_numPoints];
d_half_freq = false;
+ d_autoscale_shot = false;
setAxisTitle(QwtPlot::xBottom, "Frequency (Hz)");
setAxisScaleDraw(QwtPlot::xBottom, new FreqDisplayScaleDraw(0));
@@ -222,19 +216,25 @@ FrequencyDisplayPlot::FrequencyDisplayPlot(int nplots,
QWidget* parent)
// Turn off min/max hold plots in legend
#if QWT_VERSION < 0x060100
QWidget *w;
- QwtLegend* legendDisplay = legend();
- w = legendDisplay->find(d_min_fft_plot_curve);
+ d_legend = legend();
+ w = legend()->find(d_min_fft_plot_curve);
((QwtLegendItem*)w)->setChecked(true);
- w = legendDisplay->find(d_max_fft_plot_curve);
+ w = legend()->find(d_max_fft_plot_curve);
((QwtLegendItem*)w)->setChecked(true);
+ legend()->setVisible(false);
#else /* QWT_VERSION < 0x060100 */
QWidget *w;
w = ((QwtLegend*)legend())->legendWidget(itemToInfo(d_min_fft_plot_curve));
((QwtLegendLabel*)w)->setChecked(true);
+ ((QwtLegendLabel*)w)->setVisible(false);
+
w = ((QwtLegend*)legend())->legendWidget(itemToInfo(d_max_fft_plot_curve));
((QwtLegendLabel*)w)->setChecked(true);
+ ((QwtLegendLabel*)w)->setVisible(false);
+
#endif /* QWT_VERSION < 0x060100 */
+
replot();
}
@@ -412,8 +412,13 @@ FrequencyDisplayPlot::plotNewData(const
std::vector<double*> dataPoints,
}
}
- if(d_autoscale_state)
+ if(d_autoscale_state) {
_autoScale(bottom, top);
+ if(d_autoscale_shot) {
+ d_autoscale_state = false;
+ d_autoscale_shot = false;
+ }
+ }
d_noise_floor_amplitude = noiseFloorAmplitude;
d_peak_frequency = peakFrequency;
@@ -470,6 +475,13 @@ FrequencyDisplayPlot::setAutoScale(bool state)
}
void
+FrequencyDisplayPlot::setAutoScaleShot()
+{
+ d_autoscale_state = true;
+ d_autoscale_shot = true;
+}
+
+void
FrequencyDisplayPlot::setPlotPosHalf(bool half)
{
d_half_freq = half;
diff --git a/gr-qtgui/lib/displayform.cc b/gr-qtgui/lib/displayform.cc
index 326b96c..27a0951 100644
--- a/gr-qtgui/lib/displayform.cc
+++ b/gr-qtgui/lib/displayform.cc
@@ -374,3 +374,9 @@ DisplayForm::saveFigure()
delete filebox;
}
+
+void
+DisplayForm::disableLegend()
+{
+ d_display_plot->disableLegend();
+}
diff --git a/gr-qtgui/lib/freq_sink_c_impl.cc b/gr-qtgui/lib/freq_sink_c_impl.cc
index adc1f76..ee2fc52 100644
--- a/gr-qtgui/lib/freq_sink_c_impl.cc
+++ b/gr-qtgui/lib/freq_sink_c_impl.cc
@@ -391,6 +391,27 @@ namespace gr {
}
void
+ freq_sink_c_impl::enable_control_panel(bool en)
+ {
+ if(en)
+ d_main_gui->setupControlPanel();
+ else
+ d_main_gui->teardownControlPanel();
+ }
+
+ void
+ freq_sink_c_impl::enable_max_hold(bool en)
+ {
+ d_main_gui->notifyMaxHold(en);
+ }
+
+ void
+ freq_sink_c_impl::enable_min_hold(bool en)
+ {
+ d_main_gui->notifyMinHold(en);
+ }
+
+ void
freq_sink_c_impl::clear_max_hold()
{
d_main_gui->clearMaxHold();
@@ -403,6 +424,12 @@ namespace gr {
}
void
+ freq_sink_c_impl::disable_legend()
+ {
+ d_main_gui->disableLegend();
+ }
+
+ void
freq_sink_c_impl::reset()
{
gr::thread::scoped_lock lock(d_setlock);
diff --git a/gr-qtgui/lib/freq_sink_c_impl.h b/gr-qtgui/lib/freq_sink_c_impl.h
index b5f9cd3..908ce0b 100644
--- a/gr-qtgui/lib/freq_sink_c_impl.h
+++ b/gr-qtgui/lib/freq_sink_c_impl.h
@@ -142,8 +142,12 @@ namespace gr {
void enable_menu(bool en);
void enable_grid(bool en);
void enable_autoscale(bool en);
+ void enable_control_panel(bool en);
+ void enable_max_hold(bool en);
+ void enable_min_hold(bool en);
void clear_max_hold();
void clear_min_hold();
+ void disable_legend();
void reset();
int work(int noutput_items,
diff --git a/gr-qtgui/lib/freq_sink_f_impl.cc b/gr-qtgui/lib/freq_sink_f_impl.cc
index 1e01208..05a2ff7 100644
--- a/gr-qtgui/lib/freq_sink_f_impl.cc
+++ b/gr-qtgui/lib/freq_sink_f_impl.cc
@@ -396,6 +396,27 @@ namespace gr {
}
void
+ freq_sink_f_impl::enable_control_panel(bool en)
+ {
+ if(en)
+ d_main_gui->setupControlPanel();
+ else
+ d_main_gui->teardownControlPanel();
+ }
+
+ void
+ freq_sink_f_impl::enable_max_hold(bool en)
+ {
+ d_main_gui->notifyMaxHold(en);
+ }
+
+ void
+ freq_sink_f_impl::enable_min_hold(bool en)
+ {
+ d_main_gui->notifyMinHold(en);
+ }
+
+ void
freq_sink_f_impl::clear_max_hold()
{
d_main_gui->clearMaxHold();
@@ -408,6 +429,12 @@ namespace gr {
}
void
+ freq_sink_f_impl::disable_legend()
+ {
+ d_main_gui->disableLegend();
+ }
+
+ void
freq_sink_f_impl::reset()
{
gr::thread::scoped_lock lock(d_setlock);
diff --git a/gr-qtgui/lib/freq_sink_f_impl.h b/gr-qtgui/lib/freq_sink_f_impl.h
index 1463699..e1ae0e9 100644
--- a/gr-qtgui/lib/freq_sink_f_impl.h
+++ b/gr-qtgui/lib/freq_sink_f_impl.h
@@ -142,8 +142,12 @@ namespace gr {
void enable_menu(bool en);
void enable_grid(bool en);
void enable_autoscale(bool en);
+ void enable_control_panel(bool en);
+ void enable_max_hold(bool en);
+ void enable_min_hold(bool en);
void clear_max_hold();
void clear_min_hold();
+ void disable_legend();
void reset();
int work(int noutput_items,
diff --git a/gr-qtgui/lib/freqcontrolpanel.cc b/gr-qtgui/lib/freqcontrolpanel.cc
new file mode 100644
index 0000000..d33e010
--- /dev/null
+++ b/gr-qtgui/lib/freqcontrolpanel.cc
@@ -0,0 +1,219 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <gnuradio/qtgui/freqcontrolpanel.h>
+
+FreqControlPanel::FreqControlPanel(FreqDisplayForm *form)
+ : QVBoxLayout(),
+ d_parent(form)
+{
+ // Set up the box for trace items
+ d_trace_box = new QGroupBox("Trace Options");
+ d_trace_layout = new QVBoxLayout;
+ d_maxhold_check = new QCheckBox("Max Hold");
+ d_minhold_check = new QCheckBox("Min Hold");
+
+ d_avg_layout = new QHBoxLayout;
+ d_avg_label = new QLabel("Avg:");
+ d_slider_max = 100;
+ d_slider_min = 1;
+ d_slider_step = 1;
+ d_avg_slider = new QSlider(Qt::Horizontal);
+ d_avg_slider->setRange(d_slider_min, d_slider_max);
+ d_avg_slider->setTickInterval(d_slider_step);
+ d_avg_slider->setValue(d_slider_max);
+ d_avg_layout->addWidget(d_avg_label);
+ d_avg_layout->addWidget(d_avg_slider);
+
+ // Set up the box for axis items
+ d_axes_box = new QGroupBox("Axis Options");
+ d_axes_layout = new QVBoxLayout;
+
+ d_grid_check = new QCheckBox("Grid");
+ d_yrange_layout = new QHBoxLayout;
+ d_yrange_label = new QLabel("Y Range:");
+ d_yrange_plus = new QPushButton("+");
+ d_yrange_minus = new QPushButton("-");
+ d_yrange_plus->setMaximumWidth(30);
+ d_yrange_plus->setMinimumWidth(30);
+ d_yrange_minus->setMaximumWidth(30);
+ d_yrange_minus->setMinimumWidth(30);
+ d_yrange_layout->addWidget(d_yrange_label);
+ d_yrange_layout->addWidget(d_yrange_plus);
+ d_yrange_layout->addWidget(d_yrange_minus);
+
+ d_ymin_layout = new QHBoxLayout;
+ d_ymin_label = new QLabel("Ref Level:");
+ d_ymin_plus = new QPushButton("+");
+ d_ymin_minus = new QPushButton("-");
+ d_ymin_plus->setMaximumWidth(30);
+ d_ymin_plus->setMinimumWidth(30);
+ d_ymin_minus->setMaximumWidth(30);
+ d_ymin_minus->setMinimumWidth(30);
+ d_ymin_layout->addWidget(d_ymin_label);
+ d_ymin_layout->addWidget(d_ymin_plus);
+ d_ymin_layout->addWidget(d_ymin_minus);
+
+ d_autoscale_button = new QPushButton("Autoscale");
+
+
+ // Set up the box for FFT settings
+ d_fft_box = new QGroupBox("FFT");
+ d_fft_layout = new QVBoxLayout;
+ d_fft_size_combo = new QComboBox();
+ d_fft_size_combo->addItem("32");
+ d_fft_size_combo->addItem("64");
+ d_fft_size_combo->addItem("128");
+ d_fft_size_combo->addItem("256");
+ d_fft_size_combo->addItem("512");
+ d_fft_size_combo->addItem("1024");
+ d_fft_size_combo->addItem("2048");
+ d_fft_size_combo->addItem("4096");
+
+ d_fft_win_combo = new QComboBox();
+ d_fft_win_combo->addItem("None");
+ d_fft_win_combo->addItem("Hamming");
+ d_fft_win_combo->addItem("Hann");
+ d_fft_win_combo->addItem("Blackman");
+ d_fft_win_combo->addItem("Blackman-harris");
+ d_fft_win_combo->addItem("Rectangular");
+ d_fft_win_combo->addItem("Kaiser");
+ d_fft_win_combo->addItem("Flat-top");
+
+
+ // Set up the boxes into the layout
+ d_trace_layout->addWidget(d_maxhold_check);
+ d_trace_layout->addWidget(d_minhold_check);
+ d_trace_layout->addLayout(d_avg_layout);
+ d_trace_box->setLayout(d_trace_layout);
+
+ d_axes_layout->addWidget(d_grid_check);
+ d_axes_layout->addLayout(d_yrange_layout);
+ d_axes_layout->addLayout(d_ymin_layout);
+ d_axes_layout->addWidget(d_autoscale_button);
+ d_axes_box->setLayout(d_axes_layout);
+
+ d_fft_layout->addWidget(d_fft_size_combo);
+ d_fft_layout->addWidget(d_fft_win_combo);
+ d_fft_box->setLayout(d_fft_layout);
+
+ addWidget(d_trace_box);
+ addWidget(d_axes_box);
+ addWidget(d_fft_box);
+
+ addItem(new QSpacerItem(0, 0, QSizePolicy::Minimum,
+ QSizePolicy::Expanding));
+
+ connect(d_maxhold_check, SIGNAL(clicked(bool)),
+ d_parent, SLOT(notifyMaxHold(bool)));
+ connect(d_minhold_check, SIGNAL(clicked(bool)),
+ d_parent, SLOT(notifyMinHold(bool)));
+
+ connect(d_avg_slider, SIGNAL(valueChanged(int)),
+ this, SLOT(notifyAvgSlider(int)));
+ connect(this, SIGNAL(signalAvgSlider(float)),
+ d_parent, SLOT(setFFTAverage(float)));
+
+ connect(d_grid_check, SIGNAL(clicked(bool)),
+ d_parent, SLOT(setGrid(bool)));
+
+ connect(d_ymin_plus, SIGNAL(pressed(void)),
+ d_parent, SLOT(notifyYAxisPlus(void)));
+ connect(d_ymin_minus, SIGNAL(pressed(void)),
+ d_parent, SLOT(notifyYAxisMinus(void)));
+ connect(d_yrange_plus, SIGNAL(pressed(void)),
+ d_parent, SLOT(notifyYRangePlus(void)));
+ connect(d_yrange_minus, SIGNAL(pressed(void)),
+ d_parent, SLOT(notifyYRangeMinus(void)));
+
+ connect(d_autoscale_button, SIGNAL(pressed(void)),
+ d_parent, SLOT(autoScaleShot(void)));
+
+ connect(d_fft_size_combo, SIGNAL(currentIndexChanged(const QString&)),
+ d_parent, SLOT(notifyFFTSize(const QString&)));
+ connect(d_fft_win_combo, SIGNAL(currentIndexChanged(const QString&)),
+ d_parent, SLOT(notifyFFTWindow(const QString&)));
+}
+
+FreqControlPanel::~FreqControlPanel()
+{
+ removeWidget(d_axes_box);
+ removeWidget(d_trace_box);
+ delete d_axes_box;
+ delete d_trace_box;
+
+ // All other children of the boxes are automatically deleted.
+}
+
+void
+FreqControlPanel::toggleGrid(bool en)
+{
+ d_grid_check->setChecked(en);
+}
+
+void
+FreqControlPanel::toggleMaxHold(bool en)
+{
+ d_maxhold_check->setChecked(en);
+}
+
+void
+FreqControlPanel::toggleMinHold(bool en)
+{
+ d_minhold_check->setChecked(en);
+}
+
+void
+FreqControlPanel::notifyAvgSlider(int val)
+{
+ float fval = static_cast<float>(val) / (d_slider_max - d_slider_min);
+ emit signalAvgSlider(fval);
+ emit signalAvg(true);
+}
+
+void
+FreqControlPanel::toggleFFTSize(int val)
+{
+ int index = static_cast<int>(logf(static_cast<float>(val))/logf(2.0f)) - 5;
+ d_fft_size_combo->setCurrentIndex(index);
+}
+
+void
+FreqControlPanel::toggleFFTWindow(const gr::filter::firdes::win_type win)
+{
+ if(win == -1)
+ d_fft_win_combo->setCurrentIndex(0);
+ if(win == gr::filter::firdes::WIN_HAMMING)
+ d_fft_win_combo->setCurrentIndex(1);
+ else if(win == gr::filter::firdes::WIN_HANN)
+ d_fft_win_combo->setCurrentIndex(2);
+ else if(win == gr::filter::firdes::WIN_BLACKMAN)
+ d_fft_win_combo->setCurrentIndex(3);
+ else if(win == gr::filter::firdes::WIN_BLACKMAN_hARRIS)
+ d_fft_win_combo->setCurrentIndex(4);
+ else if(win == gr::filter::firdes::WIN_RECTANGULAR)
+ d_fft_win_combo->setCurrentIndex(5);
+ else if(win == gr::filter::firdes::WIN_KAISER)
+ d_fft_win_combo->setCurrentIndex(6);
+ else if(win == gr::filter::firdes::WIN_FLATTOP)
+ d_fft_win_combo->setCurrentIndex(7);
+}
diff --git a/gr-qtgui/lib/freqdisplayform.cc b/gr-qtgui/lib/freqdisplayform.cc
index d7fa156..bdd3a0d 100644
--- a/gr-qtgui/lib/freqdisplayform.cc
+++ b/gr-qtgui/lib/freqdisplayform.cc
@@ -22,7 +22,9 @@
#include <cmath>
#include <QMessageBox>
+#include <QSpacerItem>
#include <gnuradio/qtgui/freqdisplayform.h>
+#include <gnuradio/qtgui/freqcontrolpanel.h>
#include <iostream>
FreqDisplayForm::FreqDisplayForm(int nplots, QWidget* parent)
@@ -34,8 +36,12 @@ FreqDisplayForm::FreqDisplayForm(int nplots, QWidget* parent)
d_layout = new QGridLayout(this);
d_display_plot = new FrequencyDisplayPlot(nplots, this);
d_layout->addWidget(d_display_plot, 0, 0);
+
+ d_layout->setColumnStretch(0, 1);
setLayout(d_layout);
+ d_controlpanel = NULL;
+
d_num_real_data_points = 1024;
d_fftsize = 1024;
d_fftavg = 1.0;
@@ -65,14 +71,16 @@ FreqDisplayForm::FreqDisplayForm(int nplots, QWidget*
parent)
connect(minymenu, SIGNAL(whichTrigger(QString)),
this, SLOT(setYMin(QString)));
- d_clearmax_act = new QAction("Clear Max", this);
- d_menu->addAction(d_clearmax_act);
- connect(d_clearmax_act, SIGNAL(triggered()),
- this, SLOT(clearMaxHold()));
- d_clearmin_act = new QAction("Clear Min", this);
- d_menu->addAction(d_clearmin_act);
- connect(d_clearmin_act, SIGNAL(triggered()),
- this, SLOT(clearMinHold()));
+ d_maxhold_act = new QAction("Max Hold", this);
+ d_maxhold_act->setCheckable(true);
+ d_menu->addAction(d_maxhold_act);
+ connect(d_maxhold_act, SIGNAL(triggered(bool)),
+ this, SLOT(notifyMaxHold(bool)));
+ d_minhold_act = new QAction("Min Hold", this);
+ d_minhold_act->setCheckable(true);
+ d_menu->addAction(d_minhold_act);
+ connect(d_minhold_act, SIGNAL(triggered(bool)),
+ this, SLOT(notifyMinHold(bool)));
// Set up the trigger menu
d_triggermenu = new QMenu("Trigger", this);
@@ -86,6 +94,12 @@ FreqDisplayForm::FreqDisplayForm(int nplots, QWidget* parent)
d_triggermenu->addAction(d_tr_tag_key_act);
d_menu->addMenu(d_triggermenu);
+ d_controlpanelmenu = new QAction("Control Panel", this);
+ d_controlpanelmenu->setCheckable(true);
+ d_menu->addAction(d_controlpanelmenu);
+ connect(d_controlpanelmenu, SIGNAL(triggered(bool)),
+ this, SLOT(setupControlPanel(bool)));
+
setTriggerMode(gr::qtgui::TRIG_MODE_FREE);
connect(d_tr_mode_menu, SIGNAL(whichTrigger(gr::qtgui::trigger_mode)),
this, SLOT(setTriggerMode(gr::qtgui::trigger_mode)));
@@ -105,10 +119,22 @@ FreqDisplayForm::FreqDisplayForm(int nplots, QWidget*
parent)
connect(d_tr_tag_key_act, SIGNAL(whichTrigger(QString)),
this, SLOT(setTriggerTagKey(QString)));
+ connect(this, SIGNAL(signalClearMaxData()),
+ getPlot(), SLOT(clearMaxData()));
+ connect(this, SIGNAL(signalClearMinData()),
+ getPlot(), SLOT(clearMinData()));
+ connect(this, SIGNAL(signalSetMaxFFTVisible(bool)),
+ getPlot(), SLOT(setMaxFFTVisible(bool)));
+ connect(this, SIGNAL(signalSetMinFFTVisible(bool)),
+ getPlot(), SLOT(setMinFFTVisible(bool)));
+
Reset();
connect(d_display_plot, SIGNAL(plotPointSelected(const QPointF)),
this, SLOT(onPlotPointSelected(const QPointF)));
+
+ connect(this, SIGNAL(signalReplot()),
+ getPlot(), SLOT(replot()));
}
FreqDisplayForm::~FreqDisplayForm()
@@ -117,6 +143,64 @@ FreqDisplayForm::~FreqDisplayForm()
// Don't worry about deleting Display Plots - they are deleted when parents
are deleted
delete d_int_validator;
+
+ teardownControlPanel();
+}
+
+void
+FreqDisplayForm::setupControlPanel(bool en)
+{
+ if(en) {
+ setupControlPanel();
+ }
+ else {
+ teardownControlPanel();
+ }
+}
+
+void
+FreqDisplayForm::setupControlPanel()
+{
+ if(d_controlpanel)
+ delete d_controlpanel;
+
+ // Create the control panel layout
+ d_controlpanel = new FreqControlPanel(this);
+
+ // Connect action items in menu to controlpanel widgets
+ connect(d_grid_act, SIGNAL(triggered(bool)),
+ d_controlpanel, SLOT(toggleGrid(bool)));
+ connect(d_sizemenu, SIGNAL(whichTrigger(int)),
+ d_controlpanel, SLOT(toggleFFTSize(int)));
+ connect(d_winmenu, SIGNAL(whichTrigger(gr::filter::firdes::win_type)),
+ d_controlpanel, SLOT(toggleFFTWindow(gr::filter::firdes::win_type)));
+ connect(this, SIGNAL(signalFFTSize(int)),
+ d_controlpanel, SLOT(toggleFFTSize(int)));
+ connect(this, SIGNAL(signalFFTWindow(gr::filter::firdes::win_type)),
+ d_controlpanel, SLOT(toggleFFTWindow(gr::filter::firdes::win_type)));
+ connect(d_maxhold_act, SIGNAL(triggered(bool)),
+ d_controlpanel, SLOT(toggleMaxHold(bool)));
+ connect(d_minhold_act, SIGNAL(triggered(bool)),
+ d_controlpanel, SLOT(toggleMinHold(bool)));
+
+ d_layout->addLayout(d_controlpanel, 0, 1);
+
+ d_controlpanel->toggleGrid(d_grid_act->isChecked());
+ d_controlpanelmenu->setChecked(true);
+
+ emit signalFFTSize(getFFTSize());
+ emit signalFFTWindow(getFFTWindowType());
+}
+
+void
+FreqDisplayForm::teardownControlPanel()
+{
+ if(d_controlpanel) {
+ d_layout->removeItem(d_controlpanel);
+ delete d_controlpanel;
+ d_controlpanel = NULL;
+ }
+ d_controlpanelmenu->setChecked(false);
}
FrequencyDisplayPlot*
@@ -177,7 +261,9 @@ FreqDisplayForm::setFFTSize(const int newsize)
{
d_fftsize = newsize;
d_sizemenu->getActionFromSize(newsize)->setChecked(true);
- getPlot()->replot();
+
+ emit signalReplot();
+ emit signalFFTSize(newsize);
}
void
@@ -185,7 +271,8 @@ FreqDisplayForm::setFFTAverage(const float newavg)
{
d_fftavg = newavg;
d_avgmenu->getActionFromAvg(newavg)->setChecked(true);
- getPlot()->replot();
+ emit signalReplot();
+ //emit signalFFTAverage(newavg);
}
void
@@ -193,7 +280,8 @@ FreqDisplayForm::setFFTWindowType(const
gr::filter::firdes::win_type newwin)
{
d_fftwintype = newwin;
d_winmenu->getActionFromWindow(newwin)->setChecked(true);
- getPlot()->replot();
+ emit signalReplot();
+ emit signalFFTWindow(newwin);
}
void
@@ -249,14 +337,21 @@ FreqDisplayForm::autoScale(bool en)
d_autoscale_act->setChecked(en);
getPlot()->setAutoScale(d_autoscale_state);
- getPlot()->replot();
+ emit signalReplot();
+}
+
+void
+FreqDisplayForm::autoScaleShot()
+{
+ getPlot()->setAutoScaleShot();
+ emit signalReplot();
}
void
FreqDisplayForm::setPlotPosHalf(bool half)
{
getPlot()->setPlotPosHalf(half);
- getPlot()->replot();
+ emit signalReplot();
}
void
@@ -376,3 +471,138 @@ FreqDisplayForm::getTriggerTagKey() const
{
return d_trig_tag_key;
}
+
+
+
+/********************************************************************
+ * Notifcation messages from the control panel
+ *******************************************************************/
+
+
+void
+FreqDisplayForm::notifyYAxisPlus()
+{
+#if QWT_VERSION < 0x060100
+ QwtScaleDiv *ax = getPlot()->axisScaleDiv(QwtPlot::yLeft);
+ double range = ax->upperBound() - ax->lowerBound();
+ double step = range/20.0;
+ getPlot()->setYaxis(ax->lowerBound()+step, ax->upperBound()+step);
+
+#else
+
+ QwtScaleDiv ax = getPlot()->axisScaleDiv(QwtPlot::yLeft);
+ double range = ax.upperBound() - ax.lowerBound();
+ double step = range/20.0;
+ getPlot()->setYaxis(ax.lowerBound()+step, ax.upperBound()+step);
+#endif
+}
+
+void
+FreqDisplayForm::notifyYAxisMinus()
+{
+#if QWT_VERSION < 0x060100
+ QwtScaleDiv *ax = getPlot()->axisScaleDiv(QwtPlot::yLeft);
+ double range = ax->upperBound() - ax->lowerBound();
+ double step = range/20.0;
+ getPlot()->setYaxis(ax->lowerBound()-step, ax->upperBound()-step);
+
+#else
+
+ QwtScaleDiv ax = getPlot()->axisScaleDiv(QwtPlot::yLeft);
+ double range = ax.upperBound() - ax.lowerBound();
+ double step = range/20.0;
+ getPlot()->setYaxis(ax.lowerBound()-step, ax.upperBound()-step);
+#endif
+}
+
+void
+FreqDisplayForm::notifyYRangePlus()
+{
+#if QWT_VERSION < 0x060100
+ QwtScaleDiv *ax = getPlot()->axisScaleDiv(QwtPlot::yLeft);
+ double range = ax->upperBound() - ax->lowerBound();
+ double step = range/20.0;
+ getPlot()->setYaxis(ax->lowerBound()-step, ax->upperBound()+step);
+
+#else
+
+ QwtScaleDiv ax = getPlot()->axisScaleDiv(QwtPlot::yLeft);
+ double range = ax.upperBound() - ax.lowerBound();
+ double step = range/20.0;
+ getPlot()->setYaxis(ax.lowerBound()-step, ax.upperBound()+step);
+#endif
+}
+
+void
+FreqDisplayForm::notifyYRangeMinus()
+{
+#if QWT_VERSION < 0x060100
+ QwtScaleDiv *ax = getPlot()->axisScaleDiv(QwtPlot::yLeft);
+ double range = ax->upperBound() - ax->lowerBound();
+ double step = range/20.0;
+ getPlot()->setYaxis(ax->lowerBound()+step, ax->upperBound()-step);
+
+#else
+
+ QwtScaleDiv ax = getPlot()->axisScaleDiv(QwtPlot::yLeft);
+ double range = ax.upperBound() - ax.lowerBound();
+ double step = range/20.0;
+ getPlot()->setYaxis(ax.lowerBound()+step, ax.upperBound()-step);
+#endif
+}
+
+
+void
+FreqDisplayForm::notifyFFTSize(const QString &s)
+{
+ setFFTSize(s.toInt());
+}
+
+void
+FreqDisplayForm::notifyFFTWindow(const QString &s)
+{
+ if(s == "None") {
+ d_fftwintype = gr::filter::firdes::WIN_NONE;
+ }
+ else if(s == "Hamming") {
+ d_fftwintype = gr::filter::firdes::WIN_HAMMING;
+ }
+ else if(s == "Hann") {
+ d_fftwintype = gr::filter::firdes::WIN_HANN;
+ }
+ else if(s == "Blackman") {
+ d_fftwintype = gr::filter::firdes::WIN_BLACKMAN;
+ }
+ else if(s == "Blackman-harris") {
+ d_fftwintype = gr::filter::firdes::WIN_BLACKMAN_hARRIS;
+ }
+ else if(s == "Rectangular") {
+ d_fftwintype = gr::filter::firdes::WIN_RECTANGULAR;
+ }
+ else if(s == "Kaiser") {
+ d_fftwintype = gr::filter::firdes::WIN_KAISER;
+ }
+ else if(s == "Flat-top") {
+ d_fftwintype = gr::filter::firdes::WIN_FLATTOP;
+ }
+
+ d_winmenu->getActionFromWindow(d_fftwintype)->setChecked(true);
+ emit signalReplot();
+}
+
+
+void
+FreqDisplayForm::notifyMaxHold(bool en)
+{
+ d_maxhold_act->setChecked(en);
+ emit signalClearMaxData();
+ emit signalSetMaxFFTVisible(en);
+}
+
+void
+FreqDisplayForm::notifyMinHold(bool en)
+{
+ d_minhold_act->setChecked(en);
+ emit signalClearMinData();
+ emit signalSetMinFFTVisible(en);
+}
- [Commit-gnuradio] [gnuradio] branch master updated (cce2347 -> 93c25bc), git, 2015/04/06
- [Commit-gnuradio] [gnuradio] 04/08: qtgui: fixed an issue setting up control panel at runtime., git, 2015/04/06
- [Commit-gnuradio] [gnuradio] 06/08: qtgui: fixed stray variable; also problem between qwt 6.0 and 6.1., git, 2015/04/06
- [Commit-gnuradio] [gnuradio] 07/08: qtgui: added stop button to freq control panel., git, 2015/04/06
- [Commit-gnuradio] [gnuradio] 02/08: qtgui: toggle legend off in GRC properties., git, 2015/04/06
- [Commit-gnuradio] [gnuradio] 05/08: qtgui: enable/disable waterfall legend., git, 2015/04/06
- [Commit-gnuradio] [gnuradio] 03/08: qtgui: added trigger line and controlpanel settings., git, 2015/04/06
- [Commit-gnuradio] [gnuradio] 08/08: Merge remote-tracking branch 'tom/qtgui/freq_control_panel', git, 2015/04/06
- [Commit-gnuradio] [gnuradio] 01/08: qtgui: adds control panel to frequency sinks.,
git <=