summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Koslowski <sebastian.koslowski@gmail.com>2017-08-30 20:36:14 +0200
committerSebastian Koslowski <sebastian.koslowski@gmail.com>2017-09-06 19:37:17 +0200
commit6c85638cd5ec81140ec8bbd95bf23794e27b5c64 (patch)
tree8ae844e9a6633c1ffb5bd7fd0a1a1ea0dcfea4d9
parent4e23a380033ff4a092ef9ae1d13dec30e1cc3ccf (diff)
parent6a6eabc465c24e75f701b1e3d0033769ae76f736 (diff)
Merge branch 'next' into python3
-rw-r--r--grc/blocks/options.xml51
-rw-r--r--grc/core/generator/flow_graph.py.mako55
-rw-r--r--grc/core/platform.py1
-rw-r--r--grc/core/utils/__init__.py1
-rw-r--r--grc/core/utils/hide_bokeh_gui_options_if_not_installed.py24
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 &lt;= $(window_size)[0] &lt;= 4096</check>
<check>not $window_size or 300 &lt;= $(window_size)[1] &lt;= 4096</check>
- <doc>
+ <check>len($placement) == 4 or len($placement) == 2</check>
+ <check>all(i &gt;= 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']