Skip to content

Commit cb0efaf

Browse files
committed
Merge commit 'c0f18d'
This merges skoslowsi/master with PR 1434 merged in.
2 parents 8aa965c + c0f18d3 commit cb0efaf

File tree

5 files changed

+138
-4
lines changed

5 files changed

+138
-4
lines changed

grc/blocks/options.xml

+49-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ import wx
1919
from PyQt4 import Qt
2020
import sys
2121
#end if
22+
#if $generate_options() == 'bokeh_gui'
23+
import time
24+
import signal
25+
import functools
26+
from bokeh.client import push_session
27+
from bokeh.plotting import curdoc
28+
#end if
2229
#if not $generate_options().startswith('hb')
2330
from optparse import OptionParser
2431
from gnuradio.eng_option import eng_option
@@ -60,6 +67,10 @@ else: self.stop(); self.wait()</callback>
6067
<key>generate_options</key>
6168
<value>qt_gui</value>
6269
<type>enum</type>
70+
<option>
71+
<name>Bokeh GUI</name>
72+
<key>bokeh_gui</key>
73+
</option>
6374
<option>
6475
<name>QT GUI</name>
6576
<key>qt_gui</key>
@@ -104,12 +115,46 @@ else: self.stop(); self.wait()</callback>
104115
</option>
105116
</param>
106117
<param>
118+
<name>Widget Placement</name>
119+
<key>placement</key>
120+
<value>(0,0)</value>
121+
<type>int_vector</type>
122+
<hide>#if $generate_options() == 'bokeh_gui' then 'part' else 'all'#</hide>
123+
</param>
124+
<param>
125+
<name>Sizing Mode</name>
126+
<key>sizing_mode</key>
127+
<value>fixed</value>
128+
<type>enum</type>
129+
<hide>#if $generate_options() == 'bokeh_gui' then 'part' else 'all'#</hide>
130+
<option>
131+
<name>Fixed</name>
132+
<key>fixed</key>
133+
</option>
134+
<option>
135+
<name>Stretch Both</name>
136+
<key>stretch_both</key>
137+
</option>
138+
<option>
139+
<name>Scale Width</name>
140+
<key>scale_width</key>
141+
</option>
142+
<option>
143+
<name>Scale Height</name>
144+
<key>scale_height</key>
145+
</option>
146+
<option>
147+
<name>Scale Both</name>
148+
<key>scale_both</key>
149+
</option>
150+
</param>
151+
<param>
107152
<name>Run</name>
108153
<key>run</key>
109154
<value>True</value>
110155
<type>bool</type>
111156
<hide>
112-
#if $generate_options() in ('qt_gui', 'wx_gui')
157+
#if $generate_options() in ('qt_gui', 'wx_gui', 'bokeh_gui')
113158
#if $run()
114159
part
115160
#else
@@ -218,7 +263,9 @@ part#slurp
218263
<check>not $window_size or len($window_size) == 2</check>
219264
<check>not $window_size or 300 &lt;= $(window_size)[0] &lt;= 4096</check>
220265
<check>not $window_size or 300 &lt;= $(window_size)[1] &lt;= 4096</check>
221-
<doc>
266+
<check>len($placement) == 4 or len($placement) == 2</check>
267+
<check>all(i &gt;= 0 for i in $(placement))</check>
268+
<doc>
222269
The options block sets special parameters for the flow graph. \
223270
Only one option block is allowed per flow graph.
224271

grc/core/Platform.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
from .Port import Port
3232
from .Param import Param
3333

34-
from .utils import odict, extract_docs
34+
from .utils import odict, extract_docs, hide_bokeh_gui_options_if_not_installed
3535

3636

3737
class Platform(Element):
@@ -172,6 +172,8 @@ def build_block_library(self):
172172
self._docstring_extractor.finish()
173173
# self._docstring_extractor.wait()
174174

175+
hide_bokeh_gui_options_if_not_installed(self.blocks['options'])
176+
175177
def iter_xml_files(self):
176178
"""Iterator for block descriptions and category trees"""
177179
for block_path in self.config.block_paths:

grc/core/generator/flow_graph.tmpl

+57-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ import threading
3838

3939
## Call XInitThreads as the _very_ first thing.
4040
## After some Qt import, it's too late
41-
#if $generate_options in ('wx_gui', 'qt_gui')
41+
#if $generate_options in ('wx_gui', 'qt_gui', 'bokeh_gui')
4242
if __name__ == '__main__':
4343
import ctypes
4444
import sys
@@ -119,6 +119,15 @@ class $(class_name)(gr.top_block, Qt.QWidget):
119119

120120
self.settings = Qt.QSettings("GNU Radio", "$class_name")
121121
self.restoreGeometry(self.settings.value("geometry").toByteArray())
122+
123+
#elif $generate_options == 'bokeh_gui'
124+
125+
class $(class_name)(gr.top_block):
126+
def __init__(self, doc):
127+
gr.top_block.__init__(self, "$title")
128+
self.doc = doc
129+
self.plot_lst = []
130+
self.widget_lst = []
122131
#elif $generate_options == 'no_gui'
123132

124133

@@ -237,6 +246,22 @@ gr.io_signaturev($(len($io_sigs)), $(len($io_sigs)), [$(', '.join($size_strs))])
237246
#end if
238247
#end if
239248
#end for
249+
250+
##########################################################
251+
## Create a layout entry if not manually done for BokehGUI
252+
##########################################################
253+
#if $generate_options == 'bokeh_gui'
254+
if self.widget_lst:
255+
input_t = bokehgui.BokehLayout.widgetbox(self.widget_lst)
256+
widgetbox = bokehgui.BokehLayout.WidgetLayout(input_t)
257+
widgetbox.set_layout(*($flow_graph.get_option('placement')))
258+
list_obj = [widgetbox] + self.plot_lst
259+
else:
260+
list_obj = self.plot_lst
261+
layout_t = bokehgui.BokehLayout.create_layout(list_obj, "$flow_graph.get_option('sizing_mode')")
262+
self.doc.add_root(layout_t)
263+
#end if
264+
240265
########################################################
241266
##Create Connections
242267
## The port name should be the id of the parent block.
@@ -378,6 +403,37 @@ def main(top_block_cls=$(class_name), options=None):
378403
#end for
379404
tb.Wait()
380405
#end if
406+
#elif $generate_options == 'bokeh_gui'
407+
serverProc, port = bokehgui.utils.create_server()
408+
def killProc(signum, frame, tb):
409+
tb.stop()
410+
tb.wait()
411+
serverProc.terminate()
412+
serverProc.kill()
413+
time.sleep(1)
414+
try:
415+
\# Define the document instance
416+
doc = curdoc()
417+
#if $flow_graph.get_option('author')
418+
doc.title = "$title - $flow_graph.get_option('author')"
419+
#else
420+
doc.title = "$title"
421+
#end if
422+
session = push_session(doc, session_id="$flow_graph.get_option('id')",
423+
url = "http://localhost:" + port + "/bokehgui")
424+
\# Create Top Block instance
425+
tb = top_block_cls(doc)
426+
try:
427+
tb.start()
428+
signal.signal(signal.SIGTERM, functools.partial(killProc, tb=tb))
429+
session.loop_until_closed()
430+
finally:
431+
print "Exiting the simulation. Stopping Bokeh Server"
432+
tb.stop()
433+
tb.wait()
434+
finally:
435+
serverProc.terminate()
436+
serverProc.kill()
381437
#elif $generate_options == 'qt_gui'
382438
from distutils.version import StrictVersion
383439
if StrictVersion(Qt.qVersion()) >= StrictVersion("4.5.0"):

grc/core/utils/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@
2020
import extract_docs
2121

2222
from odict import odict
23+
from hide_bokeh_gui_options_if_not_installed import hide_bokeh_gui_options_if_not_installed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Copyright 2008-2017 Free Software Foundation, Inc.
2+
# This file is part of GNU Radio
3+
#
4+
# GNU Radio Companion is free software; you can redistribute it and/or
5+
# modify it under the terms of the GNU General Public License
6+
# as published by the Free Software Foundation; either version 2
7+
# of the License, or (at your option) any later version.
8+
#
9+
# GNU Radio Companion is distributed in the hope that it will be useful,
10+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
# GNU General Public License for more details.
13+
#
14+
# You should have received a copy of the GNU General Public License
15+
# along with this program; if not, write to the Free Software
16+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
17+
18+
19+
def hide_bokeh_gui_options_if_not_installed(options):
20+
try:
21+
import bokehgui
22+
except ImportError:
23+
generate_option = options.get_param('generate_options')
24+
list_generate_option = generate_option.get_options()
25+
for option in list_generate_option:
26+
if option.get_key() == 'bokeh_gui':
27+
list_generate_option.remove(option)
28+
return

0 commit comments

Comments
 (0)