commit-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Commit-gnuradio] [gnuradio] 06/24: qtgui: Adding a Number sink with opt


From: git
Subject: [Commit-gnuradio] [gnuradio] 06/24: qtgui: Adding a Number sink with options to set autoscale, layout style, colors, averaging.
Date: Tue, 18 Mar 2014 17:51:40 +0000 (UTC)

This is an automated email from the git hooks/post-receive script.

trondeau pushed a commit to branch master
in repository gnuradio.

commit 7d4c52b4e98ff02ac3bc73a5e543ad7dfb26e69b
Author: Tom Rondeau <address@hidden>
Date:   Mon Mar 10 23:52:21 2014 -0400

    qtgui: Adding a Number sink with options to set autoscale, layout style, 
colors, averaging.
---
 gr-qtgui/grc/qtgui_block_tree.xml                  |   9 +-
 gr-qtgui/grc/qtgui_number_sink.xml                 | 118 +++++++
 gr-qtgui/include/gnuradio/qtgui/CMakeLists.txt     |   3 +
 gr-qtgui/include/gnuradio/qtgui/DisplayPlot.h      |   3 +-
 .../include/gnuradio/qtgui/NumberDisplayPlot.h     |  54 +++
 gr-qtgui/include/gnuradio/qtgui/form_menus.h       | 210 ++++++++++--
 gr-qtgui/include/gnuradio/qtgui/number_sink.h      | 110 ++++++
 .../include/gnuradio/qtgui/numberdisplayform.h     | 101 ++++++
 .../include/gnuradio/qtgui/spectrumUpdateEvents.h  |  26 +-
 gr-qtgui/lib/CMakeLists.txt                        |   5 +
 gr-qtgui/lib/NumberDisplayPlot.cc                  |  63 ++++
 gr-qtgui/lib/number_sink_impl.cc                   | 290 ++++++++++++++++
 gr-qtgui/lib/number_sink_impl.h                    | 114 +++++++
 gr-qtgui/lib/numberdisplayform.cc                  | 375 +++++++++++++++++++++
 gr-qtgui/lib/spectrumUpdateEvents.cc               |  22 ++
 gr-qtgui/swig/qtgui_swig.i                         |   3 +
 16 files changed, 1481 insertions(+), 25 deletions(-)

diff --git a/gr-qtgui/grc/qtgui_block_tree.xml 
b/gr-qtgui/grc/qtgui_block_tree.xml
index 14516df..2fc1b03 100644
--- a/gr-qtgui/grc/qtgui_block_tree.xml
+++ b/gr-qtgui/grc/qtgui_block_tree.xml
@@ -2,19 +2,19 @@
 
 <!--
  Copyright 2012-2013 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,
@@ -38,6 +38,7 @@
       <block>qtgui_waterfall_sink_x</block>
       <block>qtgui_time_raster_sink_x</block>
       <block>qtgui_histogram_sink_x</block>
+      <block>qtgui_number_sink</block>
       <block>qtgui_sink_x</block>
     </cat>
   </cat>
diff --git a/gr-qtgui/grc/qtgui_number_sink.xml 
b/gr-qtgui/grc/qtgui_number_sink.xml
new file mode 100644
index 0000000..4471d70
--- /dev/null
+++ b/gr-qtgui/grc/qtgui_number_sink.xml
@@ -0,0 +1,118 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##QT GUI Number Sink
+###################################################
+ -->
+<block>
+  <name>QT GUI Number Sink</name>
+  <key>qtgui_number_sink</key>
+  <import>from PyQt4 import Qt</import>
+  <import>from gnuradio import qtgui</import>
+  <import>import sip</import>
+  <make>#set $win = 'self._%s_win'%$id
+qtgui.number_sink(
+        $type.size,
+       $name,
+        $avg,
+        $graph_type,
+       $nconnections
+)
+self.$(id).set_update_time($update_time)
+self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget)
+$(gui_hint()($win))</make>
+  <callback>set_update_time($update_time)</callback>
+
+  <param>
+    <name>Input Type</name>
+    <key>type</key>
+    <type>enum</type>
+    <option>
+      <name>Float</name>
+      <key>float</key>
+      <opt>size:gr.sizeof_float</opt>
+    </option>
+    <option>
+      <name>Int</name>
+      <key>int</key>
+      <opt>size:gr.sizeof_int</opt>
+    </option>
+    <option>
+      <name>Short</name>
+      <key>short</key>
+      <opt>size:gr.sizeof_short</opt>
+    </option>
+    <option>
+      <name>Byte</name>
+      <key>byte</key>
+      <opt>size:gr.sizeof_char</opt>
+    </option>
+  </param>
+
+  <param>
+    <name>Name</name>
+    <key>name</key>
+    <value>QT GUI Plot</value>
+    <type>string</type>
+  </param>
+
+  <param>
+    <name>Average</name>
+    <key>avg</key>
+    <value>0</value>
+    <type>float</type>
+  </param>
+
+  <param>
+    <name>Graph Type</name>
+    <key>graph_type</key>
+    <type>enum</type>
+    <option>
+      <name>Horizontal</name>
+      <key>qtgui.NUM_GRAPH_HORIZ</key>
+    </option>
+    <option>
+      <name>Verticle</name>
+      <key>qtgui.NUM_GRAPH_VERT</key>
+    </option>
+    <option>
+      <name>None</name>
+      <key>qtgui.NUM_GRAPH_NONE</key>
+    </option>
+  </param>
+
+  <param>
+    <name>Number of Inputs</name>
+    <key>nconnections</key>
+    <value>1</value>
+    <type>int</type>
+    <hide>part</hide>
+  </param>
+
+  <param>
+    <name>Update Period</name>
+    <key>update_time</key>
+    <value>0.10</value>
+    <type>float</type>
+    <hide>part</hide>
+  </param>
+
+  <param>
+    <name>GUI Hint</name>
+    <key>gui_hint</key>
+    <value></value>
+    <type>gui_hint</type>
+    <hide>part</hide>
+  </param>
+
+  <sink>
+    <name>in</name>
+    <type>$type</type>
+    <nports>$nconnections</nports>
+  </sink>
+  <doc>
+    The GUI hint can be used to position the widget within the application. \
+    The hint is of the form address@hidden: [row, col, row_span, col_span]. \
+    Both the tab specification and the grid position are optional.
+  </doc>
+</block>
diff --git a/gr-qtgui/include/gnuradio/qtgui/CMakeLists.txt 
b/gr-qtgui/include/gnuradio/qtgui/CMakeLists.txt
index 3c6309d..bb0d3cf 100644
--- a/gr-qtgui/include/gnuradio/qtgui/CMakeLists.txt
+++ b/gr-qtgui/include/gnuradio/qtgui/CMakeLists.txt
@@ -36,6 +36,9 @@ install(FILES
   histogram_sink_f.h
   histogramdisplayform.h
   HistogramDisplayPlot.h
+  number_sink.h
+  numberdisplayform.h
+  NumberDisplayPlot.h
   plot_raster.h
   plot_waterfall.h
   qtgui_types.h
diff --git a/gr-qtgui/include/gnuradio/qtgui/DisplayPlot.h 
b/gr-qtgui/include/gnuradio/qtgui/DisplayPlot.h
index 517f69f..73c7440 100644
--- a/gr-qtgui/include/gnuradio/qtgui/DisplayPlot.h
+++ b/gr-qtgui/include/gnuradio/qtgui/DisplayPlot.h
@@ -50,7 +50,8 @@ Q_DECLARE_METATYPE ( QColorList )
  * \brief QWidget base plot to build QTGUI plotting tools.
  * \ingroup qtgui_blk
  */
-class DisplayPlot:public QwtPlot{
+class DisplayPlot:public QwtPlot
+{
   Q_OBJECT
 
   Q_PROPERTY ( QColor line_color1 READ getLineColor1 WRITE setLineColor1 )
diff --git a/gr-qtgui/include/gnuradio/qtgui/NumberDisplayPlot.h 
b/gr-qtgui/include/gnuradio/qtgui/NumberDisplayPlot.h
new file mode 100644
index 0000000..307d806
--- /dev/null
+++ b/gr-qtgui/include/gnuradio/qtgui/NumberDisplayPlot.h
@@ -0,0 +1,54 @@
+/* -*- 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_H
+#define NUMBER_DISPLAY_PLOT_H
+
+#include <stdint.h>
+#include <cstdio>
+#include <vector>
+#include <gnuradio/qtgui/DisplayPlot.h>
+#include <gnuradio/tags.h>
+#include <qwt_plot.h>
+
+/*!
+ * \brief QWidget for displaying number plots.
+ * \ingroup qtgui_blk
+ */
+class NumberDisplayPlot: public DisplayPlot
+{
+  Q_OBJECT
+
+public:
+  NumberDisplayPlot(int nplots, QWidget*);
+  virtual ~NumberDisplayPlot();
+
+  void plotNewData(const std::vector<double> samples);
+
+  void replot();
+
+public slots:
+
+private:
+};
+
+#endif /* NUMBER_DISPLAY_PLOT_H */
diff --git a/gr-qtgui/include/gnuradio/qtgui/form_menus.h 
b/gr-qtgui/include/gnuradio/qtgui/form_menus.h
index e7ebc3a..cbd01e6 100644
--- a/gr-qtgui/include/gnuradio/qtgui/form_menus.h
+++ b/gr-qtgui/include/gnuradio/qtgui/form_menus.h
@@ -32,6 +32,7 @@
 #include <gnuradio/filter/firdes.h>
 #include <gnuradio/qtgui/qtgui_types.h>
 #include <gnuradio/qtgui/trigger_mode.h>
+#include <gnuradio/qtgui/number_sink.h>
 
 class LineColorMenu: public QMenu
 {
@@ -81,7 +82,7 @@ public:
   {
     return d_act.size();
   }
-  
+
   QAction * getAction(int which)
   {
     if(which < d_act.size())
@@ -160,7 +161,7 @@ public:
   {
     return d_act.size();
   }
-  
+
   QAction * getAction(int which)
   {
     if(which < d_act.size())
@@ -229,7 +230,7 @@ public:
   {
     return d_act.size();
   }
-  
+
   QAction * getAction(int which)
   {
     if(which < d_act.size())
@@ -312,7 +313,7 @@ public:
   {
     return d_act.size();
   }
-  
+
   QAction * getAction(int which)
   {
     if(which < d_act.size())
@@ -384,7 +385,7 @@ public:
   {
     return d_act.size();
   }
-  
+
   QAction * getAction(int which)
   {
     if(which < d_act.size())
@@ -441,7 +442,7 @@ public:
 
   ~LineTitleAction()
   {}
-  
+
 signals:
   void whichTrigger(int which, const QString &text);
 
@@ -453,7 +454,7 @@ public slots:
 
 private slots:
   void getText()
-  { 
+  {
     emit whichTrigger(d_which, d_text->text());
     d_diag->accept();
   }
@@ -521,7 +522,7 @@ public slots:
 
 private slots:
   void getText()
-  { 
+  {
     emit whichTrigger(d_text->text());
     d_diag->accept();
   }
@@ -548,7 +549,7 @@ public:
 
     d_text0 = new QLineEdit();
     d_text1 = new QLineEdit();
-    
+
     QLabel *_label0 = new QLabel(label0);
     QLabel *_label1 = new QLabel(label1);
 
@@ -584,7 +585,7 @@ public slots:
 
 private slots:
   void getText()
-  { 
+  {
     emit whichTrigger(d_text0->text(), d_text1->text());
     d_diag->accept();
   }
@@ -699,7 +700,7 @@ public slots:
   //void get13() { emit whichTrigger(8192); }
   //void get14() { emit whichTrigger(16384); }
   //void get15() { emit whichTrigger(32768); }
-  void getOther(const QString &str) 
+  void getOther(const QString &str)
   {
     int value = str.toInt();
     emit whichTrigger(value);
@@ -741,7 +742,7 @@ public:
     }
     d_act[0]->setChecked(true);
 
-    QDoubleValidator *valid = new QDoubleValidator(0.0, 1.0, 2, this);
+    QDoubleValidator *valid = new QDoubleValidator(0.0, 1.0, 3, this);
     ((OtherAction*)d_act[d_act.size()-1])->setValidator(valid);
 
     connect(d_act[0], SIGNAL(triggered()), this, SLOT(getOff()));
@@ -792,6 +793,21 @@ public:
     return d_act[static_cast<int>(which)];
   }
 
+  void setHigh(float x)
+  {
+    d_high = x;
+  }
+
+  void setMedium(float x)
+  {
+    d_medium = x;
+  }
+
+  void setLow(float x)
+  {
+    d_low = x;
+  }
+
  signals:
    void whichTrigger(float alpha);
 
@@ -800,7 +816,7 @@ public:
    void getHigh() { emit whichTrigger(d_high); }
    void getMedium() { emit whichTrigger(d_medium); }
    void getLow() { emit whichTrigger(d_low); }
-   void getOther(const QString &str) 
+   void getOther(const QString &str)
    {
      float value = str.toFloat();
      emit whichTrigger(value);
@@ -863,7 +879,7 @@ public:
   {
     return d_act.size();
   }
-  
+
   QAction * getAction(int which)
   {
     if(which < d_act.size())
@@ -958,7 +974,7 @@ public slots:
 
 private slots:
   void getText()
-  { 
+  {
     emit whichTrigger(d_text->text().toInt());
     d_diag->accept();
   }
@@ -1088,7 +1104,7 @@ public:
   {
     return d_act.size();
   }
-  
+
   QAction * getAction(int which)
   {
     if(which < d_act.size())
@@ -1166,7 +1182,7 @@ public:
   {
     return d_act.size();
   }
-  
+
   QAction * getAction(int which)
   {
     if(which < d_act.size())
@@ -1231,7 +1247,7 @@ public:
   {
     return d_act.size();
   }
-  
+
   QAction * getAction(int which)
   {
     if(which < d_act.size())
@@ -1261,6 +1277,162 @@ private:
 /********************************************************************/
 
 
+class NumberLayoutMenu: public QMenu
+{
+  Q_OBJECT
+
+public:
+  NumberLayoutMenu(QWidget *parent)
+    : QMenu("Layout", parent)
+  {
+    d_grp = new QActionGroup(this);
+    d_act.push_back(new QAction("Horizontal", this));
+    d_act.push_back(new QAction("Vertical", this));
+    d_act.push_back(new QAction("None", this));
+
+    connect(d_act[0], SIGNAL(triggered()), this, SLOT(getHoriz()));
+    connect(d_act[1], SIGNAL(triggered()), this, SLOT(getVert()));
+    connect(d_act[2], SIGNAL(triggered()), this, SLOT(getNone()));
+
+    QListIterator<QAction*> i(d_act);
+    while(i.hasNext()) {
+      QAction *a = i.next();
+      a->setCheckable(true);
+      a->setActionGroup(d_grp);
+      addAction(a);
+    }
+  }
+
+  ~NumberLayoutMenu()
+  {}
+
+  int getNumActions() const
+  {
+    return d_act.size();
+  }
+
+  QAction * getAction(int which)
+  {
+    if(which < d_act.size())
+      return d_act[which];
+    else
+      throw std::runtime_error("NumberLayoutMenu::getAction: which out of 
range.\n");
+  }
+
+  QAction * getAction(gr::qtgui::graph_t layout)
+  {
+    switch(layout) {
+    case gr::qtgui::NUM_GRAPH_HORIZ:
+      return d_act[0];
+      break;
+    case gr::qtgui::NUM_GRAPH_VERT:
+      return d_act[1];
+      break;
+    case gr::qtgui::NUM_GRAPH_NONE:
+      return d_act[1];
+      break;
+    default:
+      throw std::runtime_error("NumberLayoutMenu::getAction: unknown layout 
type.\n");
+    }
+  }
+
+signals:
+  void whichTrigger(gr::qtgui::graph_t layout);
+
+public slots:
+  void getHoriz() { emit whichTrigger(gr::qtgui::NUM_GRAPH_HORIZ); }
+  void getVert() { emit whichTrigger(gr::qtgui::NUM_GRAPH_VERT); }
+  void getNone() { emit whichTrigger(gr::qtgui::NUM_GRAPH_NONE); }
+
+private:
+  QList<QAction *> d_act;
+  QActionGroup *d_grp;
+};
+
+
+/********************************************************************/
+
+
+class NumberColorMapMenu: public QMenu
+{
+  Q_OBJECT
+
+public:
+  NumberColorMapMenu(int which, QWidget *parent)
+    : QMenu("Color Map", parent), d_which(which)
+  {
+    d_act.push_back(new QAction("Black", this));
+    d_act.push_back(new QAction("Blue-Red", this));
+    d_act.push_back(new QAction("White Hot", this));
+    d_act.push_back(new QAction("Black Hot", this));
+    d_act.push_back(new QAction("Black-Red", this));
+    d_act.push_back(new QAction("Other", this));
+
+    connect(d_act[0], SIGNAL(triggered()), this, SLOT(getBlack()));
+    connect(d_act[1], SIGNAL(triggered()), this, SLOT(getBlueRed()));
+    connect(d_act[2], SIGNAL(triggered()), this, SLOT(getWhiteHot()));
+    connect(d_act[3], SIGNAL(triggered()), this, SLOT(getBlackHot()));
+    connect(d_act[4], SIGNAL(triggered()), this, SLOT(getBlackRed()));
+    connect(d_act[5], SIGNAL(triggered()), this, SLOT(getOther()));
+
+     QListIterator<QAction*> i(d_act);
+     while(i.hasNext()) {
+       QAction *a = i.next();
+       addAction(a);
+     }
+
+     d_max_value = QColor("black");
+     d_min_value = QColor("black");
+   }
+
+   ~NumberColorMapMenu()
+   {}
+
+   int getNumActions() const
+   {
+     return d_act.size();
+   }
+
+   QAction * getAction(int which)
+   {
+     if(which < d_act.size())
+       return d_act[which];
+     else
+       throw std::runtime_error("ColorMapMenu::getAction: which out of 
range.\n");
+   }
+
+ signals:
+  void whichTrigger(int which,
+                   const QColor &min_color,
+                   const QColor &max_color);
+
+ public slots:
+  void getBlack() { emit whichTrigger(d_which, QColor("black"), 
QColor("black")); }
+  void getBlueRed() { emit whichTrigger(d_which, QColor("blue"), 
QColor("red")); }
+  void getWhiteHot() { emit whichTrigger(d_which, QColor("black"), 
QColor("white")); }
+  void getBlackHot() { emit whichTrigger(d_which, QColor("white"), 
QColor("black")); }
+  void getBlackRed() { emit whichTrigger(d_which, QColor("black"), 
QColor("red")); }
+  void getOther()
+  {
+    QMessageBox::information(this, "Set low and high intensities",
+       "In the next windows, select the low and then the high intensity 
colors.",
+       QMessageBox::Ok);
+    d_min_value = QColorDialog::getColor(d_min_value, this);
+    d_max_value = QColorDialog::getColor(d_max_value, this);
+
+    emit whichTrigger(d_which, d_min_value, d_max_value);
+  }
+
+private:
+  QList<QAction *> d_act;
+  QColor d_max_value, d_min_value;
+  int d_which;
+};
+
+
+/********************************************************************/
+
+
 class PopupMenu: public QAction
 {
   Q_OBJECT
@@ -1308,7 +1480,7 @@ public slots:
 
 private slots:
   void getText()
-  { 
+  {
     emit whichTrigger(d_text->text());
     d_diag->accept();
   }
diff --git a/gr-qtgui/include/gnuradio/qtgui/number_sink.h 
b/gr-qtgui/include/gnuradio/qtgui/number_sink.h
new file mode 100644
index 0000000..5532a96
--- /dev/null
+++ b/gr-qtgui/include/gnuradio/qtgui/number_sink.h
@@ -0,0 +1,110 @@
+/* -*- 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_H
+#define INCLUDED_QTGUI_NUMBER_SINK_H
+
+#ifdef ENABLE_PYTHON
+#include <Python.h>
+#endif
+
+#include <gnuradio/qtgui/api.h>
+#include <gnuradio/qtgui/trigger_mode.h>
+#include <gnuradio/sync_block.h>
+#include <qapplication.h>
+
+namespace gr {
+  namespace qtgui {
+
+    enum graph_t {
+      NUM_GRAPH_NONE = 0,
+      NUM_GRAPH_HORIZ,
+      NUM_GRAPH_VERT,
+    };
+
+
+    /*!
+     * \brief A graphical sink to display numerical values of input streams.
+     * \ingroup instrumentation_blk
+     * \ingroup qtgui_blk
+     *
+     * \details
+     * Number sink
+     */
+    class QTGUI_API number_sink : virtual public sync_block
+    {
+    public:
+
+      // gr::qtgui::number_sink::sptr
+      typedef boost::shared_ptr<number_sink> sptr;
+
+      /*!
+       * \brief Build a number sink
+       *
+       * \param itemsize Size of input item stream
+       * \param name title for the plot
+       * \param average Averaging coefficient (0 - 1)
+       * \param graph_type Type of graph to use (number_sink::graph_t)
+       * \param nconnections number of signals connected to sink
+       * \param parent a QWidget parent object, if any
+       */
+      static sptr make(size_t itemsize,
+                      const std::string &name,
+                       float average=0,
+                       graph_t graph_type=NUM_GRAPH_HORIZ,
+                      int nconnections=1,
+                      QWidget *parent=NULL);
+
+      virtual void exec_() = 0;
+
+#ifdef ENABLE_PYTHON
+      virtual PyObject* pyqwidget() = 0;
+#endif
+
+      virtual void set_update_time(double t) = 0;
+      virtual void set_title(const std::string &title) = 0;
+      virtual void set_average(const float avg) = 0;
+      virtual void set_graph_type(const graph_t type) = 0;
+      virtual void set_color(int which,
+                             const std::string &min,
+                             const std::string &max) = 0;
+      virtual void set_color(int which, int min, int max) = 0;
+      virtual void set_label(int which, const std::string &label) = 0;
+
+      virtual std::string title() = 0;
+      virtual float average() const = 0;
+      virtual graph_t graph_type() const = 0;
+      virtual std::string color_min() const = 0;
+      virtual std::string color_max() const = 0;
+      virtual std::string label(int which) const = 0;
+
+      virtual void enable_menu(bool en=true) = 0;
+
+      virtual void reset() = 0;
+
+      QApplication *d_qApplication;
+    };
+
+  } /* namespace qtgui */
+} /* namespace gr */
+
+#endif /* INCLUDED_QTGUI_NUMBER_SINK_H */
diff --git a/gr-qtgui/include/gnuradio/qtgui/numberdisplayform.h 
b/gr-qtgui/include/gnuradio/qtgui/numberdisplayform.h
new file mode 100644
index 0000000..0bdda95
--- /dev/null
+++ b/gr-qtgui/include/gnuradio/qtgui/numberdisplayform.h
@@ -0,0 +1,101 @@
+/* -*- 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_FORM_H
+#define NUMBER_DISPLAY_FORM_H
+
+#include <gnuradio/qtgui/spectrumUpdateEvents.h>
+#include <gnuradio/qtgui/number_sink.h>
+#include <gnuradio/qtgui/form_menus.h>
+#include <QtGui/QtGui>
+#include <qwt_thermo.h>
+#include <vector>
+
+/*!
+ * \brief DisplayForm child for managing number sink plots.
+ * \ingroup qtgui_blk
+ */
+class NumberDisplayForm : public QWidget
+{
+  Q_OBJECT
+
+  public:
+  NumberDisplayForm(int nplots=1,
+                    gr::qtgui::graph_t type=gr::qtgui::NUM_GRAPH_HORIZ,
+                    QWidget* parent = 0);
+  ~NumberDisplayForm();
+
+  gr::qtgui::graph_t graphType() const;
+  QColor colorMin() const;
+  QColor colorMax() const;
+  std::string label(int which) const;
+  float average() const;
+  float updateTime() const;
+
+public slots:
+  void mousePressEvent(QMouseEvent * e);
+  void customEvent(QEvent * e);
+  void setStop(bool on);
+  void setStop();
+  void setGraphType(const gr::qtgui::graph_t type);
+  void setColor(int which, const QColor &min, const QColor &max);
+  void setColorMin(int which, QString min);
+  void setColorMax(int which, QString max);
+  void setLabel(int which, const std::string &label);
+  void setLabel(int which, QString label);
+  void setAverage(const float avg);
+  void setUpdateTime(const float time);
+  void setUpdateTime(QString time);
+  void saveFigure();
+  void autoScale(bool on);
+
+private slots:
+  void newData(const QEvent*);
+
+private:
+  int d_nplots;
+  QGridLayout *d_layout;
+  std::vector<QLabel*> d_label;
+  std::vector<QLabel*> d_text_box;
+  std::vector<QwtThermo*> d_indicator;
+  gr::qtgui::graph_t d_graph_type;
+  float d_avg, d_update_time;
+  std::vector<float> d_max, d_min;
+
+  bool d_menu_on;
+  bool d_stop_state;
+  bool d_autoscale_state;
+
+  QMenu *d_menu;
+  QAction *d_stop_act;
+  QList<QMenu*> d_label_menu;
+  std::vector<LineTitleAction*> d_label_act;
+  FFTAverageMenu *d_avg_menu;
+  NumberLayoutMenu *d_layout_menu;
+  std::vector<NumberColorMapMenu*> d_color_menu;
+  PopupMenu *d_maxcolor_menu;
+  QAction *d_autoscale_act;
+  PopupMenu *d_update_time_menu;
+  QAction *d_save_act;
+};
+
+#endif /* NUMBER_DISPLAY_FORM_H */
diff --git a/gr-qtgui/include/gnuradio/qtgui/spectrumUpdateEvents.h 
b/gr-qtgui/include/gnuradio/qtgui/spectrumUpdateEvents.h
index dc31ba8..d26f41e 100644
--- a/gr-qtgui/include/gnuradio/qtgui/spectrumUpdateEvents.h
+++ b/gr-qtgui/include/gnuradio/qtgui/spectrumUpdateEvents.h
@@ -1,6 +1,6 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2008-2013 Free Software Foundation, Inc.
+ * Copyright 2008-2014 Free Software Foundation, Inc.
  *
  * This file is part of GNU Radio
  *
@@ -295,4 +295,28 @@ private:
 };
 
 
+/********************************************************************/
+
+
+class NumberUpdateEvent: public QEvent
+{
+public:
+  NumberUpdateEvent(const std::vector<float> samples);
+  ~NumberUpdateEvent();
+
+  int which() const;
+  const std::vector<float> getSamples() const;
+
+  static QEvent::Type Type()
+      { return QEvent::Type(SpectrumUpdateEventType); }
+
+protected:
+
+private:
+  size_t _nplots;
+  std::vector<float> _samples;
+};
+
+
+
 #endif /* SPECTRUM_UPDATE_EVENTS_H */
diff --git a/gr-qtgui/lib/CMakeLists.txt b/gr-qtgui/lib/CMakeLists.txt
index afaadb9..f46fe83 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 0000000..b1fbca9
--- /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 0000000..faf7ad4
--- /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 0000000..c453923
--- /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 0000000..d22acd0
--- /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 8c822ef..f48e079 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 */
diff --git a/gr-qtgui/swig/qtgui_swig.i b/gr-qtgui/swig/qtgui_swig.i
index 234a879..a6e64b0 100644
--- a/gr-qtgui/swig/qtgui_swig.i
+++ b/gr-qtgui/swig/qtgui_swig.i
@@ -49,6 +49,7 @@
 #include "gnuradio/qtgui/waterfall_sink_c.h"
 #include "gnuradio/qtgui/waterfall_sink_f.h"
 #include "gnuradio/qtgui/histogram_sink_f.h"
+#include "gnuradio/qtgui/number_sink.h"
 %}
 
 %include "gnuradio/qtgui/sink_c.h"
@@ -63,6 +64,7 @@
 %include "gnuradio/qtgui/waterfall_sink_c.h"
 %include "gnuradio/qtgui/waterfall_sink_f.h"
 %include "gnuradio/qtgui/histogram_sink_f.h"
+%include "gnuradio/qtgui/number_sink.h"
 
 GR_SWIG_BLOCK_MAGIC2(qtgui, sink_c);
 GR_SWIG_BLOCK_MAGIC2(qtgui, sink_f);
@@ -76,3 +78,4 @@ GR_SWIG_BLOCK_MAGIC2(qtgui, const_sink_c);
 GR_SWIG_BLOCK_MAGIC2(qtgui, waterfall_sink_c);
 GR_SWIG_BLOCK_MAGIC2(qtgui, waterfall_sink_f);
 GR_SWIG_BLOCK_MAGIC2(qtgui, histogram_sink_f);
+GR_SWIG_BLOCK_MAGIC2(qtgui, number_sink);



reply via email to

[Prev in Thread] Current Thread [Next in Thread]