summaryrefslogtreecommitdiff
path: root/gr-qtgui/lib
diff options
context:
space:
mode:
authorTom Rondeau <tom@trondeau.com>2014-03-10 23:52:21 -0400
committerTom Rondeau <tom@trondeau.com>2014-03-14 18:23:16 +0100
commit7d4c52b4e98ff02ac3bc73a5e543ad7dfb26e69b (patch)
tree7dedefb7b1a9ee80553ce5cb6a44793e84d97b87 /gr-qtgui/lib
parent5568d1e1ca12f0d002541b8cbb68ac558e826a47 (diff)
qtgui: Adding a Number sink with options to set autoscale, layout style, colors, averaging.
Diffstat (limited to 'gr-qtgui/lib')
-rw-r--r--gr-qtgui/lib/CMakeLists.txt5
-rw-r--r--gr-qtgui/lib/NumberDisplayPlot.cc63
-rw-r--r--gr-qtgui/lib/number_sink_impl.cc290
-rw-r--r--gr-qtgui/lib/number_sink_impl.h114
-rw-r--r--gr-qtgui/lib/numberdisplayform.cc375
-rw-r--r--gr-qtgui/lib/spectrumUpdateEvents.cc22
6 files changed, 869 insertions, 0 deletions
diff --git a/gr-qtgui/lib/CMakeLists.txt b/gr-qtgui/lib/CMakeLists.txt
index afaadb929b..f46fe838a3 100644
--- a/gr-qtgui/lib/CMakeLists.txt
+++ b/gr-qtgui/lib/CMakeLists.txt
@@ -30,6 +30,7 @@ set(qtgui_moc_hdrs
${qtgui_mod_includedir}/constellationdisplayform.h
${qtgui_mod_includedir}/waterfalldisplayform.h
${qtgui_mod_includedir}/histogramdisplayform.h
+ ${qtgui_mod_includedir}/numberdisplayform.h
${qtgui_mod_includedir}/form_menus.h
${qtgui_mod_includedir}/DisplayPlot.h
${qtgui_mod_includedir}/FrequencyDisplayPlot.h
@@ -38,6 +39,7 @@ set(qtgui_moc_hdrs
${qtgui_mod_includedir}/WaterfallDisplayPlot.h
${qtgui_mod_includedir}/ConstellationDisplayPlot.h
${qtgui_mod_includedir}/HistogramDisplayPlot.h
+ ${qtgui_mod_includedir}/NumberDisplayPlot.h
)
QT4_WRAP_CPP(qtgui_moc_srcs ${qtgui_moc_hdrs})
QT4_WRAP_UI(qtgui_ui_hdrs spectrumdisplayform.ui)
@@ -68,6 +70,8 @@ set(qtgui_srcs
freqdisplayform.cc
constellationdisplayform.cc
histogramdisplayform.cc
+ NumberDisplayPlot.cc
+ numberdisplayform.cc
waterfalldisplayform.cc
SpectrumGUIClass.cc
spectrumUpdateEvents.cc
@@ -85,6 +89,7 @@ set(qtgui_srcs
waterfall_sink_c_impl.cc
waterfall_sink_f_impl.cc
histogram_sink_f_impl.cc
+ number_sink_impl.cc
qtgui_util.cc
)
diff --git a/gr-qtgui/lib/NumberDisplayPlot.cc b/gr-qtgui/lib/NumberDisplayPlot.cc
new file mode 100644
index 0000000000..b1fbca9ded
--- /dev/null
+++ b/gr-qtgui/lib/NumberDisplayPlot.cc
@@ -0,0 +1,63 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2014 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 NUMBER_DISPLAY_PLOT_C
+#define NUMBER_DISPLAY_PLOT_C
+
+#include <gnuradio/qtgui/NumberDisplayPlot.h>
+
+#include <qwt_scale_draw.h>
+#include <QColor>
+#include <cmath>
+#include <iostream>
+#include <volk/volk.h>
+
+NumberDisplayPlot::NumberDisplayPlot(int nplots, QWidget* parent)
+ : DisplayPlot(nplots, parent)
+{
+ resize(0, 0);
+
+ // Setup dataPoints and plot vectors
+ // Automatically deleted when parent is deleted
+ for(int i = 0; i < d_nplots; i++) {
+
+ }
+}
+
+NumberDisplayPlot::~NumberDisplayPlot()
+{
+}
+
+void
+NumberDisplayPlot::replot()
+{
+ QwtPlot::replot();
+}
+
+void
+NumberDisplayPlot::plotNewData(const std::vector<double> samples)
+{
+ if(!d_stop) {
+ }
+}
+
+#endif /* NUMBER_DISPLAY_PLOT_C */
diff --git a/gr-qtgui/lib/number_sink_impl.cc b/gr-qtgui/lib/number_sink_impl.cc
new file mode 100644
index 0000000000..faf7ad4a15
--- /dev/null
+++ b/gr-qtgui/lib/number_sink_impl.cc
@@ -0,0 +1,290 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2014 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "number_sink_impl.h"
+#include <gnuradio/io_signature.h>
+#include <string.h>
+#include <volk/volk.h>
+#include <gnuradio/fft/fft.h>
+#include <qwt_symbol.h>
+
+namespace gr {
+ namespace qtgui {
+
+ number_sink::sptr
+ number_sink::make(size_t itemsize,
+ const std::string &name,
+ float average,
+ graph_t graph_type,
+ int nconnections,
+ QWidget *parent)
+ {
+ return gnuradio::get_initial_sptr
+ (new number_sink_impl(itemsize, name, average,
+ graph_type, nconnections, parent));
+ }
+
+ number_sink_impl::number_sink_impl(size_t itemsize,
+ const std::string &name,
+ float average,
+ graph_t graph_type,
+ int nconnections,
+ QWidget *parent)
+ : sync_block("number_sink",
+ io_signature::make(nconnections, nconnections, itemsize),
+ io_signature::make(0, 0, 0)),
+ d_itemsize(itemsize), d_name(name), d_average(average),
+ d_type(graph_type), d_nconnections(nconnections), d_parent(parent),
+ d_avg_value(nconnections), d_iir(nconnections)
+ {
+ for(int n = 0; n < d_nconnections; n++) {
+ d_avg_value[n] = 0;
+ d_iir[n].set_taps(d_average);
+ }
+
+ // Required now for Qt; argc must be greater than 0 and argv
+ // must have at least one valid character. Must be valid through
+ // life of the qApplication:
+ // http://harmattan-dev.nokia.com/docs/library/html/qt4/qapplication.html
+ d_argc = 1;
+ d_argv = new char;
+ d_argv[0] = '\0';
+
+ d_main_gui = NULL;
+
+ // Set alignment properties for VOLK
+ const int alignment_multiple =
+ volk_get_alignment() / d_itemsize;
+ set_alignment(std::max(1,alignment_multiple));
+
+ initialize();
+ }
+
+ number_sink_impl::~number_sink_impl()
+ {
+ //if(!d_main_gui->isClosed())
+ // d_main_gui->close();
+
+ delete d_argv;
+ }
+
+ bool
+ number_sink_impl::check_topology(int ninputs, int noutputs)
+ {
+ return ninputs == d_nconnections;
+ }
+
+ void
+ number_sink_impl::initialize()
+ {
+ if(qApp != NULL) {
+ d_qApplication = qApp;
+ }
+ else {
+ d_qApplication = new QApplication(d_argc, &d_argv);
+ }
+
+ d_main_gui = new NumberDisplayForm(d_nconnections, d_type, d_parent);
+
+ // initialize update time to 10 times a second
+ set_update_time(0.1);
+ }
+
+ void
+ number_sink_impl::exec_()
+ {
+ d_qApplication->exec();
+ }
+
+ QWidget*
+ number_sink_impl::qwidget()
+ {
+ return d_main_gui;
+ }
+
+#ifdef ENABLE_PYTHON
+ PyObject*
+ number_sink_impl::pyqwidget()
+ {
+ PyObject *w = PyLong_FromVoidPtr((void*)d_main_gui);
+ PyObject *retarg = Py_BuildValue("N", w);
+ return retarg;
+ }
+#endif
+
+ void
+ number_sink_impl::set_update_time(double t)
+ {
+ //convert update time to ticks
+ gr::high_res_timer_type tps = gr::high_res_timer_tps();
+ d_main_gui->setUpdateTime(t);
+ d_update_time = t * tps;
+ d_last_time = 0;
+ }
+
+ void
+ number_sink_impl::set_title(const std::string &title)
+ {
+ //d_main_gui->setTitle(title.c_str());
+ }
+
+ void
+ number_sink_impl::set_average(const float avg)
+ {
+ d_average = avg;
+ for(int n = 0; n < d_nconnections; n++) {
+ d_avg_value[n] = 0;
+ d_iir[n].set_taps(d_average);
+ }
+ }
+
+ void
+ number_sink_impl::set_graph_type(const graph_t type)
+ {
+ d_main_gui->setGraphType(type);
+ }
+
+ void
+ number_sink_impl::set_color(int which,
+ const std::string &min,
+ const std::string &max)
+ {
+ d_main_gui->setColor(which,
+ QColor(min.c_str()),
+ QColor(max.c_str()));
+ }
+
+ void
+ number_sink_impl::set_color(int which, int min, int max)
+ {
+ d_main_gui->setColor(which, QColor(min), QColor(max));
+ }
+
+ void
+ number_sink_impl::set_label(int which, const std::string &label)
+ {
+ d_main_gui->setLabel(which, label);
+ }
+
+ std::string
+ number_sink_impl::title()
+ {
+ //return d_main_gui->title().toStdString();
+ return "";
+ }
+
+ float
+ number_sink_impl::average() const
+ {
+ return d_average;
+ }
+
+ graph_t
+ number_sink_impl::graph_type() const
+ {
+ return d_main_gui->graphType();
+ }
+
+ std::string
+ number_sink_impl::color_min() const
+ {
+ //return d_main_gui->colorMin();
+ return "min color";
+ }
+
+ std::string
+ number_sink_impl::color_max() const
+ {
+ return d_main_gui->colorMax().name().toStdString();
+ }
+
+ std::string
+ number_sink_impl::label(int which) const
+ {
+ return d_main_gui->label(which);
+ }
+
+ void
+ number_sink_impl::enable_menu(bool en)
+ {
+ //d_main_gui->enableMenu(en);
+ }
+
+ void
+ number_sink_impl::reset()
+ {
+ gr::thread::scoped_lock lock(d_mutex);
+ _reset();
+ }
+
+ void
+ number_sink_impl::_reset()
+ {
+ }
+
+ int
+ number_sink_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ gr::thread::scoped_lock lock(d_mutex);
+
+ float new_avg = d_main_gui->average();
+ set_update_time(d_main_gui->updateTime());
+ if(new_avg != d_average) {
+ set_average(new_avg);
+ }
+
+ if(d_average > 0) {
+ for(int n = 0; n < d_nconnections; n++) {
+ float *in = (float*)input_items[n];
+ for(int i = 0; i < noutput_items; i++) {
+ d_avg_value[n] = d_iir[n].filter(in[i]);
+ }
+ }
+ }
+
+ // Plot if we are able to update
+ if(gr::high_res_timer_now() - d_last_time > d_update_time) {
+ d_last_time = gr::high_res_timer_now();
+ std::vector<float> d(d_nconnections);
+ if(d_average > 0) {
+ for(int n = 0; n < d_nconnections; n++)
+ d[n] = d_avg_value[n];
+ }
+ else {
+ for(int n = 0; n < d_nconnections; n++)
+ d[n] = ((float*)input_items[n])[0];
+ }
+ d_qApplication->postEvent(d_main_gui,
+ new NumberUpdateEvent(d));
+ }
+
+ return noutput_items;;
+ }
+
+ } /* namespace qtgui */
+} /* namespace gr */
diff --git a/gr-qtgui/lib/number_sink_impl.h b/gr-qtgui/lib/number_sink_impl.h
new file mode 100644
index 0000000000..c453923a17
--- /dev/null
+++ b/gr-qtgui/lib/number_sink_impl.h
@@ -0,0 +1,114 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2014 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 INCLUDED_QTGUI_NUMBER_SINK_IMPL_H
+#define INCLUDED_QTGUI_NUMBER_SINK_IMPL_H
+
+#include <gnuradio/qtgui/number_sink.h>
+#include <gnuradio/qtgui/numberdisplayform.h>
+#include <gnuradio/filter/single_pole_iir.h>
+#include <gnuradio/thread/thread.h>
+#include <gnuradio/high_res_timer.h>
+
+namespace gr {
+ namespace qtgui {
+
+ class QTGUI_API number_sink_impl : public number_sink
+ {
+ private:
+ void initialize();
+
+ gr::thread::mutex d_mutex;
+
+ size_t d_itemsize;
+ std::string d_name;
+ float d_average;
+ graph_t d_type;
+ int d_nconnections;
+
+ int d_index, d_start, d_end;
+ std::vector<double*> d_buffers;
+ std::vector< std::vector<gr::tag_t> > d_tags;
+
+ int d_argc;
+ char *d_argv;
+ QWidget *d_parent;
+ NumberDisplayForm *d_main_gui;
+
+ std::vector<float> d_avg_value;
+ std::vector<filter::single_pole_iir<float,float,float> > d_iir;
+
+ gr::high_res_timer_type d_update_time;
+ gr::high_res_timer_type d_last_time;
+
+ void _reset();
+ void _npoints_resize();
+ void _gui_update_trigger();
+
+ public:
+ number_sink_impl(size_t itemsize,
+ const std::string &name,
+ float average=0,
+ graph_t graph_type=NUM_GRAPH_HORIZ,
+ int nconnections=1,
+ QWidget *parent=NULL);
+ ~number_sink_impl();
+
+ bool check_topology(int ninputs, int noutputs);
+
+ void exec_();
+ QWidget* qwidget();
+
+#ifdef ENABLE_PYTHON
+ PyObject* pyqwidget();
+#endif
+
+ void set_update_time(double t);
+ void set_title(const std::string &title);
+ void set_average(const float avg);
+ void set_graph_type(const graph_t type);
+ void set_color(int which,
+ const std::string &min,
+ const std::string &max);
+ void set_color(int which, int min, int max);
+ void set_label(int which, const std::string &label);
+
+ std::string title();
+ float average() const;
+ graph_t graph_type() const;
+ std::string color_min() const;
+ std::string color_max() const;
+ std::string label(int which) const;
+
+ void enable_menu(bool en);
+
+ void reset();
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace qtgui */
+} /* namespace gr */
+
+#endif /* INCLUDED_QTGUI_NUMBER_SINK_IMPL_H */
diff --git a/gr-qtgui/lib/numberdisplayform.cc b/gr-qtgui/lib/numberdisplayform.cc
new file mode 100644
index 0000000000..d22acd0e60
--- /dev/null
+++ b/gr-qtgui/lib/numberdisplayform.cc
@@ -0,0 +1,375 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2014 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 <cmath>
+#include <QMessageBox>
+#include <gnuradio/qtgui/numberdisplayform.h>
+#include <iostream>
+#include <qwt_color_map.h>
+
+NumberDisplayForm::NumberDisplayForm(int nplots, gr::qtgui::graph_t type,
+ QWidget* parent)
+ : QWidget(parent)
+{
+ d_nplots = nplots;
+ d_layout = new QGridLayout(this);
+ for(int i = 0; i < d_nplots; i++) {
+ d_min.push_back(+1e32);
+ d_max.push_back(-1e32);
+ d_label.push_back(new QLabel(QString("Data %1").arg(i)));
+ d_text_box.push_back(new QLabel(QString("0")));
+
+ d_indicator.push_back(new QwtThermo());
+ d_indicator[i]->setScale(-1, 1);
+ d_indicator[i]->setOriginMode(QwtThermo::OriginCustom);
+ d_indicator[i]->setOrigin(0.0);
+
+ switch(type) {
+ case(gr::qtgui::NUM_GRAPH_HORIZ):
+ d_indicator[i]->setOrientation(Qt::Horizontal);
+ d_layout->addWidget(d_label[i], 2*i, 0);
+ d_layout->addWidget(d_text_box[i], 2*i, 1);
+ d_layout->addWidget(d_indicator[i], 2*i+1, 1);
+ break;
+ case(gr::qtgui::NUM_GRAPH_VERT):
+ d_indicator[i]->setOrientation(Qt::Vertical);
+ d_layout->addWidget(d_label[i], 0, i);
+ d_layout->addWidget(d_text_box[i], 1, i);
+ d_layout->addWidget(d_indicator[i], 2, i);
+ break;
+ case(gr::qtgui::NUM_GRAPH_NONE):
+ default:
+ d_layout->addWidget(d_label[i], 0, i);
+ d_layout->addWidget(d_text_box[i], 1, i);
+ }
+
+ setColor(i, QColor("black"), QColor("black"));
+ }
+
+ d_avg = 0.0;
+ d_update_time = 0.1;
+
+ d_menu_on = true;
+ d_menu = new QMenu(this);
+
+ // Create a set of actions for the menu
+ d_stop_act = new QAction("Stop", this);
+ d_stop_act->setStatusTip(tr("Start/Stop"));
+ connect(d_stop_act, SIGNAL(triggered()), this, SLOT(setStop()));
+ d_stop_state = false;
+ d_menu->addAction(d_stop_act);
+
+ // Menu items for each number line
+ for(int i = 0; i < d_nplots; i++) {
+ d_label_act.push_back(new LineTitleAction(i, this));
+ connect(d_label_act[i], SIGNAL(whichTrigger(int, const QString&)),
+ this, SLOT(setLabel(int, const QString&)));
+
+ d_label_menu.push_back(new QMenu(tr(""), this));
+ d_label_menu[i]->addAction(d_label_act[i]);
+
+ d_color_menu.push_back(new NumberColorMapMenu(i, this));
+ connect(d_color_menu[i], SIGNAL(whichTrigger(int, const QColor&, const QColor&)),
+ this, SLOT(setColor(int, const QColor&, const QColor&)));
+ d_label_menu[i]->addMenu(d_color_menu[i]);
+
+ d_menu->addMenu(d_label_menu[i]);
+ }
+
+ d_avg_menu = new FFTAverageMenu(this);
+ d_avg_menu->setTitle("Average");
+ d_avg_menu->setHigh(0.001);
+ d_avg_menu->setMedium(0.01);
+ d_avg_menu->setLow(0.1);
+ connect(d_avg_menu, SIGNAL(whichTrigger(float)),
+ this, SLOT(setAverage(const float)));
+ d_menu->addMenu(d_avg_menu);
+
+ d_layout_menu = new NumberLayoutMenu(this);
+ connect(d_layout_menu, SIGNAL(whichTrigger(gr::qtgui::graph_t)),
+ this, SLOT(setGraphType(const gr::qtgui::graph_t)));
+ d_menu->addMenu(d_layout_menu);
+
+ d_autoscale_act = new QAction("Auto Scale", this);
+ d_autoscale_act->setCheckable(true);
+ connect(d_autoscale_act, SIGNAL(triggered(bool)),
+ this, SLOT(autoScale(bool)));
+ d_autoscale_state = false;
+ d_menu->addAction(d_autoscale_act);
+
+ d_update_time_menu = new PopupMenu("Update Time", this);
+ connect(d_update_time_menu, SIGNAL(whichTrigger(QString)),
+ this, SLOT(setUpdateTime(QString)));
+ d_menu->addAction(d_update_time_menu);
+
+ d_save_act = new QAction("Save", this);
+ d_save_act->setStatusTip(tr("Save Figure"));
+ connect(d_save_act, SIGNAL(triggered()), this, SLOT(saveFigure()));
+ d_menu->addAction(d_save_act);
+
+ setLayout(d_layout);
+}
+
+NumberDisplayForm::~NumberDisplayForm()
+{
+ // Qt deletes children when parent is deleted
+}
+
+void
+NumberDisplayForm::mousePressEvent(QMouseEvent * e)
+{
+ bool ctrloff = Qt::ControlModifier != QApplication::keyboardModifiers();
+ if((e->button() == Qt::MidButton) && ctrloff && (d_menu_on)) {
+ if(d_stop_state == false)
+ d_stop_act->setText(tr("Stop"));
+ else
+ d_stop_act->setText(tr("Start"));
+
+ // Update the line titles if changed externally
+ for(int i = 0; i < d_nplots; i++) {
+ d_label_menu[i]->setTitle(label(i).c_str());
+ }
+ d_menu->exec(e->globalPos());
+ }
+}
+
+void
+NumberDisplayForm::setStop(bool on)
+{
+ if(!on) {
+ d_stop_state = false;
+ }
+ else {
+ d_stop_state = true;
+ }
+}
+
+void
+NumberDisplayForm::setStop()
+{
+ if(d_stop_state == false)
+ setStop(true);
+ else
+ setStop(false);
+}
+
+void
+NumberDisplayForm::saveFigure()
+{
+ QPixmap qpix = QPixmap::grabWidget(this);
+
+ QString types = QString(tr("JPEG file (*.jpg);;Portable Network Graphics file (*.png);;Bitmap file (*.bmp);;TIFF file (*.tiff)"));
+
+ QString filename, filetype;
+ QFileDialog *filebox = new QFileDialog(0, "Save Image", "./", types);
+ filebox->setViewMode(QFileDialog::Detail);
+ if(filebox->exec()) {
+ filename = filebox->selectedFiles()[0];
+ filetype = filebox->selectedNameFilter();
+ }
+ else {
+ return;
+ }
+
+ if(filetype.contains(".jpg")) {
+ qpix.save(filename, "JPEG");
+ }
+ else if(filetype.contains(".png")) {
+ qpix.save(filename, "PNG");
+ }
+ else if(filetype.contains(".bmp")) {
+ qpix.save(filename, "BMP");
+ }
+ else if(filetype.contains(".tiff")) {
+ qpix.save(filename, "TIFF");
+ }
+ else {
+ qpix.save(filename, "JPEG");
+ }
+
+ delete filebox;
+}
+
+void
+NumberDisplayForm::newData(const QEvent* updateEvent)
+{
+ if(!d_stop_state) {
+ NumberUpdateEvent *tevent = (NumberUpdateEvent*)updateEvent;
+ const std::vector<float> samples = tevent->getSamples();
+
+ for(int i = 0; i < d_nplots; i++) {
+ d_text_box[i]->setText(QString("%1").arg(samples[i], 4, ' '));
+ d_indicator[i]->setValue(samples[i]);
+ d_min[i] = std::min(d_min[i], samples[i]);
+ d_max[i] = std::max(d_max[i], samples[i]);
+
+ if(d_autoscale_state) {
+ //d_indicator[i]->setRange(d_min[i], d_max[i], false);
+ d_indicator[i]->setScale(d_min[i], d_max[i]);
+ }
+ }
+
+ }
+}
+
+void
+NumberDisplayForm::customEvent(QEvent * e)
+{
+ if(e->type() == NumberUpdateEvent::Type()) {
+ newData(e);
+ }
+}
+
+void
+NumberDisplayForm::setGraphType(const gr::qtgui::graph_t type)
+{
+ d_graph_type = type;
+ for(int i = 0; i < d_nplots; i++) {
+ d_layout->removeWidget(d_indicator[i]);
+ d_layout->removeWidget(d_label[i]);
+ d_layout->removeWidget(d_text_box[i]);
+
+ switch(d_graph_type) {
+ case(gr::qtgui::NUM_GRAPH_HORIZ):
+ d_indicator[i]->setOrientation(Qt::Horizontal);
+ d_indicator[i]->setVisible(true);
+ d_layout->addWidget(d_label[i], 2*i, 0);
+ d_layout->addWidget(d_text_box[i], 2*i, 1);
+ d_layout->addWidget(d_indicator[i], 2*i+1, 1);
+ break;
+ case(gr::qtgui::NUM_GRAPH_VERT):
+ d_indicator[i]->setOrientation(Qt::Vertical);
+ d_indicator[i]->setVisible(true);
+ d_layout->addWidget(d_label[i], 0, i);
+ d_layout->addWidget(d_text_box[i], 1, i);
+ d_layout->addWidget(d_indicator[i], 2, i);
+ break;
+ case(gr::qtgui::NUM_GRAPH_NONE):
+ default:
+ d_indicator[i]->setVisible(false);
+ d_layout->addWidget(d_label[i], 0, i);
+ d_layout->addWidget(d_text_box[i], 1, i);
+ break;
+ }
+ }
+
+}
+
+void
+NumberDisplayForm::setColor(int which, const QColor &min, const QColor &max)
+{
+ QwtLinearColorMap *map = new QwtLinearColorMap();
+ map->setColorInterval(min, max);
+ d_indicator[which]->setColorMap(map);
+}
+
+void
+NumberDisplayForm::setColorMin(int which, QString min)
+{
+ setColor(which, QColor(min), colorMax());
+}
+
+void
+NumberDisplayForm::setColorMax(int which, QString max)
+{
+ setColor(which, colorMin(), QColor(max));
+}
+
+void
+NumberDisplayForm::setLabel(int which, const std::string &label)
+{
+ d_label[which]->setText(label.c_str());
+}
+
+void
+NumberDisplayForm::setLabel(int which, QString label)
+{
+ d_label[which]->setText(label);
+}
+
+void
+NumberDisplayForm::setAverage(const float avg)
+{
+ d_avg = avg;
+}
+
+void
+NumberDisplayForm::setUpdateTime(const float time)
+{
+ d_update_time = time;
+}
+
+void
+NumberDisplayForm::setUpdateTime(QString time)
+{
+ setUpdateTime(time.toFloat());
+}
+
+gr::qtgui::graph_t
+NumberDisplayForm::graphType() const
+{
+ return d_graph_type;
+}
+
+QColor
+NumberDisplayForm::colorMin() const
+{
+ QwtLinearColorMap *map = static_cast<QwtLinearColorMap*>(d_indicator[0]->colorMap());
+ return map->color1();
+}
+
+QColor
+NumberDisplayForm::colorMax() const
+{
+ QwtLinearColorMap *map = static_cast<QwtLinearColorMap*>(d_indicator[0]->colorMap());
+ return map->color2();
+}
+
+std::string
+NumberDisplayForm::label(int which) const
+{
+ return d_label[which]->text().toStdString();
+}
+
+float
+NumberDisplayForm::average() const
+{
+ return d_avg;
+}
+
+float
+NumberDisplayForm::updateTime() const
+{
+ return d_update_time;
+}
+
+void
+NumberDisplayForm::autoScale(bool on)
+{
+ d_autoscale_state = on;
+
+ // Reset the autoscale limits
+ for(int i = 0; i < d_nplots; i++) {
+ d_min.push_back(+1e32);
+ d_max.push_back(-1e32);
+ }
+}
diff --git a/gr-qtgui/lib/spectrumUpdateEvents.cc b/gr-qtgui/lib/spectrumUpdateEvents.cc
index 8c822efb4f..f48e079861 100644
--- a/gr-qtgui/lib/spectrumUpdateEvents.cc
+++ b/gr-qtgui/lib/spectrumUpdateEvents.cc
@@ -490,4 +490,26 @@ HistogramUpdateEvent::getNumDataPoints() const
}
+
+/***************************************************************************/
+
+
+NumberUpdateEvent::NumberUpdateEvent(const std::vector<float> samples)
+ : QEvent(QEvent::Type(SpectrumUpdateEventType))
+{
+ _samples = samples;
+ _nplots = samples.size();
+}
+
+NumberUpdateEvent::~NumberUpdateEvent()
+{
+}
+
+const std::vector<float>
+NumberUpdateEvent::getSamples() const
+{
+ return _samples;
+}
+
+
#endif /* SPECTRUM_UPDATE_EVENTS_C */