diff options
author | Kartik Patel <kartikpatel1995@gmail.com> | 2017-06-14 02:37:06 +0530 |
---|---|---|
committer | Kartik Patel <kartikpatel1995@gmail.com> | 2017-08-22 00:37:30 -0500 |
commit | 3c989f90c1991195b793b53a28aa4c1f9c4d2d9c (patch) | |
tree | da70a5c67472591aa8f72b4e9bbf85a7afbbfd86 | |
parent | efcfde0e92e8fae886754436e6ad82d58831d194 (diff) |
grc: Modifications in GRC to allow BokehGUI
grc: Updated template for bokehgui
grc: Removed import from template file
grc: Added a condition to load bokeh based on installed library
grc: Allowed display from remote PC
grc: Added default layout option
grc: Added WidgetPlacement, Sizing Mode options in Options block
grc: Add terminate handler in main function
grc: default rowspan, colspan = 1
grc: Updated Document title and session id from the parameters of Options block
grc: Layout indexing starts from 0
grc: Allowed dynamic port selection
grc: Added a URL path for flow_graph
grc: Reviews incorporated
-rw-r--r-- | grc/blocks/options.xml | 51 | ||||
-rw-r--r-- | grc/core/Platform.py | 4 | ||||
-rw-r--r-- | grc/core/generator/flow_graph.tmpl | 58 | ||||
-rw-r--r-- | grc/core/utils/__init__.py | 1 | ||||
-rw-r--r-- | grc/core/utils/hide_bokeh_gui_options_if_not_installed.py | 28 |
5 files changed, 138 insertions, 4 deletions
diff --git a/grc/blocks/options.xml b/grc/blocks/options.xml index 1dee986c5c..6f3c8d5cf0 100644 --- a/grc/blocks/options.xml +++ b/grc/blocks/options.xml @@ -19,6 +19,13 @@ import wx from PyQt4 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 optparse import OptionParser from gnuradio.eng_option import eng_option @@ -61,6 +68,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> @@ -104,12 +115,46 @@ 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() in ('qt_gui', 'wx_gui') +#if $generate_options() in ('qt_gui', 'wx_gui', 'bokeh_gui') #if $run() part #else @@ -218,7 +263,9 @@ part#slurp <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/Platform.py b/grc/core/Platform.py index 297e8b0ae5..258f38cc62 100644 --- a/grc/core/Platform.py +++ b/grc/core/Platform.py @@ -31,7 +31,7 @@ from .Block import Block from .Port import Port from .Param import Param -from .utils import odict, extract_docs +from .utils import odict, extract_docs, hide_bokeh_gui_options_if_not_installed class Platform(Element): @@ -172,6 +172,8 @@ class Platform(Element): self._docstring_extractor.finish() # self._docstring_extractor.wait() + hide_bokeh_gui_options_if_not_installed(self.blocks['options']) + def iter_xml_files(self): """Iterator for block descriptions and category trees""" for block_path in self.config.block_paths: diff --git a/grc/core/generator/flow_graph.tmpl b/grc/core/generator/flow_graph.tmpl index 1ef251c46b..5550dca823 100644 --- a/grc/core/generator/flow_graph.tmpl +++ b/grc/core/generator/flow_graph.tmpl @@ -38,7 +38,7 @@ import threading ## Call XInitThreads as the _very_ first thing. ## After some Qt import, it's too late -#if $generate_options in ('wx_gui', 'qt_gui') +#if $generate_options in ('wx_gui', 'qt_gui', 'bokeh_gui') if __name__ == '__main__': import ctypes import sys @@ -119,6 +119,15 @@ class $(class_name)(gr.top_block, Qt.QWidget): self.settings = Qt.QSettings("GNU Radio", "$class_name") self.restoreGeometry(self.settings.value("geometry").toByteArray()) + +#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' @@ -237,6 +246,22 @@ gr.io_signaturev($(len($io_sigs)), $(len($io_sigs)), [$(', '.join($size_strs))]) #end if #end if #end for + +########################################################## +## 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) +#end if + ######################################################## ##Create Connections ## The port name should be the id of the parent block. @@ -378,6 +403,37 @@ def main(top_block_cls=$(class_name), options=None): #end for tb.Wait() #end if + #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 == 'qt_gui' from distutils.version import StrictVersion if StrictVersion(Qt.qVersion()) >= StrictVersion("4.5.0"): diff --git a/grc/core/utils/__init__.py b/grc/core/utils/__init__.py index 6b23da2723..2aed42d762 100644 --- a/grc/core/utils/__init__.py +++ b/grc/core/utils/__init__.py @@ -20,3 +20,4 @@ import epy_block_io import extract_docs from odict import odict +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..fc0141851a --- /dev/null +++ b/grc/core/utils/hide_bokeh_gui_options_if_not_installed.py @@ -0,0 +1,28 @@ +# 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): + try: + import bokehgui + except ImportError: + generate_option = options.get_param('generate_options') + list_generate_option = generate_option.get_options() + for option in list_generate_option: + if option.get_key() == 'bokeh_gui': + list_generate_option.remove(option) + return |