From 25c5d91fb7c4b54f1e7d77fd9af213a3675a8339 Mon Sep 17 00:00:00 2001 From: jblum Date: Mon, 6 Jul 2009 02:28:52 +0000 Subject: [PATCH] Merged r11309:11357 from grc branch. Adds notebook cabability to grc and its wxgui windows/controls. git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@11358 221aa14e-8319-0410-a670-987f0aec2ac5 --- gr-wxgui/src/python/plotter/plotter_base.py | 1 + gr-wxgui/src/python/waterfallsink_gl.py | 2 +- grc/base/Platform.py | 4 +- grc/blocks/Makefile.am | 1 + grc/blocks/block_tree.xml | 2 + grc/blocks/notebook.xml | 69 +++++++++++++++++++ grc/blocks/options.xml | 15 ++-- grc/blocks/variable_check_box.xml | 21 ++++-- grc/blocks/variable_chooser.xml | 21 ++++-- grc/blocks/variable_slider.xml | 27 +++++--- grc/blocks/variable_static_text.xml | 21 ++++-- grc/blocks/variable_text_box.xml | 21 ++++-- grc/blocks/wxgui_constellationsink2.xml | 20 ++++-- grc/blocks/wxgui_fftsink2.xml | 20 ++++-- grc/blocks/wxgui_histosink2.xml | 20 ++++-- grc/blocks/wxgui_numbersink2.xml | 20 ++++-- grc/blocks/wxgui_scopesink2.xml | 20 ++++-- grc/blocks/wxgui_waterfallsink2.xml | 20 ++++-- grc/grc_gnuradio/Makefile.am | 17 ++--- grc/grc_gnuradio/wxgui/__init__.py | 3 +- grc/grc_gnuradio/wxgui/panel.py | 49 +++++++++++++ grc/grc_gnuradio/wxgui/top_block_gui.py | 76 +++++++-------------- grc/gui/Param.py | 3 +- grc/python/Block.py | 4 +- grc/python/FlowGraph.py | 11 +-- grc/python/Generator.py | 9 ++- grc/python/Param.py | 36 ++++++++-- grc/python/expr_utils.py | 16 +++++ grc/python/flow_graph.tmpl | 32 +++++---- grc/todo.txt | 5 +- 30 files changed, 409 insertions(+), 177 deletions(-) create mode 100644 grc/blocks/notebook.xml create mode 100644 grc/grc_gnuradio/wxgui/panel.py diff --git a/gr-wxgui/src/python/plotter/plotter_base.py b/gr-wxgui/src/python/plotter/plotter_base.py index 662365a3..dede5a0a 100644 --- a/gr-wxgui/src/python/plotter/plotter_base.py +++ b/gr-wxgui/src/python/plotter/plotter_base.py @@ -168,4 +168,5 @@ class plotter_base(wx.glcanvas.GLCanvas, common.mutex): """ Force a paint event. """ + if not self._gl_init_flag: return wx.PostEvent(self, wx.PaintEvent()) diff --git a/gr-wxgui/src/python/waterfallsink_gl.py b/gr-wxgui/src/python/waterfallsink_gl.py index 91c1c7eb..2d4c959f 100644 --- a/gr-wxgui/src/python/waterfallsink_gl.py +++ b/gr-wxgui/src/python/waterfallsink_gl.py @@ -40,7 +40,6 @@ class _waterfall_sink_base(gr.hier_block2): self, parent, baseband_freq=0, - y_per_div=None, #ignore (old wrapper) ref_level=50, sample_rate=1, fft_size=512, @@ -52,6 +51,7 @@ class _waterfall_sink_base(gr.hier_block2): 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 diff --git a/grc/base/Platform.py b/grc/base/Platform.py index 3050e5e4..02d6d231 100644 --- a/grc/base/Platform.py +++ b/grc/base/Platform.py @@ -129,7 +129,9 @@ class Platform(_Element): 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 diff --git a/grc/blocks/Makefile.am b/grc/blocks/Makefile.am index d6df9fca..025c261f 100644 --- a/grc/blocks/Makefile.am +++ b/grc/blocks/Makefile.am @@ -185,6 +185,7 @@ dist_ourdata_DATA = \ import.xml \ low_pass_filter.xml \ note.xml \ + notebook.xml \ options.xml \ pad_sink.xml \ pad_source.xml \ diff --git a/grc/blocks/block_tree.xml b/grc/blocks/block_tree.xml index 4f9b1cd2..9eda2fdc 100644 --- a/grc/blocks/block_tree.xml +++ b/grc/blocks/block_tree.xml @@ -293,5 +293,7 @@ xmlrpc_server xmlrpc_client + + notebook diff --git a/grc/blocks/notebook.xml b/grc/blocks/notebook.xml new file mode 100644 index 00000000..d41db9e2 --- /dev/null +++ b/grc/blocks/notebook.xml @@ -0,0 +1,69 @@ + + + + Notebook + notebook + from grc_gnuradio import wxgui as grc_wxgui + #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 + + Tab Orientation + style + wx.NB_TOP + enum + + + + + + + Labels + labels + ['tab1', 'tab2', 'tab3'] + raw + + + Grid Position + grid_pos + + grid_pos + + + Notebook + notebook + + notebook + + isinstance($labels, (list, tuple)) + all(map(lambda x: isinstance(x, str), $labels)) + len($labels) > 0 + +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. + + diff --git a/grc/blocks/options.xml b/grc/blocks/options.xml index 06ede76f..18d6e2f0 100644 --- a/grc/blocks/options.xml +++ b/grc/blocks/options.xml @@ -20,7 +20,8 @@ from gnuradio.eng_option import eng_option #end if - self.start($autostart) + if $run: self.start() +else: self.stop(); self.wait() Title title @@ -76,12 +77,12 @@ from gnuradio.eng_option import eng_option #if $generate_options() == 'hb' then 'none' else 'all'# - Autostart - autostart + Run + run True bool #if $generate_options() == 'wx_gui' - #if str($autostart) == 'True' + #if str($run) == 'True' part#slurp #else none#slurp @@ -90,11 +91,11 @@ none#slurp all#slurp #end if @@ -135,7 +136,7 @@ The generate options controls the type of code generated. \ 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.... diff --git a/grc/blocks/variable_check_box.xml b/grc/blocks/variable_check_box.xml index 7054ca1e..a703703c 100644 --- a/grc/blocks/variable_check_box.xml +++ b/grc/blocks/variable_check_box.xml @@ -10,8 +10,10 @@ variable_check_box from gnuradio.wxgui import forms self.$(id) = $(id) = $value - self._$(id)_check_box = forms.check_box( - parent=self.GetWin(), + #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() @@ -22,11 +24,10 @@ 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 self.set_$(id)($value) self._$(id)_check_box.set_value($id) @@ -61,6 +62,12 @@ self.GridAdd(self._$(id)_check_box, $grid_pos[0], $grid_pos[1], $grid_pos[2], $g grid_pos + + Notebook + notebook + + notebook + $value in ($true, $false) This block creates a variable with a check box form. \ @@ -71,5 +78,7 @@ the default being True and False. \ 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. diff --git a/grc/blocks/variable_chooser.xml b/grc/blocks/variable_chooser.xml index 2bf19987..ee41f26d 100644 --- a/grc/blocks/variable_chooser.xml +++ b/grc/blocks/variable_chooser.xml @@ -11,8 +11,10 @@ variable_chooser from gnuradio.wxgui import forms self.$(id) = $(id) = $value - self._$(id)_chooser = forms.$(type)( - parent=self.GetWin(), + #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() @@ -26,11 +28,10 @@ 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 self.set_$(id)($value) self._$(id)_chooser.set_value($id) @@ -98,6 +99,12 @@ self.GridAdd(self._$(id)_chooser, $grid_pos[0], $grid_pos[1], $grid_pos[2], $gri grid_pos + + Notebook + notebook + + notebook + $value in $choices not $labels or len($labels) == len($choices) @@ -109,5 +116,7 @@ The choices must be a list of possible values. \ 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. diff --git a/grc/blocks/variable_slider.xml b/grc/blocks/variable_slider.xml index 875ae74a..c13d2085 100644 --- a/grc/blocks/variable_slider.xml +++ b/grc/blocks/variable_slider.xml @@ -10,10 +10,12 @@ variable_slider from gnuradio.wxgui import forms self.$(id) = $(id) = $value - _$(id)_sizer = wx.BoxSizer(wx.VERTICAL) + #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() @@ -25,8 +27,8 @@ self._$(id)_text_box = forms.text_box( 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, @@ -36,11 +38,10 @@ self._$(id)_slider = forms.slider( 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 self.set_$(id)($value) self._$(id)_slider.set_value($id) @@ -114,6 +115,12 @@ self.GridAdd(_$(id)_sizer, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3 grid_pos + + Notebook + notebook + + notebook + $min <= $value <= $max $min < $max 0 < $num_steps <= 1000 @@ -125,5 +132,7 @@ The value must be between the minimum and the maximum. \ 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. diff --git a/grc/blocks/variable_static_text.xml b/grc/blocks/variable_static_text.xml index 4be80a9b..c866b998 100644 --- a/grc/blocks/variable_static_text.xml +++ b/grc/blocks/variable_static_text.xml @@ -10,8 +10,10 @@ variable_static_text from gnuradio.wxgui import forms self.$(id) = $(id) = $value - self._$(id)_static_text = forms.static_text( - parent=self.GetWin(), + #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() @@ -25,11 +27,10 @@ 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 self.set_$(id)($value) self._$(id)_static_text.set_value($id) @@ -77,6 +78,12 @@ self.GridAdd(self._$(id)_static_text, $grid_pos[0], $grid_pos[1], $grid_pos[2], grid_pos + + Notebook + notebook + + notebook + This block creates a variable with a static text form. \ Leave the label blank to use the variable id as the label. @@ -84,5 +91,7 @@ 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. diff --git a/grc/blocks/variable_text_box.xml b/grc/blocks/variable_text_box.xml index 65d491ba..1b4b4355 100644 --- a/grc/blocks/variable_text_box.xml +++ b/grc/blocks/variable_text_box.xml @@ -10,8 +10,10 @@ variable_text_box from gnuradio.wxgui import forms self.$(id) = $(id) = $value - self._$(id)_text_box = forms.text_box( - parent=self.GetWin(), + #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() @@ -25,11 +27,10 @@ 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 self.set_$(id)($value) self._$(id)_text_box.set_value($id) @@ -81,6 +82,12 @@ self.GridAdd(self._$(id)_text_box, $grid_pos[0], $grid_pos[1], $grid_pos[2], $gr grid_pos + + Notebook + notebook + + notebook + This block creates a variable with a text box. \ Leave the label blank to use the variable id as the label. @@ -88,5 +95,7 @@ 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. diff --git a/grc/blocks/wxgui_constellationsink2.xml b/grc/blocks/wxgui_constellationsink2.xml index 471c9f4a..5969d840 100644 --- a/grc/blocks/wxgui_constellationsink2.xml +++ b/grc/blocks/wxgui_constellationsink2.xml @@ -8,8 +8,9 @@ Constellation Sink wxgui_constellationsink2 from gnuradio.wxgui import constsink_gl - constsink_gl.const_sink_c( - self.GetWin(), + #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, @@ -23,11 +24,10 @@ 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 set_sample_rate($samp_rate) @@ -108,11 +108,19 @@ self.GridAdd(self.$(id).win, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos grid_pos + + Notebook + notebook + + notebook + in complex 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. diff --git a/grc/blocks/wxgui_fftsink2.xml b/grc/blocks/wxgui_fftsink2.xml index d7763cb2..faeca37e 100644 --- a/grc/blocks/wxgui_fftsink2.xml +++ b/grc/blocks/wxgui_fftsink2.xml @@ -8,8 +8,9 @@ FFT Sink wxgui_fftsink2 from gnuradio.wxgui import fftsink2 - fftsink2.$(type.fcn)( - self.GetWin(), + #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, @@ -22,11 +23,10 @@ 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 set_baseband_freq($baseband_freq) set_sample_rate($samp_rate) @@ -157,6 +157,12 @@ self.GridAdd(self.$(id).win, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos grid_pos + + Notebook + notebook + + notebook + in $type @@ -165,5 +171,7 @@ self.GridAdd(self.$(id).win, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos 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. diff --git a/grc/blocks/wxgui_histosink2.xml b/grc/blocks/wxgui_histosink2.xml index 4de57b1c..454a4932 100644 --- a/grc/blocks/wxgui_histosink2.xml +++ b/grc/blocks/wxgui_histosink2.xml @@ -8,17 +8,17 @@ Histo Sink wxgui_histosink2 from gnuradio.wxgui import histosink_gl - histosink_gl.histo_sink_f( - self.GetWin(), + #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 set_num_bins($num_bins) set_frame_size($frame_size) @@ -46,11 +46,19 @@ self.GridAdd(self.$(id).win, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos grid_pos + + Notebook + notebook + + notebook + in float 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. diff --git a/grc/blocks/wxgui_numbersink2.xml b/grc/blocks/wxgui_numbersink2.xml index 7cc90b69..cc66cdcb 100644 --- a/grc/blocks/wxgui_numbersink2.xml +++ b/grc/blocks/wxgui_numbersink2.xml @@ -8,8 +8,9 @@ Number Sink wxgui_numbersink2 from gnuradio.wxgui import numbersink2 - numbersink2.$(type.fcn)( - self.GetWin(), + #set $parent = $notebook() and 'self.%s.GetPage(%s)'%$notebook() or 'self' +numbersink2.$(type.fcn)( + $(parent).GetWin(), unit=$units, minval=$min_value, maxval=$max_value, @@ -24,11 +25,10 @@ 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 Type @@ -157,6 +157,12 @@ self.GridAdd(self.$(id).win, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos grid_pos + + Notebook + notebook + + notebook + in $type @@ -166,6 +172,8 @@ 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. + Incoming numbers are multiplied by the factor, and then added-to by the reference level. diff --git a/grc/blocks/wxgui_scopesink2.xml b/grc/blocks/wxgui_scopesink2.xml index 78c39f80..503d5297 100644 --- a/grc/blocks/wxgui_scopesink2.xml +++ b/grc/blocks/wxgui_scopesink2.xml @@ -9,8 +9,9 @@ wxgui_scopesink2 from gnuradio.wxgui import scopesink2 from gnuradio import gr - scopesink2.$(type.fcn)( - self.GetWin(), + #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, @@ -19,11 +20,10 @@ 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 set_sample_rate($samp_rate) @@ -108,6 +108,12 @@ self.GridAdd(self.$(id).win, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos grid_pos + + Notebook + notebook + + notebook + not $xy_mode or '$type' == 'complex' or $num_inputs != 1 in @@ -122,5 +128,7 @@ Set the T Scale to 0 for automatic setting. 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. diff --git a/grc/blocks/wxgui_waterfallsink2.xml b/grc/blocks/wxgui_waterfallsink2.xml index 6d76ee86..c7d53f9f 100644 --- a/grc/blocks/wxgui_waterfallsink2.xml +++ b/grc/blocks/wxgui_waterfallsink2.xml @@ -8,8 +8,9 @@ Waterfall Sink wxgui_waterfallsink2 from gnuradio.wxgui import waterfallsink2 - waterfallsink2.$(type.fcn)( - self.GetWin(), + #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, @@ -20,11 +21,10 @@ 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 set_baseband_freq($baseband_freq) set_sample_rate($samp_rate) @@ -114,6 +114,12 @@ self.GridAdd(self.$(id).win, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos grid_pos + + Notebook + notebook + + notebook + in $type @@ -122,5 +128,7 @@ self.GridAdd(self.$(id).win, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos 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. diff --git a/grc/grc_gnuradio/Makefile.am b/grc/grc_gnuradio/Makefile.am index 9a15eb0e..63bb7282 100644 --- a/grc/grc_gnuradio/Makefile.am +++ b/grc/grc_gnuradio/Makefile.am @@ -23,11 +23,11 @@ include $(top_srcdir)/Makefile.common 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 \ @@ -36,14 +36,15 @@ blks2python_PYTHON = \ 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 diff --git a/grc/grc_gnuradio/wxgui/__init__.py b/grc/grc_gnuradio/wxgui/__init__.py index 94a0adb8..81427253 100644 --- a/grc/grc_gnuradio/wxgui/__init__.py +++ b/grc/grc_gnuradio/wxgui/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2008 Free Software Foundation, Inc. +# Copyright 2008, 2009 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -19,3 +19,4 @@ # from top_block_gui import top_block_gui +from panel import Panel diff --git a/grc/grc_gnuradio/wxgui/panel.py b/grc/grc_gnuradio/wxgui/panel.py new file mode 100644 index 00000000..e62133ca --- /dev/null +++ b/grc/grc_gnuradio/wxgui/panel.py @@ -0,0 +1,49 @@ +# 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) diff --git a/grc/grc_gnuradio/wxgui/top_block_gui.py b/grc/grc_gnuradio/wxgui/top_block_gui.py index 97bed04a..99857589 100644 --- a/grc/grc_gnuradio/wxgui/top_block_gui.py +++ b/grc/grc_gnuradio/wxgui/top_block_gui.py @@ -1,4 +1,4 @@ -# Copyright 2008 Free Software Foundation, Inc. +# Copyright 2008, 2009 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -21,13 +21,14 @@ 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. @@ -38,68 +39,37 @@ class top_block_gui(gr.top_block): #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() diff --git a/grc/gui/Param.py b/grc/gui/Param.py index 3029569b..a11fd906 100644 --- a/grc/gui/Param.py +++ b/grc/gui/Param.py @@ -25,8 +25,7 @@ import gtk PARAM_MARKUP_TMPL="""\ #set $foreground = $param.is_valid() and 'black' or 'red' -#set $value = not $param.is_valid() and 'error' or repr($param) -$encode($param.get_name()): $encode($value)""" +$encode($param.get_name()): $encode(repr($param))""" PARAM_LABEL_MARKUP_TMPL="""\ #set $foreground = $param.is_valid() and 'black' or 'red' diff --git a/grc/python/Block.py b/grc/python/Block.py index 6d759577..957fee18 100644 --- a/grc/python/Block.py +++ b/grc/python/Block.py @@ -130,7 +130,7 @@ class Block(_Block): 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) @@ -154,6 +154,6 @@ class Block(_Block): """ 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) diff --git a/grc/python/FlowGraph.py b/grc/python/FlowGraph.py index 47089a30..8cad8be4 100644 --- a/grc/python/FlowGraph.py +++ b/grc/python/FlowGraph.py @@ -99,16 +99,7 @@ class FlowGraph(_FlowGraph): @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): """ diff --git a/grc/python/Generator.py b/grc/python/Generator.py index cde7dc3d..33be4a72 100644 --- a/grc/python/Generator.py +++ b/grc/python/Generator.py @@ -90,7 +90,13 @@ Add a Misc->Throttle block to your flow graph to avoid CPU congestion.''') #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 @@ -113,6 +119,7 @@ Add a Misc->Throttle block to your flow graph to avoid CPU congestion.''') 'imports': imports, 'flow_graph': self._flow_graph, 'variables': variables, + 'notebooks': notebooks, 'controls': controls, 'parameters': parameters, 'blocks': blocks, diff --git a/grc/python/Param.py b/grc/python/Param.py index 8b5efc97..f971d0c3 100644 --- a/grc/python/Param.py +++ b/grc/python/Param.py @@ -30,7 +30,7 @@ import re 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.""" @@ -95,7 +95,8 @@ class Param(_Param): 'hex', 'string', 'bool', 'file_open', 'file_save', 'id', - 'grid_pos', 'import', + 'grid_pos', 'notebook', + 'import', ] def __repr__(self): @@ -103,6 +104,7 @@ class Param(_Param): 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 @@ -171,6 +173,7 @@ class Param(_Param): '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) @@ -201,7 +204,7 @@ class Param(_Param): 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): @@ -331,17 +334,38 @@ class Param(_Param): #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': diff --git a/grc/python/expr_utils.py b/grc/python/expr_utils.py index 1bee2249..3c39f5d8 100644 --- a/grc/python/expr_utils.py +++ b/grc/python/expr_utils.py @@ -133,5 +133,21 @@ def sort_variables(exprs): 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 diff --git a/grc/python/flow_graph.tmpl b/grc/python/flow_graph.tmpl index 742ceb94..a94e45e8 100644 --- a/grc/python/flow_graph.tmpl +++ b/grc/python/flow_graph.tmpl @@ -5,6 +5,7 @@ ##@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 @@ -52,13 +53,11 @@ $imp 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): @@ -71,8 +70,7 @@ class $(class_name)(gr.hier_block2): 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), ) @@ -92,8 +90,6 @@ class $(class_name)(gr.hier_block2): #end for ######################################################## ##Create Variables -## Set the variable to a property of self. -## Write the first line of the variable make. ######################################################## #if $variables @@ -105,9 +101,19 @@ class $(class_name)(gr.hier_block2): $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 @@ -120,7 +126,6 @@ class $(class_name)(gr.hier_block2): #end for ######################################################## ##Create Blocks -## Write the block make, and indent with 2 tabs. ######################################################## #if $blocks @@ -161,7 +166,6 @@ class $(class_name)(gr.hier_block2): ######################################################## ##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() @@ -196,7 +200,7 @@ if __name__ == '__main__': #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: ') diff --git a/grc/todo.txt b/grc/todo.txt index 3f47a1bf..de43d367 100644 --- a/grc/todo.txt +++ b/grc/todo.txt @@ -22,6 +22,8 @@ * 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 @@ -40,8 +42,6 @@ * 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) @@ -68,6 +68,7 @@ * 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 -- 2.30.2