summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gr-qtgui/doc/qtgui.dox48
-rw-r--r--gr-qtgui/examples/CMakeLists.txt1
-rw-r--r--gr-qtgui/examples/test_qtgui_msg.grc978
-rw-r--r--gr-qtgui/grc/qtgui_block_tree.xml1
-rw-r--r--gr-qtgui/grc/qtgui_edit_box_msg.xml152
-rw-r--r--gr-qtgui/include/gnuradio/qtgui/CMakeLists.txt1
-rw-r--r--gr-qtgui/include/gnuradio/qtgui/edit_box_msg.h151
-rw-r--r--gr-qtgui/include/gnuradio/qtgui/qtgui_types.h20
-rw-r--r--gr-qtgui/lib/CMakeLists.txt2
-rw-r--r--gr-qtgui/lib/edit_box_msg_impl.cc571
-rw-r--r--gr-qtgui/lib/edit_box_msg_impl.h93
-rw-r--r--gr-qtgui/swig/qtgui_swig.i15
12 files changed, 2032 insertions, 1 deletions
diff --git a/gr-qtgui/doc/qtgui.dox b/gr-qtgui/doc/qtgui.dox
index d95ab19f72..d0d7345f73 100644
--- a/gr-qtgui/doc/qtgui.dox
+++ b/gr-qtgui/doc/qtgui.dox
@@ -232,6 +232,54 @@ tb.msg_connect((msg_block, 'msg'), (tsnk, 'in'))
\endcode
+\section qtgui_widgets QTGUI Widgets
+
+The QTGUI component also includes a number of widgets that can be used
+to perform live updates of variables through standard QT input
+widgets. Most of the widgets are implemented directly in Python
+through PyQT. However, GNU Radio is introducing more widgets, written
+and therefore available in C++ that also produce messsages. The
+Python-based widgets only act as variables and so as they are changed,
+any block using those widgets to set paramters has the callback (i.e.,
+set_value()) function's called.
+
+\subsection qtgui_widgets_python Python widgets:
+
+\li Range: creates a slider and/or combo box to change to set/change
+the value of a parameter. This widget can set either float of int
+values.
+\li Entry: An edit box that allows a user to directly set a
+new value for the parameter.
+\li Chooser: Creates a drop-down menu of pre-set values.
+\li Check Box: Creates a check box. The user sets what the value of
+the check means when enabled or disabled.
+\li Push Button: Adds a button that changes state when pushed versus
+released (no sticky). The user sets up what the value is when pressed
+versus when released.
+\li Label: Adds a Label widget to annotate the GUI. Generally not used
+as a variable.
+\li Tab Widget: Adds a tab widget that can house other GUI widgets to
+format the interface. Use the GUI hint of the other QT widgets and
+instruments to specify if and where they exist in the tab widget using
+the format "tag widget name@index: row, col, row span, col
+span". Simply using "tab widget name@index" will put that widget into
+the specific index (starting at 0) of the tab widget while adding the
+"row, col, row span, col span" will allow the user to place them in
+the tab grid.
+\li
+
+
+\subsection qtgui_widgets_cpp C++ and Message-Passing Widgets
+
+\li \ref gr::qtgui::edit_box_msg "Message Edit Box": A QT edit box
+that emits a message when editing is done (e.g., user presses enter,
+tabs out of the widget, or mouse-clicks out of the widget). The
+message type is settable as are the contents. Messages can be sent as
+key:value pairs when Pair Mode is enabled. When Static Mode is
+enabled, the data type and the pair key (if in Pair Mode) are set at
+the start and cannot be changed at runtime.
+
+
\section qtgui_configuration Configuration
There is currently a single configuration option in the preferences
diff --git a/gr-qtgui/examples/CMakeLists.txt b/gr-qtgui/examples/CMakeLists.txt
index 3581bdaec1..5662dfa9c8 100644
--- a/gr-qtgui/examples/CMakeLists.txt
+++ b/gr-qtgui/examples/CMakeLists.txt
@@ -41,6 +41,7 @@ install(
qtgui_tags_viewing.grc
qtgui_vector_sink_example.grc
qtgui_message_inputs.grc
+ test_qtgui_msg.grc
DESTINATION ${GR_PKG_QTGUI_EXAMPLES_DIR}
COMPONENT "qtgui_python"
)
diff --git a/gr-qtgui/examples/test_qtgui_msg.grc b/gr-qtgui/examples/test_qtgui_msg.grc
new file mode 100644
index 0000000000..12ca0e34c9
--- /dev/null
+++ b/gr-qtgui/examples/test_qtgui_msg.grc
@@ -0,0 +1,978 @@
+<?xml version='1.0' encoding='utf-8'?>
+<?grc format='1' created='3.7.10'?>
+<flow_graph>
+ <timestamp>Wed Feb 10 14:28:57 2016</timestamp>
+ <block>
+ <key>options</key>
+ <param>
+ <key>author</key>
+ <value></value>
+ </param>
+ <param>
+ <key>window_size</key>
+ <value></value>
+ </param>
+ <param>
+ <key>category</key>
+ <value>Custom</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>description</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(8, 11)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>generate_options</key>
+ <value>qt_gui</value>
+ </param>
+ <param>
+ <key>hier_block_src_path</key>
+ <value>.:</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>test_qtgui_msg</value>
+ </param>
+ <param>
+ <key>max_nouts</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>qt_qss_theme</key>
+ <value></value>
+ </param>
+ <param>
+ <key>realtime_scheduling</key>
+ <value></value>
+ </param>
+ <param>
+ <key>run_command</key>
+ <value>{python} -u {filename}</value>
+ </param>
+ <param>
+ <key>run_options</key>
+ <value>prompt</value>
+ </param>
+ <param>
+ <key>run</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>thread_safe_setters</key>
+ <value></value>
+ </param>
+ <param>
+ <key>title</key>
+ <value></value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(168, 11)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>32000</value>
+ </param>
+ </block>
+ <block>
+ <key>analog_sig_source_x</key>
+ <param>
+ <key>amp</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>freq</key>
+ <value>1000</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(80, 83)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>analog_sig_source_x_0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>offset</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>waveform</key>
+ <value>analog.GR_COS_WAVE</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_message_debug</key>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(600, 481)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>blocks_message_debug_0</value>
+ </param>
+ </block>
+ <block>
+ <key>qtgui_edit_box_msg</key>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(104, 219)</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value>0,0,1,1</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>qtgui_edit_box_msg_0</value>
+ </param>
+ <param>
+ <key>key</key>
+ <value>freq</value>
+ </param>
+ <param>
+ <key>label</key>
+ <value>Frequency</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>is_pair</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>is_static</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value></value>
+ </param>
+ </block>
+ <block>
+ <key>qtgui_edit_box_msg</key>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(88, 371)</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value>3,1,1,1</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>qtgui_edit_box_msg_0_0</value>
+ </param>
+ <param>
+ <key>key</key>
+ <value></value>
+ </param>
+ <param>
+ <key>label</key>
+ <value></value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>is_pair</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>is_static</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>int_vec</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value></value>
+ </param>
+ </block>
+ <block>
+ <key>qtgui_edit_box_msg</key>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(272, 499)</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value>3,0,1,1</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>qtgui_edit_box_msg_0_0_0</value>
+ </param>
+ <param>
+ <key>key</key>
+ <value></value>
+ </param>
+ <param>
+ <key>label</key>
+ <value></value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>is_pair</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>is_static</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>int_vec</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value></value>
+ </param>
+ </block>
+ <block>
+ <key>qtgui_freq_sink_x</key>
+ <param>
+ <key>autoscale</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>average</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>bw</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>fc</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>ctrlpanel</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>fftsize</key>
+ <value>1024</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(512, 195)</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value>1,0,1,2</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>grid</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>qtgui_freq_sink_x_0</value>
+ </param>
+ <param>
+ <key>legend</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>alpha1</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color1</key>
+ <value>"blue"</value>
+ </param>
+ <param>
+ <key>label1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width1</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alpha10</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color10</key>
+ <value>"dark blue"</value>
+ </param>
+ <param>
+ <key>label10</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width10</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alpha2</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color2</key>
+ <value>"red"</value>
+ </param>
+ <param>
+ <key>label2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width2</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alpha3</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color3</key>
+ <value>"green"</value>
+ </param>
+ <param>
+ <key>label3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width3</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alpha4</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color4</key>
+ <value>"black"</value>
+ </param>
+ <param>
+ <key>label4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width4</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alpha5</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color5</key>
+ <value>"cyan"</value>
+ </param>
+ <param>
+ <key>label5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width5</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alpha6</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color6</key>
+ <value>"magenta"</value>
+ </param>
+ <param>
+ <key>label6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width6</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alpha7</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color7</key>
+ <value>"yellow"</value>
+ </param>
+ <param>
+ <key>label7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width7</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alpha8</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color8</key>
+ <value>"dark red"</value>
+ </param>
+ <param>
+ <key>label8</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width8</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alpha9</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color9</key>
+ <value>"dark green"</value>
+ </param>
+ <param>
+ <key>label9</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width9</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>name</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>nconnections</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>showports</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>freqhalf</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>tr_chan</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>tr_level</key>
+ <value>0.0</value>
+ </param>
+ <param>
+ <key>tr_mode</key>
+ <value>qtgui.TRIG_MODE_FREE</value>
+ </param>
+ <param>
+ <key>tr_tag</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>update_time</key>
+ <value>0.10</value>
+ </param>
+ <param>
+ <key>wintype</key>
+ <value>firdes.WIN_BLACKMAN_hARRIS</value>
+ </param>
+ <param>
+ <key>ymax</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ymin</key>
+ <value>-140</value>
+ </param>
+ </block>
+ <block>
+ <key>qtgui_waterfall_sink_x</key>
+ <param>
+ <key>bw</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>fc</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>fftsize</key>
+ <value>1024</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(512, 115)</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value>2,0,1,2</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>grid</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>qtgui_waterfall_sink_x_0</value>
+ </param>
+ <param>
+ <key>int_max</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>int_min</key>
+ <value>-140</value>
+ </param>
+ <param>
+ <key>legend</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>alpha1</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color1</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>label1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>alpha10</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color10</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>label10</key>
+ <value></value>
+ </param>
+ <param>
+ <key>alpha2</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color2</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>label2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>alpha3</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color3</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>label3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>alpha4</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color4</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>label4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>alpha5</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color5</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>label5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>alpha6</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color6</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>label6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>alpha7</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color7</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>label7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>alpha8</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color8</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>label8</key>
+ <value></value>
+ </param>
+ <param>
+ <key>alpha9</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color9</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>label9</key>
+ <value></value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>name</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>nconnections</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>showports</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>freqhalf</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>update_time</key>
+ <value>0.10</value>
+ </param>
+ <param>
+ <key>wintype</key>
+ <value>firdes.WIN_BLACKMAN_hARRIS</value>
+ </param>
+ </block>
+ <connection>
+ <source_block_id>analog_sig_source_x_0</source_block_id>
+ <sink_block_id>qtgui_freq_sink_x_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>analog_sig_source_x_0</source_block_id>
+ <sink_block_id>qtgui_waterfall_sink_x_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>qtgui_edit_box_msg_0</source_block_id>
+ <sink_block_id>qtgui_freq_sink_x_0</sink_block_id>
+ <source_key>msg</source_key>
+ <sink_key>freq</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>qtgui_edit_box_msg_0</source_block_id>
+ <sink_block_id>qtgui_waterfall_sink_x_0</sink_block_id>
+ <source_key>msg</source_key>
+ <sink_key>freq</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>qtgui_edit_box_msg_0_0</source_block_id>
+ <sink_block_id>qtgui_edit_box_msg_0_0_0</sink_block_id>
+ <source_key>msg</source_key>
+ <sink_key>val</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>qtgui_edit_box_msg_0_0_0</source_block_id>
+ <sink_block_id>blocks_message_debug_0</sink_block_id>
+ <source_key>msg</source_key>
+ <sink_key>print</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>qtgui_edit_box_msg_0_0_0</source_block_id>
+ <sink_block_id>qtgui_edit_box_msg_0_0</sink_block_id>
+ <source_key>msg</source_key>
+ <sink_key>val</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>qtgui_freq_sink_x_0</source_block_id>
+ <sink_block_id>qtgui_edit_box_msg_0</sink_block_id>
+ <source_key>freq</source_key>
+ <sink_key>val</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>qtgui_freq_sink_x_0</source_block_id>
+ <sink_block_id>qtgui_freq_sink_x_0</sink_block_id>
+ <source_key>freq</source_key>
+ <sink_key>freq</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>qtgui_waterfall_sink_x_0</source_block_id>
+ <sink_block_id>qtgui_edit_box_msg_0</sink_block_id>
+ <source_key>freq</source_key>
+ <sink_key>val</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>qtgui_waterfall_sink_x_0</source_block_id>
+ <sink_block_id>qtgui_waterfall_sink_x_0</sink_block_id>
+ <source_key>freq</source_key>
+ <sink_key>freq</sink_key>
+ </connection>
+</flow_graph>
diff --git a/gr-qtgui/grc/qtgui_block_tree.xml b/gr-qtgui/grc/qtgui_block_tree.xml
index 03db638d61..300c7a786d 100644
--- a/gr-qtgui/grc/qtgui_block_tree.xml
+++ b/gr-qtgui/grc/qtgui_block_tree.xml
@@ -55,6 +55,7 @@
<block>variable_qtgui_push_button</block>
<block>variable_qtgui_entry</block>
<block>variable_qtgui_label</block>
+ <block>qtgui_edit_box_msg</block>
</cat>
</cat>
</cat>
diff --git a/gr-qtgui/grc/qtgui_edit_box_msg.xml b/gr-qtgui/grc/qtgui_edit_box_msg.xml
new file mode 100644
index 0000000000..c7c758a612
--- /dev/null
+++ b/gr-qtgui/grc/qtgui_edit_box_msg.xml
@@ -0,0 +1,152 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##QT GUI Edit Box that sends messages
+###################################################
+ -->
+<block>
+ <name>QT GUI Message Edit Box</name>
+ <key>qtgui_edit_box_msg</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.edit_box_msg($(type.t), $value, $label, $is_pair, $is_static, $key)
+self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget)
+$(gui_hint()($win))</make>
+
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <value>string</value>
+ <type>enum</type>
+ <option>
+ <name>String</name>
+ <key>string</key>
+ <opt>t:qtgui.STRING</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>t:qtgui.INT</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>t:qtgui.FLOAT</opt>
+ </option>
+ <option>
+ <name>Double</name>
+ <key>double</key>
+ <opt>t:qtgui.DOUBLE</opt>
+ </option>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>t:qtgui.COMPLEX</opt>
+ </option>
+ <option>
+ <name>Int (Vec)</name>
+ <key>int_vec</key>
+ <opt>t:qtgui.INT_VEC</opt>
+ </option>
+ <option>
+ <name>Float (Vec)</name>
+ <key>flt_vec</key>
+ <opt>t:qtgui.FLOAT_VEC</opt>
+ </option>
+ <option>
+ <name>Double (Vec)</name>
+ <key>dbl_vec</key>
+ <opt>t:qtgui.DOUBLE_VEC</opt>
+ </option>
+ <option>
+ <name>Complex (Vec)</name>
+ <key>cpx_vec</key>
+ <opt>t:qtgui.COMPLEX_VEC</opt>
+ </option>
+ </param>
+
+ <param>
+ <name>Value</name>
+ <key>value</key>
+ <value></value>
+ <type>string</type>
+ </param>
+
+ <param>
+ <name>Label</name>
+ <key>label</key>
+ <value></value>
+ <type>string</type>
+ </param>
+
+ <param>
+ <name>Pair Mode</name>
+ <key>is_pair</key>
+ <value>True</value>
+ <type>enum</type>
+ <option>
+ <name>False</name>
+ <key>False</key>
+ </option>
+ <option>
+ <name>True</name>
+ <key>True</key>
+ </option>
+ </param>
+
+ <param>
+ <name>Static Mode</name>
+ <key>is_static</key>
+ <value>True</value>
+ <type>enum</type>
+ <option>
+ <name>False</name>
+ <key>False</key>
+ </option>
+ <option>
+ <name>True</name>
+ <key>True</key>
+ </option>
+ </param>
+
+ <param>
+ <name>Key</name>
+ <key>key</key>
+ <value></value>
+ <type>string</type>
+ <hide>#if $is_pair() == 'True' then 'none' else 'all'#</hide>
+ </param>
+
+ <param>
+ <name>GUI Hint</name>
+ <key>gui_hint</key>
+ <value></value>
+ <type>gui_hint</type>
+ <hide>part</hide>
+ </param>
+
+ <!-- If both is_pair and is_static are True, we require a default key.
+ If either or both are false, we don't care about a default key.
+ -->
+ <check>($is_pair and $is_static and len($key) &gt; 0) or not ($is_pair and $is_static)</check>
+
+ <sink>
+ <name>val</name>
+ <type>message</type>
+ <optional>1</optional>
+ </sink>
+
+ <source>
+ <name>msg</name>
+ <type>message</type>
+ <optional>1</optional>
+ </source>
+
+ <doc>
+The GUI hint can be used to position the widget within the application. \
+The hint is of the form [tab_id@tab_index]: [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 1e0c9f35f2..5d22f112af 100644
--- a/gr-qtgui/include/gnuradio/qtgui/CMakeLists.txt
+++ b/gr-qtgui/include/gnuradio/qtgui/CMakeLists.txt
@@ -38,6 +38,7 @@ install(FILES
histogram_sink_f.h
histogramdisplayform.h
HistogramDisplayPlot.h
+ edit_box_msg.h
number_sink.h
numberdisplayform.h
plot_raster.h
diff --git a/gr-qtgui/include/gnuradio/qtgui/edit_box_msg.h b/gr-qtgui/include/gnuradio/qtgui/edit_box_msg.h
new file mode 100644
index 0000000000..2976cfb2be
--- /dev/null
+++ b/gr-qtgui/include/gnuradio/qtgui/edit_box_msg.h
@@ -0,0 +1,151 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2016 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_EDIT_BOX_MSG_H
+#define INCLUDED_QTGUI_EDIT_BOX_MSG_H
+
+#ifdef ENABLE_PYTHON
+#include <Python.h>
+#endif
+
+#include <gnuradio/qtgui/qtgui_types.h>
+#include <gnuradio/qtgui/api.h>
+#include <gnuradio/block.h>
+#include <qapplication.h>
+
+namespace gr {
+ namespace qtgui {
+
+ /*!
+ * \brief Create a QT Edit Box widget where the value is posted as a message.
+ * \ingroup qtgui_blk
+ *
+ * \details
+ * This block creates a QT Edit Box widget that manages data
+ * through message passing interfaces. The 'msg' output port
+ * produces messages based on the text in the edit box and the
+ * data type set by the \p type argument (see
+ * gr::qtgui::data_type_t). The data types are checked, and WARN
+ * log messages are produced when the data is in the wrong
+ * format. Not all errors are explicitly checked for, only that
+ * conversions happen correctly. Failures are either produces as
+ * log messages or the action is simply silently dropped.
+ *
+ * The value of the edit boxes can be programmatically updated
+ * through the 'val' input message port. It is also checked for
+ * the correct data type.
+ *
+ * The \p is_pair argument to the constructor determines if the
+ * edit box handles a key:value pair. If set to True, two edit
+ * boxes are created with the left for the key and right for the
+ * value. The key is always assumed to be a string and the value
+ * is restricted by the data type setting as above.
+ *
+ * The block can take a default value. Because the block is
+ * capable of handling multiple different data types, we enter the
+ * default value as a string in the same way we expect the user to
+ * enter it into the Value edit box of the widget. We convert this
+ * default exactly the same way we convert the user-entered text
+ * in the edit box. See the next paragraph for an explanation for
+ * how to handle complex numbers.
+ *
+ * Complex numbers are currently handled a bit differently than
+ * expected. Because we use the Boost lexical_cast function,
+ * complex numbers MUST be in the form "(a,b)" to represent "a +
+ * jb". Note that you cannot even have a space after the comma, so
+ * "(1.23,10.56)" is correct while "(1.23, 10.56)" will not parse.
+ *
+ * The 'static' mode prevents the user from changing the data type
+ * or the key used in the widget. If also in 'pair' mode, the key
+ * is not displayed and so must be set in the constructor. It is
+ * an error if using static and pair modes with no default key
+ * set.
+ *
+ * Message Ports:
+ *
+ * - msg (output):
+ * Produces a PMT message from the data in the edit box. It
+ * is packaged in the PMT container determined by the \p
+ * type argument to the ctor. If the data in the box is not of
+ * the correct type and the conversion fails, the block
+ * produces a log WARN message but does nothing else with
+ * the data. If the \p is_pair flag is set on this block, it
+ * will produce a PMT pair object where the key (car) is
+ * assumed to be a string and the value (cdr) is determined
+ * by \p type.
+ *
+ * - val (input):
+ * Accepts messages to update the value in the edit
+ * boxes. The messages, as PMTs, are first checked to make
+ * sure that they are the correct type (integer, float,
+ * string, or complex), and unpacks them and converts them
+ * to QStrings to display in the edit box. When using \p
+ * is_pair, the PMT is checked to make sure it is a PMT
+ * pair. Then the key (car) is extracted as a string before
+ * the value (cdr) is processed based on the set data type
+ * of the box.
+ */
+ class QTGUI_API edit_box_msg : virtual public block
+ {
+ public:
+ // gr::qtgui::edit_box_msg::sptr
+ typedef boost::shared_ptr<edit_box_msg> sptr;
+
+ /*!
+ * \brief Constructs the Edit box block.
+ *
+ * \param type the data type of data in the value box.
+ * \param value the default value of the message. This is
+ * entered as a string regardless of the type and
+ * converted internally -- much like how the block
+ * extracts the value from the edit box and converts it.
+ * \param label a label to identify the box on screen.
+ * \param is_pair if we are using a key:value pair.
+ * \param is_static sets the key edit box as a static text box
+ * (cannot be edited live).
+ * \param key Set the key used in a key:value pair message.
+ * \param parent a QWidget parent in the QT app.
+ */
+ static sptr make(gr::qtgui::data_type_t type,
+ const std::string &value="",
+ const std::string &label="",
+ bool is_pair=true,
+ bool is_static=true,
+ const std::string &key="",
+ QWidget *parent=NULL);
+
+ virtual void exec_() = 0;
+ virtual QWidget* qwidget() = 0;
+
+#ifdef ENABLE_PYTHON
+ virtual PyObject* pyqwidget() = 0;
+#else
+ virtual void* pyqwidget() = 0;
+#endif
+
+ QApplication *d_qApplication;
+ };
+
+ } /* namespace qtgui */
+} /* namespace gr */
+
+#endif /* INCLUDED_QTGUI_EDIT_BOX_MSG_H */
diff --git a/gr-qtgui/include/gnuradio/qtgui/qtgui_types.h b/gr-qtgui/include/gnuradio/qtgui/qtgui_types.h
index e55746c48c..ae7d081013 100644
--- a/gr-qtgui/include/gnuradio/qtgui/qtgui_types.h
+++ b/gr-qtgui/include/gnuradio/qtgui/qtgui_types.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2012 Free Software Foundation, Inc.
+ * Copyright 2012,2016 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -27,6 +27,24 @@
#include <qwt_scale_draw.h>
#include <gnuradio/high_res_timer.h>
+namespace gr {
+ namespace qtgui {
+
+ enum data_type_t {
+ INT = 0,
+ FLOAT,
+ DOUBLE,
+ COMPLEX,
+ STRING,
+ INT_VEC,
+ FLOAT_VEC,
+ DOUBLE_VEC,
+ COMPLEX_VEC,
+ };
+
+ } /* namespace qtgui */
+} /* namespace gr */
+
class FreqOffsetAndPrecisionClass
{
public:
diff --git a/gr-qtgui/lib/CMakeLists.txt b/gr-qtgui/lib/CMakeLists.txt
index a0af95bbbb..276c3e4856 100644
--- a/gr-qtgui/lib/CMakeLists.txt
+++ b/gr-qtgui/lib/CMakeLists.txt
@@ -43,6 +43,7 @@ set(qtgui_moc_hdrs
${qtgui_mod_includedir}/ConstellationDisplayPlot.h
${qtgui_mod_includedir}/HistogramDisplayPlot.h
${qtgui_mod_includedir}/VectorDisplayPlot.h
+ edit_box_msg_impl.h
)
QT4_WRAP_CPP(qtgui_moc_sources ${qtgui_moc_hdrs})
QT4_WRAP_UI(qtgui_ui_hdrs spectrumdisplayform.ui)
@@ -99,6 +100,7 @@ set(qtgui_sources
ber_sink_b_impl.cc
vectordisplayform.cc
vector_sink_f_impl.cc
+ edit_box_msg_impl.cc
)
#Add Windows DLL resource file if using MSVC
diff --git a/gr-qtgui/lib/edit_box_msg_impl.cc b/gr-qtgui/lib/edit_box_msg_impl.cc
new file mode 100644
index 0000000000..e0c5f64b3d
--- /dev/null
+++ b/gr-qtgui/lib/edit_box_msg_impl.cc
@@ -0,0 +1,571 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2016 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 "edit_box_msg_impl.h"
+#include <gnuradio/io_signature.h>
+#include <gnuradio/prefs.h>
+#include <gnuradio/qtgui/utils.h>
+#include <boost/lexical_cast.hpp>
+
+namespace gr {
+ namespace qtgui {
+
+ edit_box_msg::sptr
+ edit_box_msg::make(data_type_t type, const std::string &label,
+ const std::string &value,
+ bool is_pair, bool is_static,
+ const std::string &key, QWidget* parent)
+ {
+ return gnuradio::get_initial_sptr
+ (new edit_box_msg_impl(type, value, label, is_pair,
+ is_static, key, parent));
+ }
+
+ edit_box_msg_impl::edit_box_msg_impl(data_type_t type, const std::string &label,
+ const std::string &value,
+ bool is_pair, bool is_static,
+ const std::string &key, QWidget* parent)
+ : block("edit_box_msg",
+ io_signature::make(0, 0, 0),
+ io_signature::make(0, 0, 0)),
+ QObject(parent)
+ {
+ // 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';
+
+ if(qApp != NULL) {
+ d_qApplication = qApp;
+ }
+ else {
+#if QT_VERSION >= 0x040500
+ std::string style = prefs::singleton()->get_string("qtgui", "style", "raster");
+ QApplication::setGraphicsSystem(QString(style.c_str()));
+#endif
+ d_qApplication = new QApplication(d_argc, &d_argv);
+ }
+
+ // If a style sheet is set in the prefs file, enable it here.
+ std::string qssfile = prefs::singleton()->get_string("qtgui","qss","");
+ if(qssfile.size() > 0) {
+ QString sstext = get_qt_style_sheet(QString(qssfile.c_str()));
+ d_qApplication->setStyleSheet(sstext);
+ }
+
+ d_is_pair = is_pair;
+ d_is_static = is_static;
+
+ d_val = new QLineEdit();
+ d_val->setObjectName("qtgui_editboxmsg_val"); // used to set background color
+ d_val->setText(QString(value.c_str()));
+
+ set_type(type);
+
+ d_group = new QGroupBox();
+ d_vlayout = new QVBoxLayout(parent);
+ d_hlayout = new QHBoxLayout(parent);
+
+ if(d_is_pair) {
+ d_key = new QLineEdit();
+
+ QString key_text = QString(key.c_str());
+ d_key->setText(key_text);
+
+ // If static, we create the d_key object, which we use later
+ // to be consistent about getting the key string. But we do
+ // not add it to the layout.
+ if(d_is_static) {
+ d_key->setEnabled(false);
+
+ QFontMetrics fm = d_key->fontMetrics();
+ int width = 15 + fm.width(key_text);
+
+ d_key->setFixedWidth(width);
+
+ // Verify that a default key has been set or emit an error
+ if(key.size() == 0) {
+ throw std::runtime_error("When using static + pair mode, please set a default key.");
+ }
+ }
+ else {
+ // Adding it to the layout if in non-static mode so users
+ // can see and update the key.
+ d_hlayout->addWidget(d_key);
+ }
+ }
+
+ d_label = NULL;
+ if(label != "") {
+ d_label = new QLabel(QString(label.c_str()));
+ d_vlayout->addWidget(d_label);
+ }
+
+ d_hlayout->addWidget(d_val);
+
+ if(!d_is_static) {
+ // If not static, we can change the key and the data type of
+ // the value box.
+ d_type_box = new QComboBox();
+ d_type_box->setEditable(false);
+
+ // Items listed in order of enum data_type_t
+ d_type_box->addItem("Int");
+ d_type_box->addItem("Float");
+ d_type_box->addItem("Double");
+ d_type_box->addItem("Complex");
+ d_type_box->addItem("String");
+ d_type_box->addItem("Int (vec)");
+ d_type_box->addItem("Float (vec)");
+ d_type_box->addItem("Double (vec)");
+ d_type_box->addItem("Complex (vec)");
+ d_type_box->setCurrentIndex(d_type);
+ d_hlayout->addWidget(d_type_box);
+
+ QObject::connect(d_type_box, SIGNAL(currentIndexChanged(int)),
+ this, SLOT(set_type(int)));
+ }
+
+ d_vlayout->addItem(d_hlayout);
+ d_group->setLayout(d_vlayout);
+
+ QObject::connect(d_val, SIGNAL(editingFinished()),
+ this, SLOT(edit_finished()));
+
+ d_msg = pmt::PMT_NIL;
+
+ message_port_register_out(pmt::mp("msg"));
+ message_port_register_in(pmt::mp("val"));
+
+ set_msg_handler(pmt::mp("val"),
+ boost::bind(&edit_box_msg_impl::set_value, this, _1));
+ }
+
+ edit_box_msg_impl::~edit_box_msg_impl()
+ {
+ delete d_argv;
+ delete d_group;
+ delete d_hlayout;
+ delete d_vlayout;
+ delete d_val;
+ if(d_is_pair)
+ delete d_key;
+ if(d_label)
+ delete d_label;
+ }
+
+ bool
+ edit_box_msg_impl::start()
+ {
+ QString text = d_val->text();
+ if(!text.isEmpty()) {
+ edit_finished();
+ }
+
+ return block::start();
+ }
+
+ void
+ edit_box_msg_impl::exec_()
+ {
+ d_qApplication->exec();
+ }
+
+ QWidget*
+ edit_box_msg_impl::qwidget()
+ {
+ return (QWidget*)d_group;
+ }
+
+#ifdef ENABLE_PYTHON
+ PyObject*
+ edit_box_msg_impl::pyqwidget()
+ {
+ PyObject *w = PyLong_FromVoidPtr((void*)d_group);
+ PyObject *retarg = Py_BuildValue("N", w);
+ return retarg;
+ }
+#else
+ void *
+ edit_box_msg_impl::pyqwidget()
+ {
+ return NULL;
+ }
+#endif
+
+ void
+ edit_box_msg_impl::set_type(int type)
+ {
+ set_type(static_cast<data_type_t>(type));
+ }
+
+ void
+ edit_box_msg_impl::set_type(gr::qtgui::data_type_t type)
+ {
+ d_type = type;
+
+ switch(d_type) {
+ case INT:
+ case INT_VEC:
+ d_val->setStyleSheet("QLineEdit#qtgui_editboxmsg_val {background-color: #4CAF50;}");
+ break;
+ case FLOAT:
+ case FLOAT_VEC:
+ d_val->setStyleSheet("QLineEdit#qtgui_editboxmsg_val {background-color: #F57C00;}");
+ break;
+ case DOUBLE:
+ case DOUBLE_VEC:
+ d_val->setStyleSheet("QLineEdit#qtgui_editboxmsg_val {background-color: #00BCD4;}");
+ break;
+ case COMPLEX:
+ case COMPLEX_VEC:
+ d_val->setStyleSheet("QLineEdit#qtgui_editboxmsg_val {background-color: #2196F3;}");
+ break;
+ case STRING:
+ d_val->setStyleSheet("QLineEdit#qtgui_editboxmsg_val {background-color: #FFFFFF; color: #000000;}");
+ break;
+ }
+ }
+
+ void
+ edit_box_msg_impl::set_value(pmt::pmt_t val)
+ {
+ // If the contents of the new value are the same as we already
+ // had, don't update anything, just exit and move on.
+ if(pmt::eqv(val, d_msg)) {
+ return;
+ }
+
+ int xi;
+ float xf;
+ double xd;
+ std::string xs;
+ gr_complex xc;
+
+ d_msg = val;
+
+ // Only update key if we're expecting a pair
+ if(d_is_pair) {
+ // If we are, make sure that the PMT is actually a pair
+ if(pmt::is_pair(val)) {
+ pmt::pmt_t key = pmt::car(val);
+ std::string skey = pmt::symbol_to_string(key);
+
+ // If static, check to make sure that the key of the
+ // incoming message matches our key. If it doesn't, emit a
+ // warning and exit without changing anything.
+ if(d_is_static) {
+ std::string cur_key = d_key->text().toStdString();
+ if(skey != cur_key) {
+ GR_LOG_WARN(d_logger, boost::format("Got key '%1%' but expected '%2%'") \
+ % skey % cur_key);
+ return;
+ }
+ }
+ val = pmt::cdr(val);
+ d_key->setText(QString(skey.c_str()));
+ }
+ else {
+ GR_LOG_WARN(d_logger, "Did not find PMT pair");
+ return;
+ }
+ }
+
+ switch(d_type) {
+ case INT:
+ if(pmt::is_integer(val)) {
+ xi = pmt::to_long(val);
+ d_val->setText(QString::number(xi));
+ }
+ else {
+ GR_LOG_WARN(d_logger, "Conversion from integer failed");
+ return;
+ }
+ break;
+ case INT_VEC:
+ if(pmt::is_s32vector(val)) {
+ QStringList text_list;
+ const std::vector<int32_t> xv = pmt::s32vector_elements(val);
+ for(size_t i = 0; i < xv.size(); i++) {
+ text_list.append(QString::number(xv[i]));
+ }
+ d_val->setText(text_list.join(", "));
+ }
+ else {
+ GR_LOG_WARN(d_logger, "Conversion from integer vector failed");
+ return;
+ }
+ break;
+ case FLOAT:
+ if(pmt::is_real(val)) {
+ xf = pmt::to_float(val);
+ d_val->setText(QString::number(xf));
+ }
+ else {
+ GR_LOG_WARN(d_logger, "Conversion from float failed");
+ return;
+ }
+ break;
+ case FLOAT_VEC:
+ if(pmt::is_f32vector(val)) {
+ QStringList text_list;
+ const std::vector<float> xv = pmt::f32vector_elements(val);
+ for(size_t i = 0; i < xv.size(); i++) {
+ text_list.append(QString::number(xv[i]));
+ }
+ d_val->setText(text_list.join(", "));
+ }
+ else {
+ GR_LOG_WARN(d_logger, "Conversion from float vector failed");
+ return;
+ }
+ break;
+ case DOUBLE:
+ if(pmt::is_real(val)) {
+ xd = pmt::to_double(val);
+ d_val->setText(QString::number(xd));
+ }
+ else {
+ GR_LOG_WARN(d_logger, "Conversion from double failed");
+ return;
+ }
+ break;
+ case DOUBLE_VEC:
+ if(pmt::is_f64vector(val)) {
+ QStringList text_list;
+ const std::vector<double> xv = pmt::f64vector_elements(val);
+ for(size_t i = 0; i < xv.size(); i++) {
+ text_list.append(QString::number(xv[i]));
+ }
+ d_val->setText(text_list.join(", "));
+ }
+ else {
+ GR_LOG_WARN(d_logger, "Conversion from double vector failed");
+ return;
+ }
+ break;
+ case COMPLEX:
+ if(pmt::is_complex(val)) {
+ xc = pmt::to_complex(val);
+ d_val->setText(QString("(%1,%2)").arg(xc.real()).arg(xc.imag()));
+ }
+ else {
+ GR_LOG_WARN(d_logger, "Conversion from complex failed");
+ return;
+ }
+ break;
+ case COMPLEX_VEC:
+ if(pmt::is_c32vector(val)) {
+ QStringList text_list;
+ const std::vector<gr_complex> xv = pmt::c32vector_elements(val);
+ for(size_t i = 0; i < xv.size(); i++) {
+ text_list.append(QString("(%1,%2)").arg(xv[i].real()).arg(xv[i].imag()));
+ }
+ d_val->setText(text_list.join(", "));
+ }
+ else {
+ GR_LOG_WARN(d_logger, "Conversion from complex vector failed");
+ return;
+ }
+ break;
+ case STRING:
+ if(pmt::is_symbol(val)) {
+ xs = pmt::symbol_to_string(val);
+ d_val->setText(QString(xs.c_str()));
+ }
+ else {
+ GR_LOG_WARN(d_logger, "Conversion from string failed");
+ return;
+ }
+ break;
+ }
+
+ // Emit the new message to pass updates downstream.
+ // Loops are prevented by the early exit if d_msg == val.
+ message_port_pub(pmt::mp("msg"), d_msg);
+ }
+
+ void
+ edit_box_msg_impl::edit_finished()
+ {
+ QString text = d_val->text();
+ bool conv_ok = true;
+ int xi;
+ float xf;
+ double xd;
+ std::string xs;
+ gr_complex xc;
+
+ switch(d_type) {
+ case INT:
+ xi = text.toInt(&conv_ok);
+ if(conv_ok) {
+ d_msg = pmt::from_long(xi);
+ }
+ else {
+ GR_LOG_WARN(d_logger, "Conversion to integer failed");
+ return;
+ }
+ break;
+ case INT_VEC:
+ {
+ std::vector<int32_t> xv;
+ QStringList text_list = text.split(",");
+ for(int i = 0; i < text_list.size(); ++i) {
+ QString s = text_list.at(i);
+ s = s.remove(QChar(' '));
+ int t = s.toInt(&conv_ok);
+ if(conv_ok) {
+ xv.push_back(t);
+ }
+ else {
+ GR_LOG_WARN(d_logger, "Conversion to integer vector failed");
+ return;
+ }
+ }
+ d_msg = pmt::init_s32vector(xv.size(), xv);
+ }
+ break;
+ case FLOAT:
+ xf = text.toFloat(&conv_ok);
+ if(conv_ok) {
+ d_msg = pmt::from_float(xf);
+ }
+ else {
+ GR_LOG_WARN(d_logger, "Conversion to float failed");
+ return;
+ }
+ break;
+ case FLOAT_VEC:
+ {
+ std::vector<float> xv;
+ QStringList text_list = text.split(",");
+ for(int i = 0; i < text_list.size(); ++i) {
+ QString s = text_list.at(i);
+ s = s.remove(QChar(' '));
+ float t = s.toFloat(&conv_ok);
+ if(conv_ok) {
+ xv.push_back(t);
+ }
+ else {
+ GR_LOG_WARN(d_logger, "Conversion to float vector failed");
+ return;
+ }
+ }
+ d_msg = pmt::init_f32vector(xv.size(), xv);
+ }
+ break;
+ case DOUBLE:
+ xd = text.toDouble(&conv_ok);
+ if(conv_ok) {
+ d_msg = pmt::from_double(xd);
+ }
+ else {
+ GR_LOG_WARN(d_logger, "Conversion to double failed");
+ return;
+ }
+ break;
+ case DOUBLE_VEC:
+ {
+ std::vector<double> xv;
+ QStringList text_list = text.split(",");
+ for(int i = 0; i < text_list.size(); ++i) {
+ QString s = text_list.at(i);
+ s = s.remove(QChar(' '));
+ double t = s.toDouble(&conv_ok);
+ if(conv_ok) {
+ xv.push_back(t);
+ }
+ else {
+ GR_LOG_WARN(d_logger, "Conversion to double vector failed");
+ return;
+ }
+ }
+ d_msg = pmt::init_f64vector(xv.size(), xv);
+ }
+ break;
+ case COMPLEX:
+ try {
+ xc = boost::lexical_cast<gr_complex>(text.toStdString());
+ }
+ catch(boost::bad_lexical_cast const & e) {
+ GR_LOG_WARN(d_logger, boost::format("Conversion to complex failed (%1%)") \
+ % e.what());
+ return;
+ }
+ d_msg = pmt::from_complex(xc.real(), xc.imag());
+ break;
+ case COMPLEX_VEC:
+ {
+ std::vector<gr_complex> xv;
+ QStringList text_list = text.split(",");
+ bool even = false;
+ gr_complex c;
+ float re, im;
+ for(int i = 0; i < text_list.size(); ++i) {
+ QString s = text_list.at(i);
+ s = s.remove(QChar(' '));
+ s = s.remove(QChar(')'));
+ s = s.remove(QChar('('));
+ float t = s.toFloat(&conv_ok);
+ if(conv_ok) {
+ if(even) {
+ im = t;
+ xv.push_back(gr_complex(re, im));
+ even = false;
+ }
+ else {
+ re = t;
+ even = true;
+ }
+ }
+ else {
+ GR_LOG_WARN(d_logger, "Conversion to complex vector failed");
+ return;
+ }
+ }
+ d_msg = pmt::init_c32vector(xv.size(), xv);
+ }
+ break;
+ case STRING:
+ xs = text.toStdString();
+ d_msg = pmt::intern(xs);
+ break;
+ }
+
+ if(d_is_pair) {
+ std::string key = d_key->text().toStdString();
+ d_msg = pmt::cons(pmt::intern(key), d_msg);
+ }
+
+ message_port_pub(pmt::mp("msg"), d_msg);
+ }
+
+ } /* namespace qtgui */
+} /* namespace gr */
diff --git a/gr-qtgui/lib/edit_box_msg_impl.h b/gr-qtgui/lib/edit_box_msg_impl.h
new file mode 100644
index 0000000000..c60b3de9b0
--- /dev/null
+++ b/gr-qtgui/lib/edit_box_msg_impl.h
@@ -0,0 +1,93 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2016 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_EDIT_BOX_MSG_IMPL_H
+#define INCLUDED_QTGUI_EDIT_BOX_MSG_IMPL_H
+
+#include <gnuradio/qtgui/edit_box_msg.h>
+#include <QGroupBox>
+#include <QVBoxLayout>
+#include <QHBoxLayout>
+#include <QLineEdit>
+#include <QComboBox>
+#include <QLabel>
+
+namespace gr {
+ namespace qtgui {
+
+ class QTGUI_API edit_box_msg_impl
+ : public QObject, public edit_box_msg
+ {
+ Q_OBJECT
+
+ private:
+ int d_argc;
+ char *d_argv;
+ data_type_t d_type;
+ bool d_is_pair;
+ bool d_is_static;
+
+ QGroupBox *d_group;
+ QVBoxLayout *d_vlayout;
+ QHBoxLayout *d_hlayout;
+ QLabel *d_label;
+ QLineEdit *d_val;
+ QLineEdit *d_key;
+ QComboBox *d_type_box;
+
+ pmt::pmt_t d_msg;
+
+ public:
+ edit_box_msg_impl(gr::qtgui::data_type_t type,
+ const std::string &value="",
+ const std::string &label="",
+ bool is_pair=false,
+ bool is_static=true,
+ const std::string &key="",
+ QWidget* parent=0);
+ ~edit_box_msg_impl();
+
+ // Overload the start method of gr::block to emit a message if a
+ // default value is provided.
+ bool start();
+
+ void exec_();
+ QWidget* qwidget();
+
+#ifdef ENABLE_PYTHON
+ PyObject* pyqwidget();
+#else
+ void* pyqwidget();
+#endif
+
+ void set_value(pmt::pmt_t val);
+
+ public slots:
+ void edit_finished();
+ void set_type(int);
+ void set_type(gr::qtgui::data_type_t type);
+ };
+
+ } /* namespace qtgui */
+} /* namespace gr */
+
+#endif /* INCLUDED_QTGUI_EDIT_BOX_MSG_IMPL_H */
diff --git a/gr-qtgui/swig/qtgui_swig.i b/gr-qtgui/swig/qtgui_swig.i
index 9664a71786..d9595e4d66 100644
--- a/gr-qtgui/swig/qtgui_swig.i
+++ b/gr-qtgui/swig/qtgui_swig.i
@@ -37,6 +37,18 @@ namespace gr {
NUM_GRAPH_VERT,
};
+ enum data_type_t {
+ INT = 0,
+ FLOAT,
+ DOUBLE,
+ COMPLEX,
+ STRING,
+ INT_VEC,
+ FLOAT_VEC,
+ DOUBLE_VEC,
+ COMPLEX_VEC,
+ };
+
} /* namespace qtgui */
} /* namespace gr */
@@ -75,6 +87,7 @@ enum{
#include "gnuradio/qtgui/number_sink.h"
#include "gnuradio/qtgui/ber_sink_b.h"
#include "gnuradio/qtgui/vector_sink_f.h"
+#include "gnuradio/qtgui/edit_box_msg.h"
%}
%include "gnuradio/qtgui/sink_c.h"
@@ -92,6 +105,7 @@ enum{
%include "gnuradio/qtgui/number_sink.h"
%include "gnuradio/qtgui/ber_sink_b.h"
%include "gnuradio/qtgui/vector_sink_f.h"
+%include "gnuradio/qtgui/edit_box_msg.h"
GR_SWIG_BLOCK_MAGIC2(qtgui, sink_c);
GR_SWIG_BLOCK_MAGIC2(qtgui, sink_f);
@@ -108,3 +122,4 @@ GR_SWIG_BLOCK_MAGIC2(qtgui, histogram_sink_f);
GR_SWIG_BLOCK_MAGIC2(qtgui, number_sink);
GR_SWIG_BLOCK_MAGIC2(qtgui, ber_sink_b);
GR_SWIG_BLOCK_MAGIC2(qtgui, vector_sink_f);
+GR_SWIG_BLOCK_MAGIC2(qtgui, edit_box_msg);