diff options
author | ghostop14 <ghostop14@gmail.com> | 2020-02-02 13:52:39 -0500 |
---|---|---|
committer | devnulling <devnulling@users.noreply.github.com> | 2020-02-19 15:46:54 -0800 |
commit | 5cd7b4cd472e9dca41f19e2cdfed4393374c9fe0 (patch) | |
tree | cb6a607483d03510b90d43c5956e88b691744fff | |
parent | bebed18070bb3366c53f8d1b775c5ed5959859ea (diff) |
gr-qtgui: Incorporate new GUI controls
These updates expand the user interface capabilities of
GNU Radio. This PR includes all of the controls more fully
documented here: https://github.com/ghostop14/gr-guiextra
63 files changed, 8049 insertions, 4 deletions
diff --git a/gr-qtgui/examples/CMakeLists.txt b/gr-qtgui/examples/CMakeLists.txt index 53a03d6b09..7c38dacad4 100644 --- a/gr-qtgui/examples/CMakeLists.txt +++ b/gr-qtgui/examples/CMakeLists.txt @@ -30,5 +30,32 @@ install( qtgui_tags_viewing.grc qtgui_vector_sink_example.grc test_qtgui_msg.grc + test_autocorrelator.grc + test_appbackground.grc + show_controls2.grc + test_toggleswitch.grc + test_toggleswitch2.grc + test_toggle.grc + test_msgpush.grc + test_msgcheckbox.grc + test_levelgauge.grc + test_led.grc + test_graphicscaled.grc + test_graphicitem.grc + test_distanceradar.grc + test_digitalnumcontrol_ro.grc + test_digitalnumcontrol.grc + test_dialcontrol.grc + test_dialcontrol2.grc + test_compass_stream.grc + test_compass.grc + show_dialgauge2.grc + show_dialgauge1.grc + show_controls.grc + test_msgcheckbox_str.grc + test_graphicitem_overlay.grc + gnuradio_logo.png + satdishsmall.png + earth.jpg DESTINATION ${GR_PKG_QTGUI_EXAMPLES_DIR} ) diff --git a/gr-qtgui/examples/earth.jpg b/gr-qtgui/examples/earth.jpg Binary files differnew file mode 100644 index 0000000000..b04dbddec6 --- /dev/null +++ b/gr-qtgui/examples/earth.jpg diff --git a/gr-qtgui/examples/gnuradio_logo.png b/gr-qtgui/examples/gnuradio_logo.png Binary files differnew file mode 100644 index 0000000000..f4941d2c4b --- /dev/null +++ b/gr-qtgui/examples/gnuradio_logo.png diff --git a/gr-qtgui/examples/satdishsmall.png b/gr-qtgui/examples/satdishsmall.png Binary files differnew file mode 100644 index 0000000000..0a893a491e --- /dev/null +++ b/gr-qtgui/examples/satdishsmall.png diff --git a/gr-qtgui/examples/show_controls.grc b/gr-qtgui/examples/show_controls.grc new file mode 100644 index 0000000000..2911093c5c --- /dev/null +++ b/gr-qtgui/examples/show_controls.grc @@ -0,0 +1,334 @@ +options: + parameters: + author: '' + catch_exceptions: 'True' + category: '[GRC Hier Blocks]' + cmake_opt: '' + comment: '' + copyright: '' + description: '' + gen_cmake: 'On' + gen_linking: dynamic + generate_options: qt_gui + hier_block_src_path: '.:' + id: show_controls + max_nouts: '0' + output_language: python + placement: (0,0) + qt_qss_theme: '' + realtime_scheduling: '' + run: 'True' + run_command: '{python} -u {filename}' + run_options: prompt + sizing_mode: fixed + thread_safe_setters: '' + title: Control Demo + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 8] + rotation: 0 + state: enabled + +blocks: +- name: angle + id: variable_qtgui_dial_control + parameters: + comment: '' + gui_hint: 1,0,1,1 + label: Angle + maximum: '360' + minimum: '0' + minsize: '100' + outputmsgname: value + relBackgroundColor: default + scaleFactor: '1' + showvalue: 'True' + type: int + value: '25' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [128, 220.0] + rotation: 0 + state: true +- name: freq + id: qtgui_msgdigitalnumbercontrol + parameters: + ThousandsSeparator: ',' + affinity: '' + alias: '' + comment: '' + gui_hint: 0,0,1,2 + lbl: Frequency + maxFreqHz: 1700e6 + maxoutbuf: '0' + minFreqHz: 30e6 + minoutbuf: '0' + outputmsgname: freq + readOnly: 'False' + relBackgroundColor: black + relFontColor: white + value: 139.712e6 + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [224, 76.0] + rotation: 0 + state: true +- name: gain + id: variable_qtgui_dial_control + parameters: + comment: '' + gui_hint: 1,3,1,1 + label: Gain + maximum: '100' + minimum: '0' + minsize: '100' + outputmsgname: value + relBackgroundColor: aqua + scaleFactor: '1' + showvalue: 'False' + type: int + value: '6' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [712, 204.0] + rotation: 0 + state: true +- name: ledstatus + id: variable_qtgui_toggle_button_msg + parameters: + comment: '' + gui_hint: 0,2,1,1 + initPressed: 'True' + label: LED + outputmsgname: value + pressBackgroundColor: green + pressFontColor: default + pressed: 'True' + relBackgroundColor: red + relFontColor: default + released: 'False' + type: bool + value: 'True' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [552, 12.0] + rotation: 0 + state: true +- name: qtgui_levelgauge_0 + id: qtgui_levelgauge + parameters: + affinity: '' + alias: '' + backgroundColor: default + barColor: default + comment: '' + fontColor: default + gui_hint: 1,4,1,1 + isVertical: 'True' + label: Gain + maximum: '100' + minimum: '0' + msize: '300' + position: '2' + scaleFactor: '1' + showValue: 'False' + type: int + value: gain + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [936, 204.0] + rotation: 0 + state: enabled +- name: qtgui_levelgauge_0_0 + id: qtgui_levelgauge + parameters: + affinity: '' + alias: '' + backgroundColor: yellow + barColor: red + comment: '' + fontColor: default + gui_hint: 2,4,1,1 + isVertical: 'False' + label: Gain + maximum: '100' + minimum: '0' + msize: '300' + position: '2' + scaleFactor: '1' + showValue: 'True' + type: int + value: gain + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [928, 340.0] + rotation: 0 + state: enabled +- name: samp_rate + id: variable + parameters: + comment: '' + value: '32000' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [184, 12] + rotation: 0 + state: enabled +- name: blocks_null_sink_0 + id: blocks_null_sink + parameters: + affinity: '' + alias: '' + bus_structure_sink: '[[0,],]' + comment: '' + num_inputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [696, 448.0] + rotation: 0 + state: true +- name: blocks_null_source_0 + id: blocks_null_source + parameters: + affinity: '' + alias: '' + bus_structure_source: '[[0,],]' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + num_outputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [312, 448.0] + rotation: 0 + state: true +- name: blocks_throttle_0 + id: blocks_throttle + parameters: + affinity: '' + alias: '' + comment: '' + ignoretag: 'True' + maxoutbuf: '0' + minoutbuf: '0' + samples_per_second: samp_rate + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [520, 444.0] + rotation: 0 + state: true +- name: import_0 + id: import + parameters: + alias: '' + comment: '' + imports: import subprocess + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [290, 12] + rotation: 0 + state: true +- name: qtgui_compass_0 + id: qtgui_compass + parameters: + affinity: '' + alias: '' + backgroundColor: white + comment: '' + fullNeedle: '1' + gui_hint: 1,1,2,2 + min_size: '100' + name: Azimuth + needleBodyColor: black + needleTipColor: red + position: '1' + scaleColor: black + setDebug: 'False' + update_time: '0.10' + usemsg: 'True' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [336, 244.0] + rotation: 0 + state: true +- name: qtgui_graphicitem_0 + id: qtgui_graphicitem + parameters: + affinity: '' + alias: '' + comment: '' + file: subprocess.getoutput("gnuradio-config-info --prefix") + "/share/gnuradio/examples/qt-gui/earth.jpg" + fixedsize: 'False' + gui_hint: 0,4,1,1 + height: '0' + scaleImage: 'False' + width: '0' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [975, 36] + rotation: 0 + state: true +- name: qtgui_ledindicator_0 + id: qtgui_ledindicator + parameters: + affinity: '' + alias: '' + cellalignment: '1' + comment: '' + gui_hint: 0,3,1,1 + label: AOS + maxSize: '40' + offColor: red + onColor: green + position: '1' + state: ledstatus + verticalalignment: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [768, 36.0] + rotation: 0 + state: true + +connections: +- [angle, value, qtgui_compass_0, angle] +- [blocks_null_source_0, '0', blocks_throttle_0, '0'] +- [blocks_throttle_0, '0', blocks_null_sink_0, '0'] + +metadata: + file_format: 1 diff --git a/gr-qtgui/examples/show_controls2.grc b/gr-qtgui/examples/show_controls2.grc new file mode 100644 index 0000000000..ee16ed9aab --- /dev/null +++ b/gr-qtgui/examples/show_controls2.grc @@ -0,0 +1,178 @@ +options: + parameters: + author: '' + category: '[GRC Hier Blocks]' + cmake_opt: '' + comment: '' + copyright: '' + description: '' + gen_cmake: 'On' + gen_linking: dynamic + generate_options: qt_gui + hier_block_src_path: '.:' + id: show_controls2 + max_nouts: '0' + output_language: python + placement: (0,0) + qt_qss_theme: '' + realtime_scheduling: '' + run: 'True' + run_command: '{python} -u {filename}' + run_options: prompt + sizing_mode: fixed + thread_safe_setters: '' + title: gr-guiextra + window_size: '' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 8] + rotation: 0 + state: enabled + +blocks: +- name: qtgui_dialgauge_0 + id: qtgui_dialgauge + parameters: + affinity: '' + alias: '' + backgroundColor: white + barColor: red + comment: '' + fontColor: black + gui_hint: 0,2,1,1 + label: '' + maximum: '360.0' + minimum: '0.0' + msize: '160' + position: '1' + showValue: 'True' + type: real + value: '0.0' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [632, 20.0] + rotation: 0 + state: true +- name: samp_rate + id: variable + parameters: + comment: '' + value: '32000' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [184, 12] + rotation: 0 + state: enabled +- name: setval + id: variable_qtgui_dial_control + parameters: + comment: '' + gui_hint: 0,0,1,1 + label: Dial + maximum: '3600.0' + minimum: '0.0' + minsize: '100' + relBackgroundColor: default + scaleFactor: 1/10 + showvalue: 'False' + type: real + value: '1200.0' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [368, 4.0] + rotation: 0 + state: true +- name: toggleswitch + id: variable_qtgui_toggle_switch + parameters: + cellalignment: '1' + comment: '' + gui_hint: 1,0,1,1 + initPressed: 'False' + label: Toggle Switch + position: '4' + pressed: '1' + released: '0' + switchOffBackground: blue + switchOnBackground: green + type: int + value: '0' + verticalalignment: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [576, 184.0] + rotation: 0 + state: true +- name: blocks_null_sink_0 + id: blocks_null_sink + parameters: + affinity: '' + alias: '' + bus_structure_sink: '[[0,],]' + comment: '' + num_inputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [696, 448.0] + rotation: 0 + state: true +- name: blocks_null_source_0 + id: blocks_null_source + parameters: + affinity: '' + alias: '' + bus_structure_source: '[[0,],]' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + num_outputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [312, 448.0] + rotation: 0 + state: true +- name: blocks_throttle_0 + id: blocks_throttle + parameters: + affinity: '' + alias: '' + comment: '' + ignoretag: 'True' + maxoutbuf: '0' + minoutbuf: '0' + samples_per_second: samp_rate + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [520, 444.0] + rotation: 0 + state: true + +connections: +- [blocks_null_source_0, '0', blocks_throttle_0, '0'] +- [blocks_throttle_0, '0', blocks_null_sink_0, '0'] +- [setval, value, qtgui_dialgauge_0, value] + +metadata: + file_format: 1 diff --git a/gr-qtgui/examples/show_dialgauge1.grc b/gr-qtgui/examples/show_dialgauge1.grc new file mode 100644 index 0000000000..0e1e6f4878 --- /dev/null +++ b/gr-qtgui/examples/show_dialgauge1.grc @@ -0,0 +1,170 @@ +options: + parameters: + author: '' + category: '[GRC Hier Blocks]' + cmake_opt: '' + comment: '' + copyright: '' + description: '' + gen_cmake: 'On' + gen_linking: dynamic + generate_options: qt_gui + hier_block_src_path: '.:' + id: test_dialgauge1 + max_nouts: '0' + output_language: python + placement: (0,0) + qt_qss_theme: '' + realtime_scheduling: '' + run: 'True' + run_command: '{python} -u {filename}' + run_options: prompt + sizing_mode: fixed + thread_safe_setters: '' + title: Test Dial Gauge + window_size: '' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 8] + rotation: 0 + state: enabled + +blocks: +- name: qtgui_dialgauge_0 + id: qtgui_dialgauge + parameters: + affinity: '' + alias: '' + backgroundColor: white + barColor: red + comment: '' + fontColor: black + gui_hint: 0,2,1,1 + label: '' + maximum: '360.0' + minimum: '0.0' + msize: '160' + position: '1' + showValue: 'True' + type: real + value: '0.0' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [632, 20.0] + rotation: 0 + state: true +- name: samp_rate + id: variable + parameters: + comment: '' + value: '32000' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [184, 12] + rotation: 0 + state: enabled +- name: throughput + id: variable_qtgui_dial_control + parameters: + comment: '' + gui_hint: 0,0,1,1 + label: Dial + maximum: '3600.0' + minimum: '0.0' + minsize: '100' + outputmsgname: value + relBackgroundColor: default + scaleFactor: 1/10 + showvalue: 'False' + type: real + value: '0.0' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [368, 4.0] + rotation: 0 + state: true +- name: blocks_message_debug_0 + id: blocks_message_debug + parameters: + affinity: '' + alias: '' + comment: '' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [672, 176.0] + rotation: 0 + state: true +- name: blocks_null_sink_0 + id: blocks_null_sink + parameters: + affinity: '' + alias: '' + bus_structure_sink: '[[0,],]' + comment: '' + num_inputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [696, 448.0] + rotation: 0 + state: true +- name: blocks_null_source_0 + id: blocks_null_source + parameters: + affinity: '' + alias: '' + bus_structure_source: '[[0,],]' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + num_outputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [312, 448.0] + rotation: 0 + state: true +- name: blocks_throttle_0 + id: blocks_throttle + parameters: + affinity: '' + alias: '' + comment: '' + ignoretag: 'True' + maxoutbuf: '0' + minoutbuf: '0' + samples_per_second: samp_rate + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [520, 444.0] + rotation: 0 + state: true + +connections: +- [blocks_null_source_0, '0', blocks_throttle_0, '0'] +- [blocks_throttle_0, '0', blocks_null_sink_0, '0'] +- [throughput, value, blocks_message_debug_0, print] +- [throughput, value, qtgui_dialgauge_0, value] + +metadata: + file_format: 1 diff --git a/gr-qtgui/examples/show_dialgauge2.grc b/gr-qtgui/examples/show_dialgauge2.grc new file mode 100644 index 0000000000..467f691d2d --- /dev/null +++ b/gr-qtgui/examples/show_dialgauge2.grc @@ -0,0 +1,154 @@ +options: + parameters: + author: '' + category: '[GRC Hier Blocks]' + cmake_opt: '' + comment: '' + copyright: '' + description: '' + gen_cmake: 'On' + gen_linking: dynamic + generate_options: qt_gui + hier_block_src_path: '.:' + id: test_dialgauge2 + max_nouts: '0' + output_language: python + placement: (0,0) + qt_qss_theme: '' + realtime_scheduling: '' + run: 'True' + run_command: '{python} -u {filename}' + run_options: prompt + sizing_mode: fixed + thread_safe_setters: '' + title: Test Dial Gauge + window_size: '' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 8] + rotation: 0 + state: enabled + +blocks: +- name: qtgui_dialgauge_0 + id: qtgui_dialgauge + parameters: + affinity: '' + alias: '' + backgroundColor: white + barColor: red + comment: '' + fontColor: black + gui_hint: 0,2,1,1 + label: Throughput + maximum: '360.0' + minimum: '0.0' + msize: '160' + position: '2' + showValue: 'True' + type: real + value: throughput + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [632, 20.0] + rotation: 0 + state: true +- name: samp_rate + id: variable + parameters: + comment: '' + value: '32000' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [184, 12] + rotation: 0 + state: enabled +- name: throughput + id: variable_qtgui_dial_control + parameters: + comment: '' + gui_hint: 0,0,1,1 + label: Variable Val + maximum: '3600.0' + minimum: '0.0' + minsize: '100' + relBackgroundColor: default + scaleFactor: 1/10 + showvalue: 'False' + type: real + value: '0.0' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [368, 4.0] + rotation: 0 + state: true +- name: blocks_null_sink_0 + id: blocks_null_sink + parameters: + affinity: '' + alias: '' + bus_structure_sink: '[[0,],]' + comment: '' + num_inputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [696, 448.0] + rotation: 0 + state: true +- name: blocks_null_source_0 + id: blocks_null_source + parameters: + affinity: '' + alias: '' + bus_structure_source: '[[0,],]' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + num_outputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [312, 448.0] + rotation: 0 + state: true +- name: blocks_throttle_0 + id: blocks_throttle + parameters: + affinity: '' + alias: '' + comment: '' + ignoretag: 'True' + maxoutbuf: '0' + minoutbuf: '0' + samples_per_second: samp_rate + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [520, 444.0] + rotation: 0 + state: true + +connections: +- [blocks_null_source_0, '0', blocks_throttle_0, '0'] +- [blocks_throttle_0, '0', blocks_null_sink_0, '0'] + +metadata: + file_format: 1 diff --git a/gr-qtgui/examples/test_appbackground.grc b/gr-qtgui/examples/test_appbackground.grc new file mode 100644 index 0000000000..c606cd2420 --- /dev/null +++ b/gr-qtgui/examples/test_appbackground.grc @@ -0,0 +1,136 @@ +options: + parameters: + author: '' + catch_exceptions: 'True' + category: '[GRC Hier Blocks]' + cmake_opt: '' + comment: '' + copyright: '' + description: '' + gen_cmake: 'On' + gen_linking: dynamic + generate_options: qt_gui + hier_block_src_path: '.:' + id: test_appbackground + max_nouts: '0' + output_language: python + placement: (0,0) + qt_qss_theme: '' + realtime_scheduling: '' + run: 'True' + run_command: '{python} -u {filename}' + run_options: prompt + sizing_mode: fixed + thread_safe_setters: '' + title: Test App Background + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 8] + rotation: 0 + state: enabled + +blocks: +- name: samp_rate + id: variable + parameters: + comment: '' + value: '32000' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [184, 12] + rotation: 0 + state: enabled +- name: blocks_null_sink_0 + id: blocks_null_sink + parameters: + affinity: '' + alias: '' + bus_structure_sink: '[[0,],]' + comment: '' + num_inputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [431, 131] + rotation: 0 + state: true +- name: blocks_null_source_0 + id: blocks_null_source + parameters: + affinity: '' + alias: '' + bus_structure_source: '[[0,],]' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + num_outputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [55, 131] + rotation: 0 + state: true +- name: blocks_throttle_0 + id: blocks_throttle + parameters: + affinity: '' + alias: '' + comment: '' + ignoretag: 'True' + maxoutbuf: '0' + minoutbuf: '0' + samples_per_second: samp_rate + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [229, 127] + rotation: 0 + state: true +- name: import_0 + id: import + parameters: + alias: '' + comment: '' + imports: import subprocess + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [278, 17] + rotation: 0 + state: true +- name: qtgui_grbackground_0 + id: qtgui_grbackground + parameters: + alias: '' + alignment: center + comment: '' + file: subprocess.getoutput("gnuradio-config-info --prefix") + "/share/gnuradio/examples/qt-gui/gnuradio_logo.png" + relBackgroundColor: default + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [438, 22] + rotation: 0 + state: true + +connections: +- [blocks_null_source_0, '0', blocks_throttle_0, '0'] +- [blocks_throttle_0, '0', blocks_null_sink_0, '0'] + +metadata: + file_format: 1 diff --git a/gr-qtgui/examples/test_autocorrelator.grc b/gr-qtgui/examples/test_autocorrelator.grc new file mode 100644 index 0000000000..2bc0339e58 --- /dev/null +++ b/gr-qtgui/examples/test_autocorrelator.grc @@ -0,0 +1,208 @@ +options: + parameters: + author: '' + catch_exceptions: 'True' + category: '[GRC Hier Blocks]' + cmake_opt: '' + comment: '' + copyright: '' + description: '' + gen_cmake: 'On' + gen_linking: dynamic + generate_options: qt_gui + hier_block_src_path: '.:' + id: test_autocorrelator + max_nouts: '0' + output_language: python + placement: (0,0) + qt_qss_theme: '' + realtime_scheduling: '' + run: 'True' + run_command: '{python} -u {filename}' + run_options: prompt + sizing_mode: fixed + thread_safe_setters: '' + title: '' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 8] + rotation: 0 + state: enabled + +blocks: +- name: fac_decimation + id: variable + parameters: + comment: '' + value: '10' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [640, 12] + rotation: 0 + state: enabled +- name: fac_size + id: variable + parameters: + comment: '' + value: '512' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [440, 12] + rotation: 0 + state: enabled +- name: freq + id: variable + parameters: + comment: '' + value: 2441e6 + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [312, 12] + rotation: 0 + state: enabled +- name: samp_rate + id: variable + parameters: + comment: '' + value: 10e3 + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [200, 12] + rotation: 0 + state: enabled +- name: window_time + id: variable + parameters: + comment: '' + value: samp_rate/fac_size + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [528, 12] + rotation: 0 + state: enabled +- name: analog_sig_source_x_0 + id: analog_sig_source_x + parameters: + affinity: '' + alias: '' + amp: '1' + comment: '' + freq: '1000' + maxoutbuf: '0' + minoutbuf: '0' + offset: '0' + phase: '0' + samp_rate: samp_rate + type: complex + waveform: analog.GR_TRI_WAVE + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [216, 272] + rotation: 0 + state: enabled +- name: blocks_throttle_0 + id: blocks_throttle + parameters: + affinity: '' + alias: '' + comment: '' + ignoretag: 'True' + maxoutbuf: '0' + minoutbuf: '0' + samples_per_second: samp_rate + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [448, 300] + rotation: 0 + state: enabled +- name: import_0 + id: import + parameters: + alias: '' + comment: '' + imports: import math + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1112, 20] + rotation: 0 + state: enabled +- name: qtgui_auto_correlator_sink_0 + id: qtgui_auto_correlator_sink + parameters: + affinity: '' + alias: '' + autoScale: 'True' + comment: '' + fac_decimation: '10' + fac_size: '512' + grid: 'True' + gui_hint: 2,0,1,3 + sampRate: samp_rate + title: '""' + useDB: 'True' + yMax: '1' + yMin: '0' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [795, 417] + rotation: 0 + state: true +- name: qtgui_sink_x_0 + id: qtgui_sink_x + parameters: + affinity: '' + alias: '' + bw: samp_rate + comment: '' + fc: freq + fftsize: '1024' + gui_hint: 0,0,1,3 + maxoutbuf: '0' + minoutbuf: '0' + name: '""' + plotconst: 'False' + plotfreq: 'True' + plottime: 'True' + plotwaterfall: 'True' + rate: '10' + showports: 'True' + showrf: 'False' + type: complex + wintype: firdes.WIN_BLACKMAN_hARRIS + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [784, 288] + rotation: 0 + state: enabled + +connections: +- [analog_sig_source_x_0, '0', blocks_throttle_0, '0'] +- [blocks_throttle_0, '0', qtgui_auto_correlator_sink_0, '0'] +- [blocks_throttle_0, '0', qtgui_sink_x_0, '0'] + +metadata: + file_format: 1 diff --git a/gr-qtgui/examples/test_compass.grc b/gr-qtgui/examples/test_compass.grc new file mode 100644 index 0000000000..e02a2fbcb4 --- /dev/null +++ b/gr-qtgui/examples/test_compass.grc @@ -0,0 +1,155 @@ +options: + parameters: + author: '' + category: '[GRC Hier Blocks]' + cmake_opt: '' + comment: '' + copyright: '' + description: '' + gen_cmake: 'On' + gen_linking: dynamic + generate_options: qt_gui + hier_block_src_path: '.:' + id: test_compass + max_nouts: '0' + output_language: python + placement: (0,0) + qt_qss_theme: '' + realtime_scheduling: '' + run: 'True' + run_command: '{python} -u {filename}' + run_options: prompt + sizing_mode: fixed + thread_safe_setters: '' + title: Test Compass + window_size: '' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 8] + rotation: 0 + state: enabled + +blocks: +- name: samp_rate + id: variable + parameters: + comment: '' + value: '32000' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [184, 12] + rotation: 0 + state: enabled +- name: variable_qtgui_dial_control_0 + id: variable_qtgui_dial_control + parameters: + comment: '' + gui_hint: '' + label: Angle + maximum: '360' + minimum: '0' + minsize: '100' + relBackgroundColor: default + scaleFactor: '1' + showvalue: 'True' + type: int + value: '0' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [352, 68.0] + rotation: 0 + state: true +- name: blocks_null_sink_0 + id: blocks_null_sink + parameters: + affinity: '' + alias: '' + bus_structure_sink: '[[0,],]' + comment: '' + num_inputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [680, 304.0] + rotation: 0 + state: true +- name: blocks_null_source_0 + id: blocks_null_source + parameters: + affinity: '' + alias: '' + bus_structure_source: '[[0,],]' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + num_outputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [304, 304.0] + rotation: 0 + state: true +- name: blocks_throttle_0 + id: blocks_throttle + parameters: + affinity: '' + alias: '' + comment: '' + ignoretag: 'True' + maxoutbuf: '0' + minoutbuf: '0' + samples_per_second: samp_rate + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [504, 300.0] + rotation: 0 + state: true +- name: qtgui_compass_0 + id: qtgui_compass + parameters: + affinity: '' + alias: '' + backgroundColor: white + comment: '' + fullNeedle: '1' + gui_hint: '' + min_size: '250' + name: Azimuth + needleBodyColor: black + needleTipColor: red + position: '1' + scaleColor: black + setDebug: 'False' + update_time: '0.10' + usemsg: 'True' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [640, 76.0] + rotation: 0 + state: true + +connections: +- [blocks_null_source_0, '0', blocks_throttle_0, '0'] +- [blocks_throttle_0, '0', blocks_null_sink_0, '0'] +- [variable_qtgui_dial_control_0, value, qtgui_compass_0, angle] + +metadata: + file_format: 1 diff --git a/gr-qtgui/examples/test_compass_stream.grc b/gr-qtgui/examples/test_compass_stream.grc new file mode 100644 index 0000000000..369baa95fc --- /dev/null +++ b/gr-qtgui/examples/test_compass_stream.grc @@ -0,0 +1,135 @@ +options: + parameters: + author: '' + category: '[GRC Hier Blocks]' + cmake_opt: '' + comment: '' + copyright: '' + description: '' + gen_cmake: 'On' + gen_linking: dynamic + generate_options: qt_gui + hier_block_src_path: '.:' + id: test_compass_stream + max_nouts: '0' + output_language: python + placement: (0,0) + qt_qss_theme: '' + realtime_scheduling: '' + run: 'True' + run_command: '{python} -u {filename}' + run_options: prompt + sizing_mode: fixed + thread_safe_setters: '' + title: Test Compass + window_size: '' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 8] + rotation: 0 + state: enabled + +blocks: +- name: az + id: variable_qtgui_range + parameters: + comment: '' + gui_hint: 0,0,1,1 + label: AZ + min_len: '200' + orient: Qt.Horizontal + rangeType: float + start: '0' + step: '1' + stop: '360' + value: '0' + widget: counter_slider + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [296, 20.0] + rotation: 0 + state: true +- name: samp_rate + id: variable + parameters: + comment: '' + value: '32000' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [184, 12] + rotation: 0 + state: enabled +- name: analog_const_source_x_0 + id: analog_const_source_x + parameters: + affinity: '' + alias: '' + comment: '' + const: az + maxoutbuf: '0' + minoutbuf: '0' + type: float + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [88, 220.0] + rotation: 0 + state: true +- name: blocks_throttle_0_0 + id: blocks_throttle + parameters: + affinity: '' + alias: '' + comment: '' + ignoretag: 'True' + maxoutbuf: '0' + minoutbuf: '0' + samples_per_second: samp_rate + type: float + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [304, 220.0] + rotation: 0 + state: true +- name: qtgui_compass_0 + id: qtgui_compass + parameters: + affinity: '' + alias: '' + backgroundColor: white + comment: '' + fullNeedle: '1' + gui_hint: 1,0,1,1 + min_size: '250' + name: Azimuth + needleBodyColor: black + needleTipColor: red + position: '1' + scaleColor: black + setDebug: 'False' + update_time: '0.10' + usemsg: 'False' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [640, 76.0] + rotation: 0 + state: true + +connections: +- [analog_const_source_x_0, '0', blocks_throttle_0_0, '0'] +- [blocks_throttle_0_0, '0', qtgui_compass_0, '0'] + +metadata: + file_format: 1 diff --git a/gr-qtgui/examples/test_dialcontrol.grc b/gr-qtgui/examples/test_dialcontrol.grc new file mode 100644 index 0000000000..923a81a7a5 --- /dev/null +++ b/gr-qtgui/examples/test_dialcontrol.grc @@ -0,0 +1,156 @@ +options: + parameters: + author: '' + category: '[GRC Hier Blocks]' + cmake_opt: '' + comment: '' + copyright: '' + description: '' + gen_cmake: 'On' + gen_linking: dynamic + generate_options: qt_gui + hier_block_src_path: '.:' + id: test_dial + max_nouts: '0' + output_language: python + placement: (0,0) + qt_qss_theme: '' + realtime_scheduling: '' + run: 'True' + run_command: '{python} -u {filename}' + run_options: prompt + sizing_mode: fixed + thread_safe_setters: '' + title: Test Dial Control + window_size: '' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 8] + rotation: 0 + state: enabled + +blocks: +- name: samp_rate + id: variable + parameters: + comment: '' + value: '32000' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [184, 12] + rotation: 0 + state: enabled +- name: variable_qtgui_label_0 + id: variable_qtgui_label + parameters: + comment: '' + formatter: None + gui_hint: 1,0,1,1 + label: Freq + type: int + value: volume + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [944, 44.0] + rotation: 0 + state: enabled +- name: volume + id: variable_qtgui_dial_control + parameters: + comment: '' + gui_hint: '' + label: '' + maximum: '100' + minimum: '0' + relBackgroundColor: default + type: int + value: '0' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [544, 36.0] + rotation: 0 + state: true +- name: blocks_message_debug_0 + id: blocks_message_debug + parameters: + affinity: '' + alias: '' + comment: '' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [744, 104.0] + rotation: 0 + state: enabled +- name: blocks_null_sink_0 + id: blocks_null_sink + parameters: + affinity: '' + alias: '' + bus_structure_sink: '[[0,],]' + comment: '' + num_inputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [680, 304.0] + rotation: 0 + state: true +- name: blocks_null_source_0 + id: blocks_null_source + parameters: + affinity: '' + alias: '' + bus_structure_source: '[[0,],]' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + num_outputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [304, 304.0] + rotation: 0 + state: true +- name: blocks_throttle_0 + id: blocks_throttle + parameters: + affinity: '' + alias: '' + comment: '' + ignoretag: 'True' + maxoutbuf: '0' + minoutbuf: '0' + samples_per_second: samp_rate + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [504, 300.0] + rotation: 0 + state: true + +connections: +- [blocks_null_source_0, '0', blocks_throttle_0, '0'] +- [blocks_throttle_0, '0', blocks_null_sink_0, '0'] +- [volume, value, blocks_message_debug_0, print] + +metadata: + file_format: 1 diff --git a/gr-qtgui/examples/test_dialcontrol2.grc b/gr-qtgui/examples/test_dialcontrol2.grc new file mode 100644 index 0000000000..07318c1581 --- /dev/null +++ b/gr-qtgui/examples/test_dialcontrol2.grc @@ -0,0 +1,157 @@ +options: + parameters: + author: '' + category: '[GRC Hier Blocks]' + cmake_opt: '' + comment: '' + copyright: '' + description: '' + gen_cmake: 'On' + gen_linking: dynamic + generate_options: qt_gui + hier_block_src_path: '.:' + id: test_dial2 + max_nouts: '0' + output_language: python + placement: (0,0) + qt_qss_theme: '' + realtime_scheduling: '' + run: 'True' + run_command: '{python} -u {filename}' + run_options: prompt + sizing_mode: fixed + thread_safe_setters: '' + title: Test Dial Control + window_size: '' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 8] + rotation: 0 + state: enabled + +blocks: +- name: samp_rate + id: variable + parameters: + comment: '' + value: '32000' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [184, 12] + rotation: 0 + state: enabled +- name: variable_qtgui_label_0 + id: variable_qtgui_label + parameters: + comment: '' + formatter: None + gui_hint: 1,0,1,1 + label: Freq + type: real + value: volume + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [696, 28.0] + rotation: 0 + state: enabled +- name: volume + id: variable_qtgui_dial_control + parameters: + comment: '' + gui_hint: '' + label: Volume + maximum: '1000.0' + minimum: '0.0' + relBackgroundColor: default + scaleFactor: 1.0/1000.0 + type: real + value: '0.0' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [544, 36.0] + rotation: 0 + state: true +- name: blocks_message_debug_0 + id: blocks_message_debug + parameters: + affinity: '' + alias: '' + comment: '' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [704, 144.0] + rotation: 0 + state: enabled +- name: blocks_null_sink_0 + id: blocks_null_sink + parameters: + affinity: '' + alias: '' + bus_structure_sink: '[[0,],]' + comment: '' + num_inputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [680, 304.0] + rotation: 0 + state: true +- name: blocks_null_source_0 + id: blocks_null_source + parameters: + affinity: '' + alias: '' + bus_structure_source: '[[0,],]' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + num_outputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [304, 304.0] + rotation: 0 + state: true +- name: blocks_throttle_0 + id: blocks_throttle + parameters: + affinity: '' + alias: '' + comment: '' + ignoretag: 'True' + maxoutbuf: '0' + minoutbuf: '0' + samples_per_second: samp_rate + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [504, 300.0] + rotation: 0 + state: true + +connections: +- [blocks_null_source_0, '0', blocks_throttle_0, '0'] +- [blocks_throttle_0, '0', blocks_null_sink_0, '0'] +- [volume, value, blocks_message_debug_0, print] + +metadata: + file_format: 1 diff --git a/gr-qtgui/examples/test_digitalnumcontrol.grc b/gr-qtgui/examples/test_digitalnumcontrol.grc new file mode 100644 index 0000000000..e84ffb9b2e --- /dev/null +++ b/gr-qtgui/examples/test_digitalnumcontrol.grc @@ -0,0 +1,186 @@ +options: + parameters: + author: '' + catch_exceptions: 'True' + category: '[GRC Hier Blocks]' + cmake_opt: '' + comment: '' + copyright: '' + description: '' + gen_cmake: 'On' + gen_linking: dynamic + generate_options: qt_gui + hier_block_src_path: '.:' + id: test_dignum + max_nouts: '0' + output_language: python + placement: (0,0) + qt_qss_theme: '' + realtime_scheduling: '' + run: 'True' + run_command: '{python} -u {filename}' + run_options: prompt + sizing_mode: fixed + thread_safe_setters: '' + title: Test Digital Number Control + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 8] + rotation: 0 + state: enabled + +blocks: +- name: freq + id: qtgui_msgdigitalnumbercontrol + parameters: + ThousandsSeparator: ',' + affinity: '' + alias: '' + comment: '' + gui_hint: 0,1,1,1 + lbl: Frequency + maxFreqHz: 1700e6 + maxoutbuf: '0' + minFreqHz: 30e6 + minoutbuf: '0' + outputmsgname: freq + readOnly: 'False' + relBackgroundColor: black + relFontColor: white + value: 100e6 + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [424, 52.0] + rotation: 0 + state: true +- name: samp_rate + id: variable + parameters: + comment: '' + value: '32000' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [184, 12] + rotation: 0 + state: enabled +- name: variable_qtgui_label_0 + id: variable_qtgui_label + parameters: + comment: '' + formatter: None + gui_hint: 1,0,1,1 + label: Current Freq + type: real + value: freq + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [944, 44.0] + rotation: 0 + state: enabled +- name: blocks_message_debug_0 + id: blocks_message_debug + parameters: + affinity: '' + alias: '' + comment: '' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [736, 80.0] + rotation: 0 + state: enabled +- name: blocks_null_sink_0 + id: blocks_null_sink + parameters: + affinity: '' + alias: '' + bus_structure_sink: '[[0,],]' + comment: '' + num_inputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [680, 304.0] + rotation: 0 + state: true +- name: blocks_null_source_0 + id: blocks_null_source + parameters: + affinity: '' + alias: '' + bus_structure_source: '[[0,],]' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + num_outputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [304, 304.0] + rotation: 0 + state: true +- name: blocks_throttle_0 + id: blocks_throttle + parameters: + affinity: '' + alias: '' + comment: '' + ignoretag: 'True' + maxoutbuf: '0' + minoutbuf: '0' + samples_per_second: samp_rate + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [504, 300.0] + rotation: 0 + state: true +- name: qtgui_edit_box_msg_0 + id: qtgui_edit_box_msg + parameters: + affinity: '' + alias: '' + comment: '' + gui_hint: 0,0,1,1 + is_pair: 'True' + is_static: 'True' + key: value + label: Msg-based input + maxoutbuf: '0' + minoutbuf: '0' + type: float + value: 90e6 + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [176, 84.0] + rotation: 0 + state: true + +connections: +- [blocks_null_source_0, '0', blocks_throttle_0, '0'] +- [blocks_throttle_0, '0', blocks_null_sink_0, '0'] +- [freq, valueout, blocks_message_debug_0, print] +- [qtgui_edit_box_msg_0, msg, freq, valuein] + +metadata: + file_format: 1 diff --git a/gr-qtgui/examples/test_digitalnumcontrol_ro.grc b/gr-qtgui/examples/test_digitalnumcontrol_ro.grc new file mode 100644 index 0000000000..a7bf47b5ce --- /dev/null +++ b/gr-qtgui/examples/test_digitalnumcontrol_ro.grc @@ -0,0 +1,168 @@ +options: + parameters: + author: '' + catch_exceptions: 'True' + category: '[GRC Hier Blocks]' + cmake_opt: '' + comment: '' + copyright: '' + description: '' + gen_cmake: 'On' + gen_linking: dynamic + generate_options: qt_gui + hier_block_src_path: '.:' + id: test_dignum_ro + max_nouts: '0' + output_language: python + placement: (0,0) + qt_qss_theme: '' + realtime_scheduling: '' + run: 'True' + run_command: '{python} -u {filename}' + run_options: prompt + sizing_mode: fixed + thread_safe_setters: '' + title: Test Digital Number Control + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 8] + rotation: 0 + state: enabled + +blocks: +- name: freq + id: qtgui_msgdigitalnumbercontrol + parameters: + ThousandsSeparator: ',' + affinity: '' + alias: '' + comment: '' + gui_hint: 0,1,1,1 + lbl: Frequency + maxFreqHz: 1700e6 + maxoutbuf: '0' + minFreqHz: 30e6 + minoutbuf: '0' + outputmsgname: freq + readOnly: 'True' + relBackgroundColor: black + relFontColor: gray + value: input_freq + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [424, 52.0] + rotation: 0 + state: true +- name: input_freq + id: variable_qtgui_range + parameters: + comment: '' + gui_hint: 0,0,1,1 + label: '' + min_len: '200' + orient: Qt.Horizontal + rangeType: float + start: 90e6 + step: 1e3 + stop: 100e6 + value: 95.7e6 + widget: counter_slider + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [176, 128.0] + rotation: 0 + state: true +- name: samp_rate + id: variable + parameters: + comment: '' + value: '32000' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [184, 12] + rotation: 0 + state: enabled +- name: blocks_message_debug_0 + id: blocks_message_debug + parameters: + affinity: '' + alias: '' + comment: '' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [736, 80.0] + rotation: 0 + state: enabled +- name: blocks_null_sink_0 + id: blocks_null_sink + parameters: + affinity: '' + alias: '' + bus_structure_sink: '[[0,],]' + comment: '' + num_inputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [680, 304.0] + rotation: 0 + state: true +- name: blocks_null_source_0 + id: blocks_null_source + parameters: + affinity: '' + alias: '' + bus_structure_source: '[[0,],]' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + num_outputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [304, 304.0] + rotation: 0 + state: true +- name: blocks_throttle_0 + id: blocks_throttle + parameters: + affinity: '' + alias: '' + comment: '' + ignoretag: 'True' + maxoutbuf: '0' + minoutbuf: '0' + samples_per_second: samp_rate + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [504, 300.0] + rotation: 0 + state: true + +connections: +- [blocks_null_source_0, '0', blocks_throttle_0, '0'] +- [blocks_throttle_0, '0', blocks_null_sink_0, '0'] +- [freq, valueout, blocks_message_debug_0, print] + +metadata: + file_format: 1 diff --git a/gr-qtgui/examples/test_distanceradar.grc b/gr-qtgui/examples/test_distanceradar.grc new file mode 100644 index 0000000000..0c5068414a --- /dev/null +++ b/gr-qtgui/examples/test_distanceradar.grc @@ -0,0 +1,177 @@ +options: + parameters: + author: '' + category: '[GRC Hier Blocks]' + cmake_opt: '' + comment: '' + copyright: '' + description: '' + gen_cmake: 'On' + gen_linking: dynamic + generate_options: qt_gui + hier_block_src_path: '.:' + id: test_distanceradar + max_nouts: '0' + output_language: python + placement: (0,0) + qt_qss_theme: '' + realtime_scheduling: '' + run: 'True' + run_command: '{python} -u {filename}' + run_options: prompt + sizing_mode: fixed + thread_safe_setters: '' + title: Test Distance Radar + window_size: '' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 8] + rotation: 0 + state: enabled + +blocks: +- name: samp_rate + id: variable + parameters: + comment: '' + value: '32000' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [184, 12] + rotation: 0 + state: enabled +- name: blocks_null_sink_0 + id: blocks_null_sink + parameters: + affinity: '' + alias: '' + bus_structure_sink: '[[0,],]' + comment: '' + num_inputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [744, 424.0] + rotation: 0 + state: true +- name: blocks_null_source_0 + id: blocks_null_source + parameters: + affinity: '' + alias: '' + bus_structure_source: '[[0,],]' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + num_outputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [312, 424.0] + rotation: 0 + state: true +- name: blocks_throttle_0 + id: blocks_throttle + parameters: + affinity: '' + alias: '' + comment: '' + ignoretag: 'True' + maxoutbuf: '0' + minoutbuf: '0' + samples_per_second: samp_rate + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [520, 420.0] + rotation: 0 + state: true +- name: variable_qtgui_distanceradar_0 + id: variable_qtgui_distanceradar + parameters: + backgroundColor: black + comment: '' + fontColor: white + gui_hint: '' + label: Radius + ringColor: red + ticklabels: '[''20'', ''40'', ''60'', ''80'', ''100'']' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [880, 208.0] + rotation: 0 + state: true +- name: variable_qtgui_msg_push_button_0 + id: variable_qtgui_msg_push_button + parameters: + comment: '' + gui_hint: 0,0,1,1 + label: 25% + msgName: radius + type: int + value: '25' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [304, 36.0] + rotation: 0 + state: true +- name: variable_qtgui_msg_push_button_0_0 + id: variable_qtgui_msg_push_button + parameters: + comment: '' + gui_hint: 1,0,1,1 + label: 50% + msgName: radius + type: int + value: '50' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [536, 28.0] + rotation: 0 + state: true +- name: variable_qtgui_msg_push_button_0_0_0 + id: variable_qtgui_msg_push_button + parameters: + comment: '' + gui_hint: 2,0,1,1 + label: 75% + msgName: radius + type: int + value: '75' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [504, 204.0] + rotation: 0 + state: true + +connections: +- [blocks_null_source_0, '0', blocks_throttle_0, '0'] +- [blocks_throttle_0, '0', blocks_null_sink_0, '0'] +- [variable_qtgui_msg_push_button_0, pressed, variable_qtgui_distanceradar_0, radius] +- [variable_qtgui_msg_push_button_0_0, pressed, variable_qtgui_distanceradar_0, radius] +- [variable_qtgui_msg_push_button_0_0_0, pressed, variable_qtgui_distanceradar_0, + radius] + +metadata: + file_format: 1 diff --git a/gr-qtgui/examples/test_graphicitem.grc b/gr-qtgui/examples/test_graphicitem.grc new file mode 100644 index 0000000000..349e20ccd2 --- /dev/null +++ b/gr-qtgui/examples/test_graphicitem.grc @@ -0,0 +1,140 @@ +options: + parameters: + author: '' + catch_exceptions: 'True' + category: '[GRC Hier Blocks]' + cmake_opt: '' + comment: '' + copyright: '' + description: '' + gen_cmake: 'On' + gen_linking: dynamic + generate_options: qt_gui + hier_block_src_path: '.:' + id: test_graphicitem + max_nouts: '0' + output_language: python + placement: (0,0) + qt_qss_theme: '' + realtime_scheduling: '' + run: 'True' + run_command: '{python} -u {filename}' + run_options: prompt + sizing_mode: fixed + thread_safe_setters: '' + title: Test Graphic Item + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 8] + rotation: 0 + state: enabled + +blocks: +- name: samp_rate + id: variable + parameters: + comment: '' + value: '32000' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [184, 12] + rotation: 0 + state: enabled +- name: blocks_null_sink_0 + id: blocks_null_sink + parameters: + affinity: '' + alias: '' + bus_structure_sink: '[[0,],]' + comment: '' + num_inputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [680, 304.0] + rotation: 0 + state: true +- name: blocks_null_source_0 + id: blocks_null_source + parameters: + affinity: '' + alias: '' + bus_structure_source: '[[0,],]' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + num_outputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [304, 304.0] + rotation: 0 + state: true +- name: blocks_throttle_0 + id: blocks_throttle + parameters: + affinity: '' + alias: '' + comment: '' + ignoretag: 'True' + maxoutbuf: '0' + minoutbuf: '0' + samples_per_second: samp_rate + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [504, 300.0] + rotation: 0 + state: true +- name: import_0 + id: import + parameters: + alias: '' + comment: '' + imports: import subprocess + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [286, 15] + rotation: 0 + state: true +- name: qtgui_graphicitem_0 + id: qtgui_graphicitem + parameters: + affinity: '' + alias: '' + comment: '' + file: subprocess.getoutput("gnuradio-config-info --prefix") + "/share/gnuradio/examples/qt-gui/gnuradio_logo.png" + fixedsize: 'False' + gui_hint: '' + height: '100' + scaleImage: 'False' + width: '200' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [528, 20.0] + rotation: 0 + state: true + +connections: +- [blocks_null_source_0, '0', blocks_throttle_0, '0'] +- [blocks_throttle_0, '0', blocks_null_sink_0, '0'] + +metadata: + file_format: 1 diff --git a/gr-qtgui/examples/test_graphicitem_overlay.grc b/gr-qtgui/examples/test_graphicitem_overlay.grc new file mode 100644 index 0000000000..cc1d233717 --- /dev/null +++ b/gr-qtgui/examples/test_graphicitem_overlay.grc @@ -0,0 +1,185 @@ +options: + parameters: + author: '' + catch_exceptions: 'True' + category: '[GRC Hier Blocks]' + cmake_opt: '' + comment: '' + copyright: '' + description: '' + gen_cmake: 'On' + gen_linking: dynamic + generate_options: qt_gui + hier_block_src_path: '.:' + id: test_graphic_overlay + max_nouts: '0' + output_language: python + placement: (0,0) + qt_qss_theme: '' + realtime_scheduling: '' + run: 'True' + run_command: '{python} -u {filename}' + run_options: prompt + sizing_mode: fixed + thread_safe_setters: '' + title: Test Graphic Item Overlay + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 8] + rotation: 0 + state: enabled + +blocks: +- name: overlayfile + id: variable + parameters: + comment: '' + value: subprocess.getoutput("gnuradio-config-info --prefix") + "/share/gnuradio/examples/qt-gui/satdishsmall.png" + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [437, 16] + rotation: 0 + state: true +- name: samp_rate + id: variable + parameters: + comment: '' + value: '32000' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [184, 12] + rotation: 0 + state: enabled +- name: blocks_message_debug_0 + id: blocks_message_debug + parameters: + affinity: '' + alias: '' + comment: '' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [632, 152.0] + rotation: 0 + state: enabled +- name: blocks_null_sink_0 + id: blocks_null_sink + parameters: + affinity: '' + alias: '' + bus_structure_sink: '[[0,],]' + comment: '' + num_inputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [680, 304.0] + rotation: 0 + state: true +- name: blocks_null_source_0 + id: blocks_null_source + parameters: + affinity: '' + alias: '' + bus_structure_source: '[[0,],]' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + num_outputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [304, 304.0] + rotation: 0 + state: true +- name: blocks_throttle_0 + id: blocks_throttle + parameters: + affinity: '' + alias: '' + comment: '' + ignoretag: 'True' + maxoutbuf: '0' + minoutbuf: '0' + samples_per_second: samp_rate + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [504, 300.0] + rotation: 0 + state: true +- name: import_0 + id: import + parameters: + alias: '' + comment: '' + imports: import subprocess + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [283, 22] + rotation: 0 + state: true +- name: qtgui_graphicitem_0 + id: qtgui_graphicitem + parameters: + affinity: '' + alias: '' + comment: '' + file: subprocess.getoutput("gnuradio-config-info --prefix") + "/share/gnuradio/examples/qt-gui/earth.jpg" + fixedsize: 'False' + gui_hint: '' + height: '240' + scaleImage: 'True' + width: '320' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [683, 57] + rotation: 0 + state: true +- name: qtgui_graphicoverlay_0 + id: qtgui_graphicoverlay + parameters: + affinity: '' + alias: '' + comment: '' + listDelay: '1.0' + maxoutbuf: '0' + minoutbuf: '0' + overlayList: '[{''filename'':overlayfile,''x'':10,''y'':0,''scalefactor'':1},{''filename'':overlayfile,''x'':20,''y'':20,''scalefactor'':2},{''filename'':overlayfile,''x'':30,''y'':40,''scalefactor'':2},{''filename'':overlayfile,''x'':40,''y'':60,''scalefactor'':3},{''filename'':overlayfile,''x'':50,''y'':80,''scalefactor'':4}]' + repeat: 'True' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [224, 104.0] + rotation: 0 + state: true + +connections: +- [blocks_null_source_0, '0', blocks_throttle_0, '0'] +- [blocks_throttle_0, '0', blocks_null_sink_0, '0'] +- [qtgui_graphicoverlay_0, overlay, blocks_message_debug_0, print] +- [qtgui_graphicoverlay_0, overlay, qtgui_graphicitem_0, overlay] + +metadata: + file_format: 1 diff --git a/gr-qtgui/examples/test_graphicscaled.grc b/gr-qtgui/examples/test_graphicscaled.grc new file mode 100644 index 0000000000..2da1e07a7d --- /dev/null +++ b/gr-qtgui/examples/test_graphicscaled.grc @@ -0,0 +1,140 @@ +options: + parameters: + author: '' + catch_exceptions: 'True' + category: '[GRC Hier Blocks]' + cmake_opt: '' + comment: '' + copyright: '' + description: '' + gen_cmake: 'On' + gen_linking: dynamic + generate_options: qt_gui + hier_block_src_path: '.:' + id: test_graphicscaled + max_nouts: '0' + output_language: python + placement: (0,0) + qt_qss_theme: '' + realtime_scheduling: '' + run: 'True' + run_command: '{python} -u {filename}' + run_options: prompt + sizing_mode: fixed + thread_safe_setters: '' + title: Test Graphic Item + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 8] + rotation: 0 + state: enabled + +blocks: +- name: samp_rate + id: variable + parameters: + comment: '' + value: '32000' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [184, 12] + rotation: 0 + state: enabled +- name: blocks_null_sink_0 + id: blocks_null_sink + parameters: + affinity: '' + alias: '' + bus_structure_sink: '[[0,],]' + comment: '' + num_inputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [680, 304.0] + rotation: 0 + state: true +- name: blocks_null_source_0 + id: blocks_null_source + parameters: + affinity: '' + alias: '' + bus_structure_source: '[[0,],]' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + num_outputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [304, 304.0] + rotation: 0 + state: true +- name: blocks_throttle_0 + id: blocks_throttle + parameters: + affinity: '' + alias: '' + comment: '' + ignoretag: 'True' + maxoutbuf: '0' + minoutbuf: '0' + samples_per_second: samp_rate + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [504, 300.0] + rotation: 0 + state: true +- name: import_0 + id: import + parameters: + alias: '' + comment: '' + imports: import subprocess + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [286, 26] + rotation: 0 + state: true +- name: qtgui_graphicitem_0 + id: qtgui_graphicitem + parameters: + affinity: '' + alias: '' + comment: '' + file: subprocess.getoutput("gnuradio-config-info --prefix") + "/share/gnuradio/examples/qt-gui/gnuradio_logo.png" + fixedsize: 'False' + gui_hint: '' + height: '100' + scaleImage: 'True' + width: '200' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [528, 20.0] + rotation: 0 + state: true + +connections: +- [blocks_null_source_0, '0', blocks_throttle_0, '0'] +- [blocks_throttle_0, '0', blocks_null_sink_0, '0'] + +metadata: + file_format: 1 diff --git a/gr-qtgui/examples/test_led.grc b/gr-qtgui/examples/test_led.grc new file mode 100644 index 0000000000..e0bd931a77 --- /dev/null +++ b/gr-qtgui/examples/test_led.grc @@ -0,0 +1,168 @@ +options: + parameters: + author: '' + category: '[GRC Hier Blocks]' + cmake_opt: '' + comment: '' + copyright: '' + description: '' + gen_cmake: 'On' + gen_linking: dynamic + generate_options: qt_gui + hier_block_src_path: '.:' + id: test_led + max_nouts: '0' + output_language: python + placement: (0,0) + qt_qss_theme: '' + realtime_scheduling: '' + run: 'True' + run_command: '{python} -u {filename}' + run_options: prompt + sizing_mode: fixed + thread_safe_setters: '' + title: Test LED Indicator + window_size: '' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 8] + rotation: 0 + state: enabled + +blocks: +- name: ledstate + id: variable_qtgui_check_box + parameters: + comment: '' + 'false': 'False' + gui_hint: 0,0,1,1 + label: Variable-based LED State + 'true': 'True' + type: bool + value: 'True' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [768, 36.0] + rotation: 0 + state: true +- name: samp_rate + id: variable + parameters: + comment: '' + value: '32000' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [184, 12] + rotation: 0 + state: enabled +- name: variable_qtgui_toggle_button_msg_0 + id: variable_qtgui_toggle_button_msg + parameters: + comment: '' + gui_hint: 0,1,1,1 + initPressed: 'True' + label: Msg Based State + pressBackgroundColor: default + pressFontColor: default + pressed: 'True' + relBackgroundColor: default + relFontColor: default + released: 'False' + type: bool + value: 'True' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [272, 52.0] + rotation: 0 + state: true +- name: blocks_null_sink_0 + id: blocks_null_sink + parameters: + affinity: '' + alias: '' + bus_structure_sink: '[[0,],]' + comment: '' + num_inputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [680, 304.0] + rotation: 0 + state: true +- name: blocks_null_source_0 + id: blocks_null_source + parameters: + affinity: '' + alias: '' + bus_structure_source: '[[0,],]' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + num_outputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [304, 304.0] + rotation: 0 + state: true +- name: blocks_throttle_0 + id: blocks_throttle + parameters: + affinity: '' + alias: '' + comment: '' + ignoretag: 'True' + maxoutbuf: '0' + minoutbuf: '0' + samples_per_second: samp_rate + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [504, 300.0] + rotation: 0 + state: true +- name: qtgui_ledindicator_0 + id: qtgui_ledindicator + parameters: + affinity: '' + alias: '' + comment: '' + gui_hint: 1,0,1,1 + label: '"State"' + maxSize: '40' + offColor: red + onColor: green + position: '1' + state: ledstate + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [552, 40.0] + rotation: 0 + state: true + +connections: +- [blocks_null_source_0, '0', blocks_throttle_0, '0'] +- [blocks_throttle_0, '0', blocks_null_sink_0, '0'] +- [variable_qtgui_toggle_button_msg_0, state, qtgui_ledindicator_0, state] + +metadata: + file_format: 1 diff --git a/gr-qtgui/examples/test_levelgauge.grc b/gr-qtgui/examples/test_levelgauge.grc new file mode 100644 index 0000000000..d5301f581e --- /dev/null +++ b/gr-qtgui/examples/test_levelgauge.grc @@ -0,0 +1,158 @@ +options: + parameters: + author: '' + category: '[GRC Hier Blocks]' + cmake_opt: '' + comment: '' + copyright: '' + description: '' + gen_cmake: 'On' + gen_linking: dynamic + generate_options: qt_gui + hier_block_src_path: '.:' + id: test_levelgauge + max_nouts: '0' + output_language: python + placement: (0,0) + qt_qss_theme: '' + realtime_scheduling: '' + run: 'True' + run_command: '{python} -u {filename}' + run_options: prompt + sizing_mode: fixed + thread_safe_setters: '' + title: Test Level Gauge + window_size: '' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 8] + rotation: 0 + state: enabled + +blocks: +- name: qtgui_levelgauge_0 + id: qtgui_levelgauge + parameters: + affinity: '' + alias: '' + backgroundColor: default + barColor: default + comment: '' + fontColor: default + gui_hint: 0,1,1,2 + isVertical: 'False' + label: Value Test + maximum: '100' + minimum: '0' + msize: '300' + position: '1' + scaleFactor: '1' + showValue: 'True' + type: int + value: '0' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [664, 60.0] + rotation: 0 + state: true +- name: samp_rate + id: variable + parameters: + comment: '' + value: '32000' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [184, 12] + rotation: 0 + state: enabled +- name: val + id: variable_qtgui_dial_control + parameters: + comment: '' + gui_hint: 0,0,1,1 + label: Value + maximum: '100' + minimum: '0' + minsize: '100' + outputmsgname: value + relBackgroundColor: green + scaleFactor: '1' + showvalue: 'True' + type: int + value: '0' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [360, 52.0] + rotation: 0 + state: true +- name: blocks_null_sink_0 + id: blocks_null_sink + parameters: + affinity: '' + alias: '' + bus_structure_sink: '[[0,],]' + comment: '' + num_inputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [680, 304.0] + rotation: 0 + state: true +- name: blocks_null_source_0 + id: blocks_null_source + parameters: + affinity: '' + alias: '' + bus_structure_source: '[[0,],]' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + num_outputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [304, 304.0] + rotation: 0 + state: true +- name: blocks_throttle_0 + id: blocks_throttle + parameters: + affinity: '' + alias: '' + comment: '' + ignoretag: 'True' + maxoutbuf: '0' + minoutbuf: '0' + samples_per_second: samp_rate + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [504, 300.0] + rotation: 0 + state: true + +connections: +- [blocks_null_source_0, '0', blocks_throttle_0, '0'] +- [blocks_throttle_0, '0', blocks_null_sink_0, '0'] +- [val, value, qtgui_levelgauge_0, value] + +metadata: + file_format: 1 diff --git a/gr-qtgui/examples/test_msgcheckbox.grc b/gr-qtgui/examples/test_msgcheckbox.grc new file mode 100644 index 0000000000..6b3def7561 --- /dev/null +++ b/gr-qtgui/examples/test_msgcheckbox.grc @@ -0,0 +1,157 @@ +options: + parameters: + author: '' + category: '[GRC Hier Blocks]' + cmake_opt: '' + comment: '' + copyright: '' + description: '' + gen_cmake: 'On' + gen_linking: dynamic + generate_options: qt_gui + hier_block_src_path: '.:' + id: test_msgcheckbo + max_nouts: '0' + output_language: python + placement: (0,0) + qt_qss_theme: '' + realtime_scheduling: '' + run: 'True' + run_command: '{python} -u {filename}' + run_options: prompt + sizing_mode: fixed + thread_safe_setters: '' + title: Test Msg Checkbox + window_size: '' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 8] + rotation: 0 + state: enabled + +blocks: +- name: samp_rate + id: variable + parameters: + comment: '' + value: '32000' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [184, 12] + rotation: 0 + state: enabled +- name: state + id: variable_qtgui_msgcheckbox + parameters: + cellalignment: '2' + comment: '' + gui_hint: 1,0,1,1 + initPressed: 'False' + label: State + pressed: '1' + released: '0' + type: int + value: '0' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [416, 80.0] + rotation: 0 + state: true +- name: variable_qtgui_label_0 + id: variable_qtgui_label + parameters: + comment: '' + formatter: None + gui_hint: 0,0,1,1 + label: state + type: int + value: state + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [896, 28.0] + rotation: 0 + state: true +- name: blocks_message_debug_0 + id: blocks_message_debug + parameters: + affinity: '' + alias: '' + comment: '' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [704, 80.0] + rotation: 0 + state: enabled +- name: blocks_null_sink_0 + id: blocks_null_sink + parameters: + affinity: '' + alias: '' + bus_structure_sink: '[[0,],]' + comment: '' + num_inputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [736, 216.0] + rotation: 0 + state: true +- name: blocks_null_source_0 + id: blocks_null_source + parameters: + affinity: '' + alias: '' + bus_structure_source: '[[0,],]' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + num_outputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [304, 208.0] + rotation: 0 + state: true +- name: blocks_throttle_0 + id: blocks_throttle + parameters: + affinity: '' + alias: '' + comment: '' + ignoretag: 'True' + maxoutbuf: '0' + minoutbuf: '0' + samples_per_second: samp_rate + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [512, 212.0] + rotation: 0 + state: true + +connections: +- [blocks_null_source_0, '0', blocks_throttle_0, '0'] +- [blocks_throttle_0, '0', blocks_null_sink_0, '0'] +- [state, state, blocks_message_debug_0, print] + +metadata: + file_format: 1 diff --git a/gr-qtgui/examples/test_msgcheckbox_str.grc b/gr-qtgui/examples/test_msgcheckbox_str.grc new file mode 100644 index 0000000000..653e98d587 --- /dev/null +++ b/gr-qtgui/examples/test_msgcheckbox_str.grc @@ -0,0 +1,176 @@ +options: + parameters: + author: '' + catch_exceptions: 'True' + category: '[GRC Hier Blocks]' + cmake_opt: '' + comment: '' + copyright: '' + description: '' + gen_cmake: 'On' + gen_linking: dynamic + generate_options: qt_gui + hier_block_src_path: '.:' + id: test_msgchkstr + max_nouts: '0' + output_language: python + placement: (0,0) + qt_qss_theme: '' + realtime_scheduling: '' + run: 'True' + run_command: '{python} -u {filename}' + run_options: prompt + sizing_mode: fixed + thread_safe_setters: '' + title: Test Msg Checkbox + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 8] + rotation: 0 + state: enabled + +blocks: +- name: filename + id: variable_qtgui_msgcheckbox + parameters: + cellalignment: '2' + comment: '' + gui_hint: 0,0,1,1 + initPressed: 'False' + label: Change Image + outputmsgname: filename + pressed: subprocess.getoutput("gnuradio-config-info --prefix") + "/share/gnuradio/examples/qt-gui/earth.jpg" + released: subprocess.getoutput("gnuradio-config-info --prefix") + "/share/gnuradio/examples/qt-gui/gnuradio_logo.png" + type: string + value: subprocess.getoutput("gnuradio-config-info --prefix") + "/share/gnuradio/examples/qt-gui/gnuradio_logo.png" + verticalalignment: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [424, 60.0] + rotation: 0 + state: true +- name: samp_rate + id: variable + parameters: + comment: '' + value: '32000' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [184, 12] + rotation: 0 + state: enabled +- name: blocks_message_debug_0 + id: blocks_message_debug + parameters: + affinity: '' + alias: '' + comment: '' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [904, 64.0] + rotation: 0 + state: enabled +- name: blocks_null_sink_0 + id: blocks_null_sink + parameters: + affinity: '' + alias: '' + bus_structure_sink: '[[0,],]' + comment: '' + num_inputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [736, 216.0] + rotation: 0 + state: true +- name: blocks_null_source_0 + id: blocks_null_source + parameters: + affinity: '' + alias: '' + bus_structure_source: '[[0,],]' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + num_outputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [304, 208.0] + rotation: 0 + state: true +- name: blocks_throttle_0 + id: blocks_throttle + parameters: + affinity: '' + alias: '' + comment: '' + ignoretag: 'True' + maxoutbuf: '0' + minoutbuf: '0' + samples_per_second: samp_rate + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [512, 212.0] + rotation: 0 + state: true +- name: import_0 + id: import + parameters: + alias: '' + comment: '' + imports: import subprocess + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [289, 11] + rotation: 0 + state: true +- name: qtgui_graphicitem_0 + id: qtgui_graphicitem + parameters: + affinity: '' + alias: '' + comment: '' + file: subprocess.getoutput("gnuradio-config-info --prefix") + "/share/gnuradio/examples/qt-gui/gnuradio_logo.png" + fixedsize: 'False' + gui_hint: 1,0,1,1 + height: '0' + scaleImage: 'False' + width: '0' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [904, 224.0] + rotation: 0 + state: true + +connections: +- [blocks_null_source_0, '0', blocks_throttle_0, '0'] +- [blocks_throttle_0, '0', blocks_null_sink_0, '0'] +- [filename, state, blocks_message_debug_0, print] +- [filename, state, qtgui_graphicitem_0, filename] + +metadata: + file_format: 1 diff --git a/gr-qtgui/examples/test_msgpush.grc b/gr-qtgui/examples/test_msgpush.grc new file mode 100644 index 0000000000..58e574ebb4 --- /dev/null +++ b/gr-qtgui/examples/test_msgpush.grc @@ -0,0 +1,140 @@ +options: + parameters: + author: '' + category: '[GRC Hier Blocks]' + cmake_opt: '' + comment: '' + copyright: '' + description: '' + gen_cmake: 'On' + gen_linking: dynamic + generate_options: qt_gui + hier_block_src_path: '.:' + id: test_msgpush + max_nouts: '0' + output_language: python + placement: (0,0) + qt_qss_theme: '' + realtime_scheduling: '' + run: 'True' + run_command: '{python} -u {filename}' + run_options: prompt + sizing_mode: fixed + thread_safe_setters: '' + title: Test Message Push Button + window_size: '' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 8] + rotation: 0 + state: enabled + +blocks: +- name: samp_rate + id: variable + parameters: + comment: '' + value: '32000' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [184, 12] + rotation: 0 + state: enabled +- name: blocks_message_debug_0 + id: blocks_message_debug + parameters: + affinity: '' + alias: '' + comment: '' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [704, 80.0] + rotation: 0 + state: enabled +- name: blocks_null_sink_0 + id: blocks_null_sink + parameters: + affinity: '' + alias: '' + bus_structure_sink: '[[0,],]' + comment: '' + num_inputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [736, 216.0] + rotation: 0 + state: true +- name: blocks_null_source_0 + id: blocks_null_source + parameters: + affinity: '' + alias: '' + bus_structure_source: '[[0,],]' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + num_outputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [304, 208.0] + rotation: 0 + state: true +- name: blocks_throttle_0 + id: blocks_throttle + parameters: + affinity: '' + alias: '' + comment: '' + ignoretag: 'True' + maxoutbuf: '0' + minoutbuf: '0' + samples_per_second: samp_rate + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [512, 212.0] + rotation: 0 + state: true +- name: state + id: variable_qtgui_msg_push_button + parameters: + comment: '' + gui_hint: '' + label: state + msgName: pressed + relBackgroundColor: default + relFontColor: default + type: int + value: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [424, 44.0] + rotation: 0 + state: true + +connections: +- [blocks_null_source_0, '0', blocks_throttle_0, '0'] +- [blocks_throttle_0, '0', blocks_null_sink_0, '0'] +- [state, pressed, blocks_message_debug_0, print] + +metadata: + file_format: 1 diff --git a/gr-qtgui/examples/test_toggle.grc b/gr-qtgui/examples/test_toggle.grc new file mode 100644 index 0000000000..ab2cac14c7 --- /dev/null +++ b/gr-qtgui/examples/test_toggle.grc @@ -0,0 +1,167 @@ +options: + parameters: + author: '' + category: '[GRC Hier Blocks]' + cmake_opt: '' + comment: '' + copyright: '' + description: '' + gen_cmake: 'On' + gen_linking: dynamic + generate_options: qt_gui + hier_block_src_path: '.:' + id: test_toggle + max_nouts: '0' + output_language: python + placement: (0,0) + qt_qss_theme: '' + realtime_scheduling: '' + run: 'True' + run_command: '{python} -u {filename}' + run_options: prompt + sizing_mode: fixed + thread_safe_setters: '' + title: Test Toggle Button + window_size: '' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 8] + rotation: 0 + state: enabled + +blocks: +- name: samp_rate + id: variable + parameters: + comment: '' + value: '32000' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [184, 12] + rotation: 0 + state: enabled +- name: state + id: variable_qtgui_toggle_button_msg + parameters: + comment: '' + gui_hint: 0,0,1,1 + initPressed: 'False' + label: State + outputmsgname: value + pressBackgroundColor: default + pressFontColor: default + pressed: '1' + relBackgroundColor: default + relFontColor: default + released: '0' + type: int + value: '0' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [392, 28.0] + rotation: 0 + state: true +- name: blocks_message_debug_0 + id: blocks_message_debug + parameters: + affinity: '' + alias: '' + comment: '' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [704, 80.0] + rotation: 0 + state: enabled +- name: blocks_null_sink_0 + id: blocks_null_sink + parameters: + affinity: '' + alias: '' + bus_structure_sink: '[[0,],]' + comment: '' + num_inputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [736, 216.0] + rotation: 0 + state: true +- name: blocks_null_source_0 + id: blocks_null_source + parameters: + affinity: '' + alias: '' + bus_structure_source: '[[0,],]' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + num_outputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [304, 208.0] + rotation: 0 + state: true +- name: blocks_throttle_0 + id: blocks_throttle + parameters: + affinity: '' + alias: '' + comment: '' + ignoretag: 'True' + maxoutbuf: '0' + minoutbuf: '0' + samples_per_second: samp_rate + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [512, 212.0] + rotation: 0 + state: true +- name: qtgui_ledindicator_0 + id: qtgui_ledindicator + parameters: + affinity: '' + alias: '' + cellalignment: '1' + comment: '' + gui_hint: 0,1,1,1 + label: '"State"' + maxSize: '40' + offColor: red + onColor: green + position: '1' + state: state + verticalalignment: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [912, 44.0] + rotation: 0 + state: true + +connections: +- [blocks_null_source_0, '0', blocks_throttle_0, '0'] +- [blocks_throttle_0, '0', blocks_null_sink_0, '0'] +- [state, state, blocks_message_debug_0, print] + +metadata: + file_format: 1 diff --git a/gr-qtgui/examples/test_toggleswitch.grc b/gr-qtgui/examples/test_toggleswitch.grc new file mode 100644 index 0000000000..3637baeb00 --- /dev/null +++ b/gr-qtgui/examples/test_toggleswitch.grc @@ -0,0 +1,153 @@ +options: + parameters: + author: '' + category: '[GRC Hier Blocks]' + cmake_opt: '' + comment: '' + copyright: '' + description: '' + gen_cmake: 'On' + gen_linking: dynamic + generate_options: qt_gui + hier_block_src_path: '.:' + id: test_toggleswitch + max_nouts: '0' + output_language: python + placement: (0,0) + qt_qss_theme: '' + realtime_scheduling: '' + run: 'True' + run_command: '{python} -u {filename}' + run_options: prompt + sizing_mode: fixed + thread_safe_setters: '' + title: Test Toggle Switch + window_size: '' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 8] + rotation: 0 + state: enabled + +blocks: +- name: ledstate + id: variable_qtgui_toggle_switch + parameters: + cellalignment: '1' + comment: '' + gui_hint: 0,0,1,1 + initPressed: 'False' + label: State + position: '3' + pressed: '1' + released: '0' + switchOffBackground: gray + switchOnBackground: green + type: int + value: '0' + verticalalignment: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [312, 60.0] + rotation: 0 + state: true +- name: samp_rate + id: variable + parameters: + comment: '' + value: '32000' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [184, 12] + rotation: 0 + state: enabled +- name: blocks_null_sink_0 + id: blocks_null_sink + parameters: + affinity: '' + alias: '' + bus_structure_sink: '[[0,],]' + comment: '' + num_inputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [680, 304.0] + rotation: 0 + state: true +- name: blocks_null_source_0 + id: blocks_null_source + parameters: + affinity: '' + alias: '' + bus_structure_source: '[[0,],]' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + num_outputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [304, 304.0] + rotation: 0 + state: true +- name: blocks_throttle_0 + id: blocks_throttle + parameters: + affinity: '' + alias: '' + comment: '' + ignoretag: 'True' + maxoutbuf: '0' + minoutbuf: '0' + samples_per_second: samp_rate + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [504, 300.0] + rotation: 0 + state: true +- name: qtgui_ledindicator_0 + id: qtgui_ledindicator + parameters: + affinity: '' + alias: '' + cellalignment: '1' + comment: '' + gui_hint: 1,0,1,1 + label: '"State"' + maxSize: '40' + offColor: red + onColor: green + position: '1' + state: ledstate + verticalalignment: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [624, 52.0] + rotation: 0 + state: true + +connections: +- [blocks_null_source_0, '0', blocks_throttle_0, '0'] +- [blocks_throttle_0, '0', blocks_null_sink_0, '0'] + +metadata: + file_format: 1 diff --git a/gr-qtgui/examples/test_toggleswitch2.grc b/gr-qtgui/examples/test_toggleswitch2.grc new file mode 100644 index 0000000000..cfd2d0444c --- /dev/null +++ b/gr-qtgui/examples/test_toggleswitch2.grc @@ -0,0 +1,169 @@ +options: + parameters: + author: '' + category: '[GRC Hier Blocks]' + cmake_opt: '' + comment: '' + copyright: '' + description: '' + gen_cmake: 'On' + gen_linking: dynamic + generate_options: qt_gui + hier_block_src_path: '.:' + id: test_toggleswitch2 + max_nouts: '0' + output_language: python + placement: (0,0) + qt_qss_theme: '' + realtime_scheduling: '' + run: 'True' + run_command: '{python} -u {filename}' + run_options: prompt + sizing_mode: fixed + thread_safe_setters: '' + title: Test Toggle Switch + window_size: '' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 8] + rotation: 0 + state: enabled + +blocks: +- name: ledstate_id_0 + id: variable_qtgui_toggle_switch + parameters: + cellalignment: '1' + comment: '' + gui_hint: 0,0,1,1 + initPressed: 'False' + label: Toggle + outputmsgname: value + position: '4' + pressed: '1' + released: '0' + switchOffBackground: gray + switchOnBackground: green + type: int + value: '0' + verticalalignment: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [312, 60.0] + rotation: 0 + state: true +- name: samp_rate + id: variable + parameters: + comment: '' + value: '32000' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [184, 12] + rotation: 0 + state: enabled +- name: blocks_message_debug_0 + id: blocks_message_debug + parameters: + affinity: '' + alias: '' + comment: '' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [688, 168.0] + rotation: 0 + state: true +- name: blocks_null_sink_0 + id: blocks_null_sink + parameters: + affinity: '' + alias: '' + bus_structure_sink: '[[0,],]' + comment: '' + num_inputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [680, 304.0] + rotation: 0 + state: true +- name: blocks_null_source_0 + id: blocks_null_source + parameters: + affinity: '' + alias: '' + bus_structure_source: '[[0,],]' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + num_outputs: '1' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [304, 304.0] + rotation: 0 + state: true +- name: blocks_throttle_0 + id: blocks_throttle + parameters: + affinity: '' + alias: '' + comment: '' + ignoretag: 'True' + maxoutbuf: '0' + minoutbuf: '0' + samples_per_second: samp_rate + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [504, 300.0] + rotation: 0 + state: true +- name: qtgui_ledindicator_0 + id: qtgui_ledindicator + parameters: + affinity: '' + alias: '' + cellalignment: '1' + comment: '' + gui_hint: 1,0,1,1 + label: '"State"' + maxSize: '40' + offColor: red + onColor: green + position: '1' + state: '0' + verticalalignment: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [624, 52.0] + rotation: 0 + state: true + +connections: +- [blocks_null_source_0, '0', blocks_throttle_0, '0'] +- [blocks_throttle_0, '0', blocks_null_sink_0, '0'] +- [ledstate_id_0, state, blocks_message_debug_0, print] +- [ledstate_id_0, state, qtgui_ledindicator_0, state] + +metadata: + file_format: 1 diff --git a/gr-qtgui/grc/qtgui.tree.yml b/gr-qtgui/grc/qtgui.tree.yml index e479adf6af..51bbc807dc 100644 --- a/gr-qtgui/grc/qtgui.tree.yml +++ b/gr-qtgui/grc/qtgui.tree.yml @@ -21,3 +21,20 @@ - variable_qtgui_entry - variable_qtgui_label - qtgui_edit_box_msg + - qtgui_auto_correlator_sink + - qtgui_grbackground + - variable_qtgui_azelplot + - qtgui_compass + - variable_qtgui_dial_control + - qtgui_dialgauge + - variable_qtgui_distanceradar + - qtgui_graphicitem + - qtgui_graphicoverlay + - qtgui_ledindicator + - qtgui_levelgauge + - variable_qtgui_msgcheckbox + - qtgui_msgdigitalnumbercontrol + - variable_qtgui_msg_push_button + - variable_qtgui_toggle_button_msg + - variable_qtgui_toggle_switch +
\ No newline at end of file diff --git a/gr-qtgui/grc/qtgui_appbackground.block.yml b/gr-qtgui/grc/qtgui_appbackground.block.yml new file mode 100644 index 0000000000..639c7693ec --- /dev/null +++ b/gr-qtgui/grc/qtgui_appbackground.block.yml @@ -0,0 +1,48 @@ +id: qtgui_grbackground +label: QT GUI App Background +category: '[Core]/GUI Widgets/QT' +flags: [ python ] + +parameters: +- id: file + label: File + dtype: file_open +- id: alignment + label: Image Alignment + dtype: enum + default: 'center' + options: ['center', 'Top Left'] + option_labels: ['center','top left'] + hide: 'part' +- id: relBackgroundColor + label: Background + dtype: enum + default: 'default' + options: ['default', 'silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + option_labels: ['default','silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + hide: 'part' + +templates: + imports: import PyQt5 + make: |- + None + if "${relBackgroundColor}" != 'default': + bkcolor="background-color: ${relBackgroundColor};" + else: + bkcolor="" + + styleSht = self.styleSheet() + + if len(${file}) > 0: + bkgnd="background-image: url(" + ${file} + "); background-repeat: repeat_n; background-position: " + "${alignment}" + ";" + else: + bkgnd = '' + + styleSht += "QWidget{" + bkgnd + bkcolor + "}" + + self.setStyleSheet(styleSht) + +documentation: |- + This block sets the application window background to the specified graphic and/or color. A standard color name (see background-color style sheet options) can also be provided. + +file_format: 1 diff --git a/gr-qtgui/grc/qtgui_autocorrelator_sink.block.yml b/gr-qtgui/grc/qtgui_autocorrelator_sink.block.yml new file mode 100644 index 0000000000..b7ff072d32 --- /dev/null +++ b/gr-qtgui/grc/qtgui_autocorrelator_sink.block.yml @@ -0,0 +1,85 @@ +id: qtgui_auto_correlator_sink +label: QT GUI Fast Auto-Correlator Sink +category: '[Core]/GUI Widgets/QT' + +parameters: +- id: sampRate + label: Sample Rate + dtype: float + default: samp_rate +- id: fac_size + label: FAC Size + dtype: int + default: '512' +- id: fac_decimation + label: FAC Decimation + dtype: int + default: '10' +- id: useDB + label: Output + dtype: enum + options: ['True', 'False'] + option_labels: [dB, Normalized] +- id: title + label: Title + dtype: string + default: '""' + hide: part +- id: grid + label: Show Grid + dtype: enum + options: ['True', 'False'] + option_labels: ['Yes', 'No'] + hide: part +- id: autoScale + label: Auto-Scale + dtype: enum + options: ['True', 'False'] + option_labels: ['Yes', 'No'] + hide: part +- id: yMin + label: Y Min + dtype: float + default: '0' + hide: part +- id: yMax + label: Y Max + dtype: float + default: '1' + hide: part +- id: gui_hint + label: GUI Hint + dtype: gui_hint + hide: part + +inputs: +- domain: stream + dtype: complex + +templates: + imports: from gnuradio import qtgui + make: |- + <% + win = 'self._%s_win'%id + %>\ + qtgui.AutoCorrelatorSink(${sampRate}, + ${fac_size}, + ${fac_decimation}, + ${title}, + ${autoScale}, + ${grid}, + ${yMin}, + ${yMax}, + ${useDB} + ) + self._${id}_win = self.${id}.getWidget() + ${gui_hint() % win} + +documentation: |- + This block uses the Wiener Khinchin theorem that the FFT of a signal's power spectrum is its auto-correlation function. + + FAC Size controls the FFT size and therefore the length of time (samp_rate/fac_size) the auto-correlation runs over. + + 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. + +file_format: 1 diff --git a/gr-qtgui/grc/qtgui_azelplot.block.yml b/gr-qtgui/grc/qtgui_azelplot.block.yml new file mode 100644 index 0000000000..9acb957eb9 --- /dev/null +++ b/gr-qtgui/grc/qtgui_azelplot.block.yml @@ -0,0 +1,52 @@ +id: variable_qtgui_azelplot +label: QT GUI Az-El Plot +category: '[Core]/GUI Widgets/QT' +flags: [ show_id, python ] + +parameters: +- id: label + label: Label + dtype: string + hide: ${ ('none' if label else 'part') } +- id: backgroundColor + label: Background + dtype: enum + default: 'white' + options: ['#efefef', 'lightgray', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + option_labels: ['background gray','light gray', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + hide: 'part' +- id: dotColor + label: Dot Color + dtype: enum + default: 'ro' + options: ['bo', 'go', 'ro', 'co', 'mo', 'yo', 'ko', 'wo'] + option_labels: ['blue', 'green', 'red', 'cyan', 'magenta', 'yellow', 'black', 'white'] + hide: 'part' +- id: gui_hint + label: GUI Hint + dtype: gui_hint + hide: part + +inputs: +- domain: message + id: azel + optional: false + +templates: + imports: from gnuradio import qtgui + var_make: self.${id} = None + make: |- + <% + win = '_distance_radar_%s'%id + %>\ + ${win} = qtgui.AzElPlot(${label}, "${backgroundColor}", "${dotColor}", self) + self.${id} = ${win} + + ${gui_hint() % win} + +documentation: |- + This block creates a polar plot with azimuth represented as the angle clockwise around the circle, and elevation represented as the radius. 90 degrees elevation is center (directly overhead), while the horizon (0 degrees) is the outside circe. Note that if an elevation < 0 is provided, the marker will turn to an open circle on the perimeter at the specified azimuth angle. + + 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. + +file_format: 1 diff --git a/gr-qtgui/grc/qtgui_compass.block.yml b/gr-qtgui/grc/qtgui_compass.block.yml new file mode 100644 index 0000000000..a40009a7ab --- /dev/null +++ b/gr-qtgui/grc/qtgui_compass.block.yml @@ -0,0 +1,104 @@ +id: qtgui_compass +label: QT GUI Compass +category: '[Core]/GUI Widgets/QT' + +parameters: +- id: name + label: Label + dtype: string + hide: ${ ('none' if len(name) > 0 else 'part') } +- id: position + label: Label Position + dtype: enum + default: '1' + options: ['1', '2'] + option_labels: ['Above', 'Below'] + hide: 'part' +- id: update_time + label: Update Period + dtype: float + default: '0.10' +- id: min_size + label: Min Size (px) + dtype: int + default: '250' +- id: fullNeedle + label: Needle + dtype: enum + options: ['1', '0', '2'] + option_labels: [Full, Indicator, Ambig -Pi to Pi] +- id: usemsg + label: Input Type + dtype: enum + default: 'False' + options: ['False', 'True'] + option_labels: ['Stream', 'Message'] +- id: backgroundColor + label: Backround Color + dtype: enum + default: 'default' + options: ['default', 'silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + option_labels: ['default', 'silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + hide: 'part' +- id: needleTipColor + label: Needle Tip Color + dtype: enum + default: 'red' + options: ['silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + option_labels: ['silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + hide: 'part' +- id: needleBodyColor + label: Needle Body Color + dtype: enum + default: 'black' + options: ['silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + option_labels: ['silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + hide: 'part' +- id: scaleColor + label: Scale Color + dtype: enum + default: 'black' + options: ['silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + option_labels: ['silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + hide: 'part' +- id: setDebug + label: Print Updates + dtype: enum + default: 'False' + options: ['False', 'True'] + option_labels: ['No', 'Yes'] + hide: 'part' +- id: gui_hint + label: GUI Hint + dtype: gui_hint + hide: part + +inputs: +- domain: stream + dtype: float + optional: true +- domain: message + id: angle + optional: true + +templates: + imports: from gnuradio import qtgui + make: |- + <% + win = 'self._%s_win'%id + %>\ + ${win} = qtgui.GrCompass(${name}, ${min_size}, ${update_time}, ${setDebug}, ${fullNeedle},${usemsg},${position},"${backgroundColor}") + ${win}.setColors("${backgroundColor}","${needleTipColor}", "${needleBodyColor}", "${scaleColor}") + self._${id} = ${win} + ${gui_hint() % win} + +documentation: |- + This block takes angle in degrees as input and displays it on a compass. + Args: + update_time: Time-interval between GUI update. + min_val: Min. value displayed on the compass. + max_val: Max. value displayed on the compass. + step: Step-size. + arc_bias: Clockwise rotation applied to dial. + usemsg: Use the message instead of the stream input. +file_format: 1 diff --git a/gr-qtgui/grc/qtgui_dialcontrol.block.yml b/gr-qtgui/grc/qtgui_dialcontrol.block.yml new file mode 100644 index 0000000000..db555dbd7d --- /dev/null +++ b/gr-qtgui/grc/qtgui_dialcontrol.block.yml @@ -0,0 +1,98 @@ +id: variable_qtgui_dial_control +label: QT GUI Dial +category: '[Core]/GUI Widgets/QT' +flags: [ show_id, python ] + +parameters: +- id: label + label: Label + dtype: string + hide: ${ ('none' if label else 'part') } +- id: type + label: Type + dtype: enum + default: int + options: [real, int] + option_labels: [Float, Integer] + option_attributes: + conv: [float, int] + hide: part +- id: value + label: Default Value + dtype: ${ type } + default: '0' +- id: minimum + label: Minimum + dtype: ${ type } + default: '0' +- id: maximum + label: Maximum + dtype: ${ type } + default: '100' +- id: scaleFactor + label: Scale Factor + dtype: ${ type } + default: '1' + hide: ${ ('part' if type=='real' else 'all') } +- id: showvalue + label: Show Value + dtype: bool + default: 'False' +- id: minsize + label: Minimum Size + dtype: int + default: '100' + hide: part +- id: outputmsgname + label: Message Property Name + dtype: string + default: 'value' + hide: 'part' +- id: relBackgroundColor + label: Color + dtype: enum + default: 'default' + options: ['default', 'silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + option_labels: ['default', 'silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + hide: 'part' +- id: gui_hint + label: GUI Hint + dtype: gui_hint + hide: part +value: ${ value } + +outputs: +- domain: message + id: value + optional: true + +templates: + imports: from gnuradio import qtgui + var_make: self.${id} = ${id} = ${value} + make: |- + <% + win = '_%s_dial_control'%id + %>\ + + if "${type}" == "int": + isFloat = False + scaleFactor = 1 + else: + isFloat = True + scaleFactor = ${scaleFactor} + + ${win} = qtgui.GrDialControl(${label}, self, ${minimum},${maximum},${value},"${relBackgroundColor}",self.set_${id},isFloat, scaleFactor, ${minsize}, ${showvalue}, "${outputmsgname}") + self.${id} = ${win} + + ${gui_hint() % win} + +documentation: |- + This block creates a dial control. The control does control a variable which can be used for other items. Leave the label blank to use the variable id as the label. + + The block also creates an optional message with the control value that can be used in message-based applications. + + Note: Dials only produce integer values, so the scale factor can be used with the min/max to adjust the output value to the desired range. Think of the min/max as the increments, and the scale factor as the adjustment to get the values you want. + + 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. + +file_format: 1 diff --git a/gr-qtgui/grc/qtgui_dialgauge.block.yml b/gr-qtgui/grc/qtgui_dialgauge.block.yml new file mode 100644 index 0000000000..d77e4e7265 --- /dev/null +++ b/gr-qtgui/grc/qtgui_dialgauge.block.yml @@ -0,0 +1,104 @@ +id: qtgui_dialgauge +label: QT GUI Dial Gauge +category: '[Core]/GUI Widgets/QT' + +parameters: +- id: label + label: Label + dtype: string + hide: ${ ('none' if label else 'part') } +- id: position + label: Label Position + dtype: enum + default: '1' + options: ['1', '2'] + option_labels: ['Above', 'Below'] + hide: 'part' +- id: type + label: Type + dtype: enum + default: int + options: [real, int] + option_labels: [Float, Integer] + option_attributes: + conv: [float, int] + hide: 'part' +- id: value + label: Value + dtype: ${ type } + default: '0' +- id: minimum + label: Minimum + dtype: ${ type } + default: '0' +- id: maximum + label: Maximum + dtype: ${ type } + default: '100' +- id: showValue + label: Show Value + dtype: bool + default: 'False' +- id: msize + label: Control Size (px) + dtype: int + default: '100' + hide: part +- id: barColor + label: Filled Bar Color + dtype: enum + default: 'blue' + options: ['silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + option_labels: ['silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + hide: 'part' +- id: backgroundColor + label: Empty Bar Color + dtype: enum + default: 'white' + options: ['silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + option_labels: ['silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + hide: 'part' +- id: fontColor + label: Font Color + dtype: enum + default: 'black' + options: ['silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + option_labels: ['silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + hide: 'part' +- id: gui_hint + label: GUI Hint + dtype: gui_hint + hide: part +value: ${ value } + +inputs: +- domain: message + id: value + optional: true + +templates: + imports: from gnuradio import qtgui + make: |- + <% + win = '_%s_lg_win'%id + %>\ + + if "${type}" == "int": + isFloat = False + else: + isFloat = True + + ${win} = qtgui.GrDialGauge(${label},"${barColor}","${backgroundColor}","${fontColor}",${minimum},${maximum}, ${msize}, ${position},isFloat,${showValue},True,self) + ${win}.setValue(${value}) + self.${id} = ${win} + + ${gui_hint() % win} + callbacks: + - self.${id}.setValue(${value}) + +documentation: |- + This block creates a dial-style gauge. The value can be set either with a variable or an input message. + + 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. + +file_format: 1 diff --git a/gr-qtgui/grc/qtgui_distanceradar.block.yml b/gr-qtgui/grc/qtgui_distanceradar.block.yml new file mode 100644 index 0000000000..0960267e74 --- /dev/null +++ b/gr-qtgui/grc/qtgui_distanceradar.block.yml @@ -0,0 +1,64 @@ +id: variable_qtgui_distanceradar +label: QT GUI Distance Radar +flags: [ show_id, python ] +category: '[Core]/GUI Widgets/QT' + +parameters: +- id: label + label: Label + dtype: string + hide: ${ ('none' if label else 'part') } +- id: ticklabels + label: Ring Labels + default: ['20', '40', '60', '80', '100'] +- id: backgroundColor + label: Background + dtype: enum + default: 'black' + options: ['black', 'white', 'blue', 'red', 'green', 'yellow'] + option_labels: ['black', 'white', 'blue', 'red', 'green', 'yellow'] + hide: 'part' +- id: fontColor + label: Font Color + dtype: enum + default: 'white' + options: ['white', 'black', 'blue', 'red', 'green', 'yellow'] + option_labels: ['white', 'black', 'blue', 'red', 'green', 'yellow'] + hide: 'part' +- id: ringColor + label: Ring Color + dtype: enum + default: 'red' + options: ['red', 'white', 'black', 'blue', 'green', 'yellow'] + option_labels: ['red', 'white', 'black', 'blue', 'green', 'yellow'] + hide: 'part' +- id: gui_hint + label: GUI Hint + dtype: gui_hint + hide: part + +inputs: +- domain: message + id: radius + optional: false + +templates: + imports: from gnuradio import qtgui + var_make: self.${id} = None + make: |- + <% + win = '_distance_radar_%s'%id + %>\ + ${win} = qtgui.DistanceRadar(${label}, ${ticklabels}, "${backgroundColor}", "${fontColor}", "${ringColor}", self) + self.${id} = ${win} + + ${gui_hint() % win} + +documentation: |- + This block creates a radar-like screen used to represent distance or size. This can be used in many ways such as circles closer to the center are closer, or just the opposite where closer to the center is smaller. + + Note: Incoming values should range between 0 (center bullseye) and 100 (all the way out) + + 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. + +file_format: 1 diff --git a/gr-qtgui/grc/qtgui_graphicitem.block.yml b/gr-qtgui/grc/qtgui_graphicitem.block.yml new file mode 100644 index 0000000000..5ccc052f4c --- /dev/null +++ b/gr-qtgui/grc/qtgui_graphicitem.block.yml @@ -0,0 +1,55 @@ +id: qtgui_graphicitem +label: QT GUI Graphic Item +category: '[Core]/GUI Widgets/QT' + +parameters: +- id: file + label: File + dtype: file_open +- id: scaleImage + label: Scale Image + dtype: bool + default: 'False' + hide: part +- id: fixedsize + label: Fixed Size + dtype: bool + default: 'False' + hide: ${ 'all' if scaleImage else 'part' } +- id: width + label: Width + dtype: int + default: '0' + hide: ${ 'part' if fixedsize and not scaleImage else 'all' } +- id: height + label: height + dtype: int + default: '0' + hide: ${ 'part' if fixedsize and not scaleImage else 'all' } +- id: gui_hint + label: GUI Hint + dtype: gui_hint + hide: part + +inputs: +- domain: message + id: filename + optional: true +- domain: message + id: overlay + optional: true + +templates: + imports: from gnuradio import qtgui + make: |- + <% + win = 'self._%s_win'%id + %>\ + ${win} = qtgui.GrGraphicItem(${file},${scaleImage},${fixedsize},${width},${height}) + self._${id}_win = ${win} + ${gui_hint() % win} + +documentation: |- + This block displays the selected graphic item. You can pass a filename as a string in a message to change the image on the fly. overlays can also be added by passing in a message with a dictionary of a list of dictionaries in the car portion of the message. Each dicationary should have the following keys: 'filename','x','y', and an optional 'scalefactor'. Setting the x/y attributes to -1,-1 will remove an overlay. Otherwise items are indexed by filename and can be animated throughout the backgound image. + +file_format: 1 diff --git a/gr-qtgui/grc/qtgui_graphicoverlay.block.yml b/gr-qtgui/grc/qtgui_graphicoverlay.block.yml new file mode 100644 index 0000000000..06f04909f1 --- /dev/null +++ b/gr-qtgui/grc/qtgui_graphicoverlay.block.yml @@ -0,0 +1,36 @@ +id: qtgui_graphicoverlay +label: QT GUI Graphic Overlay Sample Source +category: '[Core]/GUI Widgets/QT' + +parameters: +- id: overlayList + label: Overlay Dict or List(dict) + default: "[{'filename':'exampleoverlay.png','x':10,'y':0,'scalefactor':1},{'filename':'exampleoverlay.png','x':20,'y':20,'scalefactor':2},{'filename':'exampleoverlay.png','x':30,'y':40,'scalefactor':2},{'filename':'exampleoverlay.png','x':40,'y':60,'scalefactor':3},{'filename':'exampleoverlay.png','x':50,'y':80,'scalefactor':4}]" + hide: 'part' +- id: listDelay + label: If List Send With Delay (sec) + dtype: real + default: '1.0' + hide: 'part' +- id: repeat + label: If List Repeat + dtype: bool + default: 'True' + hide: 'part' + +outputs: +- domain: message + id: overlay + +templates: + imports: from gnuradio import qtgui + make: qtgui.GrGraphicOverlay(${overlayList},${listDelay},${repeat}) + +documentation: |- + This block is an example of how to feed an overlay to a graphic item. The graphic item overlay is expecting a dictionary with the following keys: 'filename','x','y', and optionally a 'scalefactor'. A list of dictionaries can also be supplied to support multiple items. + + Any file can be added to the graphic item as an overlay and the particular item indexed by its filename can be updated by passing in new x/y coordinates. To remove an overlay, use coordinates -1,-1 for the x,y coordinates. + + This sample block sends either a dictionary or list of dictionaries to the graphicitem block. To test updating a single overlay item, you can use a list with the same file but different coordinates and use the update delay > 0.0 to animate it. + +file_format: 1 diff --git a/gr-qtgui/grc/qtgui_ledindicator.block.yml b/gr-qtgui/grc/qtgui_ledindicator.block.yml new file mode 100644 index 0000000000..e4011bc27a --- /dev/null +++ b/gr-qtgui/grc/qtgui_ledindicator.block.yml @@ -0,0 +1,79 @@ +id: qtgui_ledindicator +label: QT GUI LED Indicator +category: '[Core]/GUI Widgets/QT' + +parameters: +- id: label + label: Label + dtype: string + default: '""' + hide: ${ ('none' if len(label) > 0 else 'part') } +- id: position + label: Label Position + dtype: enum + default: '1' + options: ['1', '2'] + option_labels: ['Above', 'Below'] + hide: 'part' +- id: state + label: State + default: 'False' +- id: onColor + label: On Color + dtype: enum + default: 'green' + options: ['silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + option_labels: ['silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + hide: 'part' +- id: offColor + label: Off Color + dtype: enum + default: 'red' + options: ['silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + option_labels: ['silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + hide: 'part' +- id: maxSize + label: Size + dtype: int + default: '40' + hide: part +- id: cellalignment + label: Cell Alignment + dtype: enum + default: '1' + options: ['1','2','3'] + option_labels: ['Center','Left','Right'] + hide: part +- id: verticalalignment + label: Vertical Alignment + dtype: enum + default: '1' + options: ['1','2','3'] + option_labels: ['Center','Top','Bottom'] + hide: part +- id: gui_hint + label: GUI Hint + dtype: gui_hint + hide: part + +inputs: +- domain: message + id: state + optional: true + +templates: + imports: from gnuradio import qtgui + make: |- + <% + win = 'self._%s_win'%id + %>\ + ${win} = qtgui.GrLEDIndicator(${label}, "${onColor}", "${offColor}", ${state}, ${maxSize}, ${position}, ${cellalignment}, ${verticalalignment}, self) + self.${id} = ${win} + ${gui_hint() % win} + callbacks: + - setState(${state}) + +documentation: |- + This block makes a basic LED indicator + +file_format: 1 diff --git a/gr-qtgui/grc/qtgui_levelgauge.block.yml b/gr-qtgui/grc/qtgui_levelgauge.block.yml new file mode 100644 index 0000000000..c4744d8f85 --- /dev/null +++ b/gr-qtgui/grc/qtgui_levelgauge.block.yml @@ -0,0 +1,120 @@ +id: qtgui_levelgauge +label: QT GUI Level Gauge +category: '[Core]/GUI Widgets/QT' + +parameters: +- id: label + label: Label + dtype: string + hide: ${ ('none' if label else 'part') } +- id: position + label: Label Position + dtype: enum + default: '1' + options: ['1', '2'] + option_labels: ['Above', 'Below'] + hide: 'part' +- id: isVertical + label: Orientation + dtype: enum + default: 'True' + options: ['True', 'False'] + option_labels: ['Vertical', 'Horizontal'] + hide: 'part' +- id: type + label: Type + dtype: enum + default: int + options: [real, int] + option_labels: [Float, Integer] + option_attributes: + conv: [float, int] + hide: part +- id: value + label: Value + dtype: ${ type } + default: '0' +- id: minimum + label: Minimum + dtype: ${ type } + default: '0' +- id: maximum + label: Maximum + dtype: ${ type } + default: '100' +- id: scaleFactor + label: Scale Factor + dtype: ${ type } + default: '1' + hide: ${ ('part' if type=='real' else 'all') } +- id: showValue + label: Show Value + dtype: bool + default: 'False' +- id: msize + label: Control Size + dtype: int + default: '100' + hide: part +- id: barColor + label: Bar Color + dtype: enum + default: 'default' + options: ['default', 'silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + option_labels: ['default', 'silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + hide: 'part' +- id: backgroundColor + label: Background Color + dtype: enum + default: 'default' + options: ['default', 'silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + option_labels: ['default', 'silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + hide: 'part' +- id: fontColor + label: Font Color + dtype: enum + default: 'default' + options: ['default', 'silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + option_labels: ['default', 'silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + hide: 'part' +- id: gui_hint + label: GUI Hint + dtype: gui_hint + hide: part +value: ${ value } + +inputs: +- domain: message + id: value + optional: true + +templates: + imports: from gnuradio import qtgui + make: |- + <% + win = '_%s_lg_win'%id + %>\ + + if "${type}" == "int": + isFloat = False + scaleFactor = 1 + else: + isFloat = True + scaleFactor = ${scaleFactor} + + ${win} = qtgui.GrLevelGauge(${label},"${barColor}","${backgroundColor}","${fontColor}",${minimum},${maximum}, ${msize}, ${isVertical},${position},isFloat,scaleFactor,${showValue},self) + ${win}.setValue(${value}) + self.${id} = ${win} + + ${gui_hint() % win} + callbacks: + - self.${id}.setValue(${value}) + +documentation: |- + This block creates a level gauge. The value can be set either with a variable or an input message. + + NOTE: This control has some quirks due to the fact that QProgressBar only accepts integers. If you want to work with floats, you have to use the scaleFactor to map incoming values to the specified min/max range. For instance if the min/max are 0-100 but your incoming values are 0.0-1.0, you will need to set a scalefactor of 100. + + 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. + +file_format: 1 diff --git a/gr-qtgui/grc/qtgui_msgcheckbox.block.yml b/gr-qtgui/grc/qtgui_msgcheckbox.block.yml new file mode 100644 index 0000000000..34f6d6dc97 --- /dev/null +++ b/gr-qtgui/grc/qtgui_msgcheckbox.block.yml @@ -0,0 +1,89 @@ +id: variable_qtgui_msgcheckbox +label: QT GUI Msg CheckBox +category: '[Core]/GUI Widgets/QT' +flags: [ show_id, python ] + +parameters: +- id: label + label: Label + dtype: string + hide: ${ ('none' if label else 'part') } +- id: type + label: Type + dtype: enum + default: int + options: [real, int, string, bool] + option_labels: [Float, Integer, String, Boolean] + hide: part +- id: value + label: Default Value + dtype: ${ type } + default: '0' +- id: initPressed + label: Initial State + dtype: enum + default: 'False' + options: ['False', 'True'] + option_labels: ['Unchecked', 'Checked'] +- id: pressed + label: Checked + dtype: ${ type } + default: '1' +- id: released + label: Unchecked + dtype: ${ type } + default: '0' +- id: cellalignment + label: Cell Alignment + dtype: enum + default: '1' + options: ['1','2','3'] + option_labels: ['Center','Left','Right'] + hide: part +- id: verticalalignment + label: Vertical Alignment + dtype: enum + default: '1' + options: ['1','2','3'] + option_labels: ['Center','Top','Bottom'] + hide: part +- id: outputmsgname + label: Message Property Name + dtype: string + default: 'value' + hide: 'part' +- id: gui_hint + label: GUI Hint + dtype: gui_hint + hide: part +value: ${ value } + +outputs: +- domain: message + id: state + optional: true + +templates: + imports: from gnuradio import qtgui + var_make: self.${id} = ${id} = ${value} + make: |- + <% + win = '_%s_toggle_button'%id + %>\ + self._${id}_choices = {'Pressed': ${pressed}, 'Released': ${released}} + + ${win} = qtgui.MsgCheckBox(${ 'self.set_' + context.get('id')() }, ${(label if (len(label) - 2 > 0) else repr(id))}, self._${id}_choices, ${initPressed}, ${cellalignment}, ${verticalalignment},"${outputmsgname}".replace("'","")) + self.${id} = ${win} + + ${gui_hint() % win} + +documentation: |- + This block creates a variable checkbox. Leave the label blank to use the variable id as the label. + + A checkbox selects between two values of similar type, but will stay depressed until clicked again. The variable will take on one value or the other depending on whether the button is pressed or released. + + This control will also produce a state message matching the set values. + + 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. + +file_format: 1 diff --git a/gr-qtgui/grc/qtgui_msgdigitalnumbercontrol.block.yml b/gr-qtgui/grc/qtgui_msgdigitalnumbercontrol.block.yml new file mode 100644 index 0000000000..550e3c6d58 --- /dev/null +++ b/gr-qtgui/grc/qtgui_msgdigitalnumbercontrol.block.yml @@ -0,0 +1,89 @@ +id: qtgui_msgdigitalnumbercontrol +label: QT GUI Digital Number Control +category: '[Core]/GUI Widgets/QT' +flags: [ show_id, python ] + +parameters: +- id: lbl + label: Label + dtype: string + hide: ${ ('none' if lbl else 'part') } +- id: minFreqHz + label: Min Freq (Hz) + dtype: float + default: '30e6' +- id: maxFreqHz + label: Max Freq (Hz) + dtype: float + default: '1700e6' +- id: value + label: Value + dtype: real + default: '100e6' +- id: ThousandsSeparator + label: Thousands Separator + dtype: enum + default: ',' + options: [',', '.', '',] + option_labels: ['Comma', 'Period', 'None'] + hide: 'part' +- id: outputmsgname + label: Message Property Name + dtype: string + default: 'freq' + hide: 'part' +- id: relBackgroundColor + label: Background + dtype: enum + default: 'black' + options: ['silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + option_labels: ['silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + hide: 'part' +- id: relFontColor + label: Font Color + dtype: enum + default: 'white' + options: ['silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + option_labels: ['silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + hide: 'part' +- id: readOnly + label: Read Only + dtype: bool + default: 'False' + hide: 'part' +- id: gui_hint + label: GUI Hint + dtype: gui_hint + hide: part +value: ${ value } + +inputs: +- domain: message + id: valuein + optional: true + +outputs: +- domain: message + id: valueout + optional: true + +templates: + imports: from gnuradio import qtgui + var_make: self.${id} = ${id} = ${value} + make: |- + <% + win = 'self._%s_msgdigctl_win'%id + %>\ + ${win} = qtgui.MsgDigitalNumberControl(lbl = ${lbl}, min_freq_hz = ${minFreqHz}, max_freq_hz=${maxFreqHz}, parent=self, thousands_separator="${ThousandsSeparator}",background_color="${relBackgroundColor}",fontColor="${relFontColor}", var_callback=self.set_${id},outputmsgname="${outputmsgname}".replace("'","")) + ${win}.setValue(${value}) + ${win}.setReadOnly(${readOnly}) + self.${id} = ${win} + + ${gui_hint() % win} + callbacks: + - self._${id}_msgdigctl_win.setValue(${value}) + +documentation: |- + While it can be used for anything, this block replicates the frequency control found in many SDR receiver software. + +file_format: 1 diff --git a/gr-qtgui/grc/qtgui_msgpushbutton.block.yml b/gr-qtgui/grc/qtgui_msgpushbutton.block.yml new file mode 100644 index 0000000000..e9d574781e --- /dev/null +++ b/gr-qtgui/grc/qtgui_msgpushbutton.block.yml @@ -0,0 +1,71 @@ +id: variable_qtgui_msg_push_button +label: QT GUI Msg Push Button +category: '[Core]/GUI Widgets/QT' +flags: [ show_id, python ] + +parameters: +- id: label + label: Label + dtype: string + hide: ${ ('none' if label else 'part') } +- id: type + label: Type + dtype: enum + default: int + options: [real, int, string, bool] + option_labels: [Float, Integer, String, Boolean] + option_attributes: + conv: [float, int, str, bool] + hide: part +- id: msgName + label: Message Property Name + dtype: string + default: 'pressed' +- id: value + label: Message Value + dtype: ${ type } + default: '1' +- id: relBackgroundColor + label: Button Background + dtype: enum + default: 'default' + options: ['default', 'silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + option_labels: ['default', 'silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + hide: 'part' +- id: relFontColor + label: Button Font Color + dtype: enum + default: 'default' + options: ['default', 'silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + option_labels: ['default', 'silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + hide: 'part' +- id: gui_hint + label: GUI Hint + dtype: gui_hint + hide: part + +outputs: +- domain: message + id: pressed + optional: false + +templates: + imports: from gnuradio import qtgui + var_make: self.${id} = None + make: |- + <% + win = '_%s_toggle_button'%id + %>\ + ${win} = qtgui.MsgPushButton(${(label if (len(label) - 2 > 0) else repr(id))}, ${msgName},${value},"${relBackgroundColor}","${relFontColor}") + self.${id} = ${win} + + ${gui_hint() % win} + +documentation: |- + This block creates a variable push button that creates a message when clicked. Leave the label blank to use the variable id as the label. + + You can define both the output message pmt name as well as the value and value type. + + 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. + +file_format: 1 diff --git a/gr-qtgui/grc/qtgui_togglebutton.block.yml b/gr-qtgui/grc/qtgui_togglebutton.block.yml new file mode 100644 index 0000000000..abfe522883 --- /dev/null +++ b/gr-qtgui/grc/qtgui_togglebutton.block.yml @@ -0,0 +1,111 @@ +id: variable_qtgui_toggle_button_msg +label: QT GUI Toggle Button +category: '[Core]/GUI Widgets/QT' +flags: [ show_id, python ] + +parameters: +- id: label + label: Label + dtype: string + hide: ${ ('none' if label else 'part') } +- id: type + label: Type + dtype: enum + default: int + options: [real, int, string, bool] + option_labels: [Float, Integer, String, Boolean] + option_attributes: + conv: [float, int, str, bool] + hide: part +- id: value + label: Default Value + dtype: ${ type } + default: '0' +- id: initPressed + label: Initial State + dtype: enum + default: 'False' + options: ['False', 'True'] + option_labels: ['Released', 'Pressed'] +- id: pressed + label: Pressed + dtype: ${ type } + default: '1' +- id: released + label: Released + dtype: ${ type } + default: '0' +- id: outputmsgname + label: Message Property Name + dtype: string + default: 'value' + hide: 'part' +- id: relBackgroundColor + label: Released Background + dtype: enum + default: 'default' + options: ['default', 'silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + option_labels: ['default', 'silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + hide: 'part' +- id: relFontColor + label: Released Font Color + dtype: enum + default: 'default' + options: ['default', 'silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + option_labels: ['default', 'silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + hide: 'part' +- id: pressBackgroundColor + label: Pressed Background + dtype: enum + default: 'default' + options: ['default', 'silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + option_labels: ['default', 'silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + hide: 'part' +- id: pressFontColor + label: Pressed Font Color + dtype: enum + default: 'default' + options: ['default', 'silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + option_labels: ['default', 'silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + hide: 'part' +- id: gui_hint + label: GUI Hint + dtype: gui_hint + hide: part +value: ${ value } + +outputs: +- domain: message + id: state + optional: true + +templates: + imports: from gnuradio import qtgui + var_make: self.${id} = ${id} = ${value} + make: |- + <% + win = '_%s_toggle_button'%id + %>\ + if ${type} == bool: + self._${id}_choices = {'Pressed': bool(${pressed}), 'Released': bool(${released})} + elif ${type} == str: + self._${id}_choices = {'Pressed': "${pressed}".replace("'",""), 'Released': "${released}".replace("'","")} + else: + self._${id}_choices = {'Pressed': ${pressed}, 'Released': ${released}} + + ${win} = qtgui.ToggleButton(${ 'self.set_' + context.get('id')() }, ${(label if (len(label) - 2 > 0) else repr(id))}, self._${id}_choices, ${initPressed},"${outputmsgname}".replace("'","")) + ${win}.setColors("${relBackgroundColor}","${relFontColor}","${pressBackgroundColor}","${pressFontColor}") + self.${id} = ${win} + + ${gui_hint() % win} + +documentation: |- + This block creates a variable toggle button. Leave the label blank to use the variable id as the label. + + A toggle button selects between two values of similar type, but will stay depressed until clicked again. The variable will take on one value or the other depending on whether the button is pressed or released. + + This button will also produce a state message matching the set values. + + 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. + +file_format: 1 diff --git a/gr-qtgui/grc/qtgui_toggleswitch.block.yml b/gr-qtgui/grc/qtgui_toggleswitch.block.yml new file mode 100644 index 0000000000..12580ec891 --- /dev/null +++ b/gr-qtgui/grc/qtgui_toggleswitch.block.yml @@ -0,0 +1,115 @@ +id: variable_qtgui_toggle_switch +label: QT GUI Toggle Switch +category: '[Core]/GUI Widgets/QT' +flags: [ show_id, python ] + +parameters: +- id: label + label: Label + dtype: string + hide: ${ ('none' if label else 'part') } +- id: position + label: Label Position + dtype: enum + default: '4' + options: ['3', '4'] + option_labels: ['Left', 'Right'] + hide: 'part' +- id: type + label: Type + dtype: enum + default: int + options: [real, int, string, bool] + option_labels: [Float, Integer, String, Boolean] + option_attributes: + conv: [float, int, str, bool] + hide: part +- id: value + label: Default Value + dtype: ${ type } + default: '0' +- id: initPressed + label: Initial State + dtype: enum + default: 'False' + options: ['False', 'True'] + option_labels: ['Released', 'Pressed'] +- id: pressed + label: On Value + dtype: ${ type } + default: '1' +- id: released + label: Off Value + dtype: ${ type } + default: '0' +- id: outputmsgname + label: Message Property Name + dtype: string + default: 'value' + hide: 'part' +- id: switchOnBackground + label: Switch On Background + dtype: enum + default: 'green' + options: ['silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + option_labels: ['silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + hide: 'part' +- id: switchOffBackground + label: switchOffBackground + dtype: enum + default: 'gray' + options: ['silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + option_labels: ['silver', 'gray', 'black', 'white', 'red', 'green', 'blue', 'navy', 'yellow', 'orange', 'purple', 'lime', 'aqua', 'teal'] + hide: 'part' +- id: cellalignment + label: Cell Alignment + dtype: enum + default: '1' + options: ['1','2','3'] + option_labels: ['Center','Left','Right'] + hide: part +- id: verticalalignment + label: Vertical Alignment + dtype: enum + default: '1' + options: ['1','2','3'] + option_labels: ['Center','Top','Bottom'] + hide: part +- id: gui_hint + label: GUI Hint + dtype: gui_hint + hide: part +value: ${ value } + +outputs: +- domain: message + id: state + optional: true + +templates: + imports: from gnuradio import qtgui + var_make: self.${id} = ${id} = ${value} + make: |- + <% + win = '_%s_toggle_button'%id + %>\ + if ${type} == bool: + self._${id}_choices = {'Pressed': bool(${pressed}), 'Released': bool(${released})} + elif ${type} == str: + self._${id}_choices = {'Pressed': "${pressed}".replace("'",""), 'Released': "${released}".replace("'","")} + else: + self._${id}_choices = {'Pressed': ${pressed}, 'Released': ${released}} + + ${win} = qtgui.GrToggleSwitch(${ 'self.set_' + context.get('id')() }, ${label}, self._${id}_choices, ${initPressed},"${switchOnBackground}","${switchOffBackground}",${position}, 50, ${cellalignment}, ${verticalalignment},self,"${outputmsgname}".replace("'","")) + self.${id} = ${win} + + ${gui_hint() % win} + +documentation: |- + This block creates a modern toggle switch. The variable will take on one value or the other as set in the dialog. + + This button will also produce a state message matching the set values. + + 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. + +file_format: 1 diff --git a/gr-qtgui/python/qtgui/CMakeLists.txt b/gr-qtgui/python/qtgui/CMakeLists.txt index 2041038c84..bdac9ede9c 100644 --- a/gr-qtgui/python/qtgui/CMakeLists.txt +++ b/gr-qtgui/python/qtgui/CMakeLists.txt @@ -15,8 +15,23 @@ configure_file(util.py.cmakein "${CMAKE_CURRENT_BINARY_DIR}/util.py" @ONLY) GR_PYTHON_INSTALL( FILES __init__.py - "${CMAKE_CURRENT_BINARY_DIR}/range.py" - "${CMAKE_CURRENT_BINARY_DIR}/util.py" + compass.py + togglebutton.py + msgpushbutton.py + msgcheckbox.py + distanceradar.py + azelplot.py + digitalnumbercontrol.py + dialcontrol.py + ledindicator.py + graphicitem.py + levelgauge.py + dialgauge.py + toggleswitch.py + graphicoverlay.py + auto_correlator_sink.py + "${CMAKE_CURRENT_BINARY_DIR}/range.py" + "${CMAKE_CURRENT_BINARY_DIR}/util.py" DESTINATION ${GR_PYTHON_DIR}/gnuradio/qtgui ) diff --git a/gr-qtgui/python/qtgui/__init__.py b/gr-qtgui/python/qtgui/__init__.py index b56e2f78bd..d727748130 100644 --- a/gr-qtgui/python/qtgui/__init__.py +++ b/gr-qtgui/python/qtgui/__init__.py @@ -1,5 +1,5 @@ # -# Copyright 2011 Free Software Foundation, Inc. +# Copyright 2011, 2020 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -25,3 +25,22 @@ except ImportError: from .range import Range, RangeWidget from . import util + +from .compass import GrCompass +from .togglebutton import ToggleButton +from .msgpushbutton import MsgPushButton +from .distanceradar import DistanceRadar +from .azelplot import AzElPlot +from .msgcheckbox import MsgCheckBox +from .digitalnumbercontrol import MsgDigitalNumberControl +from .dialcontrol import GrDialControl +from .ledindicator import GrLEDIndicator +from .graphicitem import GrGraphicItem +from .levelgauge import GrLevelGauge +from .dialgauge import GrDialGauge +from .toggleswitch import GrToggleSwitch +from .graphicoverlay import GrGraphicOverlay +from .auto_correlator_sink import AutoCorrelatorSink +from .auto_correlator_sink import AutoCorrelator +from .auto_correlator_sink import Normalize + diff --git a/gr-qtgui/python/qtgui/auto_correlator_sink.py b/gr-qtgui/python/qtgui/auto_correlator_sink.py new file mode 100644 index 0000000000..877e60d0ad --- /dev/null +++ b/gr-qtgui/python/qtgui/auto_correlator_sink.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2020 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# + +import math +import sip + +from gnuradio import gr +from gnuradio import qtgui +from gnuradio import blocks, fft, filter + +from PyQt5 import QtGui +from PyQt5.QtWidgets import QWidget + +class Normalize(gr.hier_block2): + def __init__(self, vecsize=1024): + gr.hier_block2.__init__( + self, "Normalize", + gr.io_signature(1, 1, gr.sizeof_float*vecsize), + gr.io_signature(1, 1, gr.sizeof_float*vecsize), + ) + + ################################################## + # Parameters + ################################################## + self.vecsize = vecsize + + ################################################## + # Blocks + ################################################## + self.blocks_stream_to_vector_0 = blocks.stream_to_vector(gr.sizeof_float, vecsize) + self.blocks_repeat_0 = blocks.repeat(gr.sizeof_float, vecsize) + self.blocks_max_xx_0 = blocks.max_ff(vecsize) + self.blocks_divide_xx_0 = blocks.divide_ff(vecsize) + + ################################################## + # Connections + ################################################## + self.connect((self.blocks_divide_xx_0, 0), (self, 0)) + self.connect((self.blocks_stream_to_vector_0, 0), (self.blocks_divide_xx_0, 1)) + self.connect((self, 0), (self.blocks_max_xx_0, 0)) + self.connect((self.blocks_repeat_0, 0), (self.blocks_stream_to_vector_0, 0)) + self.connect((self.blocks_max_xx_0, 0), (self.blocks_repeat_0, 0)) + self.connect((self, 0), (self.blocks_divide_xx_0, 0)) + + + def get_vecsize(self): + return self.vecsize + + def set_vecsize(self, vecsize): + self.vecsize = vecsize + +class AutoCorrelator(gr.hier_block2): + """ + This block uses the Wiener Khinchin theorem that the FFT of a signal's + power spectrum is its auto-correlation function. + FAC Size controls the FFT size and therefore the length of time + (samp_rate/fac_size) the auto-correlation runs over. + """ + def __init__(self, sample_rate, fac_size, fac_decimation, use_db): + gr.hier_block2.__init__(self,"AutoCorrelator", + gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input sig + gr.io_signature(1, 1, gr.sizeof_float*fac_size)) # Output sig + + self.fac_size = fac_size + self.fac_decimation = fac_decimation + self.sample_rate = sample_rate + + streamToVec = blocks.stream_to_vector(gr.sizeof_gr_complex, self.fac_size) + # Make sure N is at least 1 + decimation = int(self.sample_rate/self.fac_size/self.fac_decimation) + self.one_in_n = blocks.keep_one_in_n(gr.sizeof_gr_complex * self.fac_size, max(1, decimation)) + + # FFT Note: No windowing. + fac = fft.fft_vcc(self.fac_size, True, ()) + + complex2Mag = blocks.complex_to_mag(self.fac_size) + self.avg = filter.single_pole_iir_filter_ff_make(1.0, self.fac_size) + + fac_fac = fft.fft_vfc(self.fac_size, True, ()) + fac_c2mag = blocks.complex_to_mag_make(fac_size) + + # There's a note in Baz's block about needing to add 3 dB to each bin but the DC bin, however it was never implemented + n = 20 + k = -20 * math.log10(self.fac_size) + log = blocks.nlog10_ff_make(n, self.fac_size, k) + + if use_db: + self.connect(self, streamToVec, self.one_in_n, fac, complex2Mag, fac_fac, fac_c2mag, self.avg, log, self) + else: + self.connect(self, streamToVec, self.one_in_n, fac, complex2Mag, fac_fac, fac_c2mag, self.avg, self) + +class AutoCorrelatorSink(gr.hier_block2): + """ + docstring for block AutoCorrelatorSink + """ + def __init__(self, sample_rate, fac_size, fac_decimation, title, autoScale, grid, yMin, yMax, use_db): + gr.hier_block2.__init__(self, + "AutoCorrelatorSink", + gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature + gr.io_signature(0, 0, 0)) # Output signature + + self.fac_size = fac_size + self.fac_decimation = fac_decimation + self.sample_rate = sample_rate + + autoCorr = AutoCorrelator(sample_rate, fac_size, fac_decimation, use_db) + vecToStream = blocks.vector_to_stream(gr.sizeof_float, self.fac_size) + + self.timeSink = qtgui.time_sink_f(self.fac_size/2, sample_rate, title, 1) + self.timeSink.enable_grid(grid) + self.timeSink.set_y_axis(yMin, yMax) + self.timeSink.enable_autoscale(autoScale) + self.timeSink.disable_legend() + self.timeSink.set_update_time(0.1) + + if use_db: + self.connect(self, autoCorr, vecToStream, self.timeSink) + else: + norm = Normalize(self.fac_size) + self.connect(self, autoCorr, norm, vecToStream, self.timeSink) + + + def getWidget(self): + return sip.wrapinstance(self.timeSink.pyqwidget(), QWidget) diff --git a/gr-qtgui/python/qtgui/azelplot.py b/gr-qtgui/python/qtgui/azelplot.py new file mode 100644 index 0000000000..d23d39234d --- /dev/null +++ b/gr-qtgui/python/qtgui/azelplot.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2020 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# + +from PyQt5 import QtWidgets +import numpy as np +from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas +from matplotlib.figure import Figure +import math + +from gnuradio import gr +import pmt + +class AzElPlot(gr.sync_block, FigureCanvas): + """ + This block creates a polar plot with azimuth represented as the angle + clockwise around the circle, and elevation represented as the radius. + 90 degrees elevation is center (directly overhead), + while the horizon (0 degrees) is the outside circe. Note that if an + elevation < 0 is provided, the marker will turn to an open circle + on the perimeter at the specified azimuth angle. + """ + def __init__(self, lbl, backgroundColor, dotColor, Parent=None, + width=4, height=4, dpi=90): + gr.sync_block.__init__(self, name = "MsgPushButton", in_sig = None, + out_sig = None) + + self.lbl = lbl + + self.message_port_register_in(pmt.intern("azel")) + self.set_msg_handler(pmt.intern("azel"), self.msgHandler) + + self.dotColor = dotColor + self.backgroundColor = backgroundColor + self.scaleColor = 'black' + if (self.backgroundColor == 'black'): + self.scaleColor = 'white' + + self.fig = Figure(figsize=(width, height), dpi=dpi) + self.fig.patch.set_facecolor(self.backgroundColor) + + self.axes = self.fig.add_subplot(111, polar=True, facecolor=self.backgroundColor) + + # Create an "invisible" line at 90 to set the max for the plot + self.axes.plot(np.linspace(0, 2*np.pi, 90), np.ones(90)*90, color=self.scaleColor, + linestyle='') + + # Plot line: Initialize out to 90 and blank + radius = 90 + self.blackline = self.axes.plot(np.linspace(0, 2*np.pi, 90), np.ones(90)*radius, + color=self.scaleColor, linestyle='-') + self.reddot = None + + # Rotate zero up + self.axes.set_theta_zero_location("N") + + # Set limits: + self.axes.set_rlim(0, 90) + + self.axes.set_yticklabels([], color=self.scaleColor) + self.axes.set_xticklabels(['0', '315', '270', '225', '180', '135', '90', '45'], + color=self.scaleColor) + + FigureCanvas.__init__(self, self.fig) + self.setParent(Parent) + + self.title = self.fig.suptitle(self.lbl, fontsize=8, fontweight='bold', color='black') + + FigureCanvas.setSizePolicy(self, + QtWidgets.QSizePolicy.Expanding, + QtWidgets.QSizePolicy.Expanding) + + self.setMinimumSize(240, 230) + FigureCanvas.updateGeometry(self) + + def msgHandler(self, msg): + new_val = None + + try: + new_val = pmt.to_python(pmt.car(msg)) + if new_val is not None: + if type(new_val) == dict: + if 'az' in new_val and 'el' in new_val: + self.updateData(float(new_val['az']), float(new_val['el'])) + else: + gr.log.error("az and el keys were not found in the dictionary.") + else: + gr.log.error("Value received was not a dictionary. Expecting a dictionary " + "in the car message component with az and el keys.") + else: + gr.log.error("The CAR section of the inbound message was None. " + "This part should contain the dictionary with 'az' and 'el' float keys.") + except Exception as e: + gr.log.error("[AzElPlot] Error with message conversion: %s" % str(e)) + if new_val is not None: + gr.log.error(str(new_val)) + + def updateData(self, azimuth, elevation): + if self.reddot is not None: + self.reddot.pop(0).remove() + + # Plot is angle, radius where angle is in radians + + if (elevation > 0): + # Need to reverse elevation. 90 degrees is center (directly overhead), + # and 90 degrees is horizon. + if (elevation > 90.0): + elevation = 90.0 + + convertedElevation = 90.0 - elevation + # Note: +azimuth for the plot is measured counter-clockwise, so need to reverse it. + self.reddot = self.axes.plot(-azimuth * math.pi/180.0, convertedElevation, self.dotColor, + markersize=8) + else: + # It's below the horizon. Show an open circle at the perimeter + elevation = 0.0 + self.reddot = self.axes.plot(-azimuth * math.pi/180.0, 89.0, self.dotColor, + markerfacecolor="None", markersize=16, fillstyle=None) + + self.draw() + diff --git a/gr-qtgui/python/qtgui/compass.py b/gr-qtgui/python/qtgui/compass.py new file mode 100644 index 0000000000..2c8a766f14 --- /dev/null +++ b/gr-qtgui/python/qtgui/compass.py @@ -0,0 +1,290 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2020 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# + +import time +import numpy +from gnuradio import gr +import pmt + +# First Qt and 2nd Qt are different. You'll get errors if they're both not available, +# hence the import-as to avoid name collisions + +from PyQt5 import Qt +from PyQt5.QtCore import Qt as Qtc +from PyQt5.QtCore import pyqtSignal, QPoint, pyqtProperty +from PyQt5.QtWidgets import QFrame, QWidget, QVBoxLayout, QHBoxLayout, QLabel +from PyQt5.QtGui import QPainter, QPalette, QFont, QFontMetricsF, QPen, QPolygon, QColor, QBrush + +NeedleFull = 1 +NeedleIndicator = 0 +NeedleMirrored = 2 + +class LabeledCompass(QFrame): + def __init__(self, lbl, min_size, update_time, setDebug=False, + needleType=NeedleFull, position=1, backgroundColor='default'): + # Positions: 1 = above, 2=below, 3=left, 4=right + QFrame.__init__(self) + self.numberControl = Compass(min_size, update_time, setDebug, + needleType, position, backgroundColor) + + if position < 3: + layout = QVBoxLayout() + else: + layout = QHBoxLayout() + + self.lbl = lbl + self.lblcontrol = QLabel(lbl, self) + self.lblcontrol.setAlignment(Qtc.AlignCenter) + + # add top or left + if lbl: + if position == 1 or position == 3: + layout.addWidget(self.lblcontrol) + else: + self.hasLabel = False + + layout.addWidget(self.numberControl) + + # Add bottom or right + if lbl: + if position == 2 or position == 4: + layout.addWidget(self.lblcontrol) + + layout.setAlignment(Qtc.AlignCenter | Qtc.AlignVCenter) + self.setLayout(layout) + + if lbl: + self.setMinimumSize(min_size+30, min_size+35) + else: + self.setMinimumSize(min_size, min_size) + + self.show() + def change_angle(self, angle): + self.numberControl.change_angle(angle) + + def setColors(self, backgroundColor='default', needleTip='red', needleBody='black', + scaleColor='black'): + self.numberControl.setColors(backgroundColor, needleTip, needleBody, scaleColor) + +class Compass(QWidget): + angleChanged = pyqtSignal(float) + + def __init__(self, min_size, update_time, setDebug=False, needleType=NeedleFull, + position=1, backgroundColor='default'): + QWidget.__init__(self, None) + + # Set parameters + self.debug = setDebug + self.needleType = needleType + self.update_period = update_time + self.last = time.time() + self.next_angle = 0 + + self._angle = 0.0 + self._margins = 2 + self._pointText = {0: "0", 45: "45", 90: "90", 135: "135", 180: "180", + 225: "225", 270: "270", 315: "315"} + + self.setMinimumSize(min_size, min_size) + self.setSizePolicy(Qt.QSizePolicy.Expanding, Qt.QSizePolicy.Expanding) + + self.backgroundColor = backgroundColor + self.needleTipColor = 'red' + self.needleBodyColor = 'black' + self.scaleColor = 'black' + + def setColors(self, backgroundColor='default', needleTipColor='red', needleBodyColor='black', + scaleColor='black'): + self.backgroundColor = backgroundColor + self.needleTipColor = needleTipColor + self.needleBodyColor = needleBodyColor + self.scaleColor = scaleColor + + super().update() + + def paintEvent(self, event): + painter = QPainter() + painter.begin(self) + painter.setRenderHint(QPainter.Antialiasing) + + if self.backgroundColor == 'default': + painter.fillRect(event.rect(), self.palette().brush(QPalette.Window)) + else: + size = self.size() + center_x = size.width()/2 + diameter = size.height() + brush = QBrush(QColor(self.backgroundColor), Qtc.SolidPattern) + painter.setBrush(brush) + painter.setPen(QPen(QColor(self.scaleColor), 2)) + painter.setRenderHint(QPainter.Antialiasing) + painter.drawEllipse(center_x-diameter/2+1, 1, diameter-4, diameter-4) + + self.drawMarkings(painter) + self.drawNeedle(painter) + + painter.end() + + def drawMarkings(self, painter): + painter.save() + painter.translate(self.width()/2, self.height()/2) + scale = min((self.width() - self._margins)/120.0, + (self.height() - self._margins)/120.0) + painter.scale(scale, scale) + + font = QFont(self.font()) + font.setPixelSize(8) + metrics = QFontMetricsF(font) + + painter.setFont(font) + painter.setPen(QPen(QColor(self.scaleColor))) + tickInterval = 5 + i = 0 + while i < 360: + + if i % 45 == 0: + painter.drawLine(0, -40, 0, -50) + painter.drawText(-metrics.width(self._pointText[i])/2.0, -52, self._pointText[i]) + else: + painter.drawLine(0, -45, 0, -50) + + painter.rotate(tickInterval) + i += tickInterval + + painter.restore() + + def drawNeedle(self, painter): + painter.save() + # Set up painter + painter.translate(self.width()/2, self.height()/2) + scale = min((self.width() - self._margins)/120.0, + (self.height() - self._margins)/120.0) + painter.scale(scale, scale) + painter.setPen(QPen(Qtc.NoPen)) + + # Rotate surface for painting + intAngle = int(round(self._angle)) + painter.rotate(intAngle) + + # Draw the full black needle first if needed + if self.needleType == NeedleFull: + needleTailBrush = self.palette().brush(QPalette.Shadow) + needleTailColor = QColor(self.needleBodyColor) + needleTailBrush.setColor(needleTailColor) + painter.setBrush(needleTailBrush) + + painter.drawPolygon(QPolygon([QPoint(-6, 0), QPoint(0, -45), QPoint(6, 0), + QPoint(0, 45), QPoint(-6, 0)])) + + # Now draw the red tip (on top of the black needle) + needleTipBrush = self.palette().brush(QPalette.Highlight) + needleTipColor = QColor(self.needleTipColor) + needleTipBrush.setColor(needleTipColor) + painter.setBrush(needleTipBrush) + + # First QPoint is the center bottom apex of the needle + painter.drawPolygon(QPolygon([QPoint(-3, -24), QPoint(0, -45), QPoint(3, -23), + QPoint(0, -30), QPoint(-3, -23)])) + + if self.needleType == NeedleMirrored: + # Rotate + # Need to account for the initial rotation to see how much more to rotate it. + if (intAngle == 90 or intAngle == -90 or intAngle == 270): + mirrorRotation = 180 + else: + mirrorRotation = 180 - intAngle - intAngle + painter.rotate(mirrorRotation) + + # Paint shadowed indicator + needleTipBrush = self.palette().brush(QPalette.Highlight) + needleTipColor = Qtc.gray + needleTipBrush.setColor(needleTipColor) + painter.setBrush(needleTipBrush) + + painter.drawPolygon( + QPolygon([QPoint(-3, -25), QPoint(0, -45), QPoint(3, -25), + QPoint(0, -30), QPoint(-3, -25)]) + ) + + painter.restore() + + def angle(self): + return self._angle + + def change_angle(self, angle): + if angle != self._angle: + if self.debug: + gr.log.info(("Compass angle: " + str(angle))) + + if angle < 0.0: + angle = 360.0 + angle # Angle will already be negative + + self._angle = angle + self.angleChanged.emit(angle) + self.update() + + angle = pyqtProperty(float, angle, change_angle) + + +class GrCompass(gr.sync_block, LabeledCompass): + """ + This block takes angle in degrees as input and displays it on a compass. + Three different needle formats are available, Full, indicator only, + and mirrored (mirrored is useful for direction-finding where an + ambiguity exists in front/back detection angle). + """ + def __init__(self, title, min_size, update_time, setDebug=False, needleType=NeedleFull, + usemsg=False, position=1, backgroundColor='default'): + if usemsg: + gr.sync_block.__init__(self, name="QTCompass", in_sig=[], out_sig=[]) + else: + gr.sync_block.__init__(self, name="QTCompass", in_sig=[numpy.float32], out_sig=[]) + + LabeledCompass.__init__(self, title, min_size, update_time, setDebug, needleType, + position, backgroundColor) + + self.last = time.time() + self.update_period = update_time + self.useMsg = usemsg + + self.next_angle = 0.0 + + self.message_port_register_in(pmt.intern("angle")) + self.set_msg_handler(pmt.intern("angle"), self.msgHandler) + + def msgHandler(self, msg): + try: + new_val = pmt.to_python(pmt.cdr(msg)) + + if type(new_val) == float or type(new_val) == int: + super().change_angle(float(new_val)) + else: + gr.log.error("Value received was not an int or a float: %s" % str(type(new_val))) + + except Exception as e: + gr.log.error("Error with message conversion: %s" % str(e)) + + def setColors(self, backgroundColor='default', needleTip='red', needleBody='black', + scaleColor='black'): + super().setColors(backgroundColor, needleTip, needleBody, scaleColor) + + def work(self, input_items, output_items): + if self.useMsg: + return len(input_items[0]) + + # Average inputs + self.next_angle = numpy.mean(input_items[0]) + + if (time.time() - self.last) > self.update_period: + self.last = time.time() + super().change_angle(self.next_angle) + + # Consume all inputs + return len(input_items[0]) diff --git a/gr-qtgui/python/qtgui/dialcontrol.py b/gr-qtgui/python/qtgui/dialcontrol.py new file mode 100644 index 0000000000..e5c7618b9f --- /dev/null +++ b/gr-qtgui/python/qtgui/dialcontrol.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2020 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# + +from PyQt5.QtWidgets import QFrame, QVBoxLayout, QLabel +from PyQt5 import Qt +from PyQt5.QtCore import Qt as Qtc +from PyQt5.QtCore import QSize +from gnuradio import gr +import pmt + +class LabeledDialControl(QFrame): + def __init__(self, lbl='', parent=None, minimum=0, maximum=100, defaultvalue=0, + backgroundColor='default', changedCallback=None, + minsize=100, isFloat=False, scaleFactor=1, showvalue=False, + outputmsgname='value'): + QFrame.__init__(self, parent) + self.numberControl = DialControl(minimum, maximum, defaultvalue, backgroundColor, + self.valChanged, changedCallback, minsize) + + layout = QVBoxLayout() + + self.outputmsgname = outputmsgname + self.showvalue = showvalue + self.isFloat = isFloat + self.scaleFactor = scaleFactor + self.lbl = lbl + self.lblcontrol = QLabel(lbl, self) + self.lblcontrol.setAlignment(Qtc.AlignCenter) + + if self.showvalue: + textstr = self.buildTextStr(defaultvalue*self.scaleFactor) + self.lblcontrol.setText(textstr) + + if len or self.showvalue: + self.hasLabel = True + layout.addWidget(self.lblcontrol) + else: + self.hasLabel = False + + layout.addWidget(self.numberControl) + + layout.setAlignment(Qtc.AlignCenter) + self.setLayout(layout) + self.show() + + def buildTextStr(self, new_value): + textstr = "" + if self.lbl: + textstr = self.lbl + " - " + + if self.isFloat: + textstr += "%.2f" % (new_value) + else: + textstr += str(new_value) + + return textstr + + def valChanged(self, new_value): + if not self.showvalue: + return + + if int(self.scaleFactor) != 1: + new_value = new_value * self.scaleFactor + + textstr = self.buildTextStr(new_value) + self.lblcontrol.setText(textstr) + +class DialControl(Qt.QDial): + def __init__(self, minimum=0, maximum=100, defaultvalue=0, backgroundColor='default', + lablelCallback=None, changedCallback=None, minsize=100): + Qt.QDial.__init__(self) + + if backgroundColor != "default": + self.setStyleSheet("background-color: " + backgroundColor + ";") + + self.minsize = minsize + self.changedCallback = changedCallback + self.lablelCallback = lablelCallback + super().setMinimum(minimum) + super().setMaximum(maximum) + super().setValue(defaultvalue) + super().valueChanged.connect(self.sliderMoved) + + def minimumSizeHint(self): + return QSize(self.minsize, self.minsize) + + def sliderMoved(self): + if self.changedCallback is not None: + self.changedCallback(self.value()) + + if self.lablelCallback is not None: + self.lablelCallback(self.value()) + +class GrDialControl(gr.sync_block, LabeledDialControl): + """ + This block creates a dial control. The control does control a + variable which can be used for other items. Leave the label + blank to use the variable id as the label. The block also + creates an optional message with the control value that + can be used in message-based applications. + + Note: Dials only produce integer values, so the scale factor + can be used with the min/max to adjust the output value to + the desired range. Think of the min/max as the increments, + and the scale factor as the adjustment to get the values you want. + """ + def __init__(self, lbl, parent, minimum, maximum, defaultvalue, backgroundColor='default', + varCallback=None, isFloat=False, + scaleFactor=1, minsize=100, showvalue=False, outputmsgname='value'): + gr.sync_block.__init__(self, name="GrDialControl", in_sig=None, out_sig=None) + LabeledDialControl.__init__(self, lbl, parent, minimum, maximum, defaultvalue, + backgroundColor, self.valueChanged, minsize, isFloat, + scaleFactor, showvalue) + + self.outputmsgname = outputmsgname + self.varCallback = varCallback + self.scaleFactor = scaleFactor + self.isFloat = isFloat + self.message_port_register_out(pmt.intern("value")) + + def valueChanged(self, new_value): + if int(self.scaleFactor) != 1: + new_value = new_value * self.scaleFactor + + if self.varCallback is not None: + self.varCallback(new_value) + + if self.isFloat: + self.message_port_pub(pmt.intern("value"), pmt.cons(pmt.intern(self.outputmsgname), + pmt.from_float(new_value))) + else: + self.message_port_pub(pmt.intern("value"), pmt.cons(pmt.intern(self.outputmsgname), + pmt.from_long(new_value))) + diff --git a/gr-qtgui/python/qtgui/dialgauge.py b/gr-qtgui/python/qtgui/dialgauge.py new file mode 100644 index 0000000000..af96f2e096 --- /dev/null +++ b/gr-qtgui/python/qtgui/dialgauge.py @@ -0,0 +1,208 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2020 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# + +import sys +from PyQt5.QtWidgets import QFrame, QHBoxLayout, QVBoxLayout, QLabel +from PyQt5.QtGui import QPainter, QColor, QPen, QFont, QFontMetricsF +from PyQt5 import QtCore +from PyQt5.QtCore import Qt as Qtc + +from gnuradio import gr +import pmt + +class LabeledDialGauge(QFrame): + # Positions: 1 = above, 2=below, 3=left, 4=right + def __init__(self, lbl='', barColor='blue', backgroundColor='white', fontColor='black', + minValue=0, maxValue=100, maxSize=80, position=1, + isFloat=False, showValue=False, fixedOrMin=True, parent=None): + QFrame.__init__(self, parent) + self.numberControl = DialGauge(barColor, backgroundColor, fontColor, minValue, + maxValue, maxSize, isFloat, showValue, fixedOrMin, parent) + + if position < 3: + layout = QVBoxLayout() + else: + layout = QHBoxLayout() + + self.lbl = lbl + self.showvalue = showValue + self.isFloat = isFloat + + self.lblcontrol = QLabel(lbl, self) + self.lblcontrol.setAlignment(Qtc.AlignCenter) + + # For whatever reason, the progressbar doesn't show the number in the bar if it's + # vertical, only if it's horizontal + if len: + self.lblcontrol.setText(lbl) + + if fontColor != 'default': + self.lblcontrol.setStyleSheet("QLabel { color : " + fontColor + "; }") + + # add top or left + if len: + if position == 1 or position == 3: + layout.addWidget(self.lblcontrol) + else: + self.hasLabel = False + + layout.addWidget(self.numberControl) + + # Add bottom or right + if len: + if position == 2 or position == 4: + layout.addWidget(self.lblcontrol) + + layout.setAlignment(Qtc.AlignCenter | Qtc.AlignVCenter) + self.setLayout(layout) + + self.show() + + def setValue(self, new_value): + self.numberControl.setValue(new_value) + +class DialGauge(QFrame): + def __init__(self, barColor='blue', backgroundColor='white', fontColor='black', + minValue=0, maxValue=100, maxSize=80, + isFloat=False, showValue=False, fixedOrMin=True, parent=None): + QFrame.__init__(self, parent) + + self.maxSize = maxSize + super().setMinimumSize(maxSize, maxSize) + if fixedOrMin: + super().setMaximumSize(maxSize, maxSize) + + self.backgroundColor = backgroundColor + self.barColor = barColor + self.fontColor = fontColor + self.isFloat = isFloat + self.showValue = showValue + + self.value = minValue + + self.minValue = minValue + self.maxValue = maxValue + + self.textfont = QFont(self.font()) + self.textfont.setPixelSize(16) + self.metrics = QFontMetricsF(self.textfont) + + self.startAngle = 0.0 + self.endAngle = 360.0 + self.degScaler = 16.0 # The span angle must be specified in 1/16 of a degree units + self.penWidth = max(int(0.1 * maxSize), 6) + self.halfPenWidth = int(self.penWidth / 2) + + def getValue(self): + if self.isFloat: + return float(self.value) + else: + return int(self.value) + + def setValue(self, new_value): + if new_value > self.maxValue: + new_value = self.maxValue + elif new_value < self.minValue: + new_value = self.minValue + + self.value = float(new_value) + + super().update() + + def paintEvent(self, event): + super().paintEvent(event) + + size = self.size() + + percentRange = float(self.value - self.minValue) / float(self.maxValue - self.minValue) + endAngle = self.startAngle + round(percentRange * float(self.endAngle - self.startAngle), 0) + + # Now convert angles to 1/16 scale + startAngle = int(round(self.startAngle * self.degScaler, 0)) + endAngle = int(round(endAngle * self.degScaler, 0)) + + rect = QtCore.QRect(self.halfPenWidth, self.halfPenWidth, size.width()-self.penWidth, + size.height()-self.penWidth) + + # Set up the painting canvass + painter = QPainter() + painter.begin(self) + painter.setRenderHint(QPainter.Antialiasing) + + if self.showValue: + painter.setFont(self.textfont) + painter.setPen(QPen(QColor(self.fontColor))) + + if self.isFloat: + printText = "%.2f" % self.value + else: + printText = str(int(self.value)) + + painter.drawText(size.width()/2-self.metrics.width(printText)/2, size.height()/2, + printText) + + painter.save() + painter.translate(self.width(), 0) + painter.rotate(90.0) + + # First draw complete circle + painter.setPen(QPen(QColor(self.backgroundColor), self.penWidth)) + painter.drawArc(rect, startAngle, self.endAngle*self.degScaler) + # First draw complete circle + painter.setPen(QPen(QColor(self.barColor), self.penWidth)) + painter.drawArc(rect, startAngle, -endAngle) + painter.setPen(QPen(QColor('darkgray'), 2)) + painter.drawEllipse(1, 1, rect.width()+self.penWidth-2, rect.width()+self.penWidth-2) + painter.drawEllipse(1+self.penWidth, 1+self.penWidth, rect.width()-self.penWidth-2, + rect.width()-self.penWidth-2) + painter.restore() + + painter.end() + +class GrDialGauge(gr.sync_block, LabeledDialGauge): + """ + This block creates a dial-style gauge. The value can be set + either with a variable or an input message. + """ + def __init__(self, lbl='', barColor='blue', backgroundColor='white', fontColor='black', + minValue=0, maxValue=100, maxSize=80, + position=1, isFloat=False, showValue=False, fixedOrMin=True, parent=None): + gr.sync_block.__init__(self, name="DialGauge", in_sig=None, out_sig=None) + LabeledDialGauge.__init__(self, lbl, barColor, backgroundColor, fontColor, minValue, + maxValue, maxSize, position, isFloat, showValue, fixedOrMin, + parent) + self.lbl = lbl + + if minValue > maxValue: + gr.log.error("Min value is greater than max value.") + sys.exit(1) + + self.message_port_register_in(pmt.intern("value")) + self.set_msg_handler(pmt.intern("value"), self.msgHandler) + + + def msgHandler(self, msg): + try: + new_val = pmt.to_python(pmt.cdr(msg)) + + if type(new_val) == float or type(new_val) == int: + super().setValue(new_val) + else: + gr.log.error("Value received was not an int or a float. " + "Received %s" % str(type(new_val))) + + except Exception as e: + gr.log.error("Error with message conversion: %s" % str(e)) + + + def setValue(self, new_value): + super().setValue(new_value) + diff --git a/gr-qtgui/python/qtgui/digitalnumbercontrol.py b/gr-qtgui/python/qtgui/digitalnumbercontrol.py new file mode 100644 index 0000000000..ea8bdd7eb5 --- /dev/null +++ b/gr-qtgui/python/qtgui/digitalnumbercontrol.py @@ -0,0 +1,346 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2020 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# + +from PyQt5.QtWidgets import QFrame, QVBoxLayout, QLabel +from PyQt5.QtGui import QPainter, QPixmap, QFont, QFontMetrics, QBrush, QColor +from PyQt5.QtCore import Qt, QSize +from PyQt5 import QtCore +from PyQt5.QtCore import Qt as Qtc +from PyQt5.QtCore import pyqtSignal + +from gnuradio import gr +import pmt + +# -------------- Support Classes --------------------------------- +# +# + +class LabeledDigitalNumberControl(QFrame): + def __init__(self, lbl='', min_freq_hz=0, max_freq_hz=6000000000, parent=None, + thousands_separator=',', background_color='black', fontColor='white', + click_callback=None): + QFrame.__init__(self, parent) + self.numberControl = DigitalNumberControl(min_freq_hz, max_freq_hz, self, + thousands_separator, background_color, fontColor, click_callback) + + layout = QVBoxLayout() + + self.lbl = QLabel(lbl, self) + if len: + self.hasLabel = True + layout.addWidget(self.lbl) + else: + self.hasLabel = False + + layout.addWidget(self.numberControl) + layout.setAlignment(Qtc.AlignCenter | Qtc.AlignVCenter) + self.setLayout(layout) + self.show() + + def minimumSizeHint(self): + if self.hasLabel: + return QSize(self.numberControl.minimumWidth()+10, 100) + else: + return QSize(self.numberControl.minimumWidth()+10, 50) + + def setReadOnly(self, b_read_only): + self.numberControl.setReadOnly(b_read_only) + + def setFrequency(self, new_freq): + self.numberControl.setFrequency(new_freq) + + def getFrequency(self): + return self.numberControl.getFrequency() + +class DigitalNumberControl(QFrame): + # Notifies to avoid thread conflicts on paints + updateInt = pyqtSignal(int) + updateFloat = pyqtSignal(float) + + def __init__(self, min_freq_hz=0, max_freq_hz=6000000000, parent=None, thousands_separator=',', + background_color='black', fontColor='white', click_callback=None): + QFrame.__init__(self, parent) + + self.updateInt.connect(self.onUpdateInt) + self.updateFloat.connect(self.onUpdateFloat) + + self.min_freq = int(min_freq_hz) + self.max_freq = int(max_freq_hz) + self.numDigitsInFreq = len(str(max_freq_hz)) + + self.thousands_separator = thousands_separator + self.click_callback = click_callback + + self.read_only = False + + self.setColors(QColor(background_color), QColor(fontColor)) + self.numberFont = QFont("Arial", 12, QFont.Normal) + + self.cur_freq = min_freq_hz + + self.debug_click = False + + # Determine what our width minimum is + teststr = "" + for i in range(0, self.numDigitsInFreq): + teststr += "0" + + fm = QFontMetrics(self.numberFont) + if len(self.thousands_separator) > 0: + # The -1 makes sure we don't count an extra for 123,456,789. Answer should be 2 not 3. + numgroups = int(float(self.numDigitsInFreq-1) / 3.0) + if numgroups > 0: + for i in range(0, numgroups): + teststr += self.thousands_separator + + textstr = teststr + else: + textstr = teststr + + width = fm.width(textstr) + + self.minwidth = width + + if self.minwidth < 410: + self.minwidth = 410 + + self.setMaximumHeight(70) + self.setMinimumWidth(self.minwidth) + # Show the control + self.show() + + def minimumSizeHint(self): + return QSize(self.minwidth, 50) + + def setReadOnly(self, b_read_only): + self.read_only = b_read_only + + def mousePressEvent(self, event): + super(DigitalNumberControl, self).mousePressEvent(event) + self.offset = event.pos() + + if self.read_only: + return + + fm = QFontMetrics(self.numberFont) + + if len(self.thousands_separator) > 0: + if self.thousands_separator != ".": + textstr = format(self.getFrequency(), self.thousands_separator) + else: + textstr = format(self.getFrequency(), ",") + textstr = textstr.replace(",", ".") + else: + textstr = str(self.getFrequency()) + + width = fm.width(textstr) + + # So we know: + # - the width of the text + # - The mouse click position relative to 0 (pos relative to string start + # will be size().width() - 2 - pos.x + + clickpos = self.size().width() - 2 - self.offset.x() + + found_number = False + clicked_thousands = False + for i in range(1, len(textstr)+1): + width = fm.width(textstr[-i:]) + charstr = textstr[-i:] + widthchar = fm.width(charstr[0]) + if clickpos >= (width-widthchar) and clickpos <= width: + clicked_char = i-1 + + clicked_num_index = clicked_char + + found_number = True + + if len(self.thousands_separator) > 0: + if charstr[0] != self.thousands_separator: + numSeps = charstr.count(self.thousands_separator) + clicked_num_index -= numSeps + if self.debug_click: + gr.log.info("clicked number: " + str(clicked_num_index)) + else: + clicked_thousands = True + if self.debug_click: + gr.log.info("clicked thousands separator") + else: + if self.debug_click: + gr.log.info("clicked number: " + str(clicked_char)) + + # Remember y=0 is at the top so this is reversed + clicked_up = False + if self.offset.y() > self.size().height()/2: + if self.debug_click: + gr.log.info('clicked down') + else: + if self.debug_click: + gr.log.info('clicked up') + clicked_up = True + + if not clicked_thousands: + cur_freq = self.getFrequency() + increment = pow(10, clicked_num_index) + if clicked_up: + cur_freq += increment + else: + cur_freq -= increment + + self.setFrequency(cur_freq) + if self.click_callback is not None: + self.click_callback(self.getFrequency()) + + break + + if (not found_number) and (not clicked_thousands): + # See if we clicked in the high area, if so, increment there. + clicked_up = False + if self.offset.y() > self.size().height()/2: + if self.debug_click: + gr.log.info('clicked down in the high area') + else: + if self.debug_click: + gr.log.info('clicked up in the high area') + clicked_up = True + + textstr = str(self.getFrequency()) + numNumbers = len(textstr) + increment = pow(10, numNumbers) + cur_freq = self.getFrequency() + if clicked_up: + cur_freq += increment + else: + cur_freq -= increment + + self.setFrequency(cur_freq) + if self.click_callback is not None: + self.click_callback(self.getFrequency()) + + def setColors(self, background, fontColor): + self.background_color = background + self.fontColor = fontColor + + def reverseString(self, astring): + astring = astring[::-1] + return astring + + def onUpdateInt(self, new_freq): + if (new_freq >= self.min_freq) and (new_freq <= self.max_freq): + self.cur_freq = int(new_freq) + + self.update() + + def onUpdateFloat(self, new_freq): + if (new_freq >= self.min_freq) and (new_freq <= self.max_freq): + self.cur_freq = int(new_freq) + + self.update() + + def setFrequency(self, new_freq): + if type(new_freq) == int: + self.updateInt.emit(new_freq) + else: + self.updateFloat.emit(new_freq) + + def getFrequency(self): + return self.cur_freq + + def resizeEvent(self, event): + self.pxMap = QPixmap(self.size()) + self.pxMap.fill(self.background_color) + + self.update() + + def paintEvent(self, event): + super().paintEvent(event) + + painter = QPainter(self) + + size = self.size() + brush = QBrush() + brush.setColor(self.background_color) + brush.setStyle(Qt.SolidPattern) + rect = QtCore.QRect(2, 2, size.width()-4, size.height()-4) + painter.fillRect(rect, brush) + + self.numberFont.setPixelSize(0.9 * size.height()) + painter.setFont(self.numberFont) + painter.setPen(self.fontColor) + rect = event.rect() + + if len(self.thousands_separator) > 0: + if self.thousands_separator != ".": + textstr = format(self.getFrequency(), self.thousands_separator) + else: + textstr = format(self.getFrequency(), ",") + textstr = textstr.replace(",", ".") + else: + textstr = str(self.getFrequency()) + rect = QtCore.QRect(0, 0, size.width()-4, size.height()) + painter.drawText(rect, Qt.AlignRight + Qt.AlignVCenter, textstr) + +# ################################################################################ + +# GNU Radio Class +class MsgDigitalNumberControl(gr.sync_block, LabeledDigitalNumberControl): + def __init__(self, lbl='', min_freq_hz=0, max_freq_hz=6000000000, parent=None, + thousands_separator=',', background_color='black', fontColor='white', + var_callback=None, outputmsgname='freq'): + gr.sync_block.__init__(self, name="MsgDigitalNumberControl", + in_sig=None, out_sig=None) + LabeledDigitalNumberControl.__init__(self, lbl, min_freq_hz, max_freq_hz, parent, + thousands_separator, background_color, fontColor, self.click_callback) + + self.var_callback = var_callback + self.outputmsgname = outputmsgname + + self.message_port_register_in(pmt.intern("valuein")) + self.set_msg_handler(pmt.intern("valuein"), self.msgHandler) + self.message_port_register_out(pmt.intern("valueout")) + + def msgHandler(self, msg): + try: + new_val = pmt.to_python(pmt.cdr(msg)) + + if type(new_val) == float or type(new_val) == int: + self.call_var_callback(new_val) + + self.setValue(new_val) + else: + gr.log.error("Value received was not an int or a float. %s" % str(type(new_val))) + + except Exception as e: + gr.log.error("Error with message conversion: %s" % str(e)) + + def call_var_callback(self, new_value): + if (self.var_callback is not None): + if type(self.var_callback) is float: + self.var_callback = float(new_value) + else: + self.var_callback(float(new_value)) + + def click_callback(self, new_value): + self.call_var_callback(new_value) + + self.message_port_pub(pmt.intern("valueout"), pmt.cons(pmt.intern(self.outputmsgname), pmt.from_float(float(new_value)))) + + def setValue(self, new_val): + self.setFrequency(new_val) + + self.message_port_pub(pmt.intern("valueout"), pmt.cons(pmt.intern(self.outputmsgname), pmt.from_float(float(self.getFrequency())))) + + def getValue(self): + self.getFrequency() + + def setReadOnly(self, b_read_only): + super().setReadOnly(b_read_only) + diff --git a/gr-qtgui/python/qtgui/distanceradar.py b/gr-qtgui/python/qtgui/distanceradar.py new file mode 100644 index 0000000000..170cf81f40 --- /dev/null +++ b/gr-qtgui/python/qtgui/distanceradar.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2020 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# + +import sys +from PyQt5 import QtWidgets +import numpy as np +import matplotlib.pyplot as plt +try: + from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas + from matplotlib.figure import Figure +except: + gr.log.error("Unable to import matplotlib. Please install matplotlib first " + "(e.g., via pip/pip3/dpkg/MacPorts).") + sys.exit(1) + +from gnuradio import gr +import pmt + +class DistanceRadar(gr.sync_block, FigureCanvas): + """ + This block creates a radar-like screen used to represent distance or size. + This can be used in many ways such as circles closer to the center are + closer, or just the opposite where closer to the center is smaller. + + Note: Incoming values should range between 0 (center bullseye) and + 100 (all the way out) + """ + def __init__(self, lbl, ticklabels, backgroundColor, fontColor, ringColor, Parent=None, + width=4, height=4, dpi=100): + gr.sync_block.__init__(self, name="distanceradar", in_sig=None, out_sig=None) + + self.lbl = lbl + + self.message_port_register_in(pmt.intern("radius")) + self.set_msg_handler(pmt.intern("radius"), self.msgHandler) + + self.fontColor = fontColor + self.backgroundColor = backgroundColor + self.ringColor = ringColor + + self.fig = Figure(figsize=(width, height), dpi=dpi) + self.fig.patch.set_facecolor(self.backgroundColor) + self.axes = self.fig.add_subplot(111, polar=True, facecolor=self.backgroundColor) + + # Create an "invisible" line at 100 to set the max for the plot + self.axes.plot(np.linspace(0, 2*np.pi, 100), np.ones(100)*100, color=self.fontColor, + linestyle='') + + # Plot line: Initialize out to 100 and blank + radius = 100 + self.blackline = self.axes.plot(np.linspace(0, 2*np.pi, 100), np.ones(100)*radius, + color=self.fontColor, linestyle='-') + self.redline = None + + self.filledcircle = None + # Create bullseye + circle = plt.Circle((0.0, 0.0), 20, transform=self.axes.transData._b, color=self.fontColor, + alpha=0.4) + self.bullseye = self.axes.add_artist(circle) + + # Rotate zero up + self.axes.set_theta_zero_location("N") + + self.axes.set_yticklabels(ticklabels, color=self.fontColor) + self.axes.set_xticklabels([], color=self.fontColor) + + FigureCanvas.__init__(self, self.fig) + self.setParent(Parent) + + + self.title = self.fig.suptitle(self.lbl, fontsize=8, fontweight='bold', + color=self.fontColor) + + FigureCanvas.setSizePolicy(self, + QtWidgets.QSizePolicy.Expanding, + QtWidgets.QSizePolicy.Expanding) + FigureCanvas.updateGeometry(self) + + def msgHandler(self, msg): + try: + new_val = pmt.to_python(pmt.cdr(msg)) + + if type(new_val) == float or type(new_val) == int: + self.updateData(new_val) + else: + gr.log.error("Value received was not an int or a " + "float: %s" % str(type(new_val))) + + except Exception as e: + gr.log.error("Error with message conversion: %s" % str(e)) + + def updateData(self, radius): + if self.redline is not None: + self.redline.pop(0).remove() + self.redline = self.axes.plot(np.linspace(0, 2*np.pi, 100), np.ones(100)*radius, + color='r', linestyle='-') + + if self.filledcircle: + self.filledcircle.remove() + + self.bullseye.remove() + circle = plt.Circle((0.0, 0.0), radius, transform=self.axes.transData._b, + color=self.ringColor, alpha=0.4) + self.filledcircle = self.axes.add_artist(circle) + # Create bullseye + circle = plt.Circle((0.0, 0.0), 20, transform=self.axes.transData._b, + color=self.fontColor, alpha=0.4) + self.bullseye = self.axes.add_artist(circle) + + self.draw() + diff --git a/gr-qtgui/python/qtgui/graphicitem.py b/gr-qtgui/python/qtgui/graphicitem.py new file mode 100644 index 0000000000..b1386ab586 --- /dev/null +++ b/gr-qtgui/python/qtgui/graphicitem.py @@ -0,0 +1,194 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2020 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# + +from PyQt5.QtWidgets import QLabel +from PyQt5.QtGui import QPixmap, QPainter +from PyQt5.QtCore import Qt as Qtc +from PyQt5.QtCore import QSize + +import os +import sys + +from gnuradio import gr +import pmt + +class GrGraphicItem(gr.sync_block, QLabel): + """ + This block displays the selected graphic item. You can pass a + filename as a string in a message to change the image on the fly. + overlays can also be added by passing in a message with a + dictionary of a list of dictionaries in the car portion of the + message. Each dicationary should have the following keys: + 'filename','x','y', and an optional 'scalefactor'. + Setting the x/y attributes to -1,-1 will remove an overlay. + Otherwise items are indexed by filename and can be animated + throughout the backgound image. + """ + def __init__(self, image_file, scaleImage=True, fixedSize=False, setWidth=0, setHeight=0): + gr.sync_block.__init__(self, name="GrGraphicsItem", in_sig=None, out_sig=None) + QLabel.__init__(self) + + if not os.path.isfile(image_file): + gr.log.error("ERROR: Unable to find file " + image_file) + sys.exit(1) + + try: + self.pixmap = QPixmap(image_file) + self.originalPixmap = QPixmap(image_file) + except OSError as e: + gr.log.error("ERROR: " + e.strerror) + sys.exit(1) + + self.image_file = image_file + self.scaleImage = scaleImage + self.fixedSize = fixedSize + self.setWidth = setWidth + self.setHeight = setHeight + super().setPixmap(self.pixmap) + super().setMinimumSize(1, 1) + self.overlays = {} + + self.message_port_register_in(pmt.intern("filename")) + self.set_msg_handler(pmt.intern("filename"), self.msgHandler) + + self.message_port_register_in(pmt.intern("overlay")) + self.set_msg_handler(pmt.intern("overlay"), self.overlayHandler) + + def overlayHandler(self, msg): + try: + overlayitem = pmt.to_python(pmt.car(msg)) + if overlayitem is None: + gr.log.error('Overlay message contains None in the car portion ' + 'of the message. Please pass in a dictionary or list of dictionaries in this ' + 'portion of the message. Each dictionary should have the following keys: ' + 'filename,x,y. Use x=y=-1 to remove an overlay item.') + return + + if type(overlayitem) is dict: + itemlist = [] + itemlist.append(overlayitem) + elif type(overlayitem) is list: + itemlist = overlayitem + else: + gr.log.error("Overlay message type is not correct. Please pass in " + "a dictionary or list of dictionaries in this portion of the message. Each " + "dictionary should have the following keys: filename,x,y. Use x=y=-1 to " + "remove an overlay item.") + return + + # Check each dict item to make sure it's valid. + for curitem in itemlist: + if type(curitem) == dict: + if 'filename' not in curitem: + gr.log.error("Dictionary item did not contain the 'filename' key.") + gr.log.error("Received " + str(curitem)) + continue + + if 'x' not in curitem: + gr.log.error("The dictionary for filename " + + curitem['filename'] + " did not contain an 'x' key.") + gr.log.error("Received " + str(curitem)) + continue + + if 'y' not in curitem: + gr.log.error("The dictionary for filename " + + curitem['filename'] + " did not contain an 'y' key.") + gr.log.error("Received " + str(curitem)) + continue + + if not os.path.isfile(curitem['filename']): + gr.log.error("Unable to find overlay file " + + curitem['filename']) + gr.log.error("Received " + str(curitem)) + continue + + # Now either add/update our list or remove the item. + if curitem['x'] == -1 and curitem['y'] == -1: + try: + del self.overlays[curitem['filename']] # remove item + except: + pass + else: + self.overlays[curitem['filename']] = curitem + + self.updateGraphic() + except Exception as e: + gr.log.error("Error with overlay message conversion: %s" % str(e)) + + def updateGraphic(self): + if (len(self.overlays.keys()) == 0): + try: + super().setPixmap(self.pixmap) + except Exception as e: + gr.log.error("Error updating graphic: %s" % str(e)) + return + else: + # Need to deal with overlays + tmpPxmap = self.pixmap.copy(self.pixmap.rect()) + painter = QPainter(tmpPxmap) + for curkey in self.overlays.keys(): + curOverlay = self.overlays[curkey] + try: + newOverlay = QPixmap(curkey) + if 'scalefactor' in curOverlay: + scale = curOverlay['scalefactor'] + w = newOverlay.width() + h = newOverlay.height() + newOverlay = newOverlay.scaled(int(w*scale), int(h*scale), + Qtc.KeepAspectRatio) + painter.drawPixmap(curOverlay['x'], curOverlay['y'], newOverlay) + except Exception as e: + gr.log.error("Error adding overlay: %s" % str(e)) + return + + painter.end() + + super().setPixmap(tmpPxmap) + + def msgHandler(self, msg): + try: + new_val = pmt.to_python(pmt.cdr(msg)) + image_file = new_val + if type(new_val) == str: + if not os.path.isfile(image_file): + gr.log.error("ERROR: Unable to find file " + image_file) + return + + try: + self.pixmap = QPixmap(image_file) + self.image_file = image_file + except OSError as e: + gr.log.error("ERROR: " + e.strerror) + return + + self.updateGraphic() + else: + gr.log.error("Value received was not an int or " + "a bool: %s" % str(type(new_val))) + + except Exception as e: + gr.log.error("Error with message conversion: %s" % str(e)) + + def minimumSizeHint(self): + return QSize(self.pixmap.width(),self.pixmap.height()) + + def resizeEvent(self, event): + if self.scaleImage: + w = super().width() + h = super().height() + + self.pixmap = self.originalPixmap.scaled(w, h, Qtc.KeepAspectRatio) + elif self.fixedSize and self.setWidth > 0 and self.setHeight > 0: + self.pixmap = self.originalPixmap.scaled(self.setWidth, self.setHeight, + Qtc.KeepAspectRatio) + + self.updateGraphic() + diff --git a/gr-qtgui/python/qtgui/graphicoverlay.py b/gr-qtgui/python/qtgui/graphicoverlay.py new file mode 100644 index 0000000000..defef31d17 --- /dev/null +++ b/gr-qtgui/python/qtgui/graphicoverlay.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2020 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# + +import sys +import threading +import time + +from gnuradio import gr +import pmt + +# This thread just gets us out of the sync_block's init function so the messaging +# system and scheduler are active. +class offloadThread(threading.Thread): + def __init__(self, callback, overlayList, listDelay, repeat): + threading.Thread.__init__(self) + self.callback = callback + self.overlayList = overlayList + self.listDelay = listDelay + self.threadRunning = False + self.stopThread = False + self.repeat = repeat + + def run(self): + self.stopThread = False + self.threadRunning = True + + # Wait for main __init__ to finish + time.sleep(0.5) + + if (type(self.overlayList) == list and self.listDelay > 0.0): + while self.repeat and not self.stopThread: + for curItem in self.overlayList: + self.callback(curItem) + + if self.stopThread: + break + + time.sleep(self.listDelay) + + if self.stopThread: + break + else: + self.callback(self.overlayList) + + self.threadRunning = False + +class GrGraphicOverlay(gr.sync_block): + """ + This block is an example of how to feed an overlay to a graphic item. + The graphic item overlay is expecting a dictionary with the following + keys: 'filename','x','y', and optionally a 'scalefactor'. A list of + dictionaries can also be supplied to support multiple items. + + Any file can be added to the graphic item as an overlay and the + particular item indexed by its filename can be updated by passing + in new x/y coordinates. To remove an overlay, use coordinates -1,-1 + for the x,y coordinates. + + This sample block sends either a dictionary or list of dictionaries + to the graphicitem block. To test updating a single overlay item, + you can use a list with the same file but different coordinates and + use the update delay > 0.0 to animate it. + """ + def __init__(self, overlayList, listDelay, repeat): + gr.sync_block.__init__(self, name="GrGraphicsOverlay", in_sig=None, + out_sig=None) + + self.overlayList = overlayList + self.listDelay = listDelay + if type(self.overlayList) is not dict and type(self.overlayList) is not list: + gr.log.error("The specified input is not valid. " + "Please specify either a dictionary item with the following keys: " + "'filename','x','y'[,'scalefactor'] or a list of dictionary items.") + sys.exit(1) + + self.message_port_register_out(pmt.intern("overlay")) + + self.thread = offloadThread(self.overlayCallback, self.overlayList, listDelay, + repeat) + self.thread.start() + + def overlayCallback(self, msgData): + # Need to let init finish before this can be called so need to thread it out. + meta = pmt.to_pmt(msgData) + pdu = pmt.cons(meta, pmt.PMT_NIL) + self.message_port_pub(pmt.intern('overlay'), pdu) + + def stop(self): + self.thread.stopThread = True + + while self.thread.threadRunning: + time.sleep(0.1) + + return True + diff --git a/gr-qtgui/python/qtgui/ledindicator.py b/gr-qtgui/python/qtgui/ledindicator.py new file mode 100644 index 0000000000..09b2bd8e19 --- /dev/null +++ b/gr-qtgui/python/qtgui/ledindicator.py @@ -0,0 +1,197 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2020 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# + +from PyQt5.QtWidgets import QFrame, QHBoxLayout, QVBoxLayout, QLabel +from PyQt5.QtGui import QPainter, QBrush, QColor, QPen, QFontMetricsF +from PyQt5.QtCore import Qt as Qtc +from PyQt5.QtCore import QPoint +from PyQt5.QtGui import QRadialGradient + +from gnuradio import gr +import pmt + +class LabeledLEDIndicator(QFrame): + # Positions: 1 = above, 2=below, 3=left, 4=right + def __init__(self, lbl='', onColor='green', offColor='red', initialState=False, maxSize=80, + position=1, alignment=1, valignment=1, parent=None): + QFrame.__init__(self, parent) + self.numberControl = LEDIndicator(onColor, offColor, initialState, maxSize, parent) + + if position < 3: + layout = QVBoxLayout() + else: + layout = QHBoxLayout() + + if not lbl: + lbl = " " + + self.lbl = lbl + self.lblcontrol = QLabel(lbl, self) + self.lblcontrol.setAlignment(Qtc.AlignCenter) + + # add top or left + if len: + if position == 1 or position == 3: + layout.addWidget(self.lblcontrol) + else: + self.hasLabel = False + + layout.addWidget(self.numberControl) + + # Add bottom or right + if len: + if position == 2 or position == 4: + layout.addWidget(self.lblcontrol) + + if alignment == 1: + halign = Qtc.AlignCenter + elif alignment == 2: + halign = Qtc.AlignLeft + else: + halign = Qtc.AlignRight + + if valignment == 1: + valign = Qtc.AlignVCenter + elif valignment == 2: + valign = Qtc.AlignTop + else: + valign = Qtc.AlignBottom + + layout.setAlignment(halign | valign) + self.setLayout(layout) + + if len: + textfont = self.lblcontrol.font() + metrics = QFontMetricsF(textfont) + + maxWidth = max((maxSize+30), (maxSize + metrics.width(lbl)+4)) + maxHeight = max((maxSize+35), (maxSize + metrics.height()+2)) + self.setMinimumSize(maxWidth, maxHeight) + else: + self.setMinimumSize(maxSize+2, maxSize+2) + + self.show() + + def setState(self, on_off): + self.numberControl.setState(on_off) + +class LEDIndicator(QFrame): + def __init__(self, onColor='green', offColor='red', initialState=False, maxSize=80, + parent=None): + QFrame.__init__(self, parent) + + self.maxSize = maxSize + self.curState = initialState + self.on_color = QColor(onColor) + self.off_color = QColor(offColor) + + self.setMinimumSize(maxSize, maxSize) + self.setMaximumSize(maxSize, maxSize) + + def setState(self, on_off): + self.curState = on_off + super().update() + + def paintEvent(self, event): + super().paintEvent(event) + + painter = QPainter(self) + + size = self.size() + brush = QBrush() + + smallest_dim = size.width() + if smallest_dim > size.height(): + smallest_dim = size.height() + + smallest_dim = smallest_dim/2 + smallest_dim -= 2 + + center_x = size.width()/2 + center_y = size.height()/2 + centerpoint = QPoint(center_x, center_y) + + radius = smallest_dim + + painter.setPen(QPen(QColor('lightgray'), 0)) + brush.setStyle(Qtc.SolidPattern) + + radial = QRadialGradient(center_x, center_y/2, radius) + radial.setColorAt(0, Qtc.white) + radial.setColorAt(0.8, Qtc.darkGray) + painter.setBrush(QBrush(radial)) + painter.drawEllipse(centerpoint, radius, radius) + + # Draw the colored center + radial = QRadialGradient(center_x, center_y/2, radius) + radial.setColorAt(0, Qtc.white) + + if self.curState: + radial.setColorAt(.7, self.on_color) + brush.setColor(self.on_color) + painter.setPen(QPen(self.on_color, 0)) + else: + radial.setColorAt(.7, self.off_color) + brush.setColor(self.off_color) + painter.setPen(QPen(self.off_color, 0)) + + brush.setStyle(Qtc.SolidPattern) + painter.setBrush(QBrush(radial)) + if smallest_dim <= 30: + radius = radius - 3 + elif smallest_dim <= 60: + radius = radius - 4 + elif smallest_dim <= 100: + radius = radius - 5 + elif smallest_dim <= 200: + radius = radius - 6 + elif smallest_dim <= 300: + radius = radius - 7 + else: + radius = radius - 9 + painter.drawEllipse(centerpoint, radius, radius) + +class GrLEDIndicator(gr.sync_block, LabeledLEDIndicator): + """ + This block makes a basic LED indicator + """ + def __init__(self, lbl='', onColor='green', offColor='red', initialState=False, + maxSize=80, position=1, alignment=1, valignment=1, parent=None): + gr.sync_block.__init__(self, name="LEDIndicator", in_sig=None, out_sig=None) + LabeledLEDIndicator.__init__(self, lbl, onColor, offColor, initialState, + maxSize, position, alignment, valignment, parent) + self.lbl = lbl + + self.message_port_register_in(pmt.intern("state")) + self.set_msg_handler(pmt.intern("state"), self.msgHandler) + + + def msgHandler(self, msg): + try: + new_val = pmt.to_python(pmt.cdr(msg)) + + if type(new_val) == bool or type(new_val) == int: + if type(new_val) == bool: + super().setState(new_val) + else: + if new_val == 1: + super().setState(True) + else: + super().setState(False) + else: + gr.log.error("Value received was not an int or a bool: %s" % str(type(new_val))) + + except Exception as e: + gr.log.error("Error with message conversion: %s" % str(e)) + + def setState(self, on_off): + super().setState(on_off) + diff --git a/gr-qtgui/python/qtgui/levelgauge.py b/gr-qtgui/python/qtgui/levelgauge.py new file mode 100644 index 0000000000..cee33eb58d --- /dev/null +++ b/gr-qtgui/python/qtgui/levelgauge.py @@ -0,0 +1,214 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2020 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# + +from threading import Lock +import sys + +from PyQt5.QtWidgets import QFrame, QHBoxLayout, QVBoxLayout, QLabel, QProgressBar +from PyQt5.QtGui import QColor +from PyQt5.QtCore import Qt as Qtc +from PyQt5.QtCore import pyqtSignal +from PyQt5.QtGui import QPalette + +from gnuradio import gr +import pmt + +class LabeledLevelGauge(QFrame): + # Positions: 1 = above, 2=below, 3=left, 4=right + def __init__(self, lbl='', barColor='blue', backgroundColor='white', fontColor='black', + minValue=0, maxValue=100, maxSize=80, position=1, isVertical=True, + isFloat=False, scaleFactor=1, showValue=False, parent=None): + QFrame.__init__(self, parent) + self.numberControl = LevelGauge(barColor, backgroundColor, minValue, maxValue, + maxSize, isVertical, isFloat, scaleFactor, showValue, + parent) + + if position < 3: + layout = QVBoxLayout() + else: + layout = QHBoxLayout() + + self.lbl = lbl + self.showvalue = showValue + self.isFloat = isFloat + self.isVertical = isVertical + self.scaleFactor = scaleFactor + + self.lblcontrol = QLabel(lbl, self) + self.lblcontrol.setAlignment(Qtc.AlignCenter) + + # For whatever reason, the progressbar doesn't show the number in the bar if it's + # vertical, only if it's horizontal + if self.showvalue and (isFloat or self.isVertical): + textstr = self.buildTextStr(minValue/self.scaleFactor) + self.lblcontrol.setText(textstr) + + if fontColor != 'default': + self.lblcontrol.setStyleSheet("QLabel { color : " + fontColor + "; }") + + # add top or left + if len: + if position == 1 or position == 3: + layout.addWidget(self.lblcontrol) + else: + self.hasLabel = False + + layout.addWidget(self.numberControl) + + # Add bottom or right + if len: + if position == 2 or position == 4: + layout.addWidget(self.lblcontrol) + + layout.setAlignment(Qtc.AlignCenter | Qtc.AlignVCenter) + self.setLayout(layout) + + self.show() + + def buildTextStr(self, new_value): + textstr = "" + if len(self.lbl) > 0: + textstr = self.lbl + " - " + + if self.isFloat: + textstr += "%.2f" % (new_value) + else: + textstr += str(new_value) + + return textstr + + def valChanged(self, new_value): + if not self.showvalue: + return + + if self.isFloat or self.isVertical: + if self.lbl: + textstr = self.buildTextStr(new_value) + self.lblcontrol.setText(textstr) + + def setValue(self, new_value): + self.valChanged(new_value) + + if int(self.scaleFactor) != 1: + new_value = int(new_value * self.scaleFactor) + + self.numberControl.setValue(new_value) + +class LevelGauge(QProgressBar): + # Notifies to avoid thread conflicts on paints + updateInt = pyqtSignal(int) + updateFloat = pyqtSignal(float) + + def __init__(self, barColor='blue', backgroundColor='white', minValue=0, maxValue=100, + maxSize=80, isVertical=True, isFloat=False, scaleFactor=1, showValue=False, + parent=None): + super().__init__(parent) + + self.updateInt.connect(self.onUpdateInt) + self.updateFloat.connect(self.onUpdateFloat) + + self.lock = Lock() + + self.maxSize = maxSize + + p = super().palette() + + if backgroundColor != 'default': + p.setColor(QPalette.Base, QColor(backgroundColor)) + + if barColor != 'default': + p.setColor(QPalette.Highlight, QColor(barColor)) + + if backgroundColor != 'default' or barColor != 'default': + super().setPalette(p) + + if (not isFloat) and showValue: + super().setFormat("%v") # This shows the number in the bar itself. + super().setTextVisible(True) + else: + super().setTextVisible(False) + + super().setMinimum(minValue) + super().setMaximum(maxValue) + + if isVertical: + super().setOrientation(Qtc.Vertical) + else: + super().setOrientation(Qtc.Horizontal) + + def onUpdateInt(self, new_value): + if new_value > super().maximum(): + new_value = super().maximum() + elif new_value < super().minimum(): + new_value = super().minimum() + + self.lock.acquire() + super().setValue(new_value) + self.lock.release() + + def onUpdateFloat(self, new_value): + if new_value > super().maximum(): + new_value = super().maximum() + elif new_value < super().minimum(): + new_value = super().minimum() + + self.lock.acquire() + super().setValue(new_value) + self.lock.release() + + def setValue(self, new_value): + if type(new_value) == int: + self.updateInt.emit(new_value) + else: + self.updateFloat.emit(new_value) + +class GrLevelGauge(gr.sync_block, LabeledLevelGauge): + """ + This block creates a level gauge. The value can be set either + with a variable or an input message. + + NOTE: This control has some quirks due to the fact that + QProgressBar only accepts integers. If you want to work with + floats, you have to use the scaleFactor to map incoming values + to the specified min/max range. For instance if the min/max + are 0-100 but your incoming values are 0.0-1.0, you will need + to set a scalefactor of 100. + """ + def __init__(self, lbl='', barColor='blue', backgroundColor='white', fontColor='black', + minValue=0, maxValue=100, maxSize=80, isVertical=True, position=1, + isFloat=False, scaleFactor=1, showValue=False, parent=None): + gr.sync_block.__init__(self, name="LevelGauge", in_sig=None, out_sig=None) + LabeledLevelGauge.__init__(self, lbl, barColor, backgroundColor, fontColor, minValue, + maxValue, maxSize, position, isVertical, isFloat, + scaleFactor, showValue, parent) + self.lbl = lbl + + if minValue > maxValue: + gr.log.error("Min value is greater than max value.") + sys.exit(1) + + self.message_port_register_in(pmt.intern("value")) + self.set_msg_handler(pmt.intern("value"), self.msgHandler) + + def msgHandler(self, msg): + try: + new_val = pmt.to_python(pmt.cdr(msg)) + + if type(new_val) == float or type(new_val) == int: + super().setValue(new_val) + else: + gr.log.error("Value received was not an int or a float: %s" % str(type(new_val))) + + except Exception as e: + gr.log.error("Error with message conversion: %s" % str(e)) + + def setValue(self, new_value): + super().setValue(new_value) diff --git a/gr-qtgui/python/qtgui/msgcheckbox.py b/gr-qtgui/python/qtgui/msgcheckbox.py new file mode 100644 index 0000000000..8d2a52ae07 --- /dev/null +++ b/gr-qtgui/python/qtgui/msgcheckbox.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2020 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# + +from PyQt5 import Qt +from PyQt5.QtWidgets import QFrame, QVBoxLayout +from PyQt5.QtCore import Qt as Qtc + +from gnuradio import gr +import pmt + +class CheckBoxEx(Qt.QCheckBox): + def __init__(self, lbl, callback=None): + Qt.QCheckBox.__init__(self) + self.setText(lbl) + self.callback = callback + + self.stateChanged.connect(self.onToggleClicked) + + def onToggleClicked(self): + if self.callback is not None: + self.callback(super().isChecked()) + +class MsgCheckBox(gr.sync_block, QFrame): + """ + This block creates a variable checkbox. Leave the label blank to + use the variable id as the label. A checkbox selects between + two values of similar type, but will stay depressed until + clicked again. The variable will take on one value or the other + depending on whether the button is pressed or released. + + This control will also produce a state message matching the + set values. + """ + def __init__(self, callback, lbl, pressedReleasedDict, initPressed, alignment, + valignment, outputmsgname='value'): + gr.sync_block.__init__(self, name="MsgCheckBox", in_sig=None, out_sig=None) + QFrame.__init__(self) + + self.outputmsgname = outputmsgname + self.chkBox = CheckBoxEx(lbl, self.onToggleClicked) + + layout = QVBoxLayout() + + layout.addWidget(self.chkBox) + + if alignment == 1: + halign = Qtc.AlignCenter + elif alignment == 2: + halign = Qtc.AlignLeft + else: + halign = Qtc.AlignRight + + if valignment == 1: + valign = Qtc.AlignVCenter + elif valignment == 2: + valign = Qtc.AlignTop + else: + valign = Qtc.AlignBottom + + layout.setAlignment(halign | valign) + self.setLayout(layout) + + self.callback = callback + self.pressReleasedDict = pressedReleasedDict + + self.message_port_register_out(pmt.intern("state")) + + if initPressed: + self.chkctl.setChecked(True) + + self.show() + + def onToggleClicked(self, checked): + if self.chkBox.isChecked(): + self.callback(self.pressReleasedDict['Pressed']) + + if type(self.pressReleasedDict['Pressed']) == bool: + self.message_port_pub(pmt.intern("state"), + pmt.cons(pmt.intern(self.outputmsgname), + pmt.from_bool(self.pressReleasedDict['Pressed']))) + elif type(self.pressReleasedDict['Pressed']) == int: + self.message_port_pub(pmt.intern("state"), + pmt.cons(pmt.intern(self.outputmsgname), + pmt.from_long(self.pressReleasedDict['Pressed']))) + elif type(self.pressReleasedDict['Pressed']) == float: + self.message_port_pub(pmt.intern("state"), + pmt.cons(pmt.intern(self.outputmsgname), + pmt.from_float(self.pressReleasedDict['Pressed']))) + else: + self.message_port_pub(pmt.intern("state"), + pmt.cons(pmt.intern(self.outputmsgname), + pmt.intern(self.pressReleasedDict['Pressed']))) + else: + self.callback(self.pressReleasedDict['Released']) + + if type(self.pressReleasedDict['Released']) == bool: + self.message_port_pub(pmt.intern("state"), + pmt.cons(pmt.intern(self.outputmsgname), + pmt.from_bool(self.pressReleasedDict['Released']))) + elif type(self.pressReleasedDict['Released']) == int: + self.message_port_pub(pmt.intern("state"), + pmt.cons(pmt.intern(self.outputmsgname), + pmt.from_long(self.pressReleasedDict['Released']))) + elif type(self.pressReleasedDict['Released']) == float: + self.message_port_pub(pmt.intern("state"), + pmt.cons(pmt.intern(self.outputmsgname), + pmt.from_float(self.pressReleasedDict['Released']))) + else: + self.message_port_pub(pmt.intern("state"), + pmt.cons(pmt.intern(self.outputmsgname), + pmt.intern(self.pressReleasedDict['Released']))) diff --git a/gr-qtgui/python/qtgui/msgpushbutton.py b/gr-qtgui/python/qtgui/msgpushbutton.py new file mode 100644 index 0000000000..bee142cac7 --- /dev/null +++ b/gr-qtgui/python/qtgui/msgpushbutton.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2020 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# + +from PyQt5 import Qt +from gnuradio import gr +import pmt + +class MsgPushButton(gr.sync_block, Qt.QPushButton): + """ + This block creates a variable push button that creates a message + when clicked. Leave the label blank to use the variable id as + the label. You can define both the output message pmt name as + well as the value and value type. + """ + def __init__(self, lbl, msgName, msgValue, relBackColor, relFontColor): + gr.sync_block.__init__(self, name="MsgPushButton", in_sig=None, out_sig=None) + Qt.QPushButton.__init__(self, lbl) + + self.lbl = lbl + self.msgName = msgName + self.msgValue = msgValue + + styleStr = "" + if relBackColor != 'default': + styleStr = "background-color: " + relBackColor + "; " + + if relFontColor: + styleStr += "color: " + relFontColor + "; " + + self.setStyleSheet(styleStr) + + self.clicked[bool].connect(self.onBtnClicked) + + self.message_port_register_out(pmt.intern("pressed")) + + def onBtnClicked(self, pressed): + if type(self.msgValue) == int: + self.message_port_pub(pmt.intern("pressed"), + pmt.cons(pmt.intern(self.msgName), pmt.from_long(self.msgValue))) + elif type(self.msgValue) == float: + self.message_port_pub(pmt.intern("pressed"), + pmt.cons(pmt.intern(self.msgName), pmt.from_float(self.msgValue))) + elif type(self.msgValue) == str: + self.message_port_pub(pmt.intern("pressed"), + pmt.cons(pmt.intern(self.msgName), pmt.intern(self.msgValue))) + elif type(self.msgValue) == bool: + self.message_port_pub(pmt.intern("pressed"), + pmt.cons(pmt.intern(self.msgName), pmt.from_bool(self.msgValue))) diff --git a/gr-qtgui/python/qtgui/qa_qtgui.py b/gr-qtgui/python/qtgui/qa_qtgui.py index 5d1c98bef4..457b6f8c9f 100644 --- a/gr-qtgui/python/qtgui/qa_qtgui.py +++ b/gr-qtgui/python/qtgui/qa_qtgui.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2011 Free Software Foundation, Inc. +# Copyright 2011, 2020 Free Software Foundation, Inc. # # This file is part of GNU Radio # diff --git a/gr-qtgui/python/qtgui/togglebutton.py b/gr-qtgui/python/qtgui/togglebutton.py new file mode 100644 index 0000000000..0c0cf187f6 --- /dev/null +++ b/gr-qtgui/python/qtgui/togglebutton.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2020 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# + + +from PyQt5 import Qt +from gnuradio import gr +import pmt + +class ToggleButton(gr.sync_block, Qt.QPushButton): + """ + This block creates a variable toggle button. Leave the label + blank to use the variable id as the label. A toggle button + selects between two values of similar type, but will stay + depressed until clicked again. The variable will take on one + value or the other depending on whether the button is pressed + or released. This button will also produce a state message + matching the set values. + """ + def __init__(self, callback, lbl, pressedReleasedDict, initPressed, outputmsgname='value'): + gr.sync_block.__init__(self, name="ToggleButton", in_sig=None, out_sig=None) + Qt.QPushButton.__init__(self, lbl) + self.setCheckable(True) + self.lbl = lbl + self.callback = callback + self.pressReleasedDict = pressedReleasedDict + + self.outputmsgname = outputmsgname + self.relBackColor = 'default' + self.relFontColor = 'default' + self.pressBackColor = 'default' + self.pressFontColor = 'default' + + self.message_port_register_out(pmt.intern("state")) + + if initPressed: + self.setChecked(True) + self.state = 1 + else: + self.state = 0 + + self.clicked[bool].connect(self.onToggleClicked) + + def setColors(self, relBackColor, relFontColor, pressBackColor, pressFontColor): + self.relBackColor = relBackColor + self.relFontColor = relFontColor + self.pressBackColor = pressBackColor + self.pressFontColor = pressFontColor + + self.setColor() + + def setColor(self): + if self.state: + styleStr = "" + if self.pressBackColor != 'default': + styleStr = "background-color: " + self.pressBackColor + "; " + + if self.pressFontColor: + styleStr += "color: " + self.pressFontColor + "; " + + self.setStyleSheet(styleStr) + else: + styleStr = "" + if self.relBackColor != 'default': + styleStr = "background-color: " + self.relBackColor + "; " + + if self.relFontColor: + styleStr += "color: " + self.relFontColor + "; " + + self.setStyleSheet(styleStr) + + def onToggleClicked(self, pressed): + if pressed: + self.state = 1 + self.callback(self.pressReleasedDict['Pressed']) + else: + self.state = 0 + self.callback(self.pressReleasedDict['Released']) + + self.setColor() + + if pressed: + if type(self.pressReleasedDict['Pressed']) == bool: + self.message_port_pub(pmt.intern("state"), + pmt.cons(pmt.intern(self.outputmsgname), + pmt.from_bool(self.pressReleasedDict['Pressed']))) + elif type(self.pressReleasedDict['Pressed']) == int: + self.message_port_pub(pmt.intern("state"), + pmt.cons(pmt.intern(self.outputmsgname), + pmt.from_long(self.pressReleasedDict['Pressed']))) + elif type(self.pressReleasedDict['Pressed']) == float: + self.message_port_pub(pmt.intern("state"), + pmt.cons(pmt.intern(self.outputmsgname), + pmt.from_float(self.pressReleasedDict['Pressed']))) + else: + self.message_port_pub(pmt.intern("state"), + pmt.cons(pmt.intern(self.outputmsgname), + pmt.intern(self.pressReleasedDict['Pressed']))) + else: + if type(self.pressReleasedDict['Released']) == bool: + self.message_port_pub(pmt.intern("state"), + pmt.cons(pmt.intern(self.outputmsgname), + pmt.from_bool(self.pressReleasedDict['Released']))) + elif type(self.pressReleasedDict['Released']) == int: + self.message_port_pub(pmt.intern("state"), + pmt.cons(pmt.intern(self.outputmsgname), + pmt.from_long(self.pressReleasedDict['Released']))) + elif type(self.pressReleasedDict['Released']) == float: + self.message_port_pub(pmt.intern("state"), + pmt.cons(pmt.intern(self.outputmsgname), + pmt.from_float(self.pressReleasedDict['Released']))) + else: + self.message_port_pub(pmt.intern("state"), + pmt.cons(pmt.intern(self.outputmsgname), + pmt.intern(self.pressReleasedDict['Released']))) diff --git a/gr-qtgui/python/qtgui/toggleswitch.py b/gr-qtgui/python/qtgui/toggleswitch.py new file mode 100644 index 0000000000..7ef5a113fa --- /dev/null +++ b/gr-qtgui/python/qtgui/toggleswitch.py @@ -0,0 +1,210 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2020 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# + +from gnuradio import gr +import pmt + +from PyQt5.QtWidgets import QFrame, QHBoxLayout, QVBoxLayout, QLabel +from PyQt5.QtGui import QPainter, QBrush, QColor, QPen, QFontMetricsF +from PyQt5.QtCore import Qt as Qtc +from PyQt5.QtCore import QRect + +class LabeledToggleSwitch(QFrame): + # Positions: 1 = above, 2=below, 3=left, 4=right + def __init__(self, lbl='', onColor='green', offColor='red', initialState=False, + maxSize=50, position=1, parent=None, callback=None, alignment=1, valignment=1): + QFrame.__init__(self, parent) + self.numberControl = ToggleSwitch(onColor, offColor, initialState, maxSize, + parent, callback) + + if position < 3: + layout = QVBoxLayout() + else: + layout = QHBoxLayout() + + self.lbl = lbl + self.lblcontrol = QLabel(lbl, self) + + if position == 3: # left of switch + self.lblcontrol.setAlignment(Qtc.AlignRight) + elif position == 4: # right of switch + self.lblcontrol.setAlignment(Qtc.AlignLeft) + else: + # Above or below + self.lblcontrol.setAlignment(Qtc.AlignCenter) + + # add top or left + if len: + if position == 1 or position == 3: + layout.addWidget(self.lblcontrol) + + layout.addWidget(self.numberControl) + + # Add bottom or right + if len: + if position == 2 or position == 4: + layout.addWidget(self.lblcontrol) + + if alignment == 1: + halign = Qtc.AlignCenter + elif alignment == 2: + halign = Qtc.AlignLeft + else: + halign = Qtc.AlignRight + + if valignment == 1: + valign = Qtc.AlignVCenter + elif valignment == 2: + valign = Qtc.AlignTop + else: + valign = Qtc.AlignBottom + + layout.setAlignment(halign | valign) + + self.setLayout(layout) + + textfont = self.lblcontrol.font() + metrics = QFontMetricsF(textfont) + + maxWidth = max((maxSize+4), (maxSize*2 + metrics.width(lbl))) + maxHeight = max((maxSize/2+4), (maxSize/2 + metrics.height()+2)) + + self.setMinimumSize(int(maxWidth), int(maxHeight)) + + self.show() + + def setState(self, on_off): + self.numberControl.setState(on_off) + +class ToggleSwitch(QFrame): + def __init__(self, onColor='green', offColor='red', initialState=False, maxSize=50, + parent=None, callback=None): + QFrame.__init__(self, parent) + + self.maxSize = maxSize + self.curState = initialState + self.onColor = QColor(onColor) + self.offColor = QColor(offColor) + self.callback = callback + self.setMinimumSize(maxSize, maxSize/2) + self.setMaximumSize(maxSize, maxSize/2) + + def setState(self, on_off): + self.curState = on_off + if self.callback is not None: + self.callback(on_off) + + super().update() + + def paintEvent(self, event): + super().paintEvent(event) + + painter = QPainter(self) + painter.setRenderHint(QPainter.Antialiasing) + + size = self.size() + brush = QBrush() + + center_x = size.width()/2 + + if self.curState: + brush.setColor(self.onColor) + painter.setPen(QPen(self.onColor, 0)) + else: + brush.setColor(self.offColor) + painter.setPen(QPen(self.offColor, 0)) + + brush.setStyle(Qtc.SolidPattern) + painter.setBrush(brush) + + # Draw the switch background + centerRect = QRect(size.width()/4, 0, size.width()/2-4, size.height()) + painter.drawRect(centerRect) + painter.drawEllipse(0, 0, size.height(), size.height()) + painter.drawEllipse(size.width()/2, 0, size.height(), size.height()) + + # Draw the switch itself + brush.setColor(QColor('white')) + painter.setBrush(brush) + painter.setPen(QPen(QColor('white'), 0)) + if self.curState: + painter.drawEllipse(2, 2, size.height() - 4, size.height() - 4) + else: + painter.drawEllipse(center_x+2, 2, size.height() - 4, size.height() - 4) + + def mousePressEvent(self, event): + if event.x() <= self.size().width()/2: + self.setState(True) + else: + self.setState(False) + + super().update() + +class GrToggleSwitch(gr.sync_block, LabeledToggleSwitch): + """ + This block creates a modern toggle switch. The variable will take + on one value or the other as set in the dialog. This button will + also produce a state message matching the set values. + """ + def __init__(self, callback, lbl, pressedReleasedDict, initialState=False, + onColor='green', offColor='silver', position=3, maxSize=50, + alignment=1, valignment=1, parent=None, outputmsgname='value'): + gr.sync_block.__init__(self, name="ToggleSwitch", in_sig=None, out_sig=None) + LabeledToggleSwitch.__init__(self, lbl, onColor, offColor, initialState, + maxSize, position, parent, self.notifyUpdate, + alignment, valignment) + + self.outputmsgname = outputmsgname + self.pressReleasedDict = pressedReleasedDict + self.callback = callback + self.message_port_register_out(pmt.intern("state")) + + def notifyUpdate(self, new_val): + if self.callback is not None: + if new_val: + self.callback(self.pressReleasedDict['Pressed']) + else: + self.callback(self.pressReleasedDict['Released']) + + if new_val: + if type(self.pressReleasedDict['Pressed']) == bool: + self.message_port_pub(pmt.intern("state"), + pmt.cons(pmt.intern(self.outputmsgname), + pmt.from_bool(self.pressReleasedDict['Pressed']))) + elif type(self.pressReleasedDict['Pressed']) == int: + self.message_port_pub(pmt.intern("state"), + pmt.cons(pmt.intern(self.outputmsgname), + pmt.from_long(self.pressReleasedDict['Pressed']))) + elif type(self.pressReleasedDict['Pressed']) == float: + self.message_port_pub(pmt.intern("state"), + pmt.cons(pmt.intern(self.outputmsgname), + pmt.from_float(self.pressReleasedDict['Pressed']))) + else: + self.message_port_pub(pmt.intern("state"), + pmt.cons(pmt.intern(self.outputmsgname), + pmt.intern(self.pressReleasedDict['Pressed']))) + else: + if type(self.pressReleasedDict['Released']) == bool: + self.message_port_pub(pmt.intern("state"), + pmt.cons(pmt.intern(self.outputmsgname), + pmt.from_bool(self.pressReleasedDict['Released']))) + elif type(self.pressReleasedDict['Released']) == int: + self.message_port_pub(pmt.intern("state"), + pmt.cons(pmt.intern(self.outputmsgname), + pmt.from_long(self.pressReleasedDict['Released']))) + elif type(self.pressReleasedDict['Released']) == float: + self.message_port_pub(pmt.intern("state"), + pmt.cons(pmt.intern(self.outputmsgname), + pmt.from_float(self.pressReleasedDict['Released']))) + else: + self.message_port_pub(pmt.intern("state"), + pmt.cons(pmt.intern(self.outputmsgname), + pmt.intern(self.pressReleasedDict['Released']))) |