"""
Force a paint event.
"""
+ if not self._gl_init_flag: return
wx.PostEvent(self, wx.PaintEvent())
self,
parent,
baseband_freq=0,
- y_per_div=None, #ignore (old wrapper)
ref_level=50,
sample_rate=1,
fft_size=512,
ref_scale=2.0,
dynamic_range=80,
num_lines=256,
+ **kwargs #do not end with a comma
):
#ensure avg alpha
if avg_alpha is None: avg_alpha = 2.0/fft_rate
if block_key not in self.get_block_keys():
print >> sys.stderr, 'Warning: Block key "%s" not found when loading category tree.'%(block_key)
continue
- block_tree.add_block(parent, self.get_block(block_key))
+ block = self.get_block(block_key)
+ #if it exists, the block's category overrides the block tree
+ if not block.get_category(): block_tree.add_block(parent, block)
#load the block tree
for block_tree_file in self._block_tree_files:
#recursivly add all blocks in the tree
import.xml \
low_pass_filter.xml \
note.xml \
+ notebook.xml \
options.xml \
pad_sink.xml \
pad_source.xml \
<block>xmlrpc_server</block>
<block>xmlrpc_client</block>
+
+ <block>notebook</block>
</cat>
</cat>
--- /dev/null
+<?xml version="1.0"?>
+<!--
+###################################################
+##WX GUI Notebook
+###################################################
+ -->
+<block>
+ <name>Notebook</name>
+ <key>notebook</key>
+ <import>from grc_gnuradio import wxgui as grc_wxgui</import>
+ <make>#set $parent = $notebook() and 'self.%s.GetPage(%s)'%$notebook() or 'self'
+self.$(id) = wx.Notebook($(parent).GetWin(), style=$style)
+#for $label in $labels()
+self.$(id).AddPage(grc_wxgui.Panel(self.$(id)), "$label")
+#end for
+#if not $grid_pos()
+$(parent).Add(self.$(id))
+#else
+$(parent).GridAdd(self.$(id), $(', '.join(map(str, $grid_pos()))))
+#end if</make>
+ <param>
+ <name>Tab Orientation</name>
+ <key>style</key>
+ <value>wx.NB_TOP</value>
+ <type>enum</type>
+ <option>
+ <name>Top</name>
+ <key>wx.NB_TOP</key>
+ </option>
+ <option>
+ <name>Right</name>
+ <key>wx.NB_RIGHT</key>
+ </option>
+ <option>
+ <name>Bottom</name>
+ <key>wx.NB_BOTTOM</key>
+ </option>
+ <option>
+ <name>Left</name>
+ <key>wx.NB_LEFT</key>
+ </option>
+ </param>
+ <param>
+ <name>Labels</name>
+ <key>labels</key>
+ <value>['tab1', 'tab2', 'tab3']</value>
+ <type>raw</type>
+ </param>
+ <param>
+ <name>Grid Position</name>
+ <key>grid_pos</key>
+ <value></value>
+ <type>grid_pos</type>
+ </param>
+ <param>
+ <name>Notebook</name>
+ <key>notebook</key>
+ <value></value>
+ <type>notebook</type>
+ </param>
+ <check>isinstance($labels, (list, tuple))</check>
+ <check>all(map(lambda x: isinstance(x, str), $labels))</check>
+ <check>len($labels) > 0</check>
+ <doc>
+Use the Grid Position (row, column, row span, column span) to position the graphical element in the window.
+
+Use the Notebook Param (notebook-id, page-index) to place the graphical element inside of a notebook page.
+ </doc>
+</block>
#end if
</import>
<make></make>
- <callback>self.start($autostart)</callback>
+ <callback>if $run: self.start()
+else: self.stop(); self.wait()</callback>
<param>
<name>Title</name>
<key>title</key>
<hide>#if $generate_options() == 'hb' then 'none' else 'all'#</hide>
</param>
<param>
- <name>Autostart</name>
- <key>autostart</key>
+ <name>Run</name>
+ <key>run</key>
<value>True</value>
<type>bool</type>
<hide>#if $generate_options() == 'wx_gui'
- #if str($autostart) == 'True'
+ #if str($run) == 'True'
part#slurp
#else
none#slurp
all#slurp
#end if</hide>
<option>
- <name>Yes</name>
+ <name>Autostart</name>
<key>True</key>
</option>
<option>
- <name>No</name>
+ <name>Off</name>
<key>False</key>
</option>
</param>
Non-graphical flow graphs should avoid using graphical sinks or graphical variable controls.
In a graphical application, \
-autostart can be controlled by a variable to start and stop the flowgraph at runtime.
+run can be controlled by a variable to start and stop the flowgraph at runtime.
The id of this block determines the name of the generated file and the name of the class. \
For example, an id of my_block will generate the file my_block.py and class my_block(gr....
<key>variable_check_box</key>
<import>from gnuradio.wxgui import forms</import>
<var_make>self.$(id) = $(id) = $value</var_make>
- <make>self._$(id)_check_box = forms.check_box(
- parent=self.GetWin(),
+ <make>#set $parent = $notebook() and 'self.%s.GetPage(%s)'%$notebook() or 'self'
+#set $win = 'self._%s_check_box'%$id
+$win = forms.check_box(
+ parent=$(parent).GetWin(),
value=self.$id,
callback=self.set_$(id),
#if $label()
true=$true,
false=$false,
)
-#set $grid_pos = $grid_pos()
-#if not grid_pos
-self.Add(self._$(id)_check_box)
+#if not $grid_pos()
+$(parent).Add($win)
#else
-self.GridAdd(self._$(id)_check_box, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3])
+$(parent).GridAdd($win, $(', '.join(map(str, $grid_pos()))))
#end if</make>
<callback>self.set_$(id)($value)</callback>
<callback>self._$(id)_check_box.set_value($id)</callback>
<value></value>
<type>grid_pos</type>
</param>
+ <param>
+ <name>Notebook</name>
+ <key>notebook</key>
+ <value></value>
+ <type>notebook</type>
+ </param>
<check>$value in ($true, $false)</check>
<doc>
This block creates a variable with a check box form. \
Override True and False to use alternative states.
Use the Grid Position (row, column, row span, column span) to position the graphical element in the window.
+
+Use the Notebook Param (notebook-id, page-index) to place the graphical element inside of a notebook page.
</doc>
</block>
<key>variable_chooser</key>
<import>from gnuradio.wxgui import forms</import>
<var_make>self.$(id) = $(id) = $value</var_make>
- <make>self._$(id)_chooser = forms.$(type)(
- parent=self.GetWin(),
+ <make>#set $parent = $notebook() and 'self.%s.GetPage(%s)'%$notebook() or 'self'
+#set $win = 'self._%s_chooser'%$id
+$win = forms.$(type)(
+ parent=$(parent).GetWin(),
value=self.$id,
callback=self.set_$(id),
#if $label()
style=$style,
#end if
)
-#set $grid_pos = $grid_pos()
-#if not grid_pos
-self.Add(self._$(id)_chooser)
+#if not $grid_pos()
+$(parent).Add($win)
#else
-self.GridAdd(self._$(id)_chooser, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3])
+$(parent).GridAdd($win, $(', '.join(map(str, $grid_pos()))))
#end if</make>
<callback>self.set_$(id)($value)</callback>
<callback>self._$(id)_chooser.set_value($id)</callback>
<value></value>
<type>grid_pos</type>
</param>
+ <param>
+ <name>Notebook</name>
+ <key>notebook</key>
+ <value></value>
+ <type>notebook</type>
+ </param>
<check>$value in $choices</check>
<check>not $labels or len($labels) == len($choices)</check>
<doc>
Leave labels empty to use the choices as the labels.
Use the Grid Position (row, column, row span, column span) to position the graphical element in the window.
+
+Use the Notebook Param (notebook-id, page-index) to place the graphical element inside of a notebook page.
</doc>
</block>
<key>variable_slider</key>
<import>from gnuradio.wxgui import forms</import>
<var_make>self.$(id) = $(id) = $value</var_make>
- <make>_$(id)_sizer = wx.BoxSizer(wx.VERTICAL)
+ <make>#set $parent = $notebook() and 'self.%s.GetPage(%s)'%$notebook() or 'self'
+#set $win = '_%s_sizer'%$id
+$win = wx.BoxSizer(wx.VERTICAL)
self._$(id)_text_box = forms.text_box(
- parent=self.GetWin(),
- sizer=_$(id)_sizer,
+ parent=$(parent).GetWin(),
+ sizer=$win,
value=self.$id,
callback=self.set_$(id),
#if $label()
proportion=0,
)
self._$(id)_slider = forms.slider(
- parent=self.GetWin(),
- sizer=_$(id)_sizer,
+ parent=$(parent).GetWin(),
+ sizer=$win,
value=self.$id,
callback=self.set_$(id),
minimum=$min,
cast=$(converver.slider_cast),
proportion=1,
)
-#set $grid_pos = $grid_pos()
-#if not grid_pos
-self.Add(_$(id)_sizer)
+#if not $grid_pos()
+$(parent).Add($win)
#else
-self.GridAdd(_$(id)_sizer, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3])
+$(parent).GridAdd($win, $(', '.join(map(str, $grid_pos()))))
#end if</make>
<callback>self.set_$(id)($value)</callback>
<callback>self._$(id)_slider.set_value($id)</callback>
<value></value>
<type>grid_pos</type>
</param>
+ <param>
+ <name>Notebook</name>
+ <key>notebook</key>
+ <value></value>
+ <type>notebook</type>
+ </param>
<check>$min <= $value <= $max</check>
<check>$min < $max</check>
<check>0 < $num_steps <= 1000</check>
The number of steps must be between 0 and 1000.
Use the Grid Position (row, column, row span, column span) to position the graphical element in the window.
+
+Use the Notebook Param (notebook-id, page-index) to place the graphical element inside of a notebook page.
</doc>
</block>
<key>variable_static_text</key>
<import>from gnuradio.wxgui import forms</import>
<var_make>self.$(id) = $(id) = $value</var_make>
- <make>self._$(id)_static_text = forms.static_text(
- parent=self.GetWin(),
+ <make>#set $parent = $notebook() and 'self.%s.GetPage(%s)'%$notebook() or 'self'
+#set $win = 'self._%s_static_text'%$id
+$win = forms.static_text(
+ parent=$(parent).GetWin(),
value=self.$id,
callback=self.set_$(id),
#if $label()
converter=forms.$(converver)(),
#end if
)
-#set $grid_pos = $grid_pos()
-#if not grid_pos
-self.Add(self._$(id)_static_text)
+#if not $grid_pos()
+$(parent).Add($win)
#else
-self.GridAdd(self._$(id)_static_text, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3])
+$(parent).GridAdd($win, $(', '.join(map(str, $grid_pos()))))
#end if</make>
<callback>self.set_$(id)($value)</callback>
<callback>self._$(id)_static_text.set_value($id)</callback>
<value></value>
<type>grid_pos</type>
</param>
+ <param>
+ <name>Notebook</name>
+ <key>notebook</key>
+ <value></value>
+ <type>notebook</type>
+ </param>
<doc>
This block creates a variable with a static text form. \
Leave the label blank to use the variable id as the label.
Format should be a function/lambda that converts a value into a string or None for the default formatter.
Use the Grid Position (row, column, row span, column span) to position the graphical element in the window.
+
+Use the Notebook Param (notebook-id, page-index) to place the graphical element inside of a notebook page.
</doc>
</block>
<key>variable_text_box</key>
<import>from gnuradio.wxgui import forms</import>
<var_make>self.$(id) = $(id) = $value</var_make>
- <make>self._$(id)_text_box = forms.text_box(
- parent=self.GetWin(),
+ <make>#set $parent = $notebook() and 'self.%s.GetPage(%s)'%$notebook() or 'self'
+#set $win = 'self._%s_text_box'%$id
+$win = forms.text_box(
+ parent=$(parent).GetWin(),
value=self.$id,
callback=self.set_$(id),
#if $label()
converter=forms.$(converver)(),
#end if
)
-#set $grid_pos = $grid_pos()
-#if not grid_pos
-self.Add(self._$(id)_text_box)
+#if not $grid_pos()
+$(parent).Add($win)
#else
-self.GridAdd(self._$(id)_text_box, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3])
+$(parent).GridAdd($win, $(', '.join(map(str, $grid_pos()))))
#end if</make>
<callback>self.set_$(id)($value)</callback>
<callback>self._$(id)_text_box.set_value($id)</callback>
<value></value>
<type>grid_pos</type>
</param>
+ <param>
+ <name>Notebook</name>
+ <key>notebook</key>
+ <value></value>
+ <type>notebook</type>
+ </param>
<doc>
This block creates a variable with a text box. \
Leave the label blank to use the variable id as the label.
Format should be a function/lambda that converts a value into a string or None for the default formatter.
Use the Grid Position (row, column, row span, column span) to position the graphical element in the window.
+
+Use the Notebook Param (notebook-id, page-index) to place the graphical element inside of a notebook page.
</doc>
</block>
<name>Constellation Sink</name>
<key>wxgui_constellationsink2</key>
<import>from gnuradio.wxgui import constsink_gl</import>
- <make>constsink_gl.const_sink_c(
- self.GetWin(),
+ <make>#set $parent = $notebook() and 'self.%s.GetPage(%s)'%$notebook() or 'self'
+constsink_gl.const_sink_c(
+ $(parent).GetWin(),
title=$title,
sample_rate=$samp_rate,
frame_rate=$frame_rate,
symbol_rate=$symbol_rate,
omega_limit=$omega_limit,
)
-#set $grid_pos = $grid_pos()
-#if not grid_pos
-self.Add(self.$(id).win)
+#if not $grid_pos()
+$(parent).Add(self.$(id).win)
#else
-self.GridAdd(self.$(id).win, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3])
+$(parent).GridAdd(self.$(id).win, $(', '.join(map(str, $grid_pos()))))
#end if</make>
<callback>set_sample_rate($samp_rate)</callback>
<param>
<value></value>
<type>grid_pos</type>
</param>
+ <param>
+ <name>Notebook</name>
+ <key>notebook</key>
+ <value></value>
+ <type>notebook</type>
+ </param>
<sink>
<name>in</name>
<type>complex</type>
</sink>
<doc>
Use the Grid Position (row, column, row span, column span) to position the graphical element in the window.
+
+Use the Notebook Param (notebook-id, page-index) to place the graphical element inside of a notebook page.
</doc>
</block>
<name>FFT Sink</name>
<key>wxgui_fftsink2</key>
<import>from gnuradio.wxgui import fftsink2</import>
- <make>fftsink2.$(type.fcn)(
- self.GetWin(),
+ <make>#set $parent = $notebook() and 'self.%s.GetPage(%s)'%$notebook() or 'self'
+fftsink2.$(type.fcn)(
+ $(parent).GetWin(),
baseband_freq=$baseband_freq,
y_per_div=$y_per_div,
y_divs=$y_divs,
title=$title,
peak_hold=$peak_hold,
)
-#set $grid_pos = $grid_pos()
-#if not grid_pos
-self.Add(self.$(id).win)
+#if not $grid_pos()
+$(parent).Add(self.$(id).win)
#else
-self.GridAdd(self.$(id).win, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3])
+$(parent).GridAdd(self.$(id).win, $(', '.join(map(str, $grid_pos()))))
#end if</make>
<callback>set_baseband_freq($baseband_freq)</callback>
<callback>set_sample_rate($samp_rate)</callback>
<value></value>
<type>grid_pos</type>
</param>
+ <param>
+ <name>Notebook</name>
+ <key>notebook</key>
+ <value></value>
+ <type>notebook</type>
+ </param>
<sink>
<name>in</name>
<type>$type</type>
Set Average Alpha to 0 for automatic setting.
Use the Grid Position (row, column, row span, column span) to position the graphical element in the window.
+
+Use the Notebook Param (notebook-id, page-index) to place the graphical element inside of a notebook page.
</doc>
</block>
<name>Histo Sink</name>
<key>wxgui_histosink2</key>
<import>from gnuradio.wxgui import histosink_gl</import>
- <make>histosink_gl.histo_sink_f(
- self.GetWin(),
+ <make>#set $parent = $notebook() and 'self.%s.GetPage(%s)'%$notebook() or 'self'
+histosink_gl.histo_sink_f(
+ $(parent).GetWin(),
title=$title,
num_bins=$num_bins,
frame_size=$frame_size,
)
-#set $grid_pos = $grid_pos()
-#if not grid_pos
-self.Add(self.$(id).win)
+#if not $grid_pos()
+$(parent).Add(self.$(id).win)
#else
-self.GridAdd(self.$(id).win, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3])
+$(parent).GridAdd(self.$(id).win, $(', '.join(map(str, $grid_pos()))))
#end if</make>
<callback>set_num_bins($num_bins)</callback>
<callback>set_frame_size($frame_size)</callback>
<value></value>
<type>grid_pos</type>
</param>
+ <param>
+ <name>Notebook</name>
+ <key>notebook</key>
+ <value></value>
+ <type>notebook</type>
+ </param>
<sink>
<name>in</name>
<type>float</type>
</sink>
<doc>
Use the Grid Position (row, column, row span, column span) to position the graphical element in the window.
+
+Use the Notebook Param (notebook-id, page-index) to place the graphical element inside of a notebook page.
</doc>
</block>
<name>Number Sink</name>
<key>wxgui_numbersink2</key>
<import>from gnuradio.wxgui import numbersink2</import>
- <make>numbersink2.$(type.fcn)(
- self.GetWin(),
+ <make>#set $parent = $notebook() and 'self.%s.GetPage(%s)'%$notebook() or 'self'
+numbersink2.$(type.fcn)(
+ $(parent).GetWin(),
unit=$units,
minval=$min_value,
maxval=$max_value,
peak_hold=$peak_hold,
show_gauge=$show_gauge,
)
-#set $grid_pos = $grid_pos()
-#if not grid_pos
-self.Add(self.$(id).win)
+#if not $grid_pos()
+$(parent).Add(self.$(id).win)
#else
-self.GridAdd(self.$(id).win, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3])
+$(parent).GridAdd(self.$(id).win, $(', '.join(map(str, $grid_pos()))))
#end if</make>
<param>
<name>Type</name>
<value></value>
<type>grid_pos</type>
</param>
+ <param>
+ <name>Notebook</name>
+ <key>notebook</key>
+ <value></value>
+ <type>notebook</type>
+ </param>
<sink>
<name>in</name>
<type>$type</type>
Use the Grid Position (row, column, row span, column span) to position the graphical element in the window.
+Use the Notebook Param (notebook-id, page-index) to place the graphical element inside of a notebook page.
+
Incoming numbers are multiplied by the factor, and then added-to by the reference level.
</doc>
</block>
<key>wxgui_scopesink2</key>
<import>from gnuradio.wxgui import scopesink2</import>
<import>from gnuradio import gr</import>
- <make>scopesink2.$(type.fcn)(
- self.GetWin(),
+ <make>#set $parent = $notebook() and 'self.%s.GetPage(%s)'%$notebook() or 'self'
+scopesink2.$(type.fcn)(
+ $(parent).GetWin(),
title=$title,
sample_rate=$samp_rate,
v_scale=$v_scale,
xy_mode=$xy_mode,
num_inputs=$num_inputs,
)
-#set $grid_pos = $grid_pos()
-#if not grid_pos
-self.Add(self.$(id).win)
+#if not $grid_pos()
+$(parent).Add(self.$(id).win)
#else
-self.GridAdd(self.$(id).win, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3])
+$(parent).GridAdd(self.$(id).win, $(', '.join(map(str, $grid_pos()))))
#end if</make>
<callback>set_sample_rate($samp_rate)</callback>
<param>
<value></value>
<type>grid_pos</type>
</param>
+ <param>
+ <name>Notebook</name>
+ <key>notebook</key>
+ <value></value>
+ <type>notebook</type>
+ </param>
<check>not $xy_mode or '$type' == 'complex' or $num_inputs != 1</check>
<sink>
<name>in</name>
XY Mode allows the scope to initialize as an XY plotter.
Use the Grid Position (row, column, row span, column span) to position the graphical element in the window.
+
+Use the Notebook Param (notebook-id, page-index) to place the graphical element inside of a notebook page.
</doc>
</block>
<name>Waterfall Sink</name>
<key>wxgui_waterfallsink2</key>
<import>from gnuradio.wxgui import waterfallsink2</import>
- <make>waterfallsink2.$(type.fcn)(
- self.GetWin(),
+ <make>#set $parent = $notebook() and 'self.%s.GetPage(%s)'%$notebook() or 'self'
+waterfallsink2.$(type.fcn)(
+ $(parent).GetWin(),
baseband_freq=$baseband_freq,
y_per_div=$y_per_div,
ref_level=$ref_level,
avg_alpha=#if $avg_alpha() then $avg_alpha else 'None'#,
title=$title,
)
-#set $grid_pos = $grid_pos()
-#if not grid_pos
-self.Add(self.$(id).win)
+#if not $grid_pos()
+$(parent).Add(self.$(id).win)
#else
-self.GridAdd(self.$(id).win, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3])
+$(parent).GridAdd(self.$(id).win, $(', '.join(map(str, $grid_pos()))))
#end if</make>
<callback>set_baseband_freq($baseband_freq)</callback>
<callback>set_sample_rate($samp_rate)</callback>
<value></value>
<type>grid_pos</type>
</param>
+ <param>
+ <name>Notebook</name>
+ <key>notebook</key>
+ <value></value>
+ <type>notebook</type>
+ </param>
<sink>
<name>in</name>
<type>$type</type>
Set Average Alpha to 0 for automatic setting.
Use the Grid Position (row, column, row span, column span) to position the graphical element in the window.
+
+Use the Notebook Param (notebook-id, page-index) to place the graphical element inside of a notebook page.
</doc>
</block>
grc_gnuradio_prefix = $(pythondir)/grc_gnuradio
-rootpythondir = $(grc_gnuradio_prefix)
-rootpython_PYTHON = __init__.py
+root_pythondir = $(grc_gnuradio_prefix)
+root_python_PYTHON = __init__.py
-blks2pythondir = $(grc_gnuradio_prefix)/blks2
-blks2python_PYTHON = \
+blks2_pythondir = $(grc_gnuradio_prefix)/blks2
+blks2_python_PYTHON = \
blks2/__init__.py \
blks2/error_rate.py \
blks2/packet.py \
blks2/tcp.py \
blks2/variable_sink.py
-usrppythondir = $(grc_gnuradio_prefix)/usrp
-usrppython_PYTHON = \
+usrp_pythondir = $(grc_gnuradio_prefix)/usrp
+usrp_python_PYTHON = \
usrp/__init__.py \
usrp/common.py \
usrp/dual_usrp.py \
usrp/simple_usrp.py
-wxguipythondir = $(grc_gnuradio_prefix)/wxgui
-wxguipython_PYTHON = \
+wxgui_pythondir = $(grc_gnuradio_prefix)/wxgui
+wxgui_python_PYTHON = \
wxgui/__init__.py \
+ wxgui/panel.py \
wxgui/top_block_gui.py
-# Copyright 2008 Free Software Foundation, Inc.
+# Copyright 2008, 2009 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
#
from top_block_gui import top_block_gui
+from panel import Panel
--- /dev/null
+# Copyright 2009 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio 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 3, or (at your option)
+# any later version.
+#
+# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+import wx
+
+class Panel(wx.Panel):
+ def __init__(self, parent, orient=wx.VERTICAL):
+ wx.Panel.__init__(self, parent)
+ self._box = wx.BoxSizer(orient)
+ self._grid = wx.GridBagSizer(5, 5)
+ self.Add(self._grid)
+ self.SetSizer(self._box)
+
+ def GetWin(self): return self
+
+ def Add(self, win):
+ """
+ Add a window to the wx vbox.
+ @param win the wx window
+ """
+ self._box.Add(win, 0, wx.EXPAND)
+
+ def GridAdd(self, win, row, col, row_span=1, col_span=1):
+ """
+ Add a window to the wx grid at the given position.
+ @param win the wx window
+ @param row the row specification (integer >= 0)
+ @param col the column specification (integer >= 0)
+ @param row_span the row span specification (integer >= 1)
+ @param col_span the column span specification (integer >= 1)
+ """
+ self._grid.Add(win, wx.GBPosition(row, col), wx.GBSpan(row_span, col_span), wx.EXPAND)
-# Copyright 2008 Free Software Foundation, Inc.
+# Copyright 2008, 2009 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
import wx
import sys, os
from gnuradio import gr
+import panel
default_gui_size = (200, 100)
class top_block_gui(gr.top_block):
"""gr top block with wx gui app and grid sizer."""
- def __init__(self, title='', size=default_gui_size, icon=None):
+ def __init__(self, title='', size=default_gui_size):
"""
Initialize the gr top block.
Create the wx gui elements.
#initialize
gr.top_block.__init__(self)
self._size = size
- #set the icon
- if icon and os.path.isfile(icon): self._icon = icon
- else: self._icon = None
#create gui elements
- self._wx_app = wx.App()
- self._wx_frame = wx.Frame(None , -1, title)
- self._wx_grid = wx.GridBagSizer(5, 5)
- self._wx_vbox = wx.BoxSizer(wx.VERTICAL)
+ self._app = wx.App()
+ self._frame = wx.Frame(None, title=title)
+ self._panel = panel.Panel(self._frame)
+ self.Add = self._panel.Add
+ self.GridAdd = self._panel.GridAdd
+ self.GetWin = self._panel.GetWin
- def GetWin(self):
- """
- Get the window for wx elements to fit within.
- @return the wx frame
- """
- return self._wx_frame
-
- def Add(self, win):
- """
- Add a window to the wx vbox.
- @param win the wx window
- """
- self._wx_vbox.Add(win, 0, wx.EXPAND)
-
- def GridAdd(self, win, row, col, row_span=1, col_span=1):
- """
- Add a window to the wx grid at the given position.
- @param win the wx window
- @param row the row specification (integer >= 0)
- @param col the column specification (integer >= 0)
- @param row_span the row span specification (integer >= 1)
- @param col_span the column span specification (integer >= 1)
- """
- self._wx_grid.Add(win, wx.GBPosition(row, col), wx.GBSpan(row_span, col_span), wx.EXPAND)
-
- def start(self, start=True):
- if start:
- gr.top_block.start(self)
- else:
- gr.top_block.stop(self)
- gr.top_block.wait(self)
+ def SetIcon(self, *args, **kwargs): self._frame.SetIcon(*args, **kwargs)
- def Run(self, autostart=True):
+ def Run(self, start=True):
"""
Setup the wx gui elements.
Start the gr top block.
Block with the wx main loop.
"""
- #set wx app icon
- if self._icon: self._wx_frame.SetIcon(wx.Icon(self._icon, wx.BITMAP_TYPE_ANY))
#set minimal window size
- self._wx_frame.SetSizeHints(*self._size)
+ self._frame.SetSizeHints(*self._size)
#create callback for quit
def _quit(event):
- gr.top_block.stop(self)
- self._wx_frame.Destroy()
+ self.stop(); self.wait()
+ self._frame.Destroy()
#setup app
- self._wx_vbox.Add(self._wx_grid, 0, wx.EXPAND)
- self._wx_frame.Bind(wx.EVT_CLOSE, _quit)
- self._wx_frame.SetSizerAndFit(self._wx_vbox)
- self._wx_frame.Show()
- self._wx_app.SetTopWindow(self._wx_frame)
+ self._frame.Bind(wx.EVT_CLOSE, _quit)
+ self._sizer = wx.BoxSizer(wx.VERTICAL)
+ self._sizer.Add(self._panel, 0, wx.EXPAND)
+ self._frame.SetSizerAndFit(self._sizer)
+ self._frame.SetAutoLayout(True)
+ self._frame.Show(True)
+ self._app.SetTopWindow(self._frame)
#start flow graph
- self.start(autostart)
+ if start: self.start()
#blocking main loop
- self._wx_app.MainLoop()
+ self._app.MainLoop()
PARAM_MARKUP_TMPL="""\
#set $foreground = $param.is_valid() and 'black' or 'red'
-#set $value = not $param.is_valid() and 'error' or repr($param)
-<span foreground="$foreground" font_desc="Sans 7.5"><b>$encode($param.get_name()): </b>$encode($value)</span>"""
+<span foreground="$foreground" font_desc="Sans 7.5"><b>$encode($param.get_name()): </b>$encode(repr($param))</span>"""
PARAM_LABEL_MARKUP_TMPL="""\
#set $foreground = $param.is_valid() and 'black' or 'red'
return '\n'.join([doc, extract_docs.extract(self.get_key())]).strip('\n')
def get_category(self):
- #category = extract_category.extract(self.get_key())
+ category = extract_category.extract(self.get_key())
#if category: return category
return _Block.get_category(self)
"""
def make_callback(callback):
callback = self.resolve_dependencies(callback)
- if callback.startswith('self.'): return callback
+ if 'self.' in callback: return callback
return 'self.%s.%s'%(self.get_id(), callback)
return map(make_callback, self._callbacks)
@return a sorted list of variable blocks in order of dependency (indep -> dep)
"""
variables = filter(lambda b: _variable_matcher.match(b.get_key()), self.get_enabled_blocks())
- #map var id to variable block
- id2var = dict([(var.get_id(), var) for var in variables])
- #map var id to variable code
- #variable code is a concatenation of all param code (without the id param)
- id2expr = dict([(var.get_id(), var.get_var_make()) for var in variables])
- #sort according to dependency
- sorted_ids = expr_utils.sort_variables(id2expr)
- #create list of sorted variable blocks
- variables = [id2var[id] for id in sorted_ids]
- return variables
+ return expr_utils.sort_objects(variables, lambda v: v.get_id(), lambda v: v.get_var_make())
def get_parameters(self):
"""
#list of blocks not including variables and imports and parameters and disabled
blocks = sorted(self._flow_graph.get_enabled_blocks(), lambda x, y: cmp(x.get_id(), y.get_id()))
probes = filter(lambda b: b.get_key().startswith('probe_'), blocks) #ensure probes are last in the block list
- blocks = filter(lambda b: b not in (imports + parameters + variables + probes), blocks) + probes
+ #get a list of notebooks and sort them according dependencies
+ notebooks = expr_utils.sort_objects(
+ filter(lambda b: b.get_key() == 'notebook', blocks),
+ lambda n: n.get_id(), lambda n: n.get_param('notebook').get_value(),
+ )
+ #list of regular blocks (all blocks minus the special ones)
+ blocks = filter(lambda b: b not in (imports + parameters + variables + probes + notebooks), blocks) + probes
#list of connections where each endpoint is enabled
connections = self._flow_graph.get_enabled_connections()
#list of variable names
'imports': imports,
'flow_graph': self._flow_graph,
'variables': variables,
+ 'notebooks': notebooks,
'controls': controls,
'parameters': parameters,
'blocks': blocks,
from gnuradio import gr
_check_id_matcher = re.compile('^[a-z|A-Z]\w*$')
-_show_id_matcher = re.compile('^(variable\w*|parameter|options)$')
+_show_id_matcher = re.compile('^(variable\w*|parameter|options|notebook)$')
class FileParam(EntryParam):
"""Provide an entry box for filename and a button to browse for a file."""
'hex', 'string', 'bool',
'file_open', 'file_save',
'id',
- 'grid_pos', 'import',
+ 'grid_pos', 'notebook',
+ 'import',
]
def __repr__(self):
Get the repr (nice string format) for this param.
@return the string representation
"""
+ if not self.is_valid(): return self.get_value()
if self.get_value() in self.get_option_keys(): return self.get_option(self.get_value()).get_name()
##################################################
# display logic for numbers
'string': Constants.BYTE_VECTOR_COLOR_SPEC,
'id': Constants.ID_COLOR_SPEC,
'grid_pos': Constants.INT_VECTOR_COLOR_SPEC,
+ 'notebook': Constants.INT_VECTOR_COLOR_SPEC,
'raw': Constants.WILDCARD_COLOR_SPEC,
}[self.get_type()]
except: return _Param.get_color(self)
return 'part'
except: pass
#hide empty grid positions
- if self.get_key() == 'grid_pos' and not self.get_value(): return 'part'
+ if self.get_key() in ('grid_pos', 'notebook') and not self.get_value(): return 'part'
return hide
def validate(self):
#check row span, col span
try: assert row_span > 0 and col_span > 0
except AssertionError: raise Exception, 'Row and column span must be greater than zero.'
+ #get hostage cell parent
+ try: my_parent = self.get_parent().get_param('notebook').evaluate()
+ except: my_parent = ''
#calculate hostage cells
for r in range(row_span):
for c in range(col_span):
- self._hostage_cells.append((row+r, col+c))
+ self._hostage_cells.append((my_parent, (row+r, col+c)))
#avoid collisions
params = filter(lambda p: p is not self, self.get_all_params('grid_pos'))
for param in params:
- for cell in param._hostage_cells:
- if cell in self._hostage_cells: raise Exception, 'Another graphical element is using cell "%s".'%str(cell)
+ for parent, cell in param._hostage_cells:
+ if (parent, cell) in self._hostage_cells:
+ raise Exception, 'Another graphical element is using parent "%s", cell "%s".'%(str(parent), str(cell))
return e
#########################
+ # Notebook Page Type
+ #########################
+ elif t == 'notebook':
+ if not v: return '' #allow for empty notebook
+ #get a list of all notebooks
+ notebook_blocks = filter(lambda b: b.get_key() == 'notebook', self.get_parent().get_parent().get_enabled_blocks())
+ #check for notebook param syntax
+ try: notebook_id, page_index = map(str.strip, v.split(','))
+ except: raise Exception, 'Bad notebook page format.'
+ #check that the notebook id is valid
+ try: notebook_block = filter(lambda b: b.get_id() == notebook_id, notebook_blocks)[0]
+ except: raise Exception, 'Notebook id "%s" is not an existing notebook id.'%notebook_id
+ #check that page index exists
+ try: assert int(page_index) in range(len(notebook_block.get_param('labels').get_evaluated()))
+ except: raise Exception, 'Page index "%s" is not a valid index number.'%page_index
+ return notebook_id, page_index
+ #########################
# Import Type
#########################
elif t == 'import':
for var in indep_vars: var_graph.remove_node(var)
return reversed(sorted_vars)
+def sort_objects(objects, get_id, get_expr):
+ """
+ Sort a list of objects according to their expressions.
+ @param objects the list of objects to sort
+ @param get_id the function to extract an id from the object
+ @param get_expr the function to extract an expression from the object
+ @return a list of sorted objects
+ """
+ id2obj = dict([(get_id(obj), obj) for obj in objects])
+ #map obj id to expression code
+ id2expr = dict([(get_id(obj), get_expr(obj)) for obj in objects])
+ #sort according to dependency
+ sorted_ids = sort_variables(id2expr)
+ #return list of sorted objects
+ return [id2obj[id] for id in sorted_ids]
+
if __name__ == '__main__':
for i in sort_variables({'x':'1', 'y':'x+1', 'a':'x+y', 'b':'y+1', 'c':'a+b+x+y'}): print i
##@param imports the import statements
##@param flow_graph the flow_graph
##@param variables the variable blocks
+##@param notebooks a list of notebook blocks
##@param controls the variables with gui controls
##@param parameters the paramater blocks
##@param blocks the signal blocks
class $(class_name)(grc_wxgui.top_block_gui):
def __init__($param_str):
- grc_wxgui.top_block_gui.__init__(
- self,
- title="$title",
+ grc_wxgui.top_block_gui.__init__(self, title="$title")
#if $icon
- icon="$icon.get_filename()",
+ _icon_path = "$icon.get_filename()"
+ self.SetIcon(wx.Icon(_icon_path, wx.BITMAP_TYPE_ANY))
#end if
- )
#elif $generate_options == 'no_gui'
class $(class_name)(gr.top_block):
def __init__($param_str):
gr.hier_block2.__init__(
- self,
- "$title",
+ self, "$title",
gr.io_signature($in_sig.nports, $in_sig.nports, $in_sig.size*$in_sig.vlen),
gr.io_signature($out_sig.nports, $out_sig.nports, $out_sig.size*$out_sig.vlen),
)
#end for
########################################################
##Create Variables
-## Set the variable to a property of self.
-## Write the first line of the variable make.
########################################################
#if $variables
$indent($var.get_var_make())
#end for
########################################################
+##Create Notebooks
+########################################################
+#if $notebooks
+
+ $DIVIDER
+ # Notebooks
+ $DIVIDER
+#end if
+#for $notebook in $notebooks
+ $indent($notebook.get_make())
+#end for
+########################################################
##Create Controls
-## Write the variable make (excluding first line).
-## Indent each line with 2 tabs.
########################################################
#if $controls
#end for
########################################################
##Create Blocks
-## Write the block make, and indent with 2 tabs.
########################################################
#if $blocks
########################################################
##Create Callbacks
## Write a set method for this variable that calls the callbacks
-## and sets the direct variable dependencies.
########################################################
#for $var in $parameters + $variables
#set $id = $var.get_id()
#end if
tb = $(class_name)($(', '.join($params_eq_list)))
#if $generate_options == 'wx_gui'
- tb.Run($flow_graph.get_option('autostart'))
+ tb.Run($flow_graph.get_option('run'))
#elif $generate_options == 'no_gui'
tb.start()
raw_input('Press Enter to quit: ')
* gr_ofdm_insert_preamble
* gr_ofdm_mapper_bcv
* gr_ofdm_sampler
+* size params for the graphical sinks
+* callbacks for set average on fft, waterfall, number sinks
##################################################
# Features
* configuration option for adding block paths
* orientations for ports (top, right, bottom, left)
* source defaults to right, sink defaults to left
-* grid params take a notebook argument
- * add a wx notebook block
* separation of variables and gui controls
* speedup w/ background layer and animation layer
* multiple doxygen directories (doc_dir becomes doc_path)
* params dialog needs to dynamically update for all params
* will not update for non-enum params
* needs to account for added or removed params
+ * example with grid params need update after notebook change
##################################################
# Future