diff options
author | Sebastian Koslowski <sebastian.koslowski@gmail.com> | 2017-08-30 20:36:14 +0200 |
---|---|---|
committer | Sebastian Koslowski <sebastian.koslowski@gmail.com> | 2017-09-06 19:37:17 +0200 |
commit | 6c85638cd5ec81140ec8bbd95bf23794e27b5c64 (patch) | |
tree | 8ae844e9a6633c1ffb5bd7fd0a1a1ea0dcfea4d9 | |
parent | 4e23a380033ff4a092ef9ae1d13dec30e1cc3ccf (diff) | |
parent | 6a6eabc465c24e75f701b1e3d0033769ae76f736 (diff) |
Merge branch 'next' into python3
-rw-r--r-- | grc/blocks/options.xml | 51 | ||||
-rw-r--r-- | grc/core/generator/flow_graph.py.mako | 55 | ||||
-rw-r--r-- | grc/core/platform.py | 1 | ||||
-rw-r--r-- | grc/core/utils/__init__.py | 1 | ||||
-rw-r--r-- | grc/core/utils/hide_bokeh_gui_options_if_not_installed.py | 24 |
5 files changed, 130 insertions, 2 deletions
diff --git a/grc/blocks/options.xml b/grc/blocks/options.xml index c349cd956a..21d1c9ddee 100644 --- a/grc/blocks/options.xml +++ b/grc/blocks/options.xml @@ -15,6 +15,13 @@ from PyQt5 import Qt import sys #end if +#if $generate_options() == 'bokeh_gui' +import time +import signal +import functools +from bokeh.client import push_session +from bokeh.plotting import curdoc +#end if #if not $generate_options().startswith('hb') from argparse import ArgumentParser from gnuradio.eng_arg import eng_float, intx @@ -57,6 +64,10 @@ else: self.stop(); self.wait()</callback> <value>qt_gui</value> <type>enum</type> <option> + <name>Bokeh GUI</name> + <key>bokeh_gui</key> + </option> + <option> <name>QT GUI</name> <key>qt_gui</key> </option> @@ -96,11 +107,45 @@ else: self.stop(); self.wait()</callback> </option> </param> <param> + <name>Widget Placement</name> + <key>placement</key> + <value>(0,0)</value> + <type>int_vector</type> + <hide>#if $generate_options() == 'bokeh_gui' then 'part' else 'all'#</hide> + </param> + <param> + <name>Sizing Mode</name> + <key>sizing_mode</key> + <value>fixed</value> + <type>enum</type> + <hide>#if $generate_options() == 'bokeh_gui' then 'part' else 'all'#</hide> + <option> + <name>Fixed</name> + <key>fixed</key> + </option> + <option> + <name>Stretch Both</name> + <key>stretch_both</key> + </option> + <option> + <name>Scale Width</name> + <key>scale_width</key> + </option> + <option> + <name>Scale Height</name> + <key>scale_height</key> + </option> + <option> + <name>Scale Both</name> + <key>scale_both</key> + </option> + </param> + <param> <name>Run</name> <key>run</key> <value>True</value> <type>bool</type> - <hide>#if $generate_options() != 'qt_gui' then 'all' else ('part' if $run() else 'none')#</hide> + <hide>#if $generate_options() not in ('qt_gui', 'bokeh_gui') then 'all' else ('part' if $run() else 'none')#</hide> <option> <name>Autostart</name> <key>True</key> @@ -174,7 +219,9 @@ else: self.stop(); self.wait()</callback> <check>not $window_size or len($window_size) == 2</check> <check>not $window_size or 300 <= $(window_size)[0] <= 4096</check> <check>not $window_size or 300 <= $(window_size)[1] <= 4096</check> - <doc> + <check>len($placement) == 4 or len($placement) == 2</check> + <check>all(i >= 0 for i in $(placement))</check> + <doc> The options block sets special parameters for the flow graph. \ Only one option block is allowed per flow graph. diff --git a/grc/core/generator/flow_graph.py.mako b/grc/core/generator/flow_graph.py.mako index 484441f00f..6793ad02e0 100644 --- a/grc/core/generator/flow_graph.py.mako +++ b/grc/core/generator/flow_graph.py.mako @@ -82,6 +82,14 @@ class ${class_name}(gr.top_block, Qt.QWidget): self.restoreGeometry(self.settings.value("geometry")) except: pass +#elif $generate_options == 'bokeh_gui' + +class $(class_name)(gr.top_block): + def __init__(self, doc): + gr.top_block.__init__(self, "${title}") + self.doc = doc + self.plot_lst = [] + self.widget_lst = [] % elif generate_options == 'no_gui': class ${class_name}(gr.top_block): @@ -180,6 +188,22 @@ gr.io_signaturev(${len(io_sigs)}, ${len(io_sigs)}, [${', '.join(ize_strs)}]) ## (self.${blk.name}).set_max_output_buffer(${blk.params['maxoutbuf'].get_evaluated()}) ## % endif % endfor + +########################################################## +## Create a layout entry if not manually done for BokehGUI +########################################################## +%if generate_options == 'bokeh_gui' + if self.widget_lst: + input_t = bokehgui.BokehLayout.widgetbox(self.widget_lst) + widgetbox = bokehgui.BokehLayout.WidgetLayout(input_t) + widgetbox.set_layout(*(${flow_graph.get_option('placement')})) + list_obj = [widgetbox] + self.plot_lst + else: + list_obj = self.plot_lst + layout_t = bokehgui.BokehLayout.create_layout(list_obj, "${flow_graph.get_option('sizing_mode')}") + self.doc.add_root(layout_t) +% endif + % if connections: ${'##################################################'} @@ -325,6 +349,37 @@ def main(top_block_cls=${class_name}, options=None): sys.stderr.write("Monitor '{0}' does not have an enable ('en') parameter.".format("tb.${m.name}")) % endfor qapp.exec_() + #elif $generate_options == 'bokeh_gui' + serverProc, port = bokehgui.utils.create_server() + def killProc(signum, frame, tb): + tb.stop() + tb.wait() + serverProc.terminate() + serverProc.kill() + time.sleep(1) + try: + ${'#'} Define the document instance + doc = curdoc() + #if ${flow_graph.get_option('author')} + doc.title = "$title - ${flow_graph.get_option('author')}" + #else + doc.title = "${title}" + #end if + session = push_session(doc, session_id="${flow_graph.get_option('id')}", + url = "http://localhost:" + port + "/bokehgui") + ${'#'} Create Top Block instance + tb = top_block_cls(doc) + try: + tb.start() + signal.signal(signal.SIGTERM, functools.partial(killProc, tb=tb)) + session.loop_until_closed() + finally: + print("Exiting the simulation. Stopping Bokeh Server") + tb.stop() + tb.wait() + finally: + serverProc.terminate() + serverProc.kill() % elif generate_options == 'no_gui': tb = top_block_cls(${ ', '.join(params_eq_list) }) % if flow_graph.get_option('run_options') == 'prompt': diff --git a/grc/core/platform.py b/grc/core/platform.py index 02203942f9..538bacade2 100644 --- a/grc/core/platform.py +++ b/grc/core/platform.py @@ -193,6 +193,7 @@ class Platform(Element): self._docstring_extractor.finish() # self._docstring_extractor.wait() + utils.hide_bokeh_gui_options_if_not_installed(self.blocks['options']) def _iter_files_in_block_path(self, path=None, ext='yml'): """Iterator for block descriptions and category trees""" diff --git a/grc/core/utils/__init__.py b/grc/core/utils/__init__.py index 2d12e280b5..660eb594a5 100644 --- a/grc/core/utils/__init__.py +++ b/grc/core/utils/__init__.py @@ -18,3 +18,4 @@ from __future__ import absolute_import from . import epy_block_io, expr_utils, extract_docs, flow_graph_complexity +from .hide_bokeh_gui_options_if_not_installed import hide_bokeh_gui_options_if_not_installed diff --git a/grc/core/utils/hide_bokeh_gui_options_if_not_installed.py b/grc/core/utils/hide_bokeh_gui_options_if_not_installed.py new file mode 100644 index 0000000000..f209e515a8 --- /dev/null +++ b/grc/core/utils/hide_bokeh_gui_options_if_not_installed.py @@ -0,0 +1,24 @@ +# Copyright 2008-2017 Free Software Foundation, Inc. +# This file is part of GNU Radio +# +# GNU Radio Companion is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# GNU Radio Companion is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + + +def hide_bokeh_gui_options_if_not_installed(options_blk): + try: + import bokehgui + except ImportError: + generate_options = options_blk.params['generate_options'] + del generate_options.options['bokeh_gui'] |