summaryrefslogtreecommitdiff
path: root/grc
diff options
context:
space:
mode:
authorjblum2009-05-01 20:28:04 +0000
committerjblum2009-05-01 20:28:04 +0000
commita3ba8cf268816af51c4bb39ea7ecd7e85ea0807b (patch)
tree21dbd446e92672a56b323e005088d3c03edc238f /grc
parent6ce881caaacdd60a8bea37584c7286e08bea97a7 (diff)
downloadgnuradio-a3ba8cf268816af51c4bb39ea7ecd7e85ea0807b.tar.gz
gnuradio-a3ba8cf268816af51c4bb39ea7ecd7e85ea0807b.tar.bz2
gnuradio-a3ba8cf268816af51c4bb39ea7ecd7e85ea0807b.zip
Merged grc developer branch r10679:10938
Misc fixes and internal changes. Added help menu for usage tips. Added drag and drop for blocks. Removed callback controls, adopted forms. Any type can have enumerated options. git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@10941 221aa14e-8319-0410-a670-987f0aec2ac5
Diffstat (limited to 'grc')
-rw-r--r--grc/Makefile.inc1
-rw-r--r--grc/data/platforms/python/blocks/audio_sink.xml4
-rw-r--r--grc/data/platforms/python/blocks/audio_source.xml4
-rw-r--r--grc/data/platforms/python/blocks/blks2_rational_resampler_xxx.xml4
-rw-r--r--grc/data/platforms/python/blocks/gr_fft_vxx.xml2
-rw-r--r--grc/data/platforms/python/blocks/gr_mute_xx.xml8
-rw-r--r--grc/data/platforms/python/blocks/gr_noise_source_x.xml3
-rw-r--r--grc/data/platforms/python/blocks/gr_sig_source_x.xml3
-rw-r--r--grc/data/platforms/python/blocks/gr_vector_sink_x.xml10
-rw-r--r--grc/data/platforms/python/blocks/gr_vector_source_x.xml10
-rw-r--r--grc/data/platforms/python/blocks/options.xml12
-rw-r--r--grc/data/platforms/python/blocks/parameter.xml12
-rw-r--r--grc/data/platforms/python/blocks/probe_function.xml2
-rw-r--r--grc/data/platforms/python/blocks/usrp2_sink_xxxx.xml4
-rw-r--r--grc/data/platforms/python/blocks/usrp2_source_xxxx.xml4
-rw-r--r--grc/data/platforms/python/blocks/usrp_dual_source_x.xml12
-rw-r--r--grc/data/platforms/python/blocks/usrp_simple_sink_x.xml8
-rw-r--r--grc/data/platforms/python/blocks/usrp_simple_source_x.xml16
-rw-r--r--grc/data/platforms/python/blocks/variable_chooser.xml70
-rw-r--r--grc/data/platforms/python/blocks/variable_sink.xml6
-rw-r--r--grc/data/platforms/python/blocks/variable_slider.xml77
-rw-r--r--grc/data/platforms/python/blocks/variable_text_box.xml50
-rw-r--r--grc/data/platforms/python/blocks/wxgui_constellationsink2.xml2
-rw-r--r--grc/data/platforms/python/blocks/wxgui_fftsink2.xml10
-rw-r--r--grc/data/platforms/python/blocks/wxgui_histosink2.xml2
-rw-r--r--grc/data/platforms/python/blocks/wxgui_numbersink2.xml10
-rw-r--r--grc/data/platforms/python/blocks/wxgui_scopesink2.xml6
-rw-r--r--grc/data/platforms/python/blocks/wxgui_waterfallsink2.xml4
-rw-r--r--grc/data/platforms/python/blocks/xmlrpc_client.xml4
-rw-r--r--grc/data/platforms/python/flow_graph.tmpl30
-rw-r--r--grc/examples/Makefile.am40
-rw-r--r--grc/examples/audio/Makefile.am26
-rw-r--r--grc/examples/simple/Makefile.am28
-rw-r--r--grc/examples/trellis/Makefile.am28
-rw-r--r--grc/examples/usrp/Makefile.am30
-rw-r--r--grc/examples/usrp/usrp2_const_wave.grc168
-rw-r--r--grc/examples/usrp/usrp2_dpsk_mod.grc693
-rw-r--r--grc/examples/usrp/usrp2_fft.grc133
-rw-r--r--grc/examples/usrp/usrp_two_tone_loopback.grc527
-rw-r--r--grc/examples/usrp/usrp_wbfm_receive.grc294
-rw-r--r--grc/examples/xmlrpc/Makefile.am30
-rwxr-xr-xgrc/scripts/grc8
-rw-r--r--grc/src/grc_gnuradio/wxgui/Makefile.am8
-rw-r--r--grc/src/grc_gnuradio/wxgui/__init__.py8
-rw-r--r--grc/src/grc_gnuradio/wxgui/callback_controls.py303
-rw-r--r--grc/src/grc_gnuradio/wxgui/forms/__init__.py54
-rw-r--r--grc/src/grc_gnuradio/wxgui/forms/converters.py143
-rw-r--r--grc/src/grc_gnuradio/wxgui/forms/forms.py473
-rw-r--r--grc/src/grc_gnuradio/wxgui/top_block_gui.py4
-rw-r--r--grc/src/gui/ActionHandler.py77
-rw-r--r--grc/src/gui/Actions.py140
-rw-r--r--grc/src/gui/Bars.py12
-rw-r--r--grc/src/gui/BlockTreeWindow.py42
-rw-r--r--grc/src/gui/Constants.py23
-rw-r--r--grc/src/gui/Dialogs.py20
-rw-r--r--grc/src/gui/DrawingArea.py36
-rw-r--r--grc/src/gui/ParamsDialog.py8
-rw-r--r--grc/src/platforms/base/Block.py43
-rw-r--r--grc/src/platforms/base/FlowGraph.py37
-rw-r--r--grc/src/platforms/base/Param.py103
-rw-r--r--grc/src/platforms/base/Platform.py35
-rw-r--r--grc/src/platforms/base/Port.py3
-rw-r--r--grc/src/platforms/gui/Block.py33
-rw-r--r--grc/src/platforms/gui/Connection.py6
-rw-r--r--grc/src/platforms/gui/Constants.py51
-rw-r--r--grc/src/platforms/gui/Element.py19
-rw-r--r--grc/src/platforms/gui/FlowGraph.py135
-rw-r--r--grc/src/platforms/gui/Param.py70
-rw-r--r--grc/src/platforms/gui/Port.py18
-rw-r--r--grc/src/platforms/gui/Utils.py13
-rw-r--r--grc/src/platforms/python/Block.py11
-rw-r--r--grc/src/platforms/python/Constants.py.in1
-rw-r--r--grc/src/platforms/python/FlowGraph.py28
-rw-r--r--grc/src/platforms/python/Generator.py2
-rw-r--r--grc/src/platforms/python/Param.py6
-rw-r--r--grc/src/platforms/python/Port.py9
-rw-r--r--grc/src/utils/Makefile.am3
-rw-r--r--grc/src/utils/__init__.py66
-rw-r--r--grc/src/utils/odict.py93
-rw-r--r--grc/todo.txt2
80 files changed, 2906 insertions, 1627 deletions
diff --git a/grc/Makefile.inc b/grc/Makefile.inc
index 8acd4e107..4d78070da 100644
--- a/grc/Makefile.inc
+++ b/grc/Makefile.inc
@@ -23,7 +23,6 @@ include $(top_srcdir)/Makefile.common
grc_gnuradio_prefix = $(pythondir)/grc_gnuradio
grc_src_prefix = $(pythondir)/gnuradio/grc
grc_data_prefix = $(datadir)/$(PACKAGE)/grc
-grc_examples_prefix = $(exampledir)/grc
grc_base_data_dir = $(grc_data_prefix)/platforms/base
grc_python_data_dir = $(grc_data_prefix)/platforms/python
grc_python_blocks_dir = $(grc_data_prefix)/platforms/python/blocks
diff --git a/grc/data/platforms/python/blocks/audio_sink.xml b/grc/data/platforms/python/blocks/audio_sink.xml
index decaf2a08..75d583470 100644
--- a/grc/data/platforms/python/blocks/audio_sink.xml
+++ b/grc/data/platforms/python/blocks/audio_sink.xml
@@ -13,7 +13,7 @@
<name>Sample Rate</name>
<key>samp_rate</key>
<value>32000</value>
- <type>enum</type>
+ <type>int</type>
<option>
<name>16KHz</name>
<key>16000</key>
@@ -44,7 +44,7 @@
<key>device_name</key>
<value></value>
<type>string</type>
- <hide>#if $device_name.eval then 'none' else 'part'#</hide>
+ <hide>#if $device_name() then 'none' else 'part'#</hide>
</param>
<param>
<name>OK to Block</name>
diff --git a/grc/data/platforms/python/blocks/audio_source.xml b/grc/data/platforms/python/blocks/audio_source.xml
index 21407dccd..1f5d1033e 100644
--- a/grc/data/platforms/python/blocks/audio_source.xml
+++ b/grc/data/platforms/python/blocks/audio_source.xml
@@ -13,7 +13,7 @@
<name>Sample Rate</name>
<key>samp_rate</key>
<value>32000</value>
- <type>enum</type>
+ <type>int</type>
<option>
<name>16KHz</name>
<key>16000</key>
@@ -44,7 +44,7 @@
<key>device_name</key>
<value></value>
<type>string</type>
- <hide>#if $device_name.eval then 'none' else 'part'#</hide>
+ <hide>#if $device_name() then 'none' else 'part'#</hide>
</param>
<param>
<name>OK to Block</name>
diff --git a/grc/data/platforms/python/blocks/blks2_rational_resampler_xxx.xml b/grc/data/platforms/python/blocks/blks2_rational_resampler_xxx.xml
index 2f81a50e5..b92ec8ec2 100644
--- a/grc/data/platforms/python/blocks/blks2_rational_resampler_xxx.xml
+++ b/grc/data/platforms/python/blocks/blks2_rational_resampler_xxx.xml
@@ -12,12 +12,12 @@
<make>blks2.rational_resampler_$(type)(
interpolation=$interp,
decimation=$decim,
-#if $taps.eval
+#if $taps()
taps=$taps,
#else
taps=None,
#end if
-#if $fractional_bw.eval != 0
+#if $fractional_bw() != 0
fractional_bw=$fractional_bw,
#else
fractional_bw=None,
diff --git a/grc/data/platforms/python/blocks/gr_fft_vxx.xml b/grc/data/platforms/python/blocks/gr_fft_vxx.xml
index c2c13d0ae..d398486ef 100644
--- a/grc/data/platforms/python/blocks/gr_fft_vxx.xml
+++ b/grc/data/platforms/python/blocks/gr_fft_vxx.xml
@@ -9,7 +9,7 @@
<key>gr_fft_vxx</key>
<import>from gnuradio import gr</import>
<import>from gnuradio import window</import>
- <make>#if $type.eval == "complex"
+ <make>#if $type() == "complex"
gr.fft_vcc($fft_size, $forward, $window, $shift)
#else
gr.fft_vfc($fft_size, $forward, $window)
diff --git a/grc/data/platforms/python/blocks/gr_mute_xx.xml b/grc/data/platforms/python/blocks/gr_mute_xx.xml
index 668d7c599..a9a857c6a 100644
--- a/grc/data/platforms/python/blocks/gr_mute_xx.xml
+++ b/grc/data/platforms/python/blocks/gr_mute_xx.xml
@@ -41,6 +41,14 @@
<key>mute</key>
<value>False</value>
<type>raw</type>
+ <option>
+ <name>True</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>False</name>
+ <key>False</key>
+ </option>
</param>
<sink>
<name>in</name>
diff --git a/grc/data/platforms/python/blocks/gr_noise_source_x.xml b/grc/data/platforms/python/blocks/gr_noise_source_x.xml
index 664a108d3..4fcef5148 100644
--- a/grc/data/platforms/python/blocks/gr_noise_source_x.xml
+++ b/grc/data/platforms/python/blocks/gr_noise_source_x.xml
@@ -9,6 +9,7 @@
<key>gr_noise_source_x</key>
<import>from gnuradio import gr</import>
<make>gr.noise_source_$(type.fcn)($noise_type, $amp, $seed)</make>
+ <callback>set_type($noise_type)</callback>
<callback>set_amplitude($amp)</callback>
<param>
<name>Output Type</name>
@@ -39,7 +40,7 @@
<name>Noise Type</name>
<key>noise_type</key>
<value>gr.GR_GAUSSIAN</value>
- <type>enum</type>
+ <type>raw</type>
<option>
<name>Uniform</name>
<key>gr.GR_UNIFORM</key>
diff --git a/grc/data/platforms/python/blocks/gr_sig_source_x.xml b/grc/data/platforms/python/blocks/gr_sig_source_x.xml
index 53434c430..c329dba67 100644
--- a/grc/data/platforms/python/blocks/gr_sig_source_x.xml
+++ b/grc/data/platforms/python/blocks/gr_sig_source_x.xml
@@ -10,6 +10,7 @@
<import>from gnuradio import gr</import>
<make>gr.sig_source_$(type.fcn)($samp_rate, $waveform, $freq, $amp, $offset)</make>
<callback>set_sampling_freq($samp_rate)</callback>
+ <callback>set_waveform($waveform)</callback>
<callback>set_frequency($freq)</callback>
<callback>set_amplitude($amp)</callback>
<callback>set_offset($offset)</callback>
@@ -52,7 +53,7 @@
<name>Waveform</name>
<key>waveform</key>
<value>gr.GR_COS_WAVE</value>
- <type>enum</type>
+ <type>raw</type>
<option>
<name>Constant</name>
<key>gr.GR_CONST_WAVE</key>
diff --git a/grc/data/platforms/python/blocks/gr_vector_sink_x.xml b/grc/data/platforms/python/blocks/gr_vector_sink_x.xml
index d901b1d78..3bd998698 100644
--- a/grc/data/platforms/python/blocks/gr_vector_sink_x.xml
+++ b/grc/data/platforms/python/blocks/gr_vector_sink_x.xml
@@ -8,7 +8,7 @@
<name>Vector Sink</name>
<key>gr_vector_sink_x</key>
<import>from gnuradio import gr</import>
- <make>gr.vector_sink_$(type.fcn)()</make>
+ <make>gr.vector_sink_$(type.fcn)($vlen)</make>
<param>
<name>Input Type</name>
<key>type</key>
@@ -39,8 +39,16 @@
<opt>fcn:b</opt>
</option>
</param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
<sink>
<name>in</name>
<type>$type</type>
+ <vlen>$vlen</vlen>
</sink>
</block>
diff --git a/grc/data/platforms/python/blocks/gr_vector_source_x.xml b/grc/data/platforms/python/blocks/gr_vector_source_x.xml
index 240273e42..7a6a3aeff 100644
--- a/grc/data/platforms/python/blocks/gr_vector_source_x.xml
+++ b/grc/data/platforms/python/blocks/gr_vector_source_x.xml
@@ -8,7 +8,7 @@
<name>Vector Source</name>
<key>gr_vector_source_x</key>
<import>from gnuradio import gr</import>
- <make>gr.vector_source_$(type.fcn)($vector, $repeat)</make>
+ <make>gr.vector_source_$(type.fcn)($vector, $repeat, $vlen)</make>
<param>
<name>Output Type</name>
<key>type</key>
@@ -64,8 +64,16 @@
<key>False</key>
</option>
</param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
<source>
<name>out</name>
<type>$type</type>
+ <vlen>$vlen</vlen>
</source>
</block>
diff --git a/grc/data/platforms/python/blocks/options.xml b/grc/data/platforms/python/blocks/options.xml
index 11e46bbe6..07f659af9 100644
--- a/grc/data/platforms/python/blocks/options.xml
+++ b/grc/data/platforms/python/blocks/options.xml
@@ -10,10 +10,14 @@
<name>Options</name>
<key>options</key>
<import>from gnuradio import gr
-#if $generate_options.eval == 'wx_gui'
+#if $generate_options() == 'wx_gui'
from grc_gnuradio import wxgui as grc_wxgui
import wx
#end if
+#if $generate_options() != 'hb'
+from optparse import OptionParser
+from gnuradio.eng_option import eng_option
+#end if
</import>
<make></make>
<param>
@@ -64,16 +68,16 @@ import wx
<key>category</key>
<value>Custom</value>
<type>string</type>
- <hide>#if $generate_options.eval == 'hb' then 'none' else 'all'#</hide>
+ <hide>#if $generate_options() == 'hb' then 'none' else 'all'#</hide>
</param>
<param>
<name>Realtime Scheduling</name>
<key>realtime_scheduling</key>
<value></value>
<type>enum</type>
- <hide>#if $generate_options.eval == 'hb'
+ <hide>#if $generate_options() == 'hb'
all#slurp
-#elif $realtime_scheduling.eval
+#elif $realtime_scheduling()
none#slurp
#else
part#slurp
diff --git a/grc/data/platforms/python/blocks/parameter.xml b/grc/data/platforms/python/blocks/parameter.xml
index de2085011..e7bf61564 100644
--- a/grc/data/platforms/python/blocks/parameter.xml
+++ b/grc/data/platforms/python/blocks/parameter.xml
@@ -7,13 +7,13 @@
<block>
<name>Parameter</name>
<key>parameter</key>
- <import>from optparse import OptionParser</import>
<make>$value</make>
<param>
<name>Label</name>
<key>label</key>
<value></value>
<type>string</type>
+ <hide>#if $label() then 'none' else 'part'#</hide>
</param>
<param>
<name>Value</name>
@@ -41,7 +41,7 @@
</option>
<option>
<name>Float</name>
- <key>float</key>
+ <key>eng_float</key>
<opt>type:real</opt>
<opt>hide:none</opt>
</option>
@@ -65,12 +65,14 @@
</option>
</param>
<doc>
-This block represents a parameter to the flow graph, \
-used when the flow graph is instantiated as a hier block.
+This block represents a parameter to the flow graph. \
+A parameter can be used to pass command line arguments into a top block. \
+Or, parameters can pass arguments into an instantiated hierarchical block.
The paramater value cannot depend on any variables.
-Leave the label blank to use the parameter id as the label.
+Leave the label blank to use the parameter id as the label. \
+The label only applies when this flow graph is instantiated as a hierarchical block.
When type is not None, this parameter also becomes a command line option of the form --[id] [value].
</doc>
diff --git a/grc/data/platforms/python/blocks/probe_function.xml b/grc/data/platforms/python/blocks/probe_function.xml
index d46878526..ac0b3dcde 100644
--- a/grc/data/platforms/python/blocks/probe_function.xml
+++ b/grc/data/platforms/python/blocks/probe_function.xml
@@ -9,7 +9,7 @@
<key>probe_function</key>
<import>from grc_gnuradio import blks2 as grc_blks2</import>
<make>grc_blks2.probe_function(
- probe_callback=self.$(block_id.eval).$(function_name.eval),
+ probe_callback=self.$(block_id()).$(function_name()),
probe_rate=$probe_rate,
)</make>
<callback>set_probe_rate($probe_rate)</callback>
diff --git a/grc/data/platforms/python/blocks/usrp2_sink_xxxx.xml b/grc/data/platforms/python/blocks/usrp2_sink_xxxx.xml
index e6e315786..264ed4f20 100644
--- a/grc/data/platforms/python/blocks/usrp2_sink_xxxx.xml
+++ b/grc/data/platforms/python/blocks/usrp2_sink_xxxx.xml
@@ -8,9 +8,9 @@
<name>USRP2 Sink</name>
<key>usrp2_sink_xxxx</key>
<import>from gnuradio import usrp2</import>
- <make>#if not $interface.eval and not $mac_addr.eval
+ <make>#if not $interface() and not $mac_addr()
usrp2.sink_$(type.fcn)()
-#elif not $mac_addr.eval
+#elif not $mac_addr()
usrp2.sink_$(type.fcn)($interface)
#else
usrp2.sink_$(type.fcn)($interface, $mac_addr)
diff --git a/grc/data/platforms/python/blocks/usrp2_source_xxxx.xml b/grc/data/platforms/python/blocks/usrp2_source_xxxx.xml
index 8b8ae3248..54bea7a49 100644
--- a/grc/data/platforms/python/blocks/usrp2_source_xxxx.xml
+++ b/grc/data/platforms/python/blocks/usrp2_source_xxxx.xml
@@ -8,9 +8,9 @@
<name>USRP2 Source</name>
<key>usrp2_source_xxxx</key>
<import>from gnuradio import usrp2</import>
- <make>#if not $interface.eval and not $mac_addr.eval
+ <make>#if not $interface() and not $mac_addr()
usrp2.source_$(type.fcn)()
-#elif not $mac_addr.eval
+#elif not $mac_addr()
usrp2.source_$(type.fcn)($interface)
#else
usrp2.source_$(type.fcn)($interface, $mac_addr)
diff --git a/grc/data/platforms/python/blocks/usrp_dual_source_x.xml b/grc/data/platforms/python/blocks/usrp_dual_source_x.xml
index 823850b52..cb75fcead 100644
--- a/grc/data/platforms/python/blocks/usrp_dual_source_x.xml
+++ b/grc/data/platforms/python/blocks/usrp_dual_source_x.xml
@@ -8,8 +8,8 @@
<name>USRP Dual Source</name>
<key>usrp_dual_source_x</key>
<import>from grc_gnuradio import usrp as grc_usrp</import>
- <make>grc_usrp.dual_source_$(type.fcn)(which=$which, rx_ant_a='$rx_ant_a', rx_ant_b='$rx_ant_b')
-#if $format.eval
+ <make>grc_usrp.dual_source_$(type.fcn)(which=$which, rx_ant_a=$rx_ant_a, rx_ant_b=$rx_ant_b)
+#if $format()
self.$(id).set_format(width=$format.width, shift=$format.shift)
#end if
self.$(id).set_decim_rate($decimation)
@@ -42,7 +42,7 @@ self.$(id).set_gain_b($gain_b)</make>
<key>format</key>
<value></value>
<type>enum</type>
- <hide>#if $format.eval then '' else 'part'#</hide>
+ <hide>#if $format() then '' else 'part'#</hide>
<option>
<name>16 Bits (Default)</name>
<key></key>
@@ -95,7 +95,8 @@ self.$(id).set_gain_b($gain_b)</make>
<param>
<name>RX Antenna A</name>
<key>rx_ant_a</key>
- <type>enum</type>
+ <value>RXA</value>
+ <type>string</type>
<option>
<name>RXA</name>
<key>RXA</key>
@@ -125,7 +126,8 @@ self.$(id).set_gain_b($gain_b)</make>
<param>
<name>RX Antenna B</name>
<key>rx_ant_b</key>
- <type>enum</type>
+ <value>RXA</value>
+ <type>string</type>
<option>
<name>RXA</name>
<key>RXA</key>
diff --git a/grc/data/platforms/python/blocks/usrp_simple_sink_x.xml b/grc/data/platforms/python/blocks/usrp_simple_sink_x.xml
index ca887997a..0c7fc53da 100644
--- a/grc/data/platforms/python/blocks/usrp_simple_sink_x.xml
+++ b/grc/data/platforms/python/blocks/usrp_simple_sink_x.xml
@@ -8,7 +8,7 @@
<name>USRP Sink</name>
<key>usrp_simple_sink_x</key>
<import>from grc_gnuradio import usrp as grc_usrp</import>
- <make>grc_usrp.simple_sink_$(type.fcn)(which=$which, side='$side')
+ <make>grc_usrp.simple_sink_$(type.fcn)(which=$which, side=$side)
self.$(id).set_interp_rate($interpolation)
self.$(id).set_frequency($frequency, verbose=True)
self.$(id).set_gain($gain)
@@ -61,13 +61,13 @@ self.$(id).set_auto_tr(True)
<name>Side</name>
<key>side</key>
<value>A</value>
- <type>enum</type>
+ <type>string</type>
<option>
- <name>Side A</name>
+ <name>A</name>
<key>A</key>
</option>
<option>
- <name>Side B</name>
+ <name>B</name>
<key>B</key>
</option>
</param>
diff --git a/grc/data/platforms/python/blocks/usrp_simple_source_x.xml b/grc/data/platforms/python/blocks/usrp_simple_source_x.xml
index d7f5475a6..8d7b9533d 100644
--- a/grc/data/platforms/python/blocks/usrp_simple_source_x.xml
+++ b/grc/data/platforms/python/blocks/usrp_simple_source_x.xml
@@ -8,8 +8,8 @@
<name>USRP Source</name>
<key>usrp_simple_source_x</key>
<import>from grc_gnuradio import usrp as grc_usrp</import>
- <make>grc_usrp.simple_source_$(type.fcn)(which=$which, side='$side', rx_ant='$rx_ant'#if $hb_filters.eval then ', no_hb=True' else ''#)
-#if $format.eval
+ <make>grc_usrp.simple_source_$(type.fcn)(which=$which, side=$side, rx_ant=$rx_ant#if $hb_filters() then ', no_hb=True' else ''#)
+#if $format()
self.$(id).set_format(width=$format.width, shift=$format.shift)
#end if
self.$(id).set_decim_rate($decimation)
@@ -38,7 +38,7 @@ self.$(id).set_gain($gain)</make>
<key>format</key>
<value></value>
<type>enum</type>
- <hide>#if $format.eval then '' else 'part'#</hide>
+ <hide>#if $format() then '' else 'part'#</hide>
<option>
<name>16 Bits (Default)</name>
<key></key>
@@ -77,13 +77,13 @@ self.$(id).set_gain($gain)</make>
<name>Side</name>
<key>side</key>
<value>A</value>
- <type>enum</type>
+ <type>string</type>
<option>
- <name>Side A</name>
+ <name>A</name>
<key>A</key>
</option>
<option>
- <name>Side B</name>
+ <name>B</name>
<key>B</key>
</option>
</param>
@@ -91,7 +91,7 @@ self.$(id).set_gain($gain)</make>
<name>RX Antenna</name>
<key>rx_ant</key>
<value>RXA</value>
- <type>enum</type>
+ <type>string</type>
<option>
<name>RXA</name>
<key>RXA</key>
@@ -118,7 +118,7 @@ self.$(id).set_gain($gain)</make>
<key>hb_filters</key>
<value></value>
<type>enum</type>
- <hide>#if $hb_filters.eval then 'none' else 'part'#</hide>
+ <hide>#if $hb_filters() then 'none' else 'part'#</hide>
<option>
<name>Enable</name>
<key></key>
diff --git a/grc/data/platforms/python/blocks/variable_chooser.xml b/grc/data/platforms/python/blocks/variable_chooser.xml
index 2a00a1cf2..6827c3675 100644
--- a/grc/data/platforms/python/blocks/variable_chooser.xml
+++ b/grc/data/platforms/python/blocks/variable_chooser.xml
@@ -1,42 +1,51 @@
<?xml version="1.0"?>
<!--
###################################################
-##Variable Chooser: a grc variable with multiple choices
+##Variable Chooser:
+## a gui form with enumerated choices
+## radio buttons, drop down, or button
###################################################
-->
<block>
<name>Variable Chooser</name>
<key>variable_chooser</key>
- <make>$(choices)[$value_index]
-_$(id)_control = grc_wxgui.$(chooser_type)_control(
- window=self.GetWin(),
- callback=self.set_$(id),
- #if $label.eval
+ <import>from grc_gnuradio.wxgui import forms</import>
+ <make>$value
+self['$id'] = $id
+self.subscribe('$id', self.set_$(id))
+self._$(id)_control = forms.$(type)(
+ parent=self.GetWin(),
+ ps=self,
+ key='$id',
+ #if $label()
label=$label,
- #else
+ #else
label='$id',
- #end if
- index=$value_index,
+ #end if
choices=$choices,
labels=$labels,
+#if $type() == 'radio_buttons'
+ style=$style,
+#end if
)
-#set $grid_pos = $grid_pos.eval
+#set $grid_pos = $grid_pos()
#if not grid_pos
-self.Add(_$(id)_control)
+self.Add(self._$(id)_control)
#else
-self.GridAdd(_$(id)_control, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3])
+self.GridAdd(self._$(id)_control, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3])
#end if</make>
<param>
<name>Label</name>
<key>label</key>
<value></value>
<type>string</type>
+ <hide>#if $label() then 'none' else 'part'#</hide>
</param>
<param>
- <name>Value Index</name>
- <key>value_index</key>
- <value>0</value>
- <type>int</type>
+ <name>Default Value</name>
+ <key>value</key>
+ <value>1</value>
+ <type>raw</type>
</param>
<param>
<name>Choices</name>
@@ -51,8 +60,8 @@ self.GridAdd(_$(id)_control, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos
<type>raw</type>
</param>
<param>
- <name>Chooser Type</name>
- <key>chooser_type</key>
+ <name>Type</name>
+ <key>type</key>
<value>drop_down</value>
<type>enum</type>
<option>
@@ -60,12 +69,8 @@ self.GridAdd(_$(id)_control, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos
<key>drop_down</key>
</option>
<option>
- <name>Radio Buttons Horizontal</name>
- <key>radio_buttons_horizontal</key>
- </option>
- <option>
- <name>Radio Buttons Vertical</name>
- <key>radio_buttons_vertical</key>
+ <name>Radio Buttons</name>
+ <key>radio_buttons</key>
</option>
<option>
<name>Button</name>
@@ -73,12 +78,27 @@ self.GridAdd(_$(id)_control, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos
</option>
</param>
<param>
+ <name>Style</name>
+ <key>style</key>
+ <value>wx.RA_HORIZONTAL</value>
+ <type>enum</type>
+ <hide>#if $type() == 'radio_buttons' then 'part' else 'all'#</hide>
+ <option>
+ <name>Horizontal</name>
+ <key>wx.RA_HORIZONTAL</key>
+ </option>
+ <option>
+ <name>Vertical</name>
+ <key>wx.RA_VERTICAL</key>
+ </option>
+ </param>
+ <param>
<name>Grid Position</name>
<key>grid_pos</key>
<value></value>
<type>grid_pos</type>
</param>
- <check>$value_index in range(len($choices))</check>
+ <check>$value in $choices</check>
<check>not $labels or len($labels) == len($choices)</check>
<doc>
This block creates a variable with a drop down, radio buttons, or a button. \
diff --git a/grc/data/platforms/python/blocks/variable_sink.xml b/grc/data/platforms/python/blocks/variable_sink.xml
index 87575ae1b..426bd34fb 100644
--- a/grc/data/platforms/python/blocks/variable_sink.xml
+++ b/grc/data/platforms/python/blocks/variable_sink.xml
@@ -15,13 +15,13 @@ def _$(id)_run():
while True:
time.sleep(1.0/$samp_rate)
data = self.$(id).data()
-#if $vlen.eval == 0
+#if $vlen() == 0
if data:
- self.set_$(variable.eval)(data[-1])
+ self.set_$(variable())(data[-1])
self.$(id).clear()
#else
if len(data) &gt;= $vlen:
- self.set_$(variable.eval)(data[-($vlen):])
+ self.set_$(variable())(data[-($vlen):])
self.$(id).clear()
#end if
threading.Thread(target=_$(id)_run).start()</make>
diff --git a/grc/data/platforms/python/blocks/variable_slider.xml b/grc/data/platforms/python/blocks/variable_slider.xml
index 635f3ed4c..9c8e7ece9 100644
--- a/grc/data/platforms/python/blocks/variable_slider.xml
+++ b/grc/data/platforms/python/blocks/variable_slider.xml
@@ -1,38 +1,55 @@
<?xml version="1.0"?>
<!--
###################################################
-##Variable Slider: a grc variable with key, value, min, max, step
+##Variable Slider:
+## a combined slider and text box form
###################################################
-->
<block>
<name>Variable Slider</name>
<key>variable_slider</key>
+ <import>from grc_gnuradio.wxgui import forms</import>
<make>$value
-_$(id)_control = grc_wxgui.slider_$(slider_type)_control(
- window=self.GetWin(),
- callback=self.set_$(id),
- #if $label.eval
+self['$id'] = $id
+self.subscribe('$id', self.set_$(id))
+self._$(id)_sizer = wx.BoxSizer(wx.VERTICAL)
+forms.text_box(
+ parent=self.GetWin(),
+ sizer=self._$(id)_sizer,
+ ps=self,
+ key='$id',
+ #if $label()
label=$label,
- #else
+ #else
label='$id',
- #end if
- value=$id,
- min=$min,
- max=$max,
+ #end if
+ converter=forms.$(converver)(),
+ proportion=0,
+)
+forms.slider(
+ parent=self.GetWin(),
+ sizer=self._$(id)_sizer,
+ ps=self,
+ key='$id',
+ minimum=$min,
+ maximum=$max,
num_steps=$num_steps,
- slider_length=$slider_length,
+ style=$style,
+ cast=$(converver.slider_cast),
+ proportion=1,
)
-#set $grid_pos = $grid_pos.eval
+#set $grid_pos = $grid_pos()
#if not grid_pos
-self.Add(_$(id)_control)
+self.Add(self._$(id)_sizer)
#else
-self.GridAdd(_$(id)_control, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3])
+self.GridAdd(self._$(id)_sizer, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3])
#end if</make>
<param>
<name>Label</name>
<key>label</key>
<value></value>
<type>string</type>
+ <hide>#if $label() then 'none' else 'part'#</hide>
</param>
<param>
<name>Default Value</name>
@@ -60,24 +77,34 @@ self.GridAdd(_$(id)_control, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos
<hide>part</hide>
</param>
<param>
- <name>Slider Length (px)</name>
- <key>slider_length</key>
- <value>200</value>
- <type>int</type>
+ <name>Style</name>
+ <key>style</key>
+ <value>wx.SL_HORIZONTAL</value>
+ <type>enum</type>
<hide>part</hide>
+ <option>
+ <name>Horizontal</name>
+ <key>wx.SL_HORIZONTAL</key>
+ </option>
+ <option>
+ <name>Vertical</name>
+ <key>wx.SL_VERTICAL</key>
+ </option>
</param>
<param>
- <name>Slider Type</name>
- <key>slider_type</key>
- <value>horizontal</value>
+ <name>Converter</name>
+ <key>converver</key>
+ <value>float_converter</value>
<type>enum</type>
<option>
- <name>Horizontal</name>
- <key>horizontal</key>
+ <name>Float</name>
+ <key>float_converter</key>
+ <opt>slider_cast:float</opt>
</option>
<option>
- <name>Vertical</name>
- <key>vertical</key>
+ <name>Integer</name>
+ <key>int_converter</key>
+ <opt>slider_cast:int</opt>
</option>
</param>
<param>
diff --git a/grc/data/platforms/python/blocks/variable_text_box.xml b/grc/data/platforms/python/blocks/variable_text_box.xml
index 97c6aa0d9..2857fa366 100644
--- a/grc/data/platforms/python/blocks/variable_text_box.xml
+++ b/grc/data/platforms/python/blocks/variable_text_box.xml
@@ -1,34 +1,40 @@
<?xml version="1.0"?>
<!--
###################################################
-##Variable Text Box: a grc variable with key, value
+##Variable Text Box:
+## a gui text box form
###################################################
-->
<block>
<name>Variable Text Box</name>
<key>variable_text_box</key>
+ <import>from grc_gnuradio.wxgui import forms</import>
<make>$value
-_$(id)_control = grc_wxgui.text_box_control(
- window=self.GetWin(),
- callback=self.set_$(id),
- #if $label.eval
+self['$id'] = $id
+self.subscribe('$id', self.set_$(id))
+self._$(id)_control = forms.text_box(
+ parent=self.GetWin(),
+ ps=self,
+ key='$id',
+ #if $label()
label=$label,
- #else
+ #else
label='$id',
- #end if
- value=$id,
+ #end if
+ converter=forms.$(converver)(),
)
-#set $grid_pos = $grid_pos.eval
+#set $grid_pos = $grid_pos()
#if not grid_pos
-self.Add(_$(id)_control)
+self.Add(self._$(id)_control)
#else
-self.GridAdd(_$(id)_control, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3])
+self.GridAdd(self._$(id)_control, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3])
#end if</make>
<param>
<name>Label</name>
<key>label</key>
<value></value>
<type>string</type>
+ <hide>#if $label() then 'none' else 'part'#</hide>
</param>
<param>
<name>Default Value</name>
@@ -37,6 +43,28 @@ self.GridAdd(_$(id)_control, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos
<type>raw</type>
</param>
<param>
+ <name>Converter</name>
+ <key>converver</key>
+ <value>float_converter</value>
+ <type>enum</type>
+ <option>
+ <name>Float</name>
+ <key>float_converter</key>
+ </option>
+ <option>
+ <name>Integer</name>
+ <key>int_converter</key>
+ </option>
+ <option>
+ <name>String</name>
+ <key>str_converter</key>
+ </option>
+ <option>
+ <name>Evaluate</name>
+ <key>eval_converter</key>
+ </option>
+ </param>
+ <param>
<name>Grid Position</name>
<key>grid_pos</key>
<value></value>
diff --git a/grc/data/platforms/python/blocks/wxgui_constellationsink2.xml b/grc/data/platforms/python/blocks/wxgui_constellationsink2.xml
index 69869904f..471c9f4a8 100644
--- a/grc/data/platforms/python/blocks/wxgui_constellationsink2.xml
+++ b/grc/data/platforms/python/blocks/wxgui_constellationsink2.xml
@@ -23,7 +23,7 @@
symbol_rate=$symbol_rate,
omega_limit=$omega_limit,
)
-#set $grid_pos = $grid_pos.eval
+#set $grid_pos = $grid_pos()
#if not grid_pos
self.Add(self.$(id).win)
#else
diff --git a/grc/data/platforms/python/blocks/wxgui_fftsink2.xml b/grc/data/platforms/python/blocks/wxgui_fftsink2.xml
index c729bea4b..31680f7bd 100644
--- a/grc/data/platforms/python/blocks/wxgui_fftsink2.xml
+++ b/grc/data/platforms/python/blocks/wxgui_fftsink2.xml
@@ -17,11 +17,11 @@
fft_size=$fft_size,
fft_rate=$fft_rate,
average=$average,
- avg_alpha=#if $avg_alpha.eval then $avg_alpha else 'None'#,
+ avg_alpha=#if $avg_alpha() then $avg_alpha else 'None'#,
title=$title,
peak_hold=$peak_hold,
)
-#set $grid_pos = $grid_pos.eval
+#set $grid_pos = $grid_pos()
#if not grid_pos
self.Add(self.$(id).win)
#else
@@ -112,7 +112,7 @@ self.GridAdd(self.$(id).win, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos
<key>peak_hold</key>
<value>False</value>
<type>enum</type>
- <hide>#if $peak_hold.eval == 'True' then 'none' else 'part'#</hide>
+ <hide>#if $peak_hold() == 'True' then 'none' else 'part'#</hide>
<option>
<name>On</name>
<key>True</key>
@@ -127,7 +127,7 @@ self.GridAdd(self.$(id).win, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos
<key>average</key>
<value>False</value>
<type>enum</type>
- <hide>#if $average.eval == 'True' then 'none' else 'part'#</hide>
+ <hide>#if $average() == 'True' then 'none' else 'part'#</hide>
<option>
<name>On</name>
<key>True</key>
@@ -142,7 +142,7 @@ self.GridAdd(self.$(id).win, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos
<key>avg_alpha</key>
<value>0</value>
<type>real</type>
- <hide>#if $average.eval == 'True' then 'none' else 'all'#</hide>
+ <hide>#if $average() == 'True' then 'none' else 'all'#</hide>
</param>
<param>
<name>Grid Position</name>
diff --git a/grc/data/platforms/python/blocks/wxgui_histosink2.xml b/grc/data/platforms/python/blocks/wxgui_histosink2.xml
index 3d694aedc..4de57b1c4 100644
--- a/grc/data/platforms/python/blocks/wxgui_histosink2.xml
+++ b/grc/data/platforms/python/blocks/wxgui_histosink2.xml
@@ -14,7 +14,7 @@
num_bins=$num_bins,
frame_size=$frame_size,
)
-#set $grid_pos = $grid_pos.eval
+#set $grid_pos = $grid_pos()
#if not grid_pos
self.Add(self.$(id).win)
#else
diff --git a/grc/data/platforms/python/blocks/wxgui_numbersink2.xml b/grc/data/platforms/python/blocks/wxgui_numbersink2.xml
index 1b32993e1..af0281f6a 100644
--- a/grc/data/platforms/python/blocks/wxgui_numbersink2.xml
+++ b/grc/data/platforms/python/blocks/wxgui_numbersink2.xml
@@ -20,12 +20,12 @@
sample_rate=$samp_rate,
number_rate=$number_rate,
average=$average,
- avg_alpha=#if $avg_alpha.eval then $avg_alpha else 'None'#,
+ avg_alpha=#if $avg_alpha() then $avg_alpha else 'None'#,
label=$title,
peak_hold=$peak_hold,
show_gauge=$show_gauge,
)
-#set $grid_pos = $grid_pos.eval
+#set $grid_pos = $grid_pos()
#if not grid_pos
self.Add(self.$(id).win)
#else
@@ -112,7 +112,7 @@ self.GridAdd(self.$(id).win, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos
<key>peak_hold</key>
<value>False</value>
<type>enum</type>
- <hide>#if $peak_hold.eval == 'True' then 'none' else 'part'#</hide>
+ <hide>#if $peak_hold() == 'True' then 'none' else 'part'#</hide>
<option>
<name>On</name>
<key>True</key>
@@ -127,7 +127,7 @@ self.GridAdd(self.$(id).win, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos
<key>average</key>
<value>False</value>
<type>enum</type>
- <hide>#if $average.eval == 'True' then 'none' else 'part'#</hide>
+ <hide>#if $average() == 'True' then 'none' else 'part'#</hide>
<option>
<name>On</name>
<key>True</key>
@@ -142,7 +142,7 @@ self.GridAdd(self.$(id).win, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos
<key>avg_alpha</key>
<value>0</value>
<type>real</type>
- <hide>#if $average.eval == 'True' then 'none' else 'all'#</hide>
+ <hide>#if $average() == 'True' then 'none' else 'all'#</hide>
</param>
<param>
<name>Show Gauge</name>
diff --git a/grc/data/platforms/python/blocks/wxgui_scopesink2.xml b/grc/data/platforms/python/blocks/wxgui_scopesink2.xml
index 1af0afb35..78c39f80d 100644
--- a/grc/data/platforms/python/blocks/wxgui_scopesink2.xml
+++ b/grc/data/platforms/python/blocks/wxgui_scopesink2.xml
@@ -19,7 +19,7 @@
xy_mode=$xy_mode,
num_inputs=$num_inputs,
)
-#set $grid_pos = $grid_pos.eval
+#set $grid_pos = $grid_pos()
#if not grid_pos
self.Add(self.$(id).win)
#else
@@ -71,7 +71,7 @@ self.GridAdd(self.$(id).win, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos
<key>ac_couple</key>
<value>False</value>
<type>enum</type>
- <hide>#if $ac_couple.eval == 'True' then 'none' else 'part'#</hide>
+ <hide>#if $ac_couple() == 'True' then 'none' else 'part'#</hide>
<option>
<name>Off</name>
<key>False</key>
@@ -86,7 +86,7 @@ self.GridAdd(self.$(id).win, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos
<key>xy_mode</key>
<value>False</value>
<type>enum</type>
- <hide>#if $xy_mode.eval == 'True' then 'none' else 'part'#</hide>
+ <hide>#if $xy_mode() == 'True' then 'none' else 'part'#</hide>
<option>
<name>Off</name>
<key>False</key>
diff --git a/grc/data/platforms/python/blocks/wxgui_waterfallsink2.xml b/grc/data/platforms/python/blocks/wxgui_waterfallsink2.xml
index 68d84dbba..6d76ee867 100644
--- a/grc/data/platforms/python/blocks/wxgui_waterfallsink2.xml
+++ b/grc/data/platforms/python/blocks/wxgui_waterfallsink2.xml
@@ -17,10 +17,10 @@
fft_size=$fft_size,
fft_rate=$fft_rate,
average=$options.average,
- avg_alpha=#if $avg_alpha.eval then $avg_alpha else 'None'#,
+ avg_alpha=#if $avg_alpha() then $avg_alpha else 'None'#,
title=$title,
)
-#set $grid_pos = $grid_pos.eval
+#set $grid_pos = $grid_pos()
#if not grid_pos
self.Add(self.$(id).win)
#else
diff --git a/grc/data/platforms/python/blocks/xmlrpc_client.xml b/grc/data/platforms/python/blocks/xmlrpc_client.xml
index f132a7865..dc4d154d1 100644
--- a/grc/data/platforms/python/blocks/xmlrpc_client.xml
+++ b/grc/data/platforms/python/blocks/xmlrpc_client.xml
@@ -8,8 +8,8 @@
<name>XMLRPC Client</name>
<key>xmlrpc_client</key>
<import>import xmlrpclib</import>
- <make>xmlrpclib.Server('http://$(addr.eval):$(port)')</make>
- <callback>$(callback.eval)($variable)</callback>
+ <make>xmlrpclib.Server('http://$(addr()):$(port)')</make>
+ <callback>$(callback())($variable)</callback>
<param>
<name>Address</name>
<key>addr</key>
diff --git a/grc/data/platforms/python/flow_graph.tmpl b/grc/data/platforms/python/flow_graph.tmpl
index a84b4eb0a..4c481dce4 100644
--- a/grc/data/platforms/python/flow_graph.tmpl
+++ b/grc/data/platforms/python/flow_graph.tmpl
@@ -39,13 +39,12 @@ $imp
## Setup the IO signature (hier block only).
########################################################
#set $class_name = $flow_graph.get_option('id')
-#set $param_str = ', '.join(['self'] + ['%s=%s'%(param.get_id(), param.get_make()) for param in $parameters])
#if $generate_options == 'wx_gui'
#import gtk
#set $icon = gtk.IconTheme().lookup_icon('gnuradio-grc', 32, 0)
class $(class_name)(grc_wxgui.top_block_gui):
- def __init__($param_str):
+ def __init__(self, options):
grc_wxgui.top_block_gui.__init__(
self,
title="$flow_graph.get_parent().get_name() - Executing: $flow_graph.get_option('title')",
@@ -56,11 +55,12 @@ class $(class_name)(grc_wxgui.top_block_gui):
#elif $generate_options == 'no_gui'
class $(class_name)(gr.top_block):
- def __init__($param_str):
+ def __init__(self, options):
gr.top_block.__init__(self, "$flow_graph.get_option('title')")
#elif $generate_options == 'hb'
#set $in_sig = $flow_graph.get_input_signature()
#set $out_sig = $flow_graph.get_output_signature()
+ #set $param_str = ', '.join(['self'] + ['%s=%s'%(param.get_id(), param.get_make()) for param in $parameters])
class $(class_name)(gr.hier_block2):
def __init__($param_str):
@@ -73,7 +73,7 @@ class $(class_name)(gr.hier_block2):
#end if
########################################################
##Create Parameters
-## Set the parameter to a property of self..
+## Set the parameter to a property of self.
########################################################
#if $parameters
@@ -82,7 +82,11 @@ class $(class_name)(gr.hier_block2):
$DIVIDER
#end if
#for $param in $parameters
+ #if $generate_options != 'hb'
+ self.$param.get_id() = $param.get_id() = options.$param.get_id()
+ #else
self.$param.get_id() = $param.get_id()
+ #end if
#end for
########################################################
##Create Variables
@@ -179,23 +183,19 @@ class $(class_name)(gr.hier_block2):
########################################################
#if $generate_options != 'hb'
if __name__ == '__main__':
- #set $args = list()
- #if $parameters
- parser = OptionParser()
- #for $param in $parameters
- #set $type = $param.get_param('type').get_value()
- #if $type
+ parser = OptionParser(option_class=eng_option, usage="%prog: [options]")
+ #for $param in $parameters
+ #set $type = $param.get_param('type').get_value()
+ #if $type
parser.add_option("--$param.get_id()", dest="$param.get_id()", type="$type", default=$param.get_make())
- #silent $args.append('%s=options.%s'%($param.get_id(), $param.get_id()))
- #end if
- #end for
+ #end if
+ #end for
(options, args) = parser.parse_args()
- #end if
#if $flow_graph.get_option('realtime_scheduling')
if gr.enable_realtime_scheduling() != gr.RT_OK:
print "Error: failed to enable realtime scheduling."
#end if
- tb = $(class_name)($(', '.join($args)))
+ tb = $(class_name)(options)
#if $generate_options == 'wx_gui'
tb.Run()
#elif $generate_options == 'no_gui'
diff --git a/grc/examples/Makefile.am b/grc/examples/Makefile.am
index d129cf6ba..9a2fbd53d 100644
--- a/grc/examples/Makefile.am
+++ b/grc/examples/Makefile.am
@@ -1,5 +1,5 @@
#
-# Copyright 2008 Free Software Foundation, Inc.
+# Copyright 2009 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -19,11 +19,35 @@
# Boston, MA 02110-1301, USA.
#
-include $(top_srcdir)/grc/Makefile.inc
+include $(top_srcdir)/Makefile.common
-SUBDIRS = \
- audio \
- simple \
- trellis \
- usrp \
- xmlrpc
+grc_examples_prefix = $(exampledir)/grc
+
+audiodatadir = $(grc_examples_prefix)/audio
+dist_audiodata_DATA = \
+ audio/dial_tone.grc
+
+simpledatadir = $(grc_examples_prefix)/simple
+dist_simpledata_DATA = \
+ simple/ber_simulation.grc \
+ simple/dpsk_loopback.grc
+
+trellisdatadir = $(grc_examples_prefix)/trellis
+dist_trellisdata_DATA = \
+ trellis/readme.txt \
+ trellis/interference_cancellation.grc
+
+usrpdatadir = $(grc_examples_prefix)/usrp
+dist_usrpdata_DATA = \
+ usrp/usrp2_const_wave.grc \
+ usrp/usrp2_dpsk_mod.grc \
+ usrp/usrp2_fft.grc \
+ usrp/usrp_two_tone_loopback.grc \
+ usrp/usrp_wbfm_receive.grc
+
+xmlrpcdatadir = $(grc_examples_prefix)/xmlrpc
+dist_xmlrpcdata_DATA = \
+ xmlrpc/readme.txt \
+ xmlrpc/xmlrpc_client.grc \
+ xmlrpc/xmlrpc_client_script.py\
+ xmlrpc/xmlrpc_server.grc
diff --git a/grc/examples/audio/Makefile.am b/grc/examples/audio/Makefile.am
deleted file mode 100644
index f9604c34f..000000000
--- a/grc/examples/audio/Makefile.am
+++ /dev/null
@@ -1,26 +0,0 @@
-#
-# Copyright 2008 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.
-#
-
-include $(top_srcdir)/grc/Makefile.inc
-
-ourdatadir = $(grc_examples_prefix)/audio
-
-dist_ourdata_DATA = dial_tone.grc
diff --git a/grc/examples/simple/Makefile.am b/grc/examples/simple/Makefile.am
deleted file mode 100644
index a56f98bdd..000000000
--- a/grc/examples/simple/Makefile.am
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# Copyright 2008 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.
-#
-
-include $(top_srcdir)/grc/Makefile.inc
-
-ourdatadir = $(grc_examples_prefix)/simple
-
-dist_ourdata_DATA = \
- ber_simulation.grc \
- dpsk_loopback.grc
diff --git a/grc/examples/trellis/Makefile.am b/grc/examples/trellis/Makefile.am
deleted file mode 100644
index 567773052..000000000
--- a/grc/examples/trellis/Makefile.am
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# Copyright 2008 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.
-#
-
-include $(top_srcdir)/grc/Makefile.inc
-
-ourdatadir = $(grc_examples_prefix)/trellis
-
-dist_ourdata_DATA = \
- readme.txt \
- interference_cancellation.grc
diff --git a/grc/examples/usrp/Makefile.am b/grc/examples/usrp/Makefile.am
deleted file mode 100644
index 4e969ebd4..000000000
--- a/grc/examples/usrp/Makefile.am
+++ /dev/null
@@ -1,30 +0,0 @@
-#
-# Copyright 2008, 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.
-#
-
-include $(top_srcdir)/grc/Makefile.inc
-
-ourdatadir = $(grc_examples_prefix)/usrp
-
-dist_ourdata_DATA = \
- usrp2_const_wave.grc \
- usrp2_fft.grc \
- usrp_two_tone_loopback.grc \
- usrp_wbfm_receive.grc
diff --git a/grc/examples/usrp/usrp2_const_wave.grc b/grc/examples/usrp/usrp2_const_wave.grc
index ac9570349..fdbd7c1f3 100644
--- a/grc/examples/usrp/usrp2_const_wave.grc
+++ b/grc/examples/usrp/usrp2_const_wave.grc
@@ -1,43 +1,93 @@
<?xml version='1.0' encoding='ASCII'?>
<flow_graph>
- <timestamp>Fri Jan 23 11:26:26 2009</timestamp>
+ <timestamp>Wed Apr 15 11:22:56 2009</timestamp>
<block>
- <key>options</key>
+ <key>const_source_x</key>
<param>
<key>id</key>
- <value>top_block</value>
+ <value>const_source_x_0</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>title</key>
- <value>USRP2 Const Wave</value>
+ <key>type</key>
+ <value>complex</value>
</param>
<param>
- <key>author</key>
- <value>Example</value>
+ <key>const</key>
+ <value>ampl</value>
</param>
<param>
- <key>description</key>
- <value>Carrier with constant amplitude</value>
+ <key>_coordinate</key>
+ <value>(284, 154)</value>
</param>
<param>
- <key>window_size</key>
- <value>1280, 1024</value>
+ <key>_rotation</key>
+ <value>0</value>
</param>
+ </block>
+ <block>
+ <key>usrp2_sink_xxxx</key>
<param>
- <key>generate_options</key>
- <value>wx_gui</value>
+ <key>id</key>
+ <value>usrp2_sink_xxxx_0</value>
</param>
<param>
- <key>category</key>
- <value>Custom</value>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>interface</key>
+ <value></value>
+ </param>
+ <param>
+ <key>mac_addr</key>
+ <value></value>
+ </param>
+ <param>
+ <key>interpolation</key>
+ <value>interp</value>
+ </param>
+ <param>
+ <key>frequency</key>
+ <value>tun_freq</value>
+ </param>
+ <param>
+ <key>gain</key>
+ <value>0</value>
</param>
<param>
<key>_coordinate</key>
- <value>(10, 10)</value>
+ <value>(493, 106)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>interp</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>16</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(16, 255)</value>
</param>
<param>
<key>_rotation</key>
@@ -48,7 +98,7 @@
<key>variable_slider</key>
<param>
<key>id</key>
- <value>freq</value>
+ <value>tun_freq</value>
</param>
<param>
<key>_enabled</key>
@@ -56,19 +106,19 @@
</param>
<param>
<key>label</key>
- <value>Frequency (Hz)</value>
+ <value>USRP2 Freq (Hz)</value>
</param>
<param>
<key>value</key>
- <value>15e6</value>
+ <value>2.45e9</value>
</param>
<param>
<key>min</key>
- <value>10e6</value>
+ <value>2.4e9</value>
</param>
<param>
<key>max</key>
- <value>20e6</value>
+ <value>2.5e9</value>
</param>
<param>
<key>num_steps</key>
@@ -88,7 +138,7 @@
</param>
<param>
<key>_coordinate</key>
- <value>(12, 144)</value>
+ <value>(30, 376)</value>
</param>
<param>
<key>_rotation</key>
@@ -96,42 +146,50 @@
</param>
</block>
<block>
- <key>gr_sig_source_x</key>
+ <key>variable_slider</key>
<param>
<key>id</key>
- <value>gr_sig_source_x_0</value>
+ <value>ampl</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>type</key>
- <value>complex</value>
+ <key>label</key>
+ <value>Amplitude</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>.1</value>
</param>
<param>
- <key>samp_rate</key>
+ <key>min</key>
<value>0</value>
</param>
<param>
- <key>waveform</key>
- <value>gr.GR_CONST_WAVE</value>
+ <key>max</key>
+ <value>1</value>
</param>
<param>
- <key>freq</key>
- <value>0</value>
+ <key>num_steps</key>
+ <value>100</value>
+ </param>
+ <param>
+ <key>slider_length</key>
+ <value>200</value>
</param>
<param>
- <key>amp</key>
- <value>10e3</value>
+ <key>slider_type</key>
+ <value>horizontal</value>
</param>
<param>
- <key>offset</key>
- <value>0</value>
+ <key>grid_pos</key>
+ <value></value>
</param>
<param>
<key>_coordinate</key>
- <value>(225, 27)</value>
+ <value>(204, 376)</value>
</param>
<param>
<key>_rotation</key>
@@ -139,50 +197,46 @@
</param>
</block>
<block>
- <key>usrp2_sink_xxxx</key>
+ <key>options</key>
<param>
<key>id</key>
- <value>usrp2_sink_xxxx_0</value>
+ <value>usrp2_const_wave</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>type</key>
- <value>complex</value>
- </param>
- <param>
- <key>interface</key>
- <value></value>
+ <key>title</key>
+ <value>USRP2 Constant Wave</value>
</param>
<param>
- <key>mac_addr</key>
- <value></value>
+ <key>author</key>
+ <value>Example</value>
</param>
<param>
- <key>frequency</key>
- <value>freq</value>
+ <key>description</key>
+ <value>Tune USRP2</value>
</param>
<param>
- <key>interpolation</key>
- <value>101</value>
+ <key>window_size</key>
+ <value>1280, 1024</value>
</param>
<param>
- <key>gain</key>
- <value>0</value>
+ <key>generate_options</key>
+ <value>wx_gui</value>
</param>
<param>
- <key>auto_tr</key>
- <value></value>
+ <key>category</key>
+ <value>Custom</value>
</param>
<param>
- <key>tx_enb</key>
+ <key>realtime_scheduling</key>
<value></value>
</param>
<param>
<key>_coordinate</key>
- <value>(391, 190)</value>
+ <value>(10, 10)</value>
</param>
<param>
<key>_rotation</key>
@@ -190,7 +244,7 @@
</param>
</block>
<connection>
- <source_block_id>gr_sig_source_x_0</source_block_id>
+ <source_block_id>const_source_x_0</source_block_id>
<sink_block_id>usrp2_sink_xxxx_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
diff --git a/grc/examples/usrp/usrp2_dpsk_mod.grc b/grc/examples/usrp/usrp2_dpsk_mod.grc
new file mode 100644
index 000000000..e9f9b41ea
--- /dev/null
+++ b/grc/examples/usrp/usrp2_dpsk_mod.grc
@@ -0,0 +1,693 @@
+<?xml version='1.0' encoding='ASCII'?>
+<flow_graph>
+ <timestamp>Wed Apr 15 17:31:00 2009</timestamp>
+ <block>
+ <key>options</key>
+ <param>
+ <key>id</key>
+ <value>usrp2_dpsk_mod</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value>USRP2 DPSK Modulation</value>
+ </param>
+ <param>
+ <key>author</key>
+ <value>Example</value>
+ </param>
+ <param>
+ <key>description</key>
+ <value>Generate a DPSK signal</value>
+ </param>
+ <param>
+ <key>window_size</key>
+ <value>1280, 1024</value>
+ </param>
+ <param>
+ <key>generate_options</key>
+ <value>wx_gui</value>
+ </param>
+ <param>
+ <key>category</key>
+ <value>Custom</value>
+ </param>
+ <param>
+ <key>realtime_scheduling</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(10, 10)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>100e6/interp</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(52, 166)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>usrp2_sink_xxxx</key>
+ <param>
+ <key>id</key>
+ <value>usrp2_sink_xxxx_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>interface</key>
+ <value></value>
+ </param>
+ <param>
+ <key>mac_addr</key>
+ <value></value>
+ </param>
+ <param>
+ <key>interpolation</key>
+ <value>interp</value>
+ </param>
+ <param>
+ <key>frequency</key>
+ <value>tun_freq</value>
+ </param>
+ <param>
+ <key>gain</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(1059, 56)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>gr_multiply_const_vxx</key>
+ <param>
+ <key>id</key>
+ <value>gr_multiply_const_vxx_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>const</key>
+ <value>ampl</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(679, 58)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blks2_dxpsk_mod</key>
+ <param>
+ <key>id</key>
+ <value>blks2_dxpsk_mod_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>dqpsk</value>
+ </param>
+ <param>
+ <key>samples_per_symbol</key>
+ <value>samps_per_sym</value>
+ </param>
+ <param>
+ <key>excess_bw</key>
+ <value>0.35</value>
+ </param>
+ <param>
+ <key>gray_code</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(468, 55)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>interp</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>100</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(31, 256)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>samps_per_sym</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>8</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(126, 250)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>random_source_x</key>
+ <param>
+ <key>id</key>
+ <value>random_source_x_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>byte</value>
+ </param>
+ <param>
+ <key>min</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>max</key>
+ <value>256</value>
+ </param>
+ <param>
+ <key>num_samps</key>
+ <value>1000</value>
+ </param>
+ <param>
+ <key>repeat</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(255, 39)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable_slider</key>
+ <param>
+ <key>id</key>
+ <value>ampl</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>label</key>
+ <value>Amplitude</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>.1</value>
+ </param>
+ <param>
+ <key>min</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>max</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>num_steps</key>
+ <value>100</value>
+ </param>
+ <param>
+ <key>style</key>
+ <value>wx.SL_HORIZONTAL</value>
+ </param>
+ <param>
+ <key>converver</key>
+ <value>float_converter</value>
+ </param>
+ <param>
+ <key>grid_pos</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(246, 372)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable_slider</key>
+ <param>
+ <key>id</key>
+ <value>rx_freq_off</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>label</key>
+ <value>RX Freq Offset (Hz)</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>-20e3</value>
+ </param>
+ <param>
+ <key>min</key>
+ <value>-50e3</value>
+ </param>
+ <param>
+ <key>max</key>
+ <value>+50e3</value>
+ </param>
+ <param>
+ <key>num_steps</key>
+ <value>100</value>
+ </param>
+ <param>
+ <key>style</key>
+ <value>wx.SL_HORIZONTAL</value>
+ </param>
+ <param>
+ <key>converver</key>
+ <value>float_converter</value>
+ </param>
+ <param>
+ <key>grid_pos</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(247, 508)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable_slider</key>
+ <param>
+ <key>id</key>
+ <value>tun_freq</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>label</key>
+ <value>USRP2 Freq (Hz)</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>2.45e9</value>
+ </param>
+ <param>
+ <key>min</key>
+ <value>2.4e9</value>
+ </param>
+ <param>
+ <key>max</key>
+ <value>2.5e9</value>
+ </param>
+ <param>
+ <key>num_steps</key>
+ <value>100</value>
+ </param>
+ <param>
+ <key>style</key>
+ <value>wx.SL_HORIZONTAL</value>
+ </param>
+ <param>
+ <key>converver</key>
+ <value>float_converter</value>
+ </param>
+ <param>
+ <key>grid_pos</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(49, 341)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>wxgui_constellationsink2</key>
+ <param>
+ <key>id</key>
+ <value>wxgui_constellationsink2_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value>Constellation Plot</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>frame_rate</key>
+ <value>5</value>
+ </param>
+ <param>
+ <key>const_size</key>
+ <value>2048</value>
+ </param>
+ <param>
+ <key>M</key>
+ <value>4</value>
+ </param>
+ <param>
+ <key>theta</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alpha</key>
+ <value>0.005</value>
+ </param>
+ <param>
+ <key>fmax</key>
+ <value>0.06</value>
+ </param>
+ <param>
+ <key>mu</key>
+ <value>0.5</value>
+ </param>
+ <param>
+ <key>gain_mu</key>
+ <value>0.005</value>
+ </param>
+ <param>
+ <key>symbol_rate</key>
+ <value>samp_rate/samps_per_sym</value>
+ </param>
+ <param>
+ <key>omega_limit</key>
+ <value>0.005</value>
+ </param>
+ <param>
+ <key>grid_pos</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(920, 202)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>wxgui_fftsink2</key>
+ <param>
+ <key>id</key>
+ <value>wxgui_fftsink2_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value>FFT Plot</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>baseband_freq</key>
+ <value>tun_freq</value>
+ </param>
+ <param>
+ <key>y_per_div</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ref_level</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>fft_size</key>
+ <value>1024</value>
+ </param>
+ <param>
+ <key>fft_rate</key>
+ <value>30</value>
+ </param>
+ <param>
+ <key>peak_hold</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>average</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>avg_alpha</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>grid_pos</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(691, 155)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>wxgui_scopesink2</key>
+ <param>
+ <key>id</key>
+ <value>wxgui_scopesink2_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value>Scope Plot</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>v_scale</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>t_scale</key>
+ <value>1e-6</value>
+ </param>
+ <param>
+ <key>ac_couple</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>xy_mode</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>num_inputs</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>grid_pos</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(515, 272)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>usrp2_source_xxxx</key>
+ <param>
+ <key>id</key>
+ <value>usrp2_source_xxxx_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>interface</key>
+ <value>eth1</value>
+ </param>
+ <param>
+ <key>mac_addr</key>
+ <value></value>
+ </param>
+ <param>
+ <key>decimation</key>
+ <value>interp</value>
+ </param>
+ <param>
+ <key>frequency</key>
+ <value>tun_freq + rx_freq_off</value>
+ </param>
+ <param>
+ <key>gain</key>
+ <value>30</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(270, 200)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <connection>
+ <source_block_id>random_source_x_0</source_block_id>
+ <sink_block_id>blks2_dxpsk_mod_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blks2_dxpsk_mod_0</source_block_id>
+ <sink_block_id>gr_multiply_const_vxx_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>gr_multiply_const_vxx_0</source_block_id>
+ <sink_block_id>usrp2_sink_xxxx_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>usrp2_source_xxxx_0</source_block_id>
+ <sink_block_id>wxgui_constellationsink2_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>usrp2_source_xxxx_0</source_block_id>
+ <sink_block_id>wxgui_scopesink2_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>usrp2_source_xxxx_0</source_block_id>
+ <sink_block_id>wxgui_fftsink2_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+</flow_graph>
diff --git a/grc/examples/usrp/usrp2_fft.grc b/grc/examples/usrp/usrp2_fft.grc
index e7e93b3ff..134bd4614 100644
--- a/grc/examples/usrp/usrp2_fft.grc
+++ b/grc/examples/usrp/usrp2_fft.grc
@@ -1,11 +1,11 @@
<?xml version='1.0' encoding='ASCII'?>
<flow_graph>
- <timestamp>Fri Jan 23 11:38:11 2009</timestamp>
+ <timestamp>Wed Apr 15 17:30:20 2009</timestamp>
<block>
<key>options</key>
<param>
<key>id</key>
- <value>top_block</value>
+ <value>usrp2_fft</value>
</param>
<param>
<key>_enabled</key>
@@ -13,7 +13,7 @@
</param>
<param>
<key>title</key>
- <value>USRP2 FFT</value>
+ <value>USRP2 FFT Plotter</value>
</param>
<param>
<key>author</key>
@@ -21,7 +21,7 @@
</param>
<param>
<key>description</key>
- <value>FFT of Spectrum</value>
+ <value>FFT waveform plot</value>
</param>
<param>
<key>window_size</key>
@@ -36,6 +36,10 @@
<value>Custom</value>
</param>
<param>
+ <key>realtime_scheduling</key>
+ <value></value>
+ </param>
+ <param>
<key>_coordinate</key>
<value>(10, 10)</value>
</param>
@@ -48,6 +52,29 @@
<key>variable</key>
<param>
<key>id</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>100e6/decim</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(10, 170)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
<value>decim</value>
</param>
<param>
@@ -56,11 +83,11 @@
</param>
<param>
<key>value</key>
- <value>4</value>
+ <value>16</value>
</param>
<param>
<key>_coordinate</key>
- <value>(35, 149)</value>
+ <value>(24, 267)</value>
</param>
<param>
<key>_rotation</key>
@@ -68,50 +95,50 @@
</param>
</block>
<block>
- <key>usrp2_source_xxxx</key>
+ <key>variable_slider</key>
<param>
<key>id</key>
- <value>usrp2_source_xxxx_0</value>
+ <value>tun_freq</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>type</key>
- <value>complex</value>
+ <key>label</key>
+ <value>USRP2 Freq (Hz)</value>
</param>
<param>
- <key>interface</key>
- <value></value>
+ <key>value</key>
+ <value>2.45e9</value>
</param>
<param>
- <key>mac_addr</key>
- <value></value>
+ <key>min</key>
+ <value>2.4e9</value>
</param>
<param>
- <key>frequency</key>
- <value>freq</value>
+ <key>max</key>
+ <value>2.5e9</value>
</param>
<param>
- <key>decimation</key>
- <value>decim</value>
+ <key>num_steps</key>
+ <value>100</value>
</param>
<param>
- <key>gain</key>
- <value>0</value>
+ <key>style</key>
+ <value>wx.SL_HORIZONTAL</value>
</param>
<param>
- <key>auto_tr</key>
- <value></value>
+ <key>converver</key>
+ <value>float_converter</value>
</param>
<param>
- <key>rx_ant</key>
+ <key>grid_pos</key>
<value></value>
</param>
<param>
<key>_coordinate</key>
- <value>(177, 271)</value>
+ <value>(32, 365)</value>
</param>
<param>
<key>_rotation</key>
@@ -138,23 +165,19 @@
</param>
<param>
<key>samp_rate</key>
- <value>100e6/decim</value>
+ <value>samp_rate</value>
</param>
<param>
<key>baseband_freq</key>
- <value>freq</value>
+ <value>tun_freq</value>
</param>
<param>
<key>y_per_div</key>
<value>10</value>
</param>
<param>
- <key>y_divs</key>
- <value>12</value>
- </param>
- <param>
<key>ref_level</key>
- <value>20</value>
+ <value>10</value>
</param>
<param>
<key>fft_size</key>
@@ -165,16 +188,16 @@
<value>30</value>
</param>
<param>
- <key>avg_alpha</key>
- <value>0</value>
+ <key>peak_hold</key>
+ <value>False</value>
</param>
<param>
<key>average</key>
<value>False</value>
</param>
<param>
- <key>peak_hold</key>
- <value>False</value>
+ <key>avg_alpha</key>
+ <value>0</value>
</param>
<param>
<key>grid_pos</key>
@@ -182,7 +205,7 @@
</param>
<param>
<key>_coordinate</key>
- <value>(384, 72)</value>
+ <value>(466, 100)</value>
</param>
<param>
<key>_rotation</key>
@@ -190,50 +213,42 @@
</param>
</block>
<block>
- <key>variable_slider</key>
+ <key>usrp2_source_xxxx</key>
<param>
<key>id</key>
- <value>freq</value>
+ <value>usrp2_source_xxxx_0</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>label</key>
- <value>Frequency (Hz)</value>
- </param>
- <param>
- <key>value</key>
- <value>0</value>
- </param>
- <param>
- <key>min</key>
- <value>-100e6</value>
+ <key>type</key>
+ <value>complex</value>
</param>
<param>
- <key>max</key>
- <value>100e6</value>
+ <key>interface</key>
+ <value></value>
</param>
<param>
- <key>num_steps</key>
- <value>100</value>
+ <key>mac_addr</key>
+ <value></value>
</param>
<param>
- <key>slider_length</key>
- <value>200</value>
+ <key>decimation</key>
+ <value>decim</value>
</param>
<param>
- <key>slider_type</key>
- <value>horizontal</value>
+ <key>frequency</key>
+ <value>tun_freq</value>
</param>
<param>
- <key>grid_pos</key>
- <value></value>
+ <key>gain</key>
+ <value>0</value>
</param>
<param>
<key>_coordinate</key>
- <value>(139, 129)</value>
+ <value>(211, 200)</value>
</param>
<param>
<key>_rotation</key>
diff --git a/grc/examples/usrp/usrp_two_tone_loopback.grc b/grc/examples/usrp/usrp_two_tone_loopback.grc
index e3c635d46..3df977044 100644
--- a/grc/examples/usrp/usrp_two_tone_loopback.grc
+++ b/grc/examples/usrp/usrp_two_tone_loopback.grc
@@ -1,43 +1,46 @@
<?xml version='1.0' encoding='ASCII'?>
<flow_graph>
- <timestamp>Mon Sep 8 21:47:19 2008</timestamp>
+ <timestamp>Fri Apr 17 18:23:35 2009</timestamp>
<block>
- <key>options</key>
+ <key>variable</key>
<param>
<key>id</key>
- <value>top_block</value>
+ <value>samp_rate</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>title</key>
- <value>USRP Loopback - 2 Tone</value>
+ <key>value</key>
+ <value>64e6/200</value>
</param>
<param>
- <key>author</key>
- <value>Example</value>
+ <key>_coordinate</key>
+ <value>(9, 166)</value>
</param>
<param>
- <key>description</key>
- <value>Loopback test with basic rx and basic tx</value>
+ <key>_rotation</key>
+ <value>0</value>
</param>
+ </block>
+ <block>
+ <key>variable</key>
<param>
- <key>window_size</key>
- <value>1280, 1024</value>
+ <key>id</key>
+ <value>tun_freq</value>
</param>
<param>
- <key>generate_options</key>
- <value>wx_gui</value>
+ <key>_enabled</key>
+ <value>True</value>
</param>
<param>
- <key>category</key>
- <value>Custom</value>
+ <key>value</key>
+ <value>int(100e6)</value>
</param>
<param>
<key>_coordinate</key>
- <value>(10, 10)</value>
+ <value>(116, 166)</value>
</param>
<param>
<key>_rotation</key>
@@ -45,10 +48,10 @@
</param>
</block>
<block>
- <key>usrp_simple_source_x</key>
+ <key>gr_sig_source_x</key>
<param>
<key>id</key>
- <value>usrp_simple_source_x</value>
+ <value>gr_sig_source_x</value>
</param>
<param>
<key>_enabled</key>
@@ -59,40 +62,28 @@
<value>complex</value>
</param>
<param>
- <key>number</key>
- <value>0</value>
- </param>
- <param>
- <key>subdev_spec</key>
- <value>None</value>
- </param>
- <param>
- <key>frequency</key>
- <value>tun_freq</value>
- </param>
- <param>
- <key>decimation</key>
- <value>200</value>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
</param>
<param>
- <key>gain</key>
- <value>20</value>
+ <key>waveform</key>
+ <value>gr.GR_COS_WAVE</value>
</param>
<param>
- <key>mux</key>
- <value>0x0</value>
+ <key>freq</key>
+ <value>tone1</value>
</param>
<param>
- <key>auto_tr</key>
- <value>None</value>
+ <key>amp</key>
+ <value>tone_ampl</value>
</param>
<param>
- <key>rx_ant</key>
- <value>None</value>
+ <key>offset</key>
+ <value>0</value>
</param>
<param>
<key>_coordinate</key>
- <value>(578, 319)</value>
+ <value>(258, 20)</value>
</param>
<param>
<key>_rotation</key>
@@ -100,10 +91,10 @@
</param>
</block>
<block>
- <key>wxgui_fftsink2</key>
+ <key>gr_sig_source_x</key>
<param>
<key>id</key>
- <value>wxgui_fftsink2</value>
+ <value>gr_sig_source_x0</value>
</param>
<param>
<key>_enabled</key>
@@ -114,56 +105,59 @@
<value>complex</value>
</param>
<param>
- <key>title</key>
- <value>FFT Plot</value>
- </param>
- <param>
<key>samp_rate</key>
<value>samp_rate</value>
</param>
<param>
- <key>baseband_freq</key>
- <value>0</value>
+ <key>waveform</key>
+ <value>gr.GR_COS_WAVE</value>
</param>
<param>
- <key>y_per_div</key>
- <value>10</value>
+ <key>freq</key>
+ <value>tone2</value>
</param>
<param>
- <key>y_divs</key>
- <value>8</value>
+ <key>amp</key>
+ <value>tone_ampl</value>
</param>
<param>
- <key>ref_level</key>
- <value>100</value>
+ <key>offset</key>
+ <value>0</value>
</param>
<param>
- <key>fft_size</key>
- <value>512*2</value>
+ <key>_coordinate</key>
+ <value>(255, 179)</value>
</param>
<param>
- <key>fft_rate</key>
- <value>15</value>
+ <key>_rotation</key>
+ <value>0</value>
</param>
+ </block>
+ <block>
+ <key>gr_add_xx</key>
<param>
- <key>avg_alpha</key>
- <value>0</value>
+ <key>id</key>
+ <value>gr_add_xx</value>
</param>
<param>
- <key>average</key>
- <value>False</value>
+ <key>_enabled</key>
+ <value>True</value>
</param>
<param>
- <key>peak_hold</key>
- <value>False</value>
+ <key>type</key>
+ <value>complex</value>
</param>
<param>
- <key>grid_pos</key>
- <value>1, 2, 2, 4</value>
+ <key>num_inputs</key>
+ <value>3</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
</param>
<param>
<key>_coordinate</key>
- <value>(845, 228)</value>
+ <value>(528, 78)</value>
</param>
<param>
<key>_rotation</key>
@@ -171,10 +165,10 @@
</param>
</block>
<block>
- <key>variable_slider</key>
+ <key>parameter</key>
<param>
<key>id</key>
- <value>tone2</value>
+ <value>tx_side</value>
</param>
<param>
<key>_enabled</key>
@@ -182,35 +176,19 @@
</param>
<param>
<key>label</key>
- <value>Tone 2</value>
+ <value></value>
</param>
<param>
<key>value</key>
- <value>75e3</value>
+ <value>A</value>
</param>
<param>
- <key>min</key>
- <value>0</value>
- </param>
- <param>
- <key>max</key>
- <value>150000</value>
- </param>
- <param>
- <key>num_steps</key>
- <value>100</value>
- </param>
- <param>
- <key>slider_type</key>
- <value>horizontal</value>
- </param>
- <param>
- <key>grid_pos</key>
- <value>0, 4, 1, 2</value>
+ <key>type</key>
+ <value>string</value>
</param>
<param>
<key>_coordinate</key>
- <value>(397, 478)</value>
+ <value>(688, 384)</value>
</param>
<param>
<key>_rotation</key>
@@ -218,46 +196,50 @@
</param>
</block>
<block>
- <key>variable_slider</key>
+ <key>usrp_simple_sink_x</key>
<param>
<key>id</key>
- <value>tone1</value>
+ <value>usrp_simple_sink_x</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>label</key>
- <value>Tone 1</value>
+ <key>type</key>
+ <value>complex</value>
</param>
<param>
- <key>value</key>
- <value>50e3</value>
+ <key>format</key>
+ <value></value>
</param>
<param>
- <key>min</key>
+ <key>which</key>
<value>0</value>
</param>
<param>
- <key>max</key>
- <value>150000</value>
+ <key>interpolation</key>
+ <value>400</value>
</param>
<param>
- <key>num_steps</key>
- <value>100</value>
+ <key>frequency</key>
+ <value>tun_freq</value>
</param>
<param>
- <key>slider_type</key>
- <value>horizontal</value>
+ <key>gain</key>
+ <value>0</value>
</param>
<param>
- <key>grid_pos</key>
- <value>0, 2, 1, 2</value>
+ <key>side</key>
+ <value>tx_side</value>
+ </param>
+ <param>
+ <key>transmit</key>
+ <value></value>
</param>
<param>
<key>_coordinate</key>
- <value>(220, 475)</value>
+ <value>(835, 5)</value>
</param>
<param>
<key>_rotation</key>
@@ -265,46 +247,54 @@
</param>
</block>
<block>
- <key>variable_slider</key>
+ <key>usrp_simple_source_x</key>
<param>
<key>id</key>
- <value>noise_ampl</value>
+ <value>usrp_simple_source_x</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>label</key>
- <value>Noise Ampl</value>
+ <key>type</key>
+ <value>complex</value>
</param>
<param>
- <key>value</key>
- <value>2000</value>
+ <key>format</key>
+ <value></value>
</param>
<param>
- <key>min</key>
+ <key>which</key>
<value>0</value>
</param>
<param>
- <key>max</key>
- <value>5000</value>
+ <key>decimation</key>
+ <value>200</value>
</param>
<param>
- <key>num_steps</key>
- <value>100</value>
+ <key>frequency</key>
+ <value>tun_freq</value>
</param>
<param>
- <key>slider_type</key>
- <value>vertical</value>
+ <key>gain</key>
+ <value>20</value>
</param>
<param>
- <key>grid_pos</key>
- <value>1, 1, 2, 1</value>
+ <key>side</key>
+ <value>rx_side</value>
+ </param>
+ <param>
+ <key>rx_ant</key>
+ <value>rx_ant</value>
+ </param>
+ <param>
+ <key>hb_filters</key>
+ <value></value>
</param>
<param>
<key>_coordinate</key>
- <value>(20, 243)</value>
+ <value>(479, 224)</value>
</param>
<param>
<key>_rotation</key>
@@ -312,22 +302,30 @@
</param>
</block>
<block>
- <key>variable</key>
+ <key>parameter</key>
<param>
<key>id</key>
- <value>samp_rate</value>
+ <value>rx_ant</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
+ <key>label</key>
+ <value></value>
+ </param>
+ <param>
<key>value</key>
- <value>64e6/200</value>
+ <value>RXA</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>string</value>
</param>
<param>
<key>_coordinate</key>
- <value>(9, 166)</value>
+ <value>(802, 384)</value>
</param>
<param>
<key>_rotation</key>
@@ -335,65 +333,66 @@
</param>
</block>
<block>
- <key>variable</key>
+ <key>wxgui_fftsink2</key>
<param>
<key>id</key>
- <value>tun_freq</value>
+ <value>wxgui_fftsink2</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>value</key>
- <value>int(100e6)</value>
+ <key>type</key>
+ <value>complex</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(116, 166)</value>
+ <key>title</key>
+ <value>FFT Plot</value>
</param>
<param>
- <key>_rotation</key>
- <value>0</value>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
</param>
- </block>
- <block>
- <key>gr_sig_source_x</key>
<param>
- <key>id</key>
- <value>gr_sig_source_x</value>
+ <key>baseband_freq</key>
+ <value>0</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>y_per_div</key>
+ <value>10</value>
</param>
<param>
- <key>type</key>
- <value>complex</value>
+ <key>ref_level</key>
+ <value>100</value>
</param>
<param>
- <key>samp_rate</key>
- <value>samp_rate</value>
+ <key>fft_size</key>
+ <value>512*2</value>
</param>
<param>
- <key>waveform</key>
- <value>gr.GR_COS_WAVE</value>
+ <key>fft_rate</key>
+ <value>15</value>
</param>
<param>
- <key>freq</key>
- <value>tone1</value>
+ <key>peak_hold</key>
+ <value>False</value>
</param>
<param>
- <key>amp</key>
- <value>tone_ampl</value>
+ <key>average</key>
+ <value>False</value>
</param>
<param>
- <key>offset</key>
+ <key>avg_alpha</key>
<value>0</value>
</param>
<param>
+ <key>grid_pos</key>
+ <value>1, 2, 2, 4</value>
+ </param>
+ <param>
<key>_coordinate</key>
- <value>(258, 20)</value>
+ <value>(746, 133)</value>
</param>
<param>
<key>_rotation</key>
@@ -401,42 +400,30 @@
</param>
</block>
<block>
- <key>gr_sig_source_x</key>
+ <key>parameter</key>
<param>
<key>id</key>
- <value>gr_sig_source_x0</value>
+ <value>rx_side</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>type</key>
- <value>complex</value>
- </param>
- <param>
- <key>samp_rate</key>
- <value>samp_rate</value>
- </param>
- <param>
- <key>waveform</key>
- <value>gr.GR_COS_WAVE</value>
- </param>
- <param>
- <key>freq</key>
- <value>tone2</value>
+ <key>label</key>
+ <value></value>
</param>
<param>
- <key>amp</key>
- <value>tone_ampl</value>
+ <key>value</key>
+ <value>A</value>
</param>
<param>
- <key>offset</key>
- <value>0</value>
+ <key>type</key>
+ <value>string</value>
</param>
<param>
<key>_coordinate</key>
- <value>(255, 179)</value>
+ <value>(568, 382)</value>
</param>
<param>
<key>_rotation</key>
@@ -471,7 +458,7 @@
</param>
<param>
<key>_coordinate</key>
- <value>(257, 337)</value>
+ <value>(276, 312)</value>
</param>
<param>
<key>_rotation</key>
@@ -479,30 +466,50 @@
</param>
</block>
<block>
- <key>gr_add_xx</key>
+ <key>variable_slider</key>
<param>
<key>id</key>
- <value>gr_add_xx</value>
+ <value>noise_ampl</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>type</key>
- <value>complex</value>
+ <key>label</key>
+ <value>Noise Ampl</value>
</param>
<param>
- <key>num_inputs</key>
- <value>3</value>
+ <key>value</key>
+ <value>2000</value>
</param>
<param>
- <key>vlen</key>
- <value>1</value>
+ <key>min</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>max</key>
+ <value>5000</value>
+ </param>
+ <param>
+ <key>num_steps</key>
+ <value>100</value>
+ </param>
+ <param>
+ <key>style</key>
+ <value>wx.SL_VERTICAL</value>
+ </param>
+ <param>
+ <key>converver</key>
+ <value>float_converter</value>
+ </param>
+ <param>
+ <key>grid_pos</key>
+ <value>1, 1, 2, 1</value>
</param>
<param>
<key>_coordinate</key>
- <value>(528, 78)</value>
+ <value>(20, 243)</value>
</param>
<param>
<key>_rotation</key>
@@ -510,54 +517,101 @@
</param>
</block>
<block>
- <key>usrp_simple_sink_x</key>
+ <key>variable_slider</key>
<param>
<key>id</key>
- <value>usrp_simple_sink_x</value>
+ <value>tone_ampl</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>type</key>
- <value>complex</value>
+ <key>label</key>
+ <value>Tone Ampl</value>
</param>
<param>
- <key>number</key>
+ <key>value</key>
+ <value>5000</value>
+ </param>
+ <param>
+ <key>min</key>
<value>0</value>
</param>
<param>
- <key>subdev_spec</key>
- <value>None</value>
+ <key>max</key>
+ <value>10e3</value>
</param>
<param>
- <key>frequency</key>
- <value>tun_freq</value>
+ <key>num_steps</key>
+ <value>100</value>
</param>
<param>
- <key>interpolation</key>
- <value>400</value>
+ <key>style</key>
+ <value>wx.SL_VERTICAL</value>
</param>
<param>
- <key>gain</key>
+ <key>converver</key>
+ <value>float_converter</value>
+ </param>
+ <param>
+ <key>grid_pos</key>
+ <value>1, 0, 2, 1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(28, 437)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
<value>0</value>
</param>
+ </block>
+ <block>
+ <key>variable_slider</key>
<param>
- <key>mux</key>
- <value>0x0</value>
+ <key>id</key>
+ <value>tone1</value>
</param>
<param>
- <key>auto_tr</key>
- <value>None</value>
+ <key>_enabled</key>
+ <value>True</value>
</param>
<param>
- <key>tx_enb</key>
- <value>None</value>
+ <key>label</key>
+ <value>Tone 1</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>50e3</value>
+ </param>
+ <param>
+ <key>min</key>
+ <value>-samp_rate/2</value>
+ </param>
+ <param>
+ <key>max</key>
+ <value>samp_rate/2</value>
+ </param>
+ <param>
+ <key>num_steps</key>
+ <value>100</value>
+ </param>
+ <param>
+ <key>style</key>
+ <value>wx.SL_HORIZONTAL</value>
+ </param>
+ <param>
+ <key>converver</key>
+ <value>float_converter</value>
+ </param>
+ <param>
+ <key>grid_pos</key>
+ <value>0, 0, 1, 4</value>
</param>
<param>
<key>_coordinate</key>
- <value>(835, 5)</value>
+ <value>(190, 436)</value>
</param>
<param>
<key>_rotation</key>
@@ -568,7 +622,7 @@
<key>variable_slider</key>
<param>
<key>id</key>
- <value>tone_ampl</value>
+ <value>tone2</value>
</param>
<param>
<key>_enabled</key>
@@ -576,11 +630,11 @@
</param>
<param>
<key>label</key>
- <value>Tone Ampl</value>
+ <value>Tone 2</value>
</param>
<param>
<key>value</key>
- <value>5000</value>
+ <value>75e3</value>
</param>
<param>
<key>min</key>
@@ -595,16 +649,67 @@
<value>100</value>
</param>
<param>
- <key>slider_type</key>
- <value>vertical</value>
+ <key>style</key>
+ <value>wx.SL_HORIZONTAL</value>
+ </param>
+ <param>
+ <key>converver</key>
+ <value>float_converter</value>
</param>
<param>
<key>grid_pos</key>
- <value>1, 0, 2, 1</value>
+ <value>0, 4, 1, 4</value>
</param>
<param>
<key>_coordinate</key>
- <value>(21, 422)</value>
+ <value>(367, 439)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>options</key>
+ <param>
+ <key>id</key>
+ <value>usrp_two_tone_loopback</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value>USRP Loopback - 2 Tone</value>
+ </param>
+ <param>
+ <key>author</key>
+ <value>Example</value>
+ </param>
+ <param>
+ <key>description</key>
+ <value>Loopback test with basic rx and basic tx</value>
+ </param>
+ <param>
+ <key>window_size</key>
+ <value>1280, 1024</value>
+ </param>
+ <param>
+ <key>generate_options</key>
+ <value>wx_gui</value>
+ </param>
+ <param>
+ <key>category</key>
+ <value>Custom</value>
+ </param>
+ <param>
+ <key>realtime_scheduling</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(10, 10)</value>
</param>
<param>
<key>_rotation</key>
diff --git a/grc/examples/usrp/usrp_wbfm_receive.grc b/grc/examples/usrp/usrp_wbfm_receive.grc
index 7fb621241..8f53475ab 100644
--- a/grc/examples/usrp/usrp_wbfm_receive.grc
+++ b/grc/examples/usrp/usrp_wbfm_receive.grc
@@ -1,11 +1,11 @@
<?xml version='1.0' encoding='ASCII'?>
<flow_graph>
- <timestamp>Thu Jul 24 14:27:45 2008</timestamp>
+ <timestamp>Fri Apr 17 19:06:07 2009</timestamp>
<block>
<key>options</key>
<param>
<key>id</key>
- <value>top_block</value>
+ <value>usrp_wbfm_receive</value>
</param>
<param>
<key>_enabled</key>
@@ -36,6 +36,10 @@
<value>Custom</value>
</param>
<param>
+ <key>realtime_scheduling</key>
+ <value></value>
+ </param>
+ <param>
<key>_coordinate</key>
<value>(10, 10)</value>
</param>
@@ -45,54 +49,22 @@
</param>
</block>
<block>
- <key>usrp_simple_source_x</key>
+ <key>variable</key>
<param>
<key>id</key>
- <value>usrp_simple_source_x</value>
+ <value>decim</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>type</key>
- <value>complex</value>
- </param>
- <param>
- <key>number</key>
- <value>0</value>
- </param>
- <param>
- <key>subdev_spec</key>
- <value>None</value>
- </param>
- <param>
- <key>frequency</key>
- <value>(freq+fine)*1e6</value>
- </param>
- <param>
- <key>decimation</key>
- <value>decim</value>
- </param>
- <param>
- <key>gain</key>
- <value>20</value>
- </param>
- <param>
- <key>mux</key>
- <value>0x0</value>
- </param>
- <param>
- <key>auto_tr</key>
- <value>None</value>
- </param>
- <param>
- <key>rx_ant</key>
- <value>None</value>
+ <key>value</key>
+ <value>200</value>
</param>
<param>
<key>_coordinate</key>
- <value>(277, 29)</value>
+ <value>(14, 173)</value>
</param>
<param>
<key>_rotation</key>
@@ -103,7 +75,7 @@
<key>variable_slider</key>
<param>
<key>id</key>
- <value>fine</value>
+ <value>volume</value>
</param>
<param>
<key>_enabled</key>
@@ -111,62 +83,39 @@
</param>
<param>
<key>label</key>
- <value>Fine Freq</value>
+ <value>Volume</value>
</param>
<param>
<key>value</key>
- <value>0</value>
+ <value>1</value>
</param>
<param>
<key>min</key>
- <value>-.1</value>
+ <value>0</value>
</param>
<param>
<key>max</key>
- <value>.1</value>
+ <value>10</value>
</param>
<param>
<key>num_steps</key>
<value>100</value>
</param>
<param>
- <key>slider_type</key>
- <value>horizontal</value>
- </param>
- <param>
- <key>grid_pos</key>
- <value>0, 2, 1, 2</value>
+ <key>style</key>
+ <value>wx.SL_HORIZONTAL</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(275, 246)</value>
+ <key>converver</key>
+ <value>float_converter</value>
</param>
<param>
- <key>_rotation</key>
- <value>0</value>
- </param>
- </block>
- <block>
- <key>blks2_wfm_rcv</key>
- <param>
- <key>id</key>
- <value>blks2_wfm_rcv</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
- </param>
- <param>
- <key>quad_rate</key>
- <value>64e6/decim</value>
- </param>
- <param>
- <key>audio_decimation</key>
- <value>10</value>
+ <key>grid_pos</key>
+ <value>1, 0, 1, 4</value>
</param>
<param>
<key>_coordinate</key>
- <value>(510, 37)</value>
+ <value>(991, 40)</value>
</param>
<param>
<key>_rotation</key>
@@ -174,65 +123,54 @@
</param>
</block>
<block>
- <key>audio_sink</key>
+ <key>usrp_simple_source_x</key>
<param>
<key>id</key>
- <value>audio_sink</value>
+ <value>usrp_simple_source_x</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>samp_rate</key>
- <value>32000</value>
- </param>
- <param>
- <key>device_name</key>
- <value/>
+ <key>type</key>
+ <value>complex</value>
</param>
<param>
- <key>ok_to_block</key>
- <value>True</value>
+ <key>format</key>
+ <value></value>
</param>
<param>
- <key>num_inputs</key>
- <value>1</value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(703, 241)</value>
+ <key>which</key>
+ <value>0</value>
</param>
<param>
- <key>_rotation</key>
- <value>180</value>
+ <key>decimation</key>
+ <value>decim</value>
</param>
- </block>
- <block>
- <key>gr_multiply_const_vxx</key>
<param>
- <key>id</key>
- <value>gr_multiply_const_vxx</value>
+ <key>frequency</key>
+ <value>(freq+fine)*1e6</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>gain</key>
+ <value>20</value>
</param>
<param>
- <key>type</key>
- <value>float</value>
+ <key>side</key>
+ <value>A</value>
</param>
<param>
- <key>const</key>
- <value>volume</value>
+ <key>rx_ant</key>
+ <value>None</value>
</param>
<param>
- <key>vlen</key>
- <value>1</value>
+ <key>hb_filters</key>
+ <value></value>
</param>
<param>
<key>_coordinate</key>
- <value>(764, 55)</value>
+ <value>(277, 29)</value>
</param>
<param>
<key>_rotation</key>
@@ -263,17 +201,13 @@
</param>
<param>
<key>baseband_freq</key>
- <value>0</value>
+ <value>(freq+fine)*1e6</value>
</param>
<param>
<key>y_per_div</key>
<value>10</value>
</param>
<param>
- <key>y_divs</key>
- <value>8</value>
- </param>
- <param>
<key>ref_level</key>
<value>50</value>
</param>
@@ -286,16 +220,16 @@
<value>15</value>
</param>
<param>
- <key>avg_alpha</key>
- <value>0</value>
+ <key>peak_hold</key>
+ <value>False</value>
</param>
<param>
<key>average</key>
<value>False</value>
</param>
<param>
- <key>peak_hold</key>
- <value>False</value>
+ <key>avg_alpha</key>
+ <value>0</value>
</param>
<param>
<key>grid_pos</key>
@@ -314,7 +248,7 @@
<key>variable_slider</key>
<param>
<key>id</key>
- <value>volume</value>
+ <value>freq</value>
</param>
<param>
<key>_enabled</key>
@@ -322,35 +256,39 @@
</param>
<param>
<key>label</key>
- <value>Volume</value>
+ <value>Frequency (MHz)</value>
</param>
<param>
<key>value</key>
- <value>1</value>
+ <value>100</value>
</param>
<param>
<key>min</key>
- <value>0</value>
+ <value>87.5</value>
</param>
<param>
<key>max</key>
- <value>10</value>
+ <value>108.0</value>
</param>
<param>
<key>num_steps</key>
- <value>100</value>
+ <value>1000</value>
</param>
<param>
- <key>slider_type</key>
- <value>horizontal</value>
+ <key>style</key>
+ <value>wx.SL_HORIZONTAL</value>
+ </param>
+ <param>
+ <key>converver</key>
+ <value>float_converter</value>
</param>
<param>
<key>grid_pos</key>
- <value>1, 1, 1, 2</value>
+ <value>0, 0, 1, 2</value>
</param>
<param>
<key>_coordinate</key>
- <value>(991, 40)</value>
+ <value>(104, 243)</value>
</param>
<param>
<key>_rotation</key>
@@ -361,7 +299,7 @@
<key>variable_slider</key>
<param>
<key>id</key>
- <value>freq</value>
+ <value>fine</value>
</param>
<param>
<key>_enabled</key>
@@ -369,35 +307,39 @@
</param>
<param>
<key>label</key>
- <value>Frequency</value>
+ <value>Fine Freq (MHz)</value>
</param>
<param>
<key>value</key>
- <value>100</value>
+ <value>0</value>
</param>
<param>
<key>min</key>
- <value>87.5</value>
+ <value>-.1</value>
</param>
<param>
<key>max</key>
- <value>108.0</value>
+ <value>.1</value>
</param>
<param>
<key>num_steps</key>
- <value>1000</value>
+ <value>100</value>
+ </param>
+ <param>
+ <key>style</key>
+ <value>wx.SL_HORIZONTAL</value>
</param>
<param>
- <key>slider_type</key>
- <value>horizontal</value>
+ <key>converver</key>
+ <value>float_converter</value>
</param>
<param>
<key>grid_pos</key>
- <value>0, 0, 1, 2</value>
+ <value>0, 2, 1, 2</value>
</param>
<param>
<key>_coordinate</key>
- <value>(104, 243)</value>
+ <value>(275, 246)</value>
</param>
<param>
<key>_rotation</key>
@@ -405,28 +347,98 @@
</param>
</block>
<block>
- <key>variable</key>
+ <key>blks2_wfm_rcv</key>
<param>
<key>id</key>
- <value>decim</value>
+ <value>blks2_wfm_rcv</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>value</key>
- <value>200</value>
+ <key>quad_rate</key>
+ <value>64e6/decim</value>
+ </param>
+ <param>
+ <key>audio_decimation</key>
+ <value>10</value>
</param>
<param>
<key>_coordinate</key>
- <value>(14, 173)</value>
+ <value>(510, 37)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
</block>
+ <block>
+ <key>gr_multiply_const_vxx</key>
+ <param>
+ <key>id</key>
+ <value>gr_multiply_const_vxx</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>const</key>
+ <value>volume</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(764, 55)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>audio_sink</key>
+ <param>
+ <key>id</key>
+ <value>audio_sink</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>32000</value>
+ </param>
+ <param>
+ <key>device_name</key>
+ <value></value>
+ </param>
+ <param>
+ <key>ok_to_block</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>num_inputs</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(703, 241)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>180</value>
+ </param>
+ </block>
<connection>
<source_block_id>usrp_simple_source_x</source_block_id>
<sink_block_id>blks2_wfm_rcv</sink_block_id>
@@ -451,4 +463,4 @@
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
-</flow_graph> \ No newline at end of file
+</flow_graph>
diff --git a/grc/examples/xmlrpc/Makefile.am b/grc/examples/xmlrpc/Makefile.am
deleted file mode 100644
index cfe04a547..000000000
--- a/grc/examples/xmlrpc/Makefile.am
+++ /dev/null
@@ -1,30 +0,0 @@
-#
-# Copyright 2008 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.
-#
-
-include $(top_srcdir)/grc/Makefile.inc
-
-ourdatadir = $(grc_examples_prefix)/xmlrpc
-
-dist_ourdata_DATA = \
- readme.txt \
- xmlrpc_client.grc \
- xmlrpc_client_script.py\
- xmlrpc_server.grc
diff --git a/grc/scripts/grc b/grc/scripts/grc
index e74d98616..70c7ad1ad 100755
--- a/grc/scripts/grc
+++ b/grc/scripts/grc
@@ -22,6 +22,14 @@ import pygtk
pygtk.require('2.0')
import gtk
+try: import gnuradio
+except ImportError, e:
+ d = gtk.MessageDialog(type=gtk.MESSAGE_ERROR, buttons=gtk.BUTTONS_CLOSE, message_format="""
+Cannot find module gnuradio. Is your PYTHONPATH set correctly?""")
+ d.set_title(e.message)
+ d.run()
+ exit(-1)
+
from gnuradio.grc.platforms.base.Constants import VERSION
from optparse import OptionParser
diff --git a/grc/src/grc_gnuradio/wxgui/Makefile.am b/grc/src/grc_gnuradio/wxgui/Makefile.am
index 6f731f2cb..b82ca4c90 100644
--- a/grc/src/grc_gnuradio/wxgui/Makefile.am
+++ b/grc/src/grc_gnuradio/wxgui/Makefile.am
@@ -22,8 +22,12 @@
include $(top_srcdir)/grc/Makefile.inc
ourpythondir = $(grc_gnuradio_prefix)/wxgui
-
ourpython_PYTHON = \
__init__.py \
- callback_controls.py \
top_block_gui.py
+
+oursubpythondir = $(grc_gnuradio_prefix)/wxgui/forms
+oursubpython_PYTHON = \
+ forms/__init__.py \
+ forms/converters.py \
+ forms/forms.py
diff --git a/grc/src/grc_gnuradio/wxgui/__init__.py b/grc/src/grc_gnuradio/wxgui/__init__.py
index 0b13ead9e..94a0adb8a 100644
--- a/grc/src/grc_gnuradio/wxgui/__init__.py
+++ b/grc/src/grc_gnuradio/wxgui/__init__.py
@@ -18,12 +18,4 @@
# Boston, MA 02110-1301, USA.
#
-from callback_controls import \
- button_control, \
- drop_down_control, \
- radio_buttons_horizontal_control, \
- radio_buttons_vertical_control, \
- slider_horizontal_control, \
- slider_vertical_control, \
- text_box_control
from top_block_gui import top_block_gui
diff --git a/grc/src/grc_gnuradio/wxgui/callback_controls.py b/grc/src/grc_gnuradio/wxgui/callback_controls.py
deleted file mode 100644
index 32e5d8842..000000000
--- a/grc/src/grc_gnuradio/wxgui/callback_controls.py
+++ /dev/null
@@ -1,303 +0,0 @@
-# Copyright 2008 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
-import sys
-from gnuradio import eng_notation
-
-class LabelText(wx.StaticText):
- """Label text class for uniform labels among all controls."""
-
- def __init__(self, window, label):
- wx.StaticText.__init__(self, window, label=str(label))
- font = self.GetFont()
- font.SetWeight(wx.FONTWEIGHT_BOLD)
- self.SetFont(font)
-
-class _control_base(wx.BoxSizer):
- """Control base class"""
-
- def __init__(self, window, callback):
- self.window = window
- self.callback = callback
- wx.BoxSizer.__init__(self, wx.VERTICAL)
-
- def get_window(self): return self.window
-
- def call(self): return self.callback(self.get_value())
-
- def get_value(self): raise NotImplementedError
-
- def set_value(self): raise NotImplementedError
-
-class _chooser_control_base(_control_base):
- """House a drop down or radio buttons for variable control."""
-
- def __init__(self, window, callback, label='Label', index=0, choices=[0], labels=[]):
- """
- Chooser contructor.
- Create the slider, text box, and label.
- @param window the wx parent window
- @param callback call the callback on changes
- @param label the label title
- @param index the default choice index
- @param choices a list of choices
- @param labels the choice labels or empty list
- """
- #initialize
- _control_base.__init__(self, window, callback)
- label_text = LabelText(self.get_window(), label)
- self.Add(label_text, 0, wx.ALIGN_CENTER)
- self.index = index
- self.choices = choices
- self.labels = map(str, labels or choices)
- self._init()
-
- def _handle_changed(self, event=None):
- """
- A change is detected. Call the callback.
- """
- try: self.call()
- except Exception, e: print >> sys.stderr, 'Error in exec callback from handle changed.\n', e
-
- def get_value(self):
- """
- Update the chooser.
- @return one of the possible choices
- """
- self._update()
- return self.choices[self.index]
-
-##############################################################################################
-# Button Control
-##############################################################################################
-class button_control(_chooser_control_base):
- """House a button for variable control."""
-
- def _init(self):
- self.button = wx.Button(self.get_window(), label=self.labels[self.index])
- self.button.Bind(wx.EVT_BUTTON, self._handle_changed)
- self.Add(self.button, 0, wx.ALIGN_CENTER)
-
- def _update(self):
- self.index = (self.index + 1)%len(self.choices) #circularly increment index
- self.button.SetLabel(self.labels[self.index])
-
-##############################################################################################
-# Drop Down Control
-##############################################################################################
-class drop_down_control(_chooser_control_base):
- """House a drop down for variable control."""
-
- def _init(self):
- self.drop_down = wx.Choice(self.get_window(), choices=self.labels)
- self.Add(self.drop_down, 0, wx.ALIGN_CENTER)
- self.drop_down.Bind(wx.EVT_CHOICE, self._handle_changed)
- self.drop_down.SetSelection(self.index)
-
- def _update(self):
- self.index = self.drop_down.GetSelection()
-
-##############################################################################################
-# Radio Buttons Control
-##############################################################################################
-class _radio_buttons_control_base(_chooser_control_base):
- """House radio buttons for variable control."""
-
- def _init(self):
- #create box for radio buttons
- radio_box = wx.BoxSizer(self.radio_box_orientation)
- panel = wx.Panel(self.get_window())
- panel.SetSizer(radio_box)
- self.Add(panel, 0, wx.ALIGN_CENTER)
- #create radio buttons
- self.radio_buttons = list()
- for label in self.labels:
- radio_button = wx.RadioButton(panel, label=label)
- radio_button.SetValue(False)
- self.radio_buttons.append(radio_button)
- radio_box.Add(radio_button, 0, self.radio_button_align)
- radio_button.Bind(wx.EVT_RADIOBUTTON, self._handle_changed)
- #set one radio button active
- self.radio_buttons[self.index].SetValue(True)
-
- def _update(self):
- selected_radio_button = filter(lambda rb: rb.GetValue(), self.radio_buttons)[0]
- self.index = self.radio_buttons.index(selected_radio_button)
-
-class radio_buttons_horizontal_control(_radio_buttons_control_base):
- radio_box_orientation = wx.HORIZONTAL
- radio_button_align = wx.ALIGN_CENTER
-class radio_buttons_vertical_control(_radio_buttons_control_base):
- radio_box_orientation = wx.VERTICAL
- radio_button_align = wx.ALIGN_LEFT
-
-##############################################################################################
-# Slider Control
-##############################################################################################
-class _slider_control_base(_control_base):
- """House a Slider and a Text Box for variable control."""
-
- def __init__(self, window, callback, label='Label', value=50, min=0, max=100, num_steps=100, slider_length=200):
- """
- Slider contructor.
- Create the slider, text box, and label.
- @param window the wx parent window
- @param callback call the callback on changes
- @param label the label title
- @param value the default value
- @param min the min
- @param max the max
- @param num_steps the number of steps
- @param slider_length the length of the slider bar in pixels
- """
- #initialize
- _control_base.__init__(self, window, callback)
- self.min = float(min)
- self.max = float(max)
- self.num_steps = int(num_steps)
- self.slider_length = slider_length
- #create gui elements
- label_text_sizer = wx.BoxSizer(self.label_text_orientation) #label and text box container
- label_text = LabelText(self.get_window(), '%s: '%str(label))
- self.text_box = text_box = wx.TextCtrl(self.get_window(), style=wx.TE_PROCESS_ENTER)
- text_box.Bind(wx.EVT_TEXT_ENTER, self._handle_enter) #bind this special enter hotkey event
- for obj in (label_text, text_box): #fill the container with label and text entry box
- label_text_sizer.Add(obj, 0, wx.ALIGN_CENTER)
- self.Add(label_text_sizer, 0, wx.ALIGN_CENTER)
- #make the slider
- self.slider = slider = wx.Slider(self.get_window(), size=wx.Size(*self.get_slider_size()), style=self.slider_style)
- try: slider.SetRange(0, num_steps)
- except Exception, e:
- print >> sys.stderr, 'Error in set slider range: "%s".'%e
- exit(-1)
- slider.Bind(wx.EVT_SCROLL, self._handle_scroll) #bind the scrolling event
- self.Add(slider, 0, wx.ALIGN_CENTER)
- #init slider and text box
- self.set_value(value)
-
- def get_value(self):
- """
- Get the current set value.
- @return the value (float)
- """
- return self._value
-
- def set_value(self, value):
- """
- Set the current set value.
- @param value the value (float)
- """
- self._value = value
- self._update_slider()
- self._update_text_box()
-
- def _update_slider(self):
- """
- Translate the real numerical value into a slider value.
- """
- slider_value = (float(self.get_value()) - self.min)*self.num_steps/(self.max - self.min)
- self.slider.SetValue(slider_value)
-
- def _update_text_box(self):
- """
- Update the text box value.
- Convert the value into engineering notation.
- """
- self.text_box.SetValue(eng_notation.num_to_str(self.get_value()))
-
- def _handle_scroll(self, event=None):
- """
- A scroll event is detected. Read the slider, call the callback.
- """
- slider_value = self.slider.GetValue()
- new_value = slider_value*(self.max - self.min)/self.num_steps + self.min
- self.set_value(new_value)
- try: self.call()
- except Exception, e: print >> sys.stderr, 'Error in exec callback from handle scroll.\n', e
-
- def _handle_enter(self, event=None):
- """
- An enter key was pressed. Read the text box, call the callback.
- """
- new_value = eng_notation.str_to_num(self.text_box.GetValue())
- self.set_value(new_value)
- try: self.call()
- except Exception, e: print >> sys.stderr, 'Error in exec callback from handle enter.\n', e
-
-class slider_horizontal_control(_slider_control_base):
- label_text_orientation = wx.HORIZONTAL
- slider_style = wx.SL_HORIZONTAL
- def get_slider_size(self): return self.slider_length, -1
-class slider_vertical_control(_slider_control_base):
- label_text_orientation = wx.VERTICAL
- slider_style = wx.SL_VERTICAL
- def get_slider_size(self): return -1, self.slider_length
-
-##############################################################################################
-# Text Box Control
-##############################################################################################
-class text_box_control(_control_base):
- """House a Text Box for variable control."""
-
- def __init__(self, window, callback, label='Label', value=50):
- """
- Text box contructor.
- Create the text box, and label.
- @param window the wx parent window
- @param callback call the callback on changes
- @param label the label title
- @param value the default value
- """
- #initialize
- _control_base.__init__(self, window, callback)
- #create gui elements
- label_text_sizer = wx.BoxSizer(wx.HORIZONTAL) #label and text box container
- label_text = LabelText(self.get_window(), '%s: '%str(label))
- self.text_box = text_box = wx.TextCtrl(self.get_window(), value=str(value), style=wx.TE_PROCESS_ENTER)
- text_box.Bind(wx.EVT_TEXT_ENTER, self._handle_enter) #bind this special enter hotkey event
- for obj in (label_text, text_box): #fill the container with label and text entry box
- label_text_sizer.Add(obj, 0, wx.ALIGN_CENTER)
- self.Add(label_text_sizer, 0, wx.ALIGN_CENTER)
- #detect string mode
- self._string_mode = isinstance(value, str)
-
- def get_value(self):
- """
- Get the current set value.
- @return the value (float)
- """
- return self._value
-
- def _handle_enter(self, event=None):
- """
- An enter key was pressed. Read the text box, call the callback.
- If the text cannot be evaluated, do not try callback.
- Do not evaluate the text box value in string mode.
- """
- if self._string_mode:
- self._value = str(self.text_box.GetValue())
- else:
- try: self._value = eval(self.text_box.GetValue())
- except Exception, e:
- print >> sys.stderr, 'Error in evaluate value from handle enter.\n', e
- return
- try: self.call()
- except Exception, e: print >> sys.stderr, 'Error in exec callback from handle enter.\n', e
diff --git a/grc/src/grc_gnuradio/wxgui/forms/__init__.py b/grc/src/grc_gnuradio/wxgui/forms/__init__.py
new file mode 100644
index 000000000..07226668b
--- /dev/null
+++ b/grc/src/grc_gnuradio/wxgui/forms/__init__.py
@@ -0,0 +1,54 @@
+#
+# 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.
+#
+
+"""
+The following classes will be available through gnuradio.wxgui.forms:
+"""
+
+########################################################################
+# External Converters
+########################################################################
+from converters import \
+ eval_converter, str_converter, \
+ float_converter, int_converter
+
+########################################################################
+# External Forms
+########################################################################
+from forms import \
+ radio_buttons, drop_down, notebook, \
+ button, toggle_button, single_button, \
+ check_box, text_box, static_text, \
+ slider, log_slider
+
+########################################################################
+# Helpful widgets
+########################################################################
+import wx
+
+class static_box_sizer(wx.StaticBoxSizer):
+ def __init__(self, parent, label='', bold=False, orient=wx.VERTICAL):
+ box = wx.StaticBox(parent=parent, label=label)
+ if bold:
+ font = box.GetFont()
+ font.SetWeight(wx.FONTWEIGHT_BOLD)
+ box.SetFont(font)
+ wx.StaticBoxSizer.__init__(self, box=box, orient=orient)
diff --git a/grc/src/grc_gnuradio/wxgui/forms/converters.py b/grc/src/grc_gnuradio/wxgui/forms/converters.py
new file mode 100644
index 000000000..5971cfc09
--- /dev/null
+++ b/grc/src/grc_gnuradio/wxgui/forms/converters.py
@@ -0,0 +1,143 @@
+#
+# 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.
+#
+
+from gnuradio import eng_notation
+import math
+
+class abstract_converter(object):
+ def external_to_internal(self, v):
+ """
+ Convert from user specified value to value acceptable to underlying primitive.
+ The underlying primitive usually expects strings.
+ """
+ raise NotImplementedError
+ def internal_to_external(self, s):
+ """
+ Convert from underlying primitive value to user specified value.
+ The underlying primitive usually expects strings.
+ """
+ raise NotImplementedError
+ def help(self):
+ return "Any string is acceptable"
+
+class identity_converter(abstract_converter):
+ def external_to_internal(self,v):
+ return v
+ def internal_to_external(self, s):
+ return s
+
+########################################################################
+# Commonly used converters
+########################################################################
+class chooser_converter(abstract_converter):
+ """
+ Convert between a set of possible choices and an index.
+ Used in the chooser base and all sub-classes.
+ """
+ def __init__(self, choices):
+ self._choices = choices
+ def external_to_internal(self, choice):
+ return self._choices.index(choice)
+ def internal_to_external(self, index):
+ return self._choices[index]
+ def help(self):
+ return 'Enter a possible value in choices: "%s"'%str(self._choices)
+
+class bool_converter(abstract_converter):
+ """
+ The internal representation is boolean.
+ The external representation is specified.
+ Used in the check box form.
+ """
+ def __init__(self, true, false):
+ self._true = true
+ self._false = false
+ def external_to_internal(self, v):
+ return bool(v)
+ def internal_to_external(self, v):
+ if v: return self._true
+ else: return self._false
+ def help(self):
+ return "Value must be cast-able to type bool."
+
+class eval_converter(abstract_converter):
+ """
+ A catchall converter when int and float are not enough.
+ Evaluate the internal representation with python's eval().
+ Possible uses, set a complex number, constellation points.
+ Used in text box.
+ """
+ def external_to_internal(self, s):
+ return str(s)
+ def internal_to_external(self, s):
+ return eval(s)
+ def help(self):
+ return "Value must be evaluatable by python's eval."
+
+class str_converter(abstract_converter):
+ def external_to_internal(self, v):
+ return str(v)
+ def internal_to_external(self, s):
+ return str(s)
+
+class int_converter(abstract_converter):
+ def external_to_internal(self, v):
+ return str(int(round(v)))
+ def internal_to_external(self, s):
+ return int(s, 0)
+ def help(self):
+ return "Enter an integer. Leading 0x indicates hex"
+
+class float_converter(abstract_converter):
+ def external_to_internal(self, v):
+ return eng_notation.num_to_str(v)
+ def internal_to_external(self, s):
+ return eng_notation.str_to_num(s)
+ def help(self):
+ return "Enter a float with optional scale suffix. E.g., 100.1M"
+
+class slider_converter(abstract_converter):
+ """
+ Scale values to and from the slider.
+ """
+ def __init__(self, minimum, maximum, num_steps, cast):
+ assert minimum < maximum
+ assert num_steps > 0
+ self._offset = minimum
+ self._scaler = float(maximum - minimum)/num_steps
+ self._cast = cast
+ def external_to_internal(self, v):
+ return (v - self._offset)/self._scaler
+ def internal_to_external(self, v):
+ return self._cast(v*self._scaler + self._offset)
+ def help(self):
+ return "Value should be within slider range"
+
+class log_slider_converter(slider_converter):
+ def __init__(self, min_exp, max_exp, num_steps, base):
+ assert min_exp < max_exp
+ assert num_steps > 0
+ self._base = base
+ slider_converter.__init__(self, minimum=min_exp, maximum=max_exp, num_steps=num_steps, cast=float)
+ def external_to_internal(self, v):
+ return slider_converter.external_to_internal(self, math.log(v, self._base))
+ def internal_to_external(self, v):
+ return self._base**slider_converter.internal_to_external(self, v)
diff --git a/grc/src/grc_gnuradio/wxgui/forms/forms.py b/grc/src/grc_gnuradio/wxgui/forms/forms.py
new file mode 100644
index 000000000..5c5b6bad5
--- /dev/null
+++ b/grc/src/grc_gnuradio/wxgui/forms/forms.py
@@ -0,0 +1,473 @@
+#
+# 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.
+#
+
+"""
+The forms module contains general purpose wx-gui forms for gnuradio apps.
+
+The forms follow a layered model:
+ * internal layer
+ * deals with the wxgui objects directly
+ * implemented in event handler and update methods
+ * translation layer
+ * translates the between the external and internal layers
+ * handles parsing errors between layers
+ * external layer
+ * provided external access to the user
+ * set_value, get_value, and optional callback
+ * set and get through optional pubsub and key
+"""
+
+EXT_KEY = 'external'
+INT_KEY = 'internal'
+
+import wx
+import sys
+from gnuradio.gr.pubsub import pubsub
+import converters
+
+EVT_DATA = wx.PyEventBinder(wx.NewEventType())
+class DataEvent(wx.PyEvent):
+ def __init__(self, data):
+ wx.PyEvent.__init__(self, wx.NewId(), EVT_DATA.typeId)
+ self.data = data
+
+########################################################################
+# Base Class Form
+########################################################################
+class _form_base(pubsub, wx.BoxSizer):
+ def __init__(self, parent=None, sizer=None, proportion=0, flag=wx.EXPAND, ps=None, key='', value=None, callback=None, converter=converters.identity_converter()):
+ pubsub.__init__(self)
+ wx.BoxSizer.__init__(self, wx.HORIZONTAL)
+ self._parent = parent
+ self._converter = converter
+ self._callback = callback
+ self._widgets = list()
+ #add to the sizer if provided
+ if sizer: sizer.Add(self, proportion, flag)
+ #proxy the pubsub and key into this form
+ if ps is not None:
+ assert key
+ self.proxy(EXT_KEY, ps, key)
+ #no pubsub passed, must set initial value
+ else: self.set_value(value)
+
+ def _add_widget(self, widget, label='', flag=0):
+ """
+ Add the main widget to this object sizer.
+ If label is passed, add a label as well.
+ Register the widget and the label in the widgets list (for enable/disable).
+ Bind the update handler to the widget for data events.
+ This ensures that the gui thread handles updating widgets.
+ Setup the pusub triggers for external and internal.
+ @param widget the main widget
+ @param label the optional label
+ @param flag additional flags for widget
+ """
+ #setup data event
+ widget.Bind(EVT_DATA, lambda x: self._update(x.data))
+ update = lambda x: wx.PostEvent(widget, DataEvent(x))
+ #register widget
+ self._widgets.append(widget)
+ #create optional label
+ if not label: self.Add(widget, 1, wx.ALIGN_CENTER_VERTICAL | flag)
+ else:
+ label_text = wx.StaticText(self._parent, label='%s: '%label)
+ self._widgets.append(label_text)
+ self.Add(label_text, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT)
+ self.Add(widget, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | flag)
+ #initialize without triggering pubsubs
+ self._translate_external_to_internal(self[EXT_KEY])
+ update(self[INT_KEY])
+ #subscribe all the functions
+ self.subscribe(INT_KEY, update)
+ self.subscribe(INT_KEY, self._translate_internal_to_external)
+ self.subscribe(EXT_KEY, self._translate_external_to_internal)
+ if self._callback: self.subscribe(EXT_KEY, self._callback)
+
+ def _translate_external_to_internal(self, external):
+ try:
+ internal = self._converter.external_to_internal(external)
+ #prevent infinite loop between internal and external pubsub keys by only setting if changed
+ if self[INT_KEY] != internal: self[INT_KEY] = internal
+ except Exception, e:
+ self._err_msg(external, e)
+ self[INT_KEY] = self[INT_KEY] #reset to last good setting
+
+ def _translate_internal_to_external(self, internal):
+ try:
+ external = self._converter.internal_to_external(internal)
+ #prevent infinite loop between internal and external pubsub keys by only setting if changed
+ if self[EXT_KEY] != external: self[EXT_KEY] = external
+ except Exception, e:
+ self._err_msg(internal, e)
+ self[EXT_KEY] = self[EXT_KEY] #reset to last good setting
+
+ def _err_msg(self, value, e):
+ print >> sys.stderr, 'Error translating value: "%s"\n\t%s\n\t%s'%(value, e, self._converter.help())
+
+ #override in subclasses to handle the wxgui object
+ def _update(self, value): raise NotImplementedError
+ def _handle(self, event): raise NotImplementedError
+
+ #provide a set/get interface for this form
+ def get_value(self): return self[EXT_KEY]
+ def set_value(self, value): self[EXT_KEY] = value
+
+ def Disable(self, disable=True): self.Enable(not disable)
+ def Enable(self, enable=True):
+ if enable:
+ for widget in self._widgets: widget.Enable()
+ else:
+ for widget in self._widgets: widget.Disable()
+
+########################################################################
+# Static Text Form
+########################################################################
+class static_text(_form_base):
+ def __init__(self, label='', width=-1, bold=False, converter=converters.str_converter(), **kwargs):
+ _form_base.__init__(self, converter=converter, **kwargs)
+ self._static_text = wx.StaticText(self._parent, size=wx.Size(width, -1))
+ if bold:
+ font = self._static_text.GetFont()
+ font.SetWeight(wx.FONTWEIGHT_BOLD)
+ self._static_text.SetFont(font)
+ self._add_widget(self._static_text, label)
+
+ def _update(self, label): self._static_text.SetLabel(label)
+
+########################################################################
+# Text Box Form
+########################################################################
+class text_box(_form_base):
+ def __init__(self, label='', width=-1, converter=converters.eval_converter(), **kwargs):
+ _form_base.__init__(self, converter=converter, **kwargs)
+ self._text_box = wx.TextCtrl(self._parent, size=wx.Size(width, -1), style=wx.TE_PROCESS_ENTER)
+ self._text_box.Bind(wx.EVT_TEXT_ENTER, self._handle)
+ self._add_widget(self._text_box, label)
+
+ def _handle(self, event): self[INT_KEY] = self._text_box.GetValue()
+ def _update(self, value): self._text_box.SetValue(value)
+
+########################################################################
+# Slider Form
+########################################################################
+class _slider_base(_form_base):
+ """
+ Base class for linear and log slider.
+ @param length the length of the slider in px
+ @param style wx.SL_HORIZONTAL or wx.SL_VERTICAL
+ """
+ def __init__(self, label='', length=-1, converter=None, num_steps=100, style=wx.SL_HORIZONTAL, **kwargs):
+ _form_base.__init__(self, converter=converter, **kwargs)
+ if style & wx.SL_HORIZONTAL: slider_size = wx.Size(length, -1)
+ elif style & wx.SL_VERTICAL: slider_size = wx.Size(-1, length)
+ else: raise NotImplementedError
+ self._slider = wx.Slider(self._parent, minValue=0, maxValue=num_steps, size=slider_size, style=style)
+ self._slider.Bind(wx.EVT_SCROLL, self._handle)
+ self._add_widget(self._slider, label, flag=wx.EXPAND)
+
+ def _handle(self, event): self[INT_KEY] = self._slider.GetValue()
+ def _update(self, value): self._slider.SetValue(value)
+
+class slider(_slider_base):
+ """
+ A generic linear slider.
+ @param cast a cast function, int, or float (default=float)
+ """
+ def __init__(self, minimum=-100, maximum=100, num_steps=100, step_size=None, cast=float, **kwargs):
+ assert step_size or num_steps
+ if step_size is not None: num_steps = (maximum - minimum)/step_size
+ converter = converters.slider_converter(minimum=minimum, maximum=maximum, num_steps=num_steps, cast=cast)
+ _slider_base.__init__(self, converter=converter, num_steps=num_steps, **kwargs)
+
+class log_slider(_slider_base):
+ """
+ A generic log slider.
+ """
+ def __init__(self, min_exp=0, max_exp=1, base=10, num_steps=100, step_size=None, **kwargs):
+ assert step_size or num_steps
+ if step_size is not None: num_steps = (max_exp - min_exp)/step_size
+ converter = converters.log_slider_converter(min_exp=min_exp, max_exp=max_exp, num_steps=num_steps, base=base)
+ _slider_base.__init__(self, converter=converter, num_steps=num_steps, **kwargs)
+
+########################################################################
+# Check Box Form
+########################################################################
+class check_box(_form_base):
+ def __init__(self, label='', true=True, false=False, **kwargs):
+ _form_base.__init__(self, converter=converters.bool_converter(true=true, false=false), **kwargs)
+ self._check_box = wx.CheckBox(self._parent, style=wx.CHK_2STATE, label=label)
+ self._check_box.Bind(wx.EVT_CHECKBOX, self._handle)
+ self._add_widget(self._check_box)
+
+ def _handle(self, event): self[INT_KEY] = self._check_box.IsChecked()
+ def _update(self, checked): self._check_box.SetValue(checked)
+
+########################################################################
+# Base Class Chooser Form
+########################################################################
+class _chooser_base(_form_base):
+ def __init__(self, choices=[], labels=None, **kwargs):
+ _form_base.__init__(self, converter=converters.chooser_converter(choices), **kwargs)
+ self._choices = choices
+ self._labels = map(str, labels or choices)
+
+########################################################################
+# Drop Down Chooser Form
+########################################################################
+class drop_down(_chooser_base):
+ def __init__(self, label='', **kwargs):
+ _chooser_base.__init__(self, **kwargs)
+ self._drop_down = wx.Choice(self._parent, choices=self._labels)
+ self._drop_down.Bind(wx.EVT_CHOICE, self._handle)
+ self._add_widget(self._drop_down, label)
+
+ def _handle(self, event): self[INT_KEY] = self._drop_down.GetSelection()
+ def _update(self, i): self._drop_down.SetSelection(i)
+
+########################################################################
+# Button Chooser Form
+# Circularly move through the choices with each click.
+# Can be a single-click button with one choice.
+# Can be a 2-state button with two choices.
+########################################################################
+class button(_chooser_base):
+ def __init__(self, label='', style=0, width=-1, **kwargs):
+ _chooser_base.__init__(self, **kwargs)
+ self._button = wx.Button(self._parent, size=wx.Size(width, -1), style=style)
+ self._button.Bind(wx.EVT_BUTTON, self._handle)
+ self._add_widget(self._button, label)
+
+ def _handle(self, event): self[INT_KEY] = (self[INT_KEY] + 1)%len(self._choices) #circularly increment index
+ def _update(self, i): self._button.SetLabel(self._labels[i]); self.Layout()
+
+class toggle_button(button):
+ """
+ Create a dual state button.
+ This button will alternate between True and False when clicked.
+ """
+ def __init__(self, true_label='On (click to stop)', false_label='Off (click to start)', **kwargs):
+ button.__init__(self, choices=[True, False], labels=[true_label, false_label], **kwargs)
+
+class single_button(toggle_button):
+ """
+ Create a single state button.
+ This button will callback() when clicked.
+ For use when state holding is not important.
+ """
+ def __init__(self, label='click for callback', **kwargs):
+ toggle_button.__init__(self, true_label=label, false_label=label, value=True, **kwargs)
+
+########################################################################
+# Radio Buttons Chooser Form
+########################################################################
+class radio_buttons(_chooser_base):
+ """
+ Create a radio button form.
+ @param parent the parent widget
+ @param sizer add this widget to sizer if provided (optional)
+ @param proportion the proportion when added to the sizer (default=0)
+ @param ps the pubsub object (optional)
+ @param key the pubsub key (optional)
+ @param value the default value (optional)
+ @param choices list of possible values
+ @param labels list of labels for each choice (default=choices)
+ @param major_dimension the number of rows/cols (default=auto)
+ @param label title label for this widget (optional)
+ @param style useful style args: wx.RA_HORIZONTAL, wx.RA_VERTICAL, wx.NO_BORDER (default=wx.RA_HORIZONTAL)
+ """
+ def __init__(self, style=wx.RA_HORIZONTAL, label='', major_dimension=0, **kwargs):
+ _chooser_base.__init__(self, **kwargs)
+ #create radio buttons
+ self._radio_buttons = wx.RadioBox(self._parent, choices=self._labels, style=style, label=label, majorDimension=major_dimension)
+ self._radio_buttons.Bind(wx.EVT_RADIOBOX, self._handle)
+ self._add_widget(self._radio_buttons)
+
+ def _handle(self, event): self[INT_KEY] = self._radio_buttons.GetSelection()
+ def _update(self, i): self._radio_buttons.SetSelection(i)
+
+########################################################################
+# Notebook Chooser Form
+# The notebook pages/tabs are for selecting between choices.
+# A page must be added to the notebook for each choice.
+########################################################################
+class notebook(_chooser_base):
+ def __init__(self, pages, notebook, **kwargs):
+ _chooser_base.__init__(self, **kwargs)
+ assert len(pages) == len(self._choices)
+ self._notebook = notebook
+ self._notebook.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self._handle)
+ #add pages, setting the label on each tab
+ for i, page in enumerate(pages):
+ self._notebook.AddPage(page, self._labels[i])
+ self._add_widget(self._notebook)
+
+ def _handle(self, event): self[INT_KEY] = self._notebook.GetSelection()
+ def _update(self, i): self._notebook.SetSelection(i)
+
+# ----------------------------------------------------------------
+# Stand-alone test application
+# ----------------------------------------------------------------
+
+import wx
+from gnuradio.wxgui import gui
+
+class app_gui (object):
+ def __init__(self, frame, panel, vbox, top_block, options, args):
+
+ def callback(v): print v
+
+ radio_buttons(
+ sizer=vbox,
+ parent=panel,
+ choices=[2, 4, 8, 16],
+ labels=['two', 'four', 'eight', 'sixteen'],
+ value=4,
+ style=wx.RA_HORIZONTAL,
+ label='test radio long string',
+ callback=callback,
+ #major_dimension = 2,
+ )
+
+ radio_buttons(
+ sizer=vbox,
+ parent=panel,
+ choices=[2, 4, 8, 16],
+ labels=['two', 'four', 'eight', 'sixteen'],
+ value=4,
+ style=wx.RA_VERTICAL,
+ label='test radio long string',
+ callback=callback,
+ #major_dimension = 2,
+ )
+
+ radio_buttons(
+ sizer=vbox,
+ parent=panel,
+ choices=[2, 4, 8, 16],
+ labels=['two', 'four', 'eight', 'sixteen'],
+ value=4,
+ style=wx.RA_VERTICAL | wx.NO_BORDER,
+ callback=callback,
+ #major_dimension = 2,
+ )
+
+ button(
+ sizer=vbox,
+ parent=panel,
+ choices=[2, 4, 8, 16],
+ labels=['two', 'four', 'eight', 'sixteen'],
+ value=2,
+ label='button value',
+ callback=callback,
+ #width=100,
+ )
+
+
+ drop_down(
+ sizer=vbox,
+ parent=panel,
+ choices=[2, 4, 8, 16],
+ value=2,
+ label='Choose One',
+ callback=callback,
+ )
+ check_box(
+ sizer=vbox,
+ parent=panel,
+ value=False,
+ label='check me',
+ callback=callback,
+ )
+ text_box(
+ sizer=vbox,
+ parent=panel,
+ value=3,
+ label='text box',
+ callback=callback,
+ width=200,
+ )
+
+ static_text(
+ sizer=vbox,
+ parent=panel,
+ value='bob',
+ label='static text',
+ width=-1,
+ bold=True,
+ )
+
+ slider(
+ sizer=vbox,
+ parent=panel,
+ value=12,
+ label='slider',
+ callback=callback,
+ )
+
+ log_slider(
+ sizer=vbox,
+ parent=panel,
+ value=12,
+ label='slider',
+ callback=callback,
+ )
+
+ slider(
+ sizer=vbox,
+ parent=panel,
+ value=12,
+ label='slider',
+ callback=callback,
+ style=wx.SL_VERTICAL,
+ length=30,
+ )
+
+ toggle_button(
+ sizer=vbox,
+ parent=panel,
+ value=True,
+ label='toggle it',
+ callback=callback,
+ )
+
+ single_button(
+ sizer=vbox,
+ parent=panel,
+ label='sig test',
+ callback=callback,
+ )
+
+if __name__ == "__main__":
+ try:
+
+ # Create the GUI application
+ app = gui.app(
+ gui=app_gui, # User interface class
+ title="Test Forms", # Top window title
+ )
+
+ # And run it
+ app.MainLoop()
+
+ except RuntimeError, e:
+ print e
+ sys.exit(1)
diff --git a/grc/src/grc_gnuradio/wxgui/top_block_gui.py b/grc/src/grc_gnuradio/wxgui/top_block_gui.py
index fef9d18ce..f3305d7c5 100644
--- a/grc/src/grc_gnuradio/wxgui/top_block_gui.py
+++ b/grc/src/grc_gnuradio/wxgui/top_block_gui.py
@@ -21,10 +21,11 @@
import wx
import sys, os
from gnuradio import gr
+from gnuradio.gr.pubsub import pubsub
default_gui_size = (200, 100)
-class top_block_gui(gr.top_block):
+class top_block_gui(gr.top_block, pubsub):
"""gr top block with wx gui app and grid sizer."""
def __init__(self, title='', size=default_gui_size, icon=None):
@@ -37,6 +38,7 @@ class top_block_gui(gr.top_block):
"""
#initialize
gr.top_block.__init__(self)
+ pubsub.__init__(self)
self._size = size
#set the icon
if icon and os.path.isfile(icon): self._icon = icon
diff --git a/grc/src/gui/ActionHandler.py b/grc/src/gui/ActionHandler.py
index 91dd0fb45..da0909a64 100644
--- a/grc/src/gui/ActionHandler.py
+++ b/grc/src/gui/ActionHandler.py
@@ -1,5 +1,5 @@
"""
-Copyright 2007 Free Software Foundation, Inc.
+Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -19,7 +19,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
import os
import signal
-from Constants import DIR_LEFT, DIR_RIGHT, IMAGE_FILE_EXTENSION
+from Constants import IMAGE_FILE_EXTENSION
import Actions
import pygtk
pygtk.require('2.0')
@@ -32,7 +32,8 @@ from .. utils import ParseXML
import random
from .. platforms.gui.Platform import Platform
from MainWindow import MainWindow
-from Dialogs import AboutDialog
+from ParamsDialog import ParamsDialog
+import Dialogs
from FileDialogs import OpenFlowGraphFileDialog, SaveFlowGraphFileDialog, SaveImageFileDialog
gobject.threads_init()
@@ -57,7 +58,7 @@ class ActionHandler:
#setup the main window
self.main_window = MainWindow(self.handle_states, platform)
self.main_window.connect('delete_event', self._quit)
- self.main_window.connect('key_press_event', self._handle_key_press)
+ self.main_window.connect('key-press-event', self._handle_key_press)
self.get_page = self.main_window.get_page
self.get_flow_graph = self.main_window.get_flow_graph
self.get_focus_flag = self.main_window.drawing_area.get_focus_flag
@@ -72,32 +73,25 @@ class ActionHandler:
def _handle_key_press(self, widget, event):
"""
- Handle key presses from the keyboard and translate key combos into actions.
- This key press handler is called before the gtk accelerators kick in.
- This handler ensures that key presses without a mod mask,
- only pass to the accelerators if the flow graph is in focus.
- This function also handles keys that accelerators refuse to handle: left/right,
- and keys that are not registered with an accelerator: +/-.
- @return false to let the accelerators handle the key action
+ Handle key presses from the keyboard and translate key combinations into actions.
+ This key press handler is called prior to the gtk key press handler.
+ This handler bypasses built in accelerator key handling when in focus because
+ * some keys are ignored by the accelerators like the direction keys,
+ * some keys are not registered to any accelerators but are still used.
+ When not in focus, gtk and the accelerators handle the the key press.
+ @return false to let gtk handle the key action
"""
- if self.get_focus_flag():
- try:
- self.handle_states({
- 'Left': Actions.BLOCK_ROTATE_LEFT,
- 'Right': Actions.BLOCK_ROTATE_RIGHT,
- 'Up': Actions.BLOCK_DEC_TYPE,
- 'Down': Actions.BLOCK_INC_TYPE,
- 'equal': Actions.PORT_CONTROLLER_INC,
- 'plus': Actions.PORT_CONTROLLER_INC,
- 'KP_Add': Actions.PORT_CONTROLLER_INC,
- 'minus': Actions.PORT_CONTROLLER_DEC,
- 'KP_Subtract': Actions.PORT_CONTROLLER_DEC,
- }[gtk.gdk.keyval_name(event.keyval)])
- return True
- #focus: always return false for accelerator to handle
- except: return False
- #no focus: only allow accelerator to handle when a mod is used
- return not event.state
+ #dont allow key presses to queue up
+ if gtk.events_pending(): return True
+ #extract action name from this key press
+ key_name = gtk.gdk.keyval_name(event.keyval)
+ mod_mask = event.state
+ action_name = Actions.get_action_name_from_key_name(key_name, mod_mask)
+ #handle the action if flow graph is in focus
+ if action_name and self.get_focus_flag():
+ self.handle_states(action_name)
+ return True #handled by this method
+ return False #let gtk handle the key press
def _quit(self, window, event):
"""
@@ -138,7 +132,7 @@ class ActionHandler:
Actions.APPLICATION_QUIT, Actions.FLOW_GRAPH_NEW,
Actions.FLOW_GRAPH_OPEN, Actions.FLOW_GRAPH_SAVE_AS,
Actions.FLOW_GRAPH_CLOSE, Actions.ABOUT_WINDOW_DISPLAY,
- Actions.FLOW_GRAPH_SCREEN_CAPTURE,
+ Actions.FLOW_GRAPH_SCREEN_CAPTURE, Actions.HELP_WINDOW_DISPLAY,
): Actions.get_action_from_name(action).set_sensitive(True)
if not self.init_file_paths:
self.init_file_paths = Preferences.files_open()
@@ -193,13 +187,13 @@ class ActionHandler:
elif state == Actions.BLOCK_MOVE:
self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data())
self.get_page().set_saved(False)
- elif state == Actions.BLOCK_ROTATE_LEFT:
- if self.get_flow_graph().rotate_selected(DIR_LEFT):
+ elif state == Actions.BLOCK_ROTATE_CCW:
+ if self.get_flow_graph().rotate_selected(90):
self.get_flow_graph().update()
self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data())
self.get_page().set_saved(False)
- elif state == Actions.BLOCK_ROTATE_RIGHT:
- if self.get_flow_graph().rotate_selected(DIR_RIGHT):
+ elif state == Actions.BLOCK_ROTATE_CW:
+ if self.get_flow_graph().rotate_selected(-90):
self.get_flow_graph().update()
self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data())
self.get_page().set_saved(False)
@@ -238,12 +232,15 @@ class ActionHandler:
# Window stuff
##################################################
elif state == Actions.ABOUT_WINDOW_DISPLAY:
- AboutDialog()
+ Dialogs.AboutDialog()
+ elif state == Actions.HELP_WINDOW_DISPLAY:
+ Dialogs.HelpDialog()
##################################################
# Param Modifications
##################################################
elif state == Actions.BLOCK_PARAM_MODIFY:
- if self.get_flow_graph().param_modify_selected():
+ selected_block = self.get_flow_graph().get_selected_block()
+ if selected_block and ParamsDialog(selected_block).run():
self.get_flow_graph().update()
self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data())
self.get_page().set_saved(False)
@@ -296,7 +293,7 @@ class ActionHandler:
elif state == Actions.FLOW_GRAPH_SCREEN_CAPTURE:
file_path = SaveImageFileDialog(self.get_page().get_file_path()).run()
if file_path is not None:
- pixmap = self.get_flow_graph().get_drawing_area().pixmap
+ pixmap = self.get_flow_graph().get_pixmap()
width, height = pixmap.get_size()
pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, 0, 8, width, height)
pixbuf.get_from_drawable(pixmap, pixmap.get_colormap(), 0, 0, 0, 0, width, height)
@@ -333,8 +330,8 @@ class ActionHandler:
#update general buttons
Actions.get_action_from_name(Actions.ELEMENT_DELETE).set_sensitive(bool(self.get_flow_graph().get_selected_elements()))
Actions.get_action_from_name(Actions.BLOCK_PARAM_MODIFY).set_sensitive(bool(self.get_flow_graph().get_selected_block()))
- Actions.get_action_from_name(Actions.BLOCK_ROTATE_RIGHT).set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
- Actions.get_action_from_name(Actions.BLOCK_ROTATE_LEFT).set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
+ Actions.get_action_from_name(Actions.BLOCK_ROTATE_CCW).set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
+ Actions.get_action_from_name(Actions.BLOCK_ROTATE_CW).set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
#update cut/copy/paste
Actions.get_action_from_name(Actions.BLOCK_CUT).set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
Actions.get_action_from_name(Actions.BLOCK_COPY).set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
@@ -348,7 +345,7 @@ class ActionHandler:
Actions.get_action_from_name(Actions.FLOW_GRAPH_SAVE).set_sensitive(not self.get_page().get_saved())
self.main_window.update()
#draw the flow graph
- self.get_flow_graph().draw()
+ self.get_flow_graph().queue_draw()
def update_exec_stop(self):
"""
diff --git a/grc/src/gui/Actions.py b/grc/src/gui/Actions.py
index 16f12dd4c..9b687df7e 100644
--- a/grc/src/gui/Actions.py
+++ b/grc/src/gui/Actions.py
@@ -1,5 +1,5 @@
"""
-Copyright 2007 Free Software Foundation, Inc.
+Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -28,8 +28,8 @@ APPLICATION_INITIALIZE = 'app init'
APPLICATION_QUIT = 'app quit'
PARAM_MODIFY = 'param modify'
BLOCK_MOVE = 'block move'
-BLOCK_ROTATE_LEFT = 'block rotate left'
-BLOCK_ROTATE_RIGHT = 'block rotate right'
+BLOCK_ROTATE_CCW = 'block rotate ccw'
+BLOCK_ROTATE_CW = 'block rotate cw'
BLOCK_PARAM_MODIFY = 'block param modify'
BLOCK_INC_TYPE = 'block increment type'
BLOCK_DEC_TYPE = 'block decrement type'
@@ -56,60 +56,85 @@ FLOW_GRAPH_EXEC = 'flow graph exec'
FLOW_GRAPH_KILL = 'flow graph kill'
FLOW_GRAPH_SCREEN_CAPTURE = 'flow graph screen capture'
ABOUT_WINDOW_DISPLAY = 'about window display'
+HELP_WINDOW_DISPLAY = 'help window display'
######################################################################################################
# Action Key Map
######################################################################################################
-_actions_key_map = {
- #action name: (key name, mask)
- FLOW_GRAPH_NEW: ('n', gtk.gdk.CONTROL_MASK),
- FLOW_GRAPH_OPEN: ('o', gtk.gdk.CONTROL_MASK),
- FLOW_GRAPH_SAVE: ('s', gtk.gdk.CONTROL_MASK),
- FLOW_GRAPH_CLOSE: ('w', gtk.gdk.CONTROL_MASK),
- APPLICATION_QUIT: ('q', gtk.gdk.CONTROL_MASK),
- FLOW_GRAPH_UNDO: ('z', gtk.gdk.CONTROL_MASK),
- FLOW_GRAPH_REDO: ('y', gtk.gdk.CONTROL_MASK),
- ELEMENT_DELETE: ('Delete', 0),
- BLOCK_ROTATE_LEFT: ('Left', 0),
- BLOCK_ROTATE_RIGHT: ('Right', 0),
- BLOCK_PARAM_MODIFY: ('Return', 0),
- BLOCK_ENABLE: ('e', 0),
- BLOCK_DISABLE: ('d', 0),
- BLOCK_CUT: ('x', gtk.gdk.CONTROL_MASK),
- BLOCK_COPY: ('c', gtk.gdk.CONTROL_MASK),
- BLOCK_PASTE: ('v', gtk.gdk.CONTROL_MASK),
- FLOW_GRAPH_GEN: ('F5', 0),
- FLOW_GRAPH_EXEC: ('F6', 0),
- FLOW_GRAPH_KILL: ('F7', 0),
- FLOW_GRAPH_SCREEN_CAPTURE: ('Print', 0),
-}
+_actions_key_list = (
+ #action name, key name, mod mask
+ (FLOW_GRAPH_NEW, 'n', gtk.gdk.CONTROL_MASK),
+ (FLOW_GRAPH_OPEN, 'o', gtk.gdk.CONTROL_MASK),
+ (FLOW_GRAPH_SAVE, 's', gtk.gdk.CONTROL_MASK),
+ (FLOW_GRAPH_SAVE_AS, 's', gtk.gdk.CONTROL_MASK | gtk.gdk.SHIFT_MASK),
+ (FLOW_GRAPH_CLOSE, 'w', gtk.gdk.CONTROL_MASK),
+ (APPLICATION_QUIT, 'q', gtk.gdk.CONTROL_MASK),
+ (FLOW_GRAPH_UNDO, 'z', gtk.gdk.CONTROL_MASK),
+ (FLOW_GRAPH_REDO, 'y', gtk.gdk.CONTROL_MASK),
+ (ELEMENT_DELETE, 'Delete', 0),
+ (BLOCK_ROTATE_CCW, 'Left', 0),
+ (BLOCK_ROTATE_CW, 'Right', 0),
+ (BLOCK_DEC_TYPE, 'Up', 0),
+ (BLOCK_INC_TYPE, 'Down', 0),
+ (BLOCK_PARAM_MODIFY, 'Return', 0),
+ (BLOCK_ENABLE, 'e', 0),
+ (BLOCK_DISABLE, 'd', 0),
+ (BLOCK_CUT, 'x', gtk.gdk.CONTROL_MASK),
+ (BLOCK_COPY, 'c', gtk.gdk.CONTROL_MASK),
+ (BLOCK_PASTE, 'v', gtk.gdk.CONTROL_MASK),
+ (FLOW_GRAPH_GEN, 'F5', 0),
+ (FLOW_GRAPH_EXEC, 'F6', 0),
+ (FLOW_GRAPH_KILL, 'F7', 0),
+ (FLOW_GRAPH_SCREEN_CAPTURE, 'Print', 0),
+ (HELP_WINDOW_DISPLAY, 'F1', 0),
+ #the following have no associated gtk.Action
+ (PORT_CONTROLLER_INC, 'equal', 0),
+ (PORT_CONTROLLER_INC, 'plus', 0),
+ (PORT_CONTROLLER_INC, 'KP_Add', 0),
+ (PORT_CONTROLLER_DEC, 'minus', 0),
+ (PORT_CONTROLLER_DEC, 'KP_Subtract', 0),
+)
+
+_actions_key_dict = dict(((key_name, mod_mask), action_name) for action_name, key_name, mod_mask in _actions_key_list)
+def get_action_name_from_key_name(key_name, mod_mask=0):
+ """
+ Get the action name associated with the key name and mask.
+ Both keyname and mask have to match.
+ @param key_name the name of the key
+ @param mod_mask the key press mask (shift, ctrl) 0 for none
+ @return the action name or blank string
+ """
+ key_name_mod_mask = (key_name, mod_mask)
+ if key_name_mod_mask in _actions_key_dict: return _actions_key_dict[key_name_mod_mask]
+ return ''
######################################################################################################
# Actions
######################################################################################################
_actions_list = (
- gtk.Action(FLOW_GRAPH_NEW, '_New', 'Create a new flow graph', 'gtk-new'),
- gtk.Action(FLOW_GRAPH_OPEN, '_Open', 'Open an existing flow graph', 'gtk-open'),
- gtk.Action(FLOW_GRAPH_SAVE, '_Save', 'Save the current flow graph', 'gtk-save'),
- gtk.Action(FLOW_GRAPH_SAVE_AS, 'Save _As', 'Save the current flow graph as...', 'gtk-save-as'),
- gtk.Action(FLOW_GRAPH_CLOSE, '_Close', 'Close the current flow graph', 'gtk-close'),
- gtk.Action(APPLICATION_QUIT, '_Quit', 'Quit program', 'gtk-quit'),
- gtk.Action(FLOW_GRAPH_UNDO, '_Undo', 'Undo a change to the flow graph', 'gtk-undo'),
- gtk.Action(FLOW_GRAPH_REDO, '_Redo', 'Redo a change to the flow graph', 'gtk-redo'),
- gtk.Action(ELEMENT_DELETE, '_Delete', 'Delete the selected blocks', 'gtk-delete'),
- gtk.Action(BLOCK_ROTATE_LEFT, 'Rotate _Left', 'Rotate the selected blocks 90 degrees', 'gtk-go-back'),
- gtk.Action(BLOCK_ROTATE_RIGHT, 'Rotate _Right', 'Rotate the selected blocks -90 degrees', 'gtk-go-forward'),
- gtk.Action(BLOCK_PARAM_MODIFY, '_Properties', 'Modify params for the selected block', 'gtk-properties'),
- gtk.Action(BLOCK_ENABLE, 'E_nable', 'Enable the selected blocks', 'gtk-connect'),
- gtk.Action(BLOCK_DISABLE, 'D_isable', 'Disable the selected blocks', 'gtk-disconnect'),
- gtk.Action(BLOCK_CUT, 'Cu_t', 'Cut', 'gtk-cut'),
- gtk.Action(BLOCK_COPY, '_Copy', 'Copy', 'gtk-copy'),
- gtk.Action(BLOCK_PASTE, '_Paste', 'Paste', 'gtk-paste'),
- gtk.Action(ABOUT_WINDOW_DISPLAY, '_About', 'About this program', 'gtk-about'),
- gtk.Action(FLOW_GRAPH_GEN, '_Generate', 'Generate the flow graph', 'gtk-convert'),
- gtk.Action(FLOW_GRAPH_EXEC, '_Execute', 'Execute the flow graph', 'gtk-execute'),
- gtk.Action(FLOW_GRAPH_KILL, '_Kill', 'Kill the flow graph', 'gtk-stop'),
- gtk.Action(FLOW_GRAPH_SCREEN_CAPTURE, 'S_creen Capture', 'Create a screen capture of the flow graph', 'gtk-print'),
+ gtk.Action(FLOW_GRAPH_NEW, '_New', 'Create a new flow graph', gtk.STOCK_NEW),
+ gtk.Action(FLOW_GRAPH_OPEN, '_Open', 'Open an existing flow graph', gtk.STOCK_OPEN),
+ gtk.Action(FLOW_GRAPH_SAVE, '_Save', 'Save the current flow graph', gtk.STOCK_SAVE),
+ gtk.Action(FLOW_GRAPH_SAVE_AS, 'Save _As', 'Save the current flow graph as...', gtk.STOCK_SAVE_AS),
+ gtk.Action(FLOW_GRAPH_CLOSE, '_Close', 'Close the current flow graph', gtk.STOCK_CLOSE),
+ gtk.Action(APPLICATION_QUIT, '_Quit', 'Quit program', gtk.STOCK_QUIT),
+ gtk.Action(FLOW_GRAPH_UNDO, '_Undo', 'Undo a change to the flow graph', gtk.STOCK_UNDO),
+ gtk.Action(FLOW_GRAPH_REDO, '_Redo', 'Redo a change to the flow graph', gtk.STOCK_REDO),
+ gtk.Action(ELEMENT_DELETE, '_Delete', 'Delete the selected blocks', gtk.STOCK_DELETE),
+ gtk.Action(BLOCK_ROTATE_CCW, 'Rotate Counterclockwise', 'Rotate the selected blocks 90 degrees to the left', gtk.STOCK_GO_BACK),
+ gtk.Action(BLOCK_ROTATE_CW, 'Rotate Clockwise', 'Rotate the selected blocks 90 degrees to the right', gtk.STOCK_GO_FORWARD),
+ gtk.Action(BLOCK_PARAM_MODIFY, '_Properties', 'Modify params for the selected block', gtk.STOCK_PROPERTIES),
+ gtk.Action(BLOCK_ENABLE, 'E_nable', 'Enable the selected blocks', gtk.STOCK_CONNECT),
+ gtk.Action(BLOCK_DISABLE, 'D_isable', 'Disable the selected blocks', gtk.STOCK_DISCONNECT),
+ gtk.Action(BLOCK_CUT, 'Cu_t', 'Cut', gtk.STOCK_CUT),
+ gtk.Action(BLOCK_COPY, '_Copy', 'Copy', gtk.STOCK_COPY),
+ gtk.Action(BLOCK_PASTE, '_Paste', 'Paste', gtk.STOCK_PASTE),
+ gtk.Action(ABOUT_WINDOW_DISPLAY, '_About', 'About this program', gtk.STOCK_ABOUT),
+ gtk.Action(HELP_WINDOW_DISPLAY, '_Help', 'Usage Tips', gtk.STOCK_HELP),
+ gtk.Action(FLOW_GRAPH_GEN, '_Generate', 'Generate the flow graph', gtk.STOCK_CONVERT),
+ gtk.Action(FLOW_GRAPH_EXEC, '_Execute', 'Execute the flow graph', gtk.STOCK_EXECUTE),
+ gtk.Action(FLOW_GRAPH_KILL, '_Kill', 'Kill the flow graph', gtk.STOCK_STOP),
+ gtk.Action(FLOW_GRAPH_SCREEN_CAPTURE, 'S_creen Capture', 'Create a screen capture of the flow graph', gtk.STOCK_PRINT),
)
def get_all_actions(): return _actions_list
@@ -122,16 +147,21 @@ def get_action_from_name(action_name):
@throw KeyError bad action name
@return a gtk action object
"""
- if _actions_dict.has_key(action_name): return _actions_dict[action_name]
+ if action_name in _actions_dict: return _actions_dict[action_name]
raise KeyError('Action Name: "%s" does not exist'%action_name)
+######################################################################################################
+# Accelerators
+######################################################################################################
_accel_group = gtk.AccelGroup()
def get_accel_group(): return _accel_group
-#load the actions key map
#set the accelerator group, and accelerator path
-#register the key and mod with the accelerator path
-for action_name, (key_name, mod) in _actions_key_map.iteritems():
- get_action_from_name(action_name).set_accel_group(get_accel_group())
- get_action_from_name(action_name).set_accel_path('<main>/'+action_name)
- gtk.accel_map_add_entry('<main>/'+action_name, gtk.gdk.keyval_from_name(key_name),mod)
+#register the key name and mod mask with the accelerator path
+for action_name, key_name, mod_mask in _actions_key_list:
+ try:
+ accel_path = '<main>/'+action_name
+ get_action_from_name(action_name).set_accel_group(get_accel_group())
+ get_action_from_name(action_name).set_accel_path(accel_path)
+ gtk.accel_map_add_entry(accel_path, gtk.gdk.keyval_from_name(key_name), mod_mask)
+ except KeyError: pass #no action was created for this action name
diff --git a/grc/src/gui/Bars.py b/grc/src/gui/Bars.py
index c89aea580..52e7ba1f8 100644
--- a/grc/src/gui/Bars.py
+++ b/grc/src/gui/Bars.py
@@ -1,5 +1,5 @@
"""
-Copyright 2007 Free Software Foundation, Inc.
+Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -43,8 +43,8 @@ TOOLBAR_LIST = (
Actions.FLOW_GRAPH_EXEC,
Actions.FLOW_GRAPH_KILL,
None,
- Actions.BLOCK_ROTATE_LEFT,
- Actions.BLOCK_ROTATE_RIGHT,
+ Actions.BLOCK_ROTATE_CCW,
+ Actions.BLOCK_ROTATE_CW,
None,
Actions.BLOCK_ENABLE,
Actions.BLOCK_DISABLE,
@@ -73,8 +73,8 @@ MENU_BAR_LIST = (
Actions.BLOCK_PASTE,
Actions.ELEMENT_DELETE,
None,
- Actions.BLOCK_ROTATE_LEFT,
- Actions.BLOCK_ROTATE_RIGHT,
+ Actions.BLOCK_ROTATE_CCW,
+ Actions.BLOCK_ROTATE_CW,
None,
Actions.BLOCK_ENABLE,
Actions.BLOCK_DISABLE,
@@ -87,6 +87,8 @@ MENU_BAR_LIST = (
Actions.FLOW_GRAPH_KILL,
]),
(gtk.Action('Help', '_Help', None, None), [
+ Actions.HELP_WINDOW_DISPLAY,
+ None,
Actions.ABOUT_WINDOW_DISPLAY,
]),
)
diff --git a/grc/src/gui/BlockTreeWindow.py b/grc/src/gui/BlockTreeWindow.py
index 94b9476c5..9e4bec3f9 100644
--- a/grc/src/gui/BlockTreeWindow.py
+++ b/grc/src/gui/BlockTreeWindow.py
@@ -1,5 +1,5 @@
"""
-Copyright 2007 Free Software Foundation, Inc.
+Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-from Constants import DEFAULT_BLOCKS_WINDOW_WIDTH
+from Constants import DEFAULT_BLOCKS_WINDOW_WIDTH, DND_TARGETS
import pygtk
pygtk.require('2.0')
import gtk
@@ -53,6 +53,9 @@ class BlockTreeWindow(gtk.VBox):
renderer = gtk.CellRendererText()
column = gtk.TreeViewColumn('Blocks', renderer, text=NAME_INDEX)
self.treeview.append_column(column)
+ #setup drag and drop
+ self.treeview.enable_model_drag_source(gtk.gdk.BUTTON1_MASK, DND_TARGETS, gtk.gdk.ACTION_COPY)
+ self.treeview.connect('drag-data-get', self._handle_drag_get_data)
#make the scrolled window to hold the tree view
scrolled_window = gtk.ScrolledWindow()
scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
@@ -60,12 +63,11 @@ class BlockTreeWindow(gtk.VBox):
scrolled_window.set_size_request(DEFAULT_BLOCKS_WINDOW_WIDTH, -1)
self.pack_start(scrolled_window)
#add button
- self.add_button = gtk.Button(None, 'gtk-add')
+ self.add_button = gtk.Button(None, gtk.STOCK_ADD)
self.add_button.connect('clicked', self._handle_add_button)
self.pack_start(self.add_button, False)
- #map categories to iters
- self.categories = dict()
- self.categories[tuple()] = None
+ #map categories to iters, automatic mapping for root
+ self._categories = {tuple(): None}
#add blocks and categories
self.platform.load_block_tree(self)
#initialize
@@ -78,22 +80,21 @@ class BlockTreeWindow(gtk.VBox):
"""
Add a block with category to this selection window.
Add only the category when block is None.
- @param category the category string
+ @param category the category list
@param block the block object or None
"""
- #rectify category
- category = filter(lambda x: x, category.split('/'))
+ category = tuple(category)[1:] #tuple is hashable
#add category and all sub categories
- for i in range(len(category)):
- sub_category = tuple(category[:i+1])
- if sub_category not in self.categories.keys():
- iter = self.treestore.insert_before(self.categories[tuple(category[:i])], None)
- self.treestore.set_value(iter, NAME_INDEX, '[ %s ]'%category[i])
+ for i, cat_name in enumerate(category):
+ sub_category = category[:i+1]
+ if sub_category not in self._categories:
+ iter = self.treestore.insert_before(self._categories[sub_category[:-1]], None)
+ self.treestore.set_value(iter, NAME_INDEX, '[ %s ]'%cat_name)
self.treestore.set_value(iter, KEY_INDEX, '')
- self.categories[sub_category] = iter
+ self._categories[sub_category] = iter
#add block
if block is None: return
- iter = self.treestore.insert_before(self.categories[tuple(category)], None)
+ iter = self.treestore.insert_before(self._categories[category], None)
self.treestore.set_value(iter, NAME_INDEX, block.get_name())
self.treestore.set_value(iter, KEY_INDEX, block.get_key())
@@ -127,6 +128,15 @@ class BlockTreeWindow(gtk.VBox):
############################################################
## Event Handlers
############################################################
+ def _handle_drag_get_data(self, widget, drag_context, selection_data, info, time):
+ """
+ Handle a drag and drop by setting the key to the selection object.
+ This will call the destination handler for drag and drop.
+ Only call set when the key is valid to ignore DND from categories.
+ """
+ key = self._get_selected_block_key()
+ if key: selection_data.set(selection_data.target, 8, key)
+
def _handle_mouse_button_press(self, widget, event):
"""
Handle the mouse button press.
diff --git a/grc/src/gui/Constants.py b/grc/src/gui/Constants.py
index 70e6b6b6e..f23ab8b13 100644
--- a/grc/src/gui/Constants.py
+++ b/grc/src/gui/Constants.py
@@ -1,5 +1,5 @@
"""
-Copyright 2008 Free Software Foundation, Inc.
+Copyright 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -17,6 +17,9 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
+import pygtk
+pygtk.require('2.0')
+import gtk
import os
##default path for the open/save dialogs
@@ -28,10 +31,6 @@ IMAGE_FILE_EXTENSION = '.png'
##name for new/unsaved flow graphs
NEW_FLOGRAPH_TITLE = 'untitled'
-##rotation constants
-DIR_LEFT = 'left'
-DIR_RIGHT = 'right'
-
##main window constraints
MIN_WINDOW_WIDTH = 600
MIN_WINDOW_HEIGHT = 400
@@ -42,16 +41,8 @@ MIN_DIALOG_HEIGHT = 500
DEFAULT_BLOCKS_WINDOW_WIDTH = 100
DEFAULT_REPORTS_WINDOW_WIDTH = 100
-##How close can the mouse get to the window border before mouse events are ignored.
-BORDER_PROXIMITY_SENSITIVITY = 50
-##How close the mouse can get to the edge of the visible window before scrolling is invoked.
-SCROLL_PROXIMITY_SENSITIVITY = 30
-##When the window has to be scrolled, move it this distance in the required direction.
-SCROLL_DISTANCE = 15
-##The redrawing sensitivity, how many seconds must pass between motion events before a redraw?
-MOTION_DETECT_REDRAWING_SENSITIVITY = .02
-##How close the mouse click can be to a connection and register a connection select.
-CONNECTION_SELECT_SENSITIVITY = 5
-
##The size of the state saving cache in the flow graph (for undo/redo functionality)
STATE_CACHE_SIZE = 42
+
+##Shared targets for drag and drop of blocks
+DND_TARGETS = [('STRING', gtk.TARGET_SAME_APP, 0)]
diff --git a/grc/src/gui/Dialogs.py b/grc/src/gui/Dialogs.py
index e15f8c574..d526b97b4 100644
--- a/grc/src/gui/Dialogs.py
+++ b/grc/src/gui/Dialogs.py
@@ -1,5 +1,5 @@
"""
-Copyright 2008 Free Software Foundation, Inc.
+Copyright 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -20,7 +20,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
import pygtk
pygtk.require('2.0')
import gtk
-from Constants import MIN_DIALOG_WIDTH, MIN_DIALOG_HEIGHT
from .. platforms.base.Constants import PACKAGE, VERSION
import Preferences
@@ -82,3 +81,20 @@ Achilleas Anastasopoulos -> trellis support
-----""")
self.run()
self.destroy()
+
+def HelpDialog():
+ MessageDialogHelper(
+ type=gtk.MESSAGE_INFO,
+ buttons=gtk.BUTTONS_CLOSE,
+ title='Help',
+ markup="""\
+<b>Usage Tips</b>
+
+<u>Add block</u>: drag and drop or double click a block in the block selection window.
+<u>Rotate block</u>: Select a block, press left/right on the keyboard.
+<u>Change type</u>: Select a block, press up/down on the keyboard.
+<u>Edit parameters</u>: double click on a block in the flow graph.
+<u>Make connection</u>: click on the source port of one block, then click on the sink port of another block.
+<u>Remove connection</u>: select the connection and press delete, or drag the connection.
+
+* See the menu for other keyboard shortcuts.""")
diff --git a/grc/src/gui/DrawingArea.py b/grc/src/gui/DrawingArea.py
index 3588e122d..5258979d8 100644
--- a/grc/src/gui/DrawingArea.py
+++ b/grc/src/gui/DrawingArea.py
@@ -1,5 +1,5 @@
"""
-Copyright 2007 Free Software Foundation, Inc.
+Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -20,7 +20,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
import pygtk
pygtk.require('2.0')
import gtk
-from Constants import MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT
+from Constants import MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT, DND_TARGETS
class DrawingArea(gtk.DrawingArea):
"""
@@ -51,24 +51,26 @@ class DrawingArea(gtk.DrawingArea):
gtk.gdk.LEAVE_NOTIFY_MASK | \
gtk.gdk.ENTER_NOTIFY_MASK
)
+ #setup drag and drop
+ self.drag_dest_set(gtk.DEST_DEFAULT_ALL, DND_TARGETS, gtk.gdk.ACTION_COPY)
+ self.connect('drag-data-received', self._handle_drag_data_received)
#setup the focus flag
self._focus_flag = False
self.get_focus_flag = lambda: self._focus_flag
- self.connect("leave-notify-event", self._handle_focus_event, False)
- self.connect("enter-notify-event", self._handle_focus_event, True)
+ self.connect('leave-notify-event', self._handle_focus_event, False)
+ self.connect('enter-notify-event', self._handle_focus_event, True)
#pixmap for drawing
self.pixmap = None
- self.gc = None
-
- def draw(self):
- """
- Draw the pixmap onto this drawing area.
- """
- self.window.draw_drawable(self.gc, self.pixmap, 0, 0, 0, 0, -1, -1)
##########################################################################
## Handlers
##########################################################################
+ def _handle_drag_data_received(self, widget, drag_context, x, y, selection_data, info, time):
+ """
+ Handle a drag and drop by adding a block at the given coordinate.
+ """
+ self._main_window.get_flow_graph().add_new_block(selection_data.data, (x, y))
+
def _handle_focus_event(self, widget, event, focus_flag):
"""Record the focus state of the flow graph window."""
self._focus_flag = focus_flag
@@ -83,7 +85,6 @@ class DrawingArea(gtk.DrawingArea):
double_click=(event.type == gtk.gdk._2BUTTON_PRESS),
coordinate=(event.x, event.y),
)
- return True
def _handle_mouse_button_release(self, widget, event):
"""
@@ -94,7 +95,6 @@ class DrawingArea(gtk.DrawingArea):
left_click=(event.button == 1),
coordinate=(event.x, event.y),
)
- return True
def _handle_mouse_motion(self, widget, event):
"""
@@ -104,15 +104,15 @@ class DrawingArea(gtk.DrawingArea):
self._main_window.get_flow_graph().handle_mouse_motion(
coordinate=(event.x, event.y),
)
- return True
def _handle_window_expose(self, widget, event):
"""
- Called when the window initially appears or is resized: create a new pixmap, draw the flow graph.
+ Called when window is exposed, resized, or queue_draw is called.
"""
- self.gc = self.window.new_gc()
+ gc = self.window.new_gc()
width, height = self.get_size_request()
if not self.pixmap or (width, height) != self.pixmap.get_size():
self.pixmap = gtk.gdk.Pixmap(self.window, width, height, -1)
- self._main_window.get_flow_graph().draw()
- return True
+ #double buffering: draw to pixmap, then draw pixmap
+ self._main_window.get_flow_graph().draw(gc, self.pixmap)
+ self.window.draw_drawable(gc, self.pixmap, 0, 0, 0, 0, -1, -1)
diff --git a/grc/src/gui/ParamsDialog.py b/grc/src/gui/ParamsDialog.py
index 5837ab7c4..6cc42e8fc 100644
--- a/grc/src/gui/ParamsDialog.py
+++ b/grc/src/gui/ParamsDialog.py
@@ -1,5 +1,5 @@
"""
-Copyright 2007 Free Software Foundation, Inc.
+Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -45,9 +45,11 @@ class ParamsDialog(gtk.Dialog):
SignalBlockParamsDialog contructor.
@param block the signal block
"""
- gtk.Dialog.__init__(self, buttons=('gtk-close', gtk.RESPONSE_CLOSE))
+ gtk.Dialog.__init__(self,
+ title='Properties: %s'%block.get_name(),
+ buttons=(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE),
+ )
self.block = block
- self.set_title('Properties: %s'%block.get_name())
self.set_size_request(MIN_DIALOG_WIDTH, MIN_DIALOG_HEIGHT)
vbox = gtk.VBox()
#Add the title label
diff --git a/grc/src/platforms/base/Block.py b/grc/src/platforms/base/Block.py
index bc9b58a5e..25688472c 100644
--- a/grc/src/platforms/base/Block.py
+++ b/grc/src/platforms/base/Block.py
@@ -1,5 +1,5 @@
"""
-Copyright 2008 Free Software Foundation, Inc.
+Copyright 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -17,7 +17,6 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-from ... import utils
from ... utils import odict
from Element import Element
from Param import Param
@@ -31,7 +30,7 @@ class TemplateArg(UserDict):
A cheetah template argument created from a param.
The str of this class evaluates to the param's to code method.
The use of this class as a dictionary (enum only) will reveal the enum opts.
- The eval method can return the param evaluated to a raw python data type.
+ The __call__ or () method can return the param evaluated to a raw python data type.
"""
def __init__(self, param):
@@ -44,7 +43,7 @@ class TemplateArg(UserDict):
def __str__(self):
return str(self._param.to_code())
- def eval(self):
+ def __call__(self):
return self._param.evaluate()
class Block(Element):
@@ -59,33 +58,33 @@ class Block(Element):
#build the block
Element.__init__(self, flow_graph)
#grab the data
- params = utils.listify(n, 'param')
- sources = utils.listify(n, 'source')
- sinks = utils.listify(n, 'sink')
- self._name = n['name']
- self._key = n['key']
- self._category = utils.exists_or_else(n, 'category', '')
- self._block_wrapper_path = n['block_wrapper_path']
+ params = n.findall('param')
+ sources = n.findall('source')
+ sinks = n.findall('sink')
+ self._name = n.find('name')
+ self._key = n.find('key')
+ self._category = n.find('category') or ''
+ self._block_wrapper_path = n.find('block_wrapper_path')
#create the param objects
self._params = odict()
#add the id param
self._params['id'] = self.get_parent().get_parent().Param(
self,
- {
+ odict({
'name': 'ID',
'key': 'id',
'type': 'id',
- }
+ })
)
self._params['_enabled'] = self.get_parent().get_parent().Param(
self,
- {
+ odict({
'name': 'Enabled',
'key': '_enabled',
'type': 'raw',
'value': 'True',
'hide': 'all',
- }
+ })
)
for param in map(lambda n: self.get_parent().get_parent().Param(self, n), params):
key = param.get_key()
@@ -250,13 +249,11 @@ class Block(Element):
Any param keys that do not exist will be ignored.
@param n the nested data odict
"""
- params_n = utils.listify(n, 'param')
+ params_n = n.findall('param')
for param_n in params_n:
- #key and value must exist in the n data
- if 'key' in param_n.keys() and 'value' in param_n.keys():
- key = param_n['key']
- value = param_n['value']
- #the key must exist in this block's params
- if key in self.get_param_keys():
- self.get_param(key).set_value(value)
+ key = param_n.find('key')
+ value = param_n.find('value')
+ #the key must exist in this block's params
+ if key in self.get_param_keys():
+ self.get_param(key).set_value(value)
self.validate()
diff --git a/grc/src/platforms/base/FlowGraph.py b/grc/src/platforms/base/FlowGraph.py
index aeb66ac7e..747038bfb 100644
--- a/grc/src/platforms/base/FlowGraph.py
+++ b/grc/src/platforms/base/FlowGraph.py
@@ -1,5 +1,5 @@
"""
-Copyright 2008 Free Software Foundation, Inc.
+Copyright 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -17,7 +17,6 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-from ... import utils
from ... utils import odict
from Element import Element
from Block import Block
@@ -37,7 +36,7 @@ class FlowGraph(Element):
#initialize
Element.__init__(self, platform)
#inital blank import
- self.import_data({'flow_graph': {}})
+ self.import_data()
def _get_unique_id(self, base_id=''):
"""
@@ -179,9 +178,9 @@ class FlowGraph(Element):
n['timestamp'] = time.ctime()
n['block'] = [block.export_data() for block in self.get_blocks()]
n['connection'] = [connection.export_data() for connection in self.get_connections()]
- return {'flow_graph': n}
+ return odict({'flow_graph': n})
- def import_data(self, n):
+ def import_data(self, n=None):
"""
Import blocks and connections into this flow graph.
Clear this flowgraph of all previous blocks and connections.
@@ -190,19 +189,16 @@ class FlowGraph(Element):
"""
#remove previous elements
self._elements = list()
- #the flow graph tag must exists, or use blank data
- if 'flow_graph' in n.keys(): fg_n = n['flow_graph']
- else:
- Messages.send_error_load('Flow graph data not found, loading blank flow graph.')
- fg_n = {}
- blocks_n = utils.listify(fg_n, 'block')
- connections_n = utils.listify(fg_n, 'connection')
+ #use blank data if none provided
+ fg_n = n and n.find('flow_graph') or odict()
+ blocks_n = fg_n.findall('block')
+ connections_n = fg_n.findall('connection')
#create option block
self._options_block = self.get_parent().get_new_block(self, 'options')
self._options_block.get_param('id').set_value('options')
#build the blocks
for block_n in blocks_n:
- key = block_n['key']
+ key = block_n.find('key')
if key == 'options': block = self._options_block
else: block = self.get_new_block(key)
#only load the block when the block key was valid
@@ -210,21 +206,14 @@ class FlowGraph(Element):
else: Messages.send_error_load('Block key "%s" not found in %s'%(key, self.get_parent()))
#build the connections
for connection_n in connections_n:
- #test that the data tags exist
- try:
- assert('source_block_id' in connection_n.keys())
- assert('sink_block_id' in connection_n.keys())
- assert('source_key' in connection_n.keys())
- assert('sink_key' in connection_n.keys())
- except AssertionError: continue
#try to make the connection
try:
#get the block ids
- source_block_id = connection_n['source_block_id']
- sink_block_id = connection_n['sink_block_id']
+ source_block_id = connection_n.find('source_block_id')
+ sink_block_id = connection_n.find('sink_block_id')
#get the port keys
- source_key = connection_n['source_key']
- sink_key = connection_n['sink_key']
+ source_key = connection_n.find('source_key')
+ sink_key = connection_n.find('sink_key')
#verify the blocks
block_ids = map(lambda b: b.get_id(), self.get_blocks())
assert(source_block_id in block_ids)
diff --git a/grc/src/platforms/base/Param.py b/grc/src/platforms/base/Param.py
index ebc9977fc..81783c791 100644
--- a/grc/src/platforms/base/Param.py
+++ b/grc/src/platforms/base/Param.py
@@ -1,5 +1,5 @@
"""
-Copyright 2008 Free Software Foundation, Inc.
+Copyright 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -17,13 +17,11 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-from ... import utils
from ... utils import odict
from Element import Element
import pygtk
pygtk.require('2.0')
import gtk
-import gobject
class InputParam(gtk.HBox):
"""The base class for an input parameter inside the input parameters dialog."""
@@ -60,37 +58,60 @@ class EnumParam(InputParam):
def __init__(self, *args, **kwargs):
InputParam.__init__(self, *args, **kwargs)
- input = gtk.ComboBox(gtk.ListStore(gobject.TYPE_STRING))
- cell = gtk.CellRendererText()
- input.pack_start(cell, True)
- input.add_attribute(cell, 'text', 0)
- for option in self.param.get_options(): input.append_text(option.get_name())
- input.set_active(int(self.param.get_option_keys().index(self.param.get_value())))
- input.connect("changed", self._handle_changed)
- self.pack_start(input, False)
- self.get_text = lambda: str(input.get_active()) #the get text parses the selected index to a string
+ self._input = gtk.combo_box_new_text()
+ for option in self.param.get_options(): self._input.append_text(option.get_name())
+ self._input.set_active(self.param.get_option_keys().index(self.param.get_value()))
+ self._input.connect('changed', self._handle_changed)
+ self.pack_start(self._input, False)
+ def get_text(self): return self.param.get_option_keys()[self._input.get_active()]
+
+class EnumEntryParam(InputParam):
+ """Provide an entry box and drop down menu for Raw Enum types."""
+
+ def __init__(self, *args, **kwargs):
+ InputParam.__init__(self, *args, **kwargs)
+ self._input = gtk.combo_box_entry_new_text()
+ for option in self.param.get_options(): self._input.append_text(option.get_name())
+ try: self._input.set_active(self.param.get_option_keys().index(self.param.get_value()))
+ except:
+ self._input.set_active(-1)
+ self._input.get_child().set_text(self.param.get_value())
+ self._input.connect('changed', self._handle_changed)
+ self._input.get_child().connect('changed', self._handle_changed)
+ self.pack_start(self._input, False)
+ def get_text(self):
+ if self._input.get_active() == -1: return self._input.get_child().get_text()
+ return self.param.get_option_keys()[self._input.get_active()]
+ def set_color(self, color):
+ if self._input.get_active() == -1: #custom entry, use color
+ self._input.get_child().modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse(color))
+ else: #from enum, make white background
+ self._input.get_child().modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse('#ffffff'))
class Option(Element):
- def __init__(self, param, name, key, opts):
+ def __init__(self, param, n):
Element.__init__(self, param)
- self._name = name
- self._key = key
+ self._name = n.find('name')
+ self._key = n.find('key')
self._opts = dict()
+ opts = n.findall('opt')
+ #test against opts when non enum
+ try: assert self.get_parent().is_enum() or not opts
+ except AssertionError: self._exit_with_error('Options for non-enum types cannot have sub-options')
+ #extract opts
for opt in opts:
#separate the key:value
try: key, value = opt.split(':')
except: self._exit_with_error('Error separating "%s" into key:value'%opt)
#test against repeated keys
- try: assert(not self._opts.has_key(key))
+ try: assert not self._opts.has_key(key)
except AssertionError: self._exit_with_error('Key "%s" already exists in option'%key)
#store the option
self._opts[key] = value
def __str__(self): return 'Option %s(%s)'%(self.get_name(), self.get_key())
-
def get_name(self): return self._name
-
def get_key(self): return self._key
##############################################
@@ -100,29 +121,6 @@ class Option(Element):
def get_opt(self, key): return self._opts[key]
def get_opts(self): return self._opts.values()
- ##############################################
- ## Static Make Methods
- ##############################################
- def make_option_from_n(param, n):
- """
- Make a new option from nested data.
- @param param the parent element
- @param n the nested odict
- @return a new option
- """
- #grab the data
- name = n['name']
- key = n['key']
- opts = utils.listify(n, 'opt')
- #build the option
- return Option(
- param=param,
- name=name,
- key=key,
- opts=opts,
- )
- make_option_from_n = staticmethod(make_option_from_n)
-
class Param(Element):
##possible param types
@@ -136,21 +134,16 @@ class Param(Element):
@return a new param
"""
#grab the data
- name = n['name']
- key = n['key']
- value = utils.exists_or_else(n, 'value', '')
- type = n['type']
- hide = utils.exists_or_else(n, 'hide', '')
- options = utils.listify(n, 'option')
+ self._name = n.find('name')
+ self._key = n.find('key')
+ value = n.find('value') or ''
+ self._type = n.find('type')
+ self._hide = n.find('hide') or ''
#build the param
Element.__init__(self, block)
- self._name = name
- self._key = key
- self._type = type
- self._hide = hide
#create the Option objects from the n data
self._options = odict()
- for option in map(lambda o: Option.make_option_from_n(self, o), options):
+ for option in map(lambda o: Option(self, o), n.findall('option')):
key = option.get_key()
#test against repeated keys
try: assert(key not in self.get_option_keys())
@@ -226,7 +219,7 @@ class Param(Element):
self._value = str(value) #must be a string
def get_type(self): return self.get_parent().resolve_dependencies(self._type)
- def is_enum(self): return bool(self.get_options())
+ def is_enum(self): return self._type == 'enum'
def __repr__(self):
"""
@@ -241,9 +234,13 @@ class Param(Element):
def get_input_class(self):
"""
Get the graphical gtk class to represent this parameter.
+ An enum requires and combo parameter.
+ A non-enum with options gets a combined entry/combo parameter.
+ All others get a standard entry parameter.
@return gtk input class
"""
if self.is_enum(): return EnumParam
+ if self.get_options(): return EnumEntryParam
return EntryParam
##############################################
diff --git a/grc/src/platforms/base/Platform.py b/grc/src/platforms/base/Platform.py
index 1a96594bb..1f04fa0a6 100644
--- a/grc/src/platforms/base/Platform.py
+++ b/grc/src/platforms/base/Platform.py
@@ -1,5 +1,5 @@
"""
-Copyright 2008 Free Software Foundation, Inc.
+Copyright 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -19,7 +19,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
import os
from ... utils import ParseXML
-from ... import utils
from Element import Element as _Element
from FlowGraph import FlowGraph as _FlowGraph
from Connection import Connection as _Connection
@@ -73,17 +72,17 @@ class Platform(_Element):
"""
try: ParseXML.validate_dtd(f, self._block_dtd)
except ParseXML.XMLSyntaxError, e: self._exit_with_error('Block definition "%s" failed: \n\t%s'%(f, e))
- for n in utils.listify(ParseXML.from_file(f), 'block'):
- #inject block wrapper path
- n['block_wrapper_path'] = f
- block = self.Block(self._flow_graph, n)
- key = block.get_key()
- #test against repeated keys
- try: assert(key not in self.get_block_keys())
- except AssertionError: self._exit_with_error('Key "%s" already exists in blocks'%key)
- #store the block
- self._blocks[key] = block
- self._blocks_n[key] = n
+ n = ParseXML.from_file(f).find('block')
+ #inject block wrapper path
+ n['block_wrapper_path'] = f
+ block = self.Block(self._flow_graph, n)
+ key = block.get_key()
+ #test against repeated keys
+ try: assert(key not in self.get_block_keys())
+ except AssertionError: self._exit_with_error('Key "%s" already exists in blocks'%key)
+ #store the block
+ self._blocks[key] = block
+ self._blocks_n[key] = n
def load_block_tree(self, block_tree):
"""
@@ -93,21 +92,21 @@ class Platform(_Element):
@param block_tree the block tree object
"""
#recursive function to load categories and blocks
- def load_category(cat_n, parent=''):
+ def load_category(cat_n, parent=[]):
#add this category
- parent = '%s/%s'%(parent, cat_n['name'])
+ parent = parent + [cat_n.find('name')]
block_tree.add_block(parent)
#recursive call to load sub categories
- map(lambda c: load_category(c, parent), utils.listify(cat_n, 'cat'))
+ map(lambda c: load_category(c, parent), cat_n.findall('cat'))
#add blocks in this category
- for block_key in utils.listify(cat_n, 'block'):
+ for block_key in cat_n.findall('block'):
block_tree.add_block(parent, self.get_block(block_key))
#load the block tree
f = self._block_tree
try: ParseXML.validate_dtd(f, BLOCK_TREE_DTD)
except ParseXML.XMLSyntaxError, e: self._exit_with_error('Block tree "%s" failed: \n\t%s'%(f, e))
#add all blocks in the tree
- load_category(ParseXML.from_file(f)['cat'])
+ load_category(ParseXML.from_file(f).find('cat'))
#add all other blocks, use the catgory
for block in self.get_blocks():
#blocks with empty categories are in the xml block tree or hidden
diff --git a/grc/src/platforms/base/Port.py b/grc/src/platforms/base/Port.py
index 26ad1fc4a..f46a81195 100644
--- a/grc/src/platforms/base/Port.py
+++ b/grc/src/platforms/base/Port.py
@@ -1,5 +1,5 @@
"""
-Copyright 2008 Free Software Foundation, Inc.
+Copyright 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -17,7 +17,6 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-from ... import utils
from Element import Element
class Port(Element):
diff --git a/grc/src/platforms/gui/Block.py b/grc/src/platforms/gui/Block.py
index ab6a6d0b2..4aa35bf03 100644
--- a/grc/src/platforms/gui/Block.py
+++ b/grc/src/platforms/gui/Block.py
@@ -1,5 +1,5 @@
"""
-Copyright 2007 Free Software Foundation, Inc.
+Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -20,15 +20,19 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
from Element import Element
import Utils
import Colors
-from ... gui.Constants import BORDER_PROXIMITY_SENSITIVITY
+from ... utils import odict
+from Constants import BORDER_PROXIMITY_SENSITIVITY
from Constants import \
- BLOCK_FONT, BLOCK_LABEL_PADDING, \
+ BLOCK_LABEL_PADDING, \
PORT_SEPARATION, LABEL_SEPARATION, \
PORT_BORDER_SEPARATION, POSSIBLE_ROTATIONS
import pygtk
pygtk.require('2.0')
import gtk
-import pango
+
+BLOCK_MARKUP_TMPL="""\
+#set $foreground = $block.is_valid() and 'black' or 'red'
+<span foreground="$foreground" font_desc="Sans 8"><b>$encode($block.get_name())</b></span>"""
class Block(Element):
"""The graphical signal block."""
@@ -41,23 +45,23 @@ class Block(Element):
#add the position param
self._params['_coordinate'] = self.get_parent().get_parent().Param(
self,
- {
+ odict({
'name': 'GUI Coordinate',
'key': '_coordinate',
'type': 'raw',
'value': '(0, 0)',
'hide': 'all',
- }
+ })
)
self._params['_rotation'] = self.get_parent().get_parent().Param(
self,
- {
+ odict({
'name': 'GUI Rotation',
'key': '_rotation',
'type': 'raw',
'value': '0',
'hide': 'all',
- }
+ })
)
Element.__init__(self)
@@ -130,10 +134,7 @@ class Block(Element):
#create the main layout
layout = gtk.DrawingArea().create_pango_layout('')
layouts.append(layout)
- if self.is_valid(): layout.set_markup('<b>'+Utils.xml_encode(self.get_name())+'</b>')
- else: layout.set_markup('<span foreground="red"><b>'+Utils.xml_encode(self.get_name())+'</b></span>')
- desc = pango.FontDescription(BLOCK_FONT)
- layout.set_font_description(desc)
+ layout.set_markup(Utils.parse_template(BLOCK_MARKUP_TMPL, block=self))
self.label_width, self.label_height = layout.get_pixel_size()
#display the params
for param in filter(lambda p: p.get_hide() not in ('all', 'part'), self.get_params()):
@@ -166,22 +167,22 @@ class Block(Element):
for j in range(height): vimage.put_pixel(j, width-i-1, image.get_pixel(i, j))
map(lambda p: p._create_labels(), self.get_ports())
- def draw(self, window):
+ def draw(self, gc, window):
"""
Draw the signal block with label and inputs/outputs.
+ @param gc the graphics context
@param window the gtk window to draw on
"""
x, y = self.get_coordinate()
#draw main block
- Element.draw(self, window, BG_color=self.bg_color)
+ Element.draw(self, gc, window, BG_color=self.bg_color)
#draw label image
- gc = self.get_gc()
if self.is_horizontal():
window.draw_image(gc, self.horizontal_label, 0, 0, x+BLOCK_LABEL_PADDING, y+(self.H-self.label_height)/2, -1, -1)
elif self.is_vertical():
window.draw_image(gc, self.vertical_label, 0, 0, x+(self.H-self.label_height)/2, y+BLOCK_LABEL_PADDING, -1, -1)
#draw ports
- map(lambda p: p.draw(window), self.get_ports())
+ for port in self.get_ports(): port.draw(gc, window)
def what_is_selected(self, coor, coor_m=None):
"""
diff --git a/grc/src/platforms/gui/Connection.py b/grc/src/platforms/gui/Connection.py
index b130611fb..9f243215e 100644
--- a/grc/src/platforms/gui/Connection.py
+++ b/grc/src/platforms/gui/Connection.py
@@ -106,9 +106,10 @@ class Connection(Element):
self.add_line((x1, y1), points[0])
self.add_line((x2, y2), points[0])
- def draw(self, window):
+ def draw(self, gc, window):
"""
Draw the connection.
+ @param gc the graphics context
@param window the gtk window to draw on
"""
sink = self.get_sink()
@@ -123,8 +124,7 @@ class Connection(Element):
self._source_coor = source.get_coordinate()
#draw
fg_color = self.get_enabled() and Colors.FG_COLOR or Colors.DISABLED_FG_COLOR
- Element.draw(self, window, FG_color=fg_color)
- gc = self.get_gc()
+ Element.draw(self, gc, window, FG_color=fg_color)
gc.foreground = self._foreground
#draw arrow on sink port
window.draw_polygon(gc, True, self._arrow)
diff --git a/grc/src/platforms/gui/Constants.py b/grc/src/platforms/gui/Constants.py
index 00899cb78..90c8c1c38 100644
--- a/grc/src/platforms/gui/Constants.py
+++ b/grc/src/platforms/gui/Constants.py
@@ -1,23 +1,21 @@
-#
-# Copyright 2008 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.
-#
+"""
+Copyright 2008, 2009 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
+"""
#label constraint dimensions
LABEL_SEPARATION = 3
@@ -27,11 +25,6 @@ PORT_LABEL_PADDING = 2
PORT_SEPARATION = 17
PORT_BORDER_SEPARATION = 9
PORT_MIN_WIDTH = 20
-#fonts
-PARAM_LABEL_FONT = 'Sans 9.5'
-PARAM_FONT = 'Sans 7.5'
-BLOCK_FONT = 'Sans 8'
-PORT_FONT = 'Sans 7.5'
#minimal length of connector
CONNECTOR_EXTENSION_MINIMAL = 11
#increment length for connector
@@ -41,3 +34,11 @@ CONNECTOR_ARROW_BASE = 13
CONNECTOR_ARROW_HEIGHT = 17
#possible rotations in degrees
POSSIBLE_ROTATIONS = (0, 90, 180, 270)
+#How close can the mouse get to the window border before mouse events are ignored.
+BORDER_PROXIMITY_SENSITIVITY = 50
+#How close the mouse can get to the edge of the visible window before scrolling is invoked.
+SCROLL_PROXIMITY_SENSITIVITY = 30
+#When the window has to be scrolled, move it this distance in the required direction.
+SCROLL_DISTANCE = 15
+#How close the mouse click can be to a line and register a connection select.
+LINE_SELECT_SENSITIVITY = 5
diff --git a/grc/src/platforms/gui/Element.py b/grc/src/platforms/gui/Element.py
index f97d85ff6..8ef288ed1 100644
--- a/grc/src/platforms/gui/Element.py
+++ b/grc/src/platforms/gui/Element.py
@@ -22,7 +22,7 @@ import pygtk
pygtk.require('2.0')
import gtk
import pango
-from ... gui.Constants import CONNECTION_SELECT_SENSITIVITY
+from Constants import LINE_SELECT_SENSITIVITY
from Constants import POSSIBLE_ROTATIONS
class Element(object):
@@ -61,17 +61,14 @@ class Element(object):
rotation = rotation or self.get_rotation()
return rotation in (90, 270)
- def get_gc(self): return self._gc
-
- def draw(self, window, BG_color=Colors.BG_COLOR, FG_color=Colors.FG_COLOR):
+ def draw(self, gc, window, BG_color=Colors.BG_COLOR, FG_color=Colors.FG_COLOR):
"""
Draw in the given window.
+ @param gc the graphics context
@param window the gtk window to draw on
@param BG_color the background color
@param FG_color the foreground color
"""
- gc = self.get_parent().get_gc()
- self._gc = gc
X,Y = self.get_coordinate()
for (rX,rY),(W,H) in self.areas_dict[self.get_rotation()]:
aX = X + rX
@@ -84,12 +81,12 @@ class Element(object):
gc.foreground = self.is_highlighted() and Colors.H_COLOR or FG_color
window.draw_line(gc, X+x1, Y+y1, X+x2, Y+y2)
- def rotate(self, direction):
+ def rotate(self, rotation):
"""
Rotate all of the areas by 90 degrees.
- @param direction 90 or 270 degrees
+ @param rotation multiple of 90 degrees
"""
- self.set_rotation((self.get_rotation() + direction)%360)
+ self.set_rotation((self.get_rotation() + rotation)%360)
def clear(self):
"""Empty the lines and areas."""
@@ -204,8 +201,8 @@ class Element(object):
if in_between(x, x1, x1+w) and in_between(y, y1, y1+h): return self
#handle horizontal or vertical lines
for (x1, y1), (x2, y2) in self.lines_dict[self.get_rotation()]:
- if x1 == x2: x1, x2 = x1-CONNECTION_SELECT_SENSITIVITY, x2+CONNECTION_SELECT_SENSITIVITY
- if y1 == y2: y1, y2 = y1-CONNECTION_SELECT_SENSITIVITY, y2+CONNECTION_SELECT_SENSITIVITY
+ if x1 == x2: x1, x2 = x1-LINE_SELECT_SENSITIVITY, x2+LINE_SELECT_SENSITIVITY
+ if y1 == y2: y1, y2 = y1-LINE_SELECT_SENSITIVITY, y2+LINE_SELECT_SENSITIVITY
if in_between(x, x1, x2) and in_between(y, y1, y2): return self
return None
diff --git a/grc/src/platforms/gui/FlowGraph.py b/grc/src/platforms/gui/FlowGraph.py
index cc2e27163..31d90984d 100644
--- a/grc/src/platforms/gui/FlowGraph.py
+++ b/grc/src/platforms/gui/FlowGraph.py
@@ -1,5 +1,5 @@
"""
-Copyright 2007 Free Software Foundation, Inc.
+Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -17,25 +17,19 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-from ... gui.Constants import \
- DIR_LEFT, DIR_RIGHT, \
- SCROLL_PROXIMITY_SENSITIVITY, SCROLL_DISTANCE, \
- MOTION_DETECT_REDRAWING_SENSITIVITY
+from Constants import SCROLL_PROXIMITY_SENSITIVITY, SCROLL_DISTANCE
from ... gui.Actions import \
ELEMENT_CREATE, ELEMENT_SELECT, \
BLOCK_PARAM_MODIFY, BLOCK_MOVE, \
ELEMENT_DELETE
import Colors
import Utils
-from ... import utils
-from ... gui.ParamsDialog import ParamsDialog
from Element import Element
from .. base import FlowGraph as _FlowGraph
import pygtk
pygtk.require('2.0')
import gtk
import random
-import time
from ... gui import Messages
class FlowGraph(Element):
@@ -57,7 +51,6 @@ class FlowGraph(Element):
self.element_moved = False
self.mouse_pressed = False
self.unselect()
- self.time = 0
self.press_coor = (0, 0)
#selected ports
self._old_selected_port = None
@@ -67,28 +60,31 @@ class FlowGraph(Element):
# Access Drawing Area
###########################################################################
def get_drawing_area(self): return self.drawing_area
- def get_gc(self): return self.get_drawing_area().gc
- def get_pixmap(self): return self.get_drawing_area().pixmap
+ def queue_draw(self): self.get_drawing_area().queue_draw()
def get_size(self): return self.get_drawing_area().get_size_request()
def set_size(self, *args): self.get_drawing_area().set_size_request(*args)
def get_window(self): return self.get_drawing_area().window
+ def get_pixmap(self): return self.get_drawing_area().pixmap
def get_scroll_pane(self): return self.drawing_area.get_parent()
def get_ctrl_mask(self): return self.drawing_area.ctrl_mask
- def add_new_block(self, key):
+ def add_new_block(self, key, coor=None):
"""
Add a block of the given key to this flow graph.
@param key the block key
+ @param coor an optional coordinate or None for random
"""
id = self._get_unique_id(key)
#calculate the position coordinate
h_adj = self.get_scroll_pane().get_hadjustment()
v_adj = self.get_scroll_pane().get_vadjustment()
- x = int(random.uniform(.25, .75)*h_adj.page_size + h_adj.get_value())
- y = int(random.uniform(.25, .75)*v_adj.page_size + v_adj.get_value())
+ if coor is None: coor = (
+ int(random.uniform(.25, .75)*h_adj.page_size + h_adj.get_value()),
+ int(random.uniform(.25, .75)*v_adj.page_size + v_adj.get_value()),
+ )
#get the new block
block = self.get_new_block(key)
- block.set_coordinate((x, y))
+ block.set_coordinate(coor)
block.set_rotation(0)
block.get_param('id').set_value(id)
self.handle_states(ELEMENT_CREATE)
@@ -137,15 +133,15 @@ class FlowGraph(Element):
y_off = v_adj.get_value() - y_min + v_adj.page_size/4
#create blocks
for block_n in blocks_n:
- block_key = block_n['key']
+ block_key = block_n.find('key')
if block_key == 'options': continue
block = self.get_new_block(block_key)
selected.add(block)
#set params
- params_n = utils.listify(block_n, 'param')
+ params_n = block_n.findall('param')
for param_n in params_n:
- param_key = param_n['key']
- param_value = param_n['value']
+ param_key = param_n.find('key')
+ param_value = param_n.find('value')
#setup id parameter
if param_key == 'id':
old_id2block[param_value] = block
@@ -160,8 +156,8 @@ class FlowGraph(Element):
self.update()
#create connections
for connection_n in connections_n:
- source = old_id2block[connection_n['source_block_id']].get_source(connection_n['source_key'])
- sink = old_id2block[connection_n['sink_block_id']].get_sink(connection_n['sink_key'])
+ source = old_id2block[connection_n.find('source_block_id')].get_source(connection_n.find('source_key'))
+ sink = old_id2block[connection_n.find('sink_block_id')].get_sink(connection_n.find('sink_key'))
self.connect(source, sink)
#set all pasted elements selected
for block in selected: selected = selected.union(set(block.get_connections()))
@@ -186,14 +182,6 @@ class FlowGraph(Element):
"""
return any([sb.port_controller_modify(direction) for sb in self.get_selected_blocks()])
- def param_modify_selected(self):
- """
- Create and show a param modification dialog for the selected block.
- @return true if parameters were changed
- """
- if not self.get_selected_block(): return False
- return ParamsDialog(self.get_selected_block()).run()
-
def enable_selected(self, enable):
"""
Enable/disable the selected blocks.
@@ -216,15 +204,13 @@ class FlowGraph(Element):
selected_block.move(delta_coordinate)
self.element_moved = True
- def rotate_selected(self, direction):
+ def rotate_selected(self, rotation):
"""
- Rotate the selected blocks by 90 degrees.
- @param direction DIR_LEFT or DIR_RIGHT
+ Rotate the selected blocks by multiples of 90 degrees.
+ @param rotation the rotation in degrees
@return true if changed, otherwise false.
"""
if not self.get_selected_blocks(): return False
- #determine the number of degrees to rotate
- rotation = {DIR_LEFT: 90, DIR_RIGHT:270}[direction]
#initialize min and max coordinates
min_x, min_y = self.get_selected_block().get_coordinate()
max_x, max_y = self.get_selected_block().get_coordinate()
@@ -255,55 +241,49 @@ class FlowGraph(Element):
changed = True
return changed
- def draw(self):
+ def draw(self, gc, window):
"""
Draw the background and grid if enabled.
Draw all of the elements in this flow graph onto the pixmap.
Draw the pixmap to the drawable window of this flow graph.
"""
- if self.get_gc():
- W,H = self.get_size()
- #draw the background
- self.get_gc().foreground = Colors.BACKGROUND_COLOR
- self.get_pixmap().draw_rectangle(self.get_gc(), True, 0, 0, W, H)
- #draw multi select rectangle
- if self.mouse_pressed and (not self.get_selected_elements() or self.get_ctrl_mask()):
- #coordinates
- x1, y1 = self.press_coor
- x2, y2 = self.get_coordinate()
- #calculate top-left coordinate and width/height
- x, y = int(min(x1, x2)), int(min(y1, y2))
- w, h = int(abs(x1 - x2)), int(abs(y1 - y2))
- #draw
- self.get_gc().foreground = Colors.H_COLOR
- self.get_pixmap().draw_rectangle(self.get_gc(), True, x, y, w, h)
- self.get_gc().foreground = Colors.TXT_COLOR
- self.get_pixmap().draw_rectangle(self.get_gc(), False, x, y, w, h)
- #draw blocks on top of connections
- for element in self.get_connections() + self.get_blocks():
- element.draw(self.get_pixmap())
- #draw selected blocks on top of selected connections
- for selected_element in self.get_selected_connections() + self.get_selected_blocks():
- selected_element.draw(self.get_pixmap())
- self.get_drawing_area().draw()
+ try: #set the size of the flow graph area (if changed)
+ new_size = self.get_option('window_size')
+ if self.get_size() != tuple(new_size): self.set_size(*new_size)
+ except: pass
+ W,H = self.get_size()
+ #draw the background
+ gc.foreground = Colors.BACKGROUND_COLOR
+ window.draw_rectangle(gc, True, 0, 0, W, H)
+ #draw multi select rectangle
+ if self.mouse_pressed and (not self.get_selected_elements() or self.get_ctrl_mask()):
+ #coordinates
+ x1, y1 = self.press_coor
+ x2, y2 = self.get_coordinate()
+ #calculate top-left coordinate and width/height
+ x, y = int(min(x1, x2)), int(min(y1, y2))
+ w, h = int(abs(x1 - x2)), int(abs(y1 - y2))
+ #draw
+ gc.foreground = Colors.H_COLOR
+ window.draw_rectangle(gc, True, x, y, w, h)
+ gc.foreground = Colors.TXT_COLOR
+ window.draw_rectangle(gc, False, x, y, w, h)
+ #draw blocks on top of connections
+ for element in self.get_connections() + self.get_blocks():
+ element.draw(gc, window)
+ #draw selected blocks on top of selected connections
+ for selected_element in self.get_selected_connections() + self.get_selected_blocks():
+ selected_element.draw(gc, window)
def update(self):
"""
Update highlighting so only the selected is highlighted.
Call update on all elements.
- Resize the window if size changed.
"""
- #update highlighting
- map(lambda e: e.set_highlighted(False), self.get_elements())
- for selected_element in self.get_selected_elements():
- selected_element.set_highlighted(True)
- #update all elements
- map(lambda e: e.update(), self.get_elements())
- #set the size of the flow graph area
- old_x, old_y = self.get_size()
- try: new_x, new_y = self.get_option('window_size')
- except: new_x, new_y = old_x, old_y
- if new_x != old_x or new_y != old_y: self.set_size(new_x, new_y)
+ selected_elements = self.get_selected_elements()
+ for element in self.get_elements():
+ element.set_highlighted(element in selected_elements)
+ element.update()
##########################################################################
## Get Selected
@@ -466,7 +446,6 @@ class FlowGraph(Element):
self.handle_states(BLOCK_MOVE)
self.element_moved = False
self.update_selected_elements()
- self.draw()
def handle_mouse_motion(self, coordinate):
"""
@@ -474,9 +453,8 @@ class FlowGraph(Element):
Move a selected element to the new coordinate.
Auto-scroll the scroll bars at the boundaries.
"""
- #to perform a movement, the mouse must be pressed, timediff large enough
- if not self.mouse_pressed: return
- if time.time() - self.time < MOTION_DETECT_REDRAWING_SENSITIVITY: return
+ #to perform a movement, the mouse must be pressed, no pending events
+ if gtk.events_pending() or not self.mouse_pressed: return
#perform autoscrolling
width, height = self.get_size()
x, y = coordinate
@@ -499,7 +477,6 @@ class FlowGraph(Element):
#move the selected elements and record the new coordinate
X, Y = self.get_coordinate()
if not self.get_ctrl_mask(): self.move_selected((int(x - X), int(y - Y)))
- self.draw()
self.set_coordinate((x, y))
- #update time
- self.time = time.time()
+ #queue draw for animation
+ self.queue_draw()
diff --git a/grc/src/platforms/gui/Param.py b/grc/src/platforms/gui/Param.py
index 2afe18c57..33a9b1f52 100644
--- a/grc/src/platforms/gui/Param.py
+++ b/grc/src/platforms/gui/Param.py
@@ -1,5 +1,5 @@
"""
-Copyright 2007 Free Software Foundation, Inc.
+Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -22,8 +22,30 @@ from Element import Element
import pygtk
pygtk.require('2.0')
import gtk
-import pango
-from Constants import PARAM_LABEL_FONT, PARAM_FONT
+
+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>"""
+
+PARAM_LABEL_MARKUP_TMPL="""\
+#set $foreground = $param.is_valid() and 'black' or 'red'
+#set $underline = $has_cb and 'low' or 'none'
+<span underline="$underline" foreground="$foreground" font_desc="Sans 9">$encode($param.get_name())</span>"""
+
+TIP_MARKUP_TMPL="""\
+Key: $param.get_key()
+Type: $param.get_type()
+#if $param.is_valid()
+Value: $param.evaluate()
+#elif len($param.get_error_messages()) == 1
+Error: $(param.get_error_messages()[0])
+#else
+Error:
+ #for $error_msg in $param.get_error_messages()
+ * $error_msg
+ #end for
+#end if"""
class Param(Element):
"""The graphical parameter."""
@@ -52,24 +74,12 @@ class Param(Element):
When the input changes, write the inputs to the data type.
Finish by calling the exteral callback.
"""
- value = self._input.get_text()
- if self.is_enum(): value = self.get_option_keys()[int(value)]
- self.set_value(value)
- #set the markup on the label, red for errors in corresponding data type.
- name = '<span font_desc="%s">%s</span>'%(
- PARAM_LABEL_FONT,
- Utils.xml_encode(self.get_name()),
- )
- #special markups if param is involved in a callback
- if hasattr(self.get_parent(), 'get_callbacks') and \
- filter(lambda c: self.get_key() in c, self.get_parent()._callbacks):
- name = '<span underline="low">%s</span>'%name
- if not self.is_valid():
- self._input.set_markup('<span foreground="red">%s</span>'%name)
- tip = 'Error: ' + ' '.join(self.get_error_messages())
- else:
- self._input.set_markup(name)
- tip = 'Value: %s'%str(self.evaluate())
+ self.set_value(self._input.get_text())
+ #is param is involved in a callback? #FIXME: messy
+ has_cb = \
+ hasattr(self.get_parent(), 'get_callbacks') and \
+ filter(lambda c: self.get_key() in c, self.get_parent()._callbacks)
+ self._input.set_markup(Utils.parse_template(PARAM_LABEL_MARKUP_TMPL, param=self, has_cb=has_cb))
#hide/show
if self.get_hide() == 'all': self._input.hide_all()
else: self._input.show_all()
@@ -78,30 +88,16 @@ class Param(Element):
#set the tooltip
if self._input.tp: self._input.tp.set_tip(
self._input.entry,
- 'Key: %s\nType: %s\n%s'%(self.get_key(), self.get_type(), tip),
+ Utils.parse_template(TIP_MARKUP_TMPL, param=self).strip(),
)
#execute the external callback
if self._callback: self._callback(self)
- def get_markup(self):
- """
- Create a markup to display the param as a label on the block.
- If the param is valid, use the param's repr representation.
- Otherwise, create a markup for error.
- @return pango markup string
- """
- if self.is_valid():
- return '<b>%s:</b> %s'%(Utils.xml_encode(self.get_name()), Utils.xml_encode(repr(self)))
- else:
- return '<span foreground="red"><b>%s:</b> error</span>'%Utils.xml_encode(self.get_name())
-
def get_layout(self):
"""
Create a layout based on the current markup.
@return the pango layout
"""
layout = gtk.DrawingArea().create_pango_layout('')
- layout.set_markup(self.get_markup())
- desc = pango.FontDescription(PARAM_FONT)
- layout.set_font_description(desc)
+ layout.set_markup(Utils.parse_template(PARAM_MARKUP_TMPL, param=self))
return layout
diff --git a/grc/src/platforms/gui/Port.py b/grc/src/platforms/gui/Port.py
index 85d9fea5a..3aec6e4a7 100644
--- a/grc/src/platforms/gui/Port.py
+++ b/grc/src/platforms/gui/Port.py
@@ -20,13 +20,16 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
from Element import Element
from Constants import \
PORT_SEPARATION, CONNECTOR_EXTENSION_MINIMAL, \
- CONNECTOR_EXTENSION_INCREMENT, PORT_FONT, \
+ CONNECTOR_EXTENSION_INCREMENT, \
PORT_LABEL_PADDING, PORT_MIN_WIDTH
+import Utils
import Colors
import pygtk
pygtk.require('2.0')
import gtk
-import pango
+
+PORT_MARKUP_TMPL="""\
+<span foreground="black" font_desc="Sans 7.5">$encode($port.get_name())</span>"""
class Port(Element):
"""The graphical port."""
@@ -83,9 +86,8 @@ class Port(Element):
"""Create the labels for the socket."""
self.BG_color = Colors.get_color(self.get_color())
#create the layout
- layout = gtk.DrawingArea().create_pango_layout(self.get_name())
- desc = pango.FontDescription(PORT_FONT)
- layout.set_font_description(desc)
+ layout = gtk.DrawingArea().create_pango_layout('')
+ layout.set_markup(Utils.parse_template(PORT_MARKUP_TMPL, port=self))
self.w, self.h = layout.get_pixel_size()
self.W, self.H = 2*PORT_LABEL_PADDING+self.w, 2*PORT_LABEL_PADDING+self.h
#create the pixmap
@@ -102,13 +104,13 @@ class Port(Element):
for i in range(self.w):
for j in range(self.h): vimage.put_pixel(j, self.w-i-1, image.get_pixel(i, j))
- def draw(self, window):
+ def draw(self, gc, window):
"""
Draw the socket with a label.
+ @param gc the graphics context
@param window the gtk window to draw on
"""
- Element.draw(self, window, BG_color=self.BG_color)
- gc = self.get_gc()
+ Element.draw(self, gc, window, BG_color=self.BG_color)
gc.foreground = Colors.TXT_COLOR
X,Y = self.get_coordinate()
(x,y),(w,h) = self.areas_dict[self.get_rotation()][0] #use the first area's sizes to place the labels
diff --git a/grc/src/platforms/gui/Utils.py b/grc/src/platforms/gui/Utils.py
index 17750ef45..ee6dc6cdc 100644
--- a/grc/src/platforms/gui/Utils.py
+++ b/grc/src/platforms/gui/Utils.py
@@ -1,5 +1,5 @@
"""
-Copyright 2008 Free Software Foundation, Inc.
+Copyright 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -18,6 +18,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
from Constants import POSSIBLE_ROTATIONS
+from Cheetah.Template import Template
def get_rotated_coordinate(coor, rotation):
"""
@@ -69,3 +70,13 @@ def xml_encode(string):
("'", '&apos;'),
): string = string.replace(char, safe)
return string
+
+def parse_template(tmpl_str, **kwargs):
+ """
+ Parse the template string with the given args.
+ Pass in the xml encode method for pango escape chars.
+ @param tmpl_str the template as a string
+ @return a string of the parsed template
+ """
+ kwargs['encode'] = xml_encode
+ return str(Template(tmpl_str, kwargs))
diff --git a/grc/src/platforms/python/Block.py b/grc/src/platforms/python/Block.py
index 3c45117a3..38a0ce492 100644
--- a/grc/src/platforms/python/Block.py
+++ b/grc/src/platforms/python/Block.py
@@ -19,7 +19,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
from .. base.Block import Block as _Block
from utils import extract_docs
-from ... import utils
class Block(_Block):
@@ -36,11 +35,11 @@ class Block(_Block):
@return block a new block
"""
#grab the data
- doc = utils.exists_or_else(n, 'doc', '')
- imports = map(lambda i: i.strip(), utils.listify(n, 'import'))
- make = n['make']
- checks = utils.listify(n, 'check')
- callbacks = utils.listify(n, 'callback')
+ doc = n.find('doc') or ''
+ imports = map(lambda i: i.strip(), n.findall('import'))
+ make = n.find('make')
+ checks = n.findall('check')
+ callbacks = n.findall('callback')
#build the block
_Block.__init__(
self,
diff --git a/grc/src/platforms/python/Constants.py.in b/grc/src/platforms/python/Constants.py.in
index 199b24223..502f41550 100644
--- a/grc/src/platforms/python/Constants.py.in
+++ b/grc/src/platforms/python/Constants.py.in
@@ -50,3 +50,4 @@ FLOAT_VECTOR_COLOR_SPEC = '#CC8C69'
INT_VECTOR_COLOR_SPEC = '#00CC99'
SHORT_VECTOR_COLOR_SPEC = '#CCCC33'
BYTE_VECTOR_COLOR_SPEC = '#CC66CC'
+ID_COLOR_SPEC = '#DDDDDD'
diff --git a/grc/src/platforms/python/FlowGraph.py b/grc/src/platforms/python/FlowGraph.py
index cd5635b95..95c0b38cb 100644
--- a/grc/src/platforms/python/FlowGraph.py
+++ b/grc/src/platforms/python/FlowGraph.py
@@ -1,5 +1,5 @@
"""
-Copyright 2008 Free Software Foundation, Inc.
+Copyright 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -22,21 +22,15 @@ from .. base.FlowGraph import FlowGraph as _FlowGraph
from Block import Block
from Connection import Connection
-def get_variable_code(variable):
+def _get_value_expr(variable_block):
"""
- Get the code representation for a variable.
- Normally this is the value parameter.
- For the variable chooser, use the index and choices.
- Avoid using the to_code method of the variables,
- as this forces evaluation before the variables are evaluated.
- @param variable the variable block
- @return the code string
+ Get the expression to evaluate from the value param.
+ @param variable_block the variable or parameter block
+ @return the expression string
"""
- if variable.get_key() == 'variable_chooser':
- choices = variable.get_param('choices').get_value()
- value_index = variable.get_param('value_index').get_value()
- return "(%s)[%s]"%(choices, value_index)
- return variable.get_param('value').get_value()
+ value_param = variable_block.get_param('value')
+ value_param.evaluate() #evaluate prior to code
+ return value_param.to_code()
class FlowGraph(_FlowGraph):
@@ -117,7 +111,7 @@ class FlowGraph(_FlowGraph):
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(), get_variable_code(var)) for var in variables])
+ id2expr = dict([(var.get_id(), var.get_param('value').get_value()) for var in variables])
#sort according to dependency
sorted_ids = expr_utils.sort_variables(id2expr)
#create list of sorted variable blocks
@@ -151,14 +145,14 @@ class FlowGraph(_FlowGraph):
np = dict()
for parameter in self.get_parameters():
try:
- e = self._eval(parameter.get_param('value').to_code(), n)
+ e = self._eval(_get_value_expr(parameter), n)
np[parameter.get_id()] = e
except: pass
n.update(np) #merge param namespace
#load variables
for variable in self.get_variables():
try:
- e = self._eval(get_variable_code(variable), n)
+ e = self._eval(_get_value_expr(variable), n)
n[variable.get_id()] = e
except: pass
#make namespace public
diff --git a/grc/src/platforms/python/Generator.py b/grc/src/platforms/python/Generator.py
index 83dd186c3..93321404a 100644
--- a/grc/src/platforms/python/Generator.py
+++ b/grc/src/platforms/python/Generator.py
@@ -53,7 +53,7 @@ class Generator(object):
def write(self):
#do throttle warning
all_keys = ' '.join(map(lambda b: b.get_key(), self._flow_graph.get_enabled_blocks()))
- if ('usrp' not in all_keys) and ('audio' not in all_keys) and ('throttle' not in all_keys):
+ if ('usrp' not in all_keys) and ('audio' not in all_keys) and ('throttle' not in all_keys) and self._generate_options != 'hb':
Messages.send_warning('''\
This flow graph may not have flow control: no audio or usrp blocks found. \
Add a Misc->Throttle block to your flow graph to avoid CPU congestion.''')
diff --git a/grc/src/platforms/python/Param.py b/grc/src/platforms/python/Param.py
index efebe92e5..e75a882a4 100644
--- a/grc/src/platforms/python/Param.py
+++ b/grc/src/platforms/python/Param.py
@@ -1,5 +1,5 @@
"""
-Copyright 2008 Free Software Foundation, Inc.
+Copyright 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -94,7 +94,7 @@ class Param(_Param):
Get the repr (nice string format) for this param.
@return the string representation
"""
- if self.is_enum(): return _Param.__repr__(self)
+ if self.get_value() in self.get_option_keys(): return self.get_option(self.get_value()).get_name()
##################################################
# display logic for numbers
##################################################
@@ -158,7 +158,7 @@ class Param(_Param):
#special
'hex': Constants.INT_COLOR_SPEC,
'string': Constants.BYTE_VECTOR_COLOR_SPEC,
- 'id': '#DDDDDD',
+ 'id': Constants.ID_COLOR_SPEC,
'grid_pos': Constants.INT_VECTOR_COLOR_SPEC,
}[self.get_type()]
except: return _Param.get_color(self)
diff --git a/grc/src/platforms/python/Port.py b/grc/src/platforms/python/Port.py
index 109eecb62..b5bc9696b 100644
--- a/grc/src/platforms/python/Port.py
+++ b/grc/src/platforms/python/Port.py
@@ -1,5 +1,5 @@
"""
-Copyright 2008 Free Software Foundation, Inc.
+Copyright 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -18,7 +18,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
from .. base.Port import Port as _Port
-from ... import utils
import Constants
class Port(_Port):
@@ -33,9 +32,9 @@ class Port(_Port):
@param n the nested odict
@return a new port
"""
- vlen = utils.exists_or_else(n, 'vlen', '1')
- nports = utils.exists_or_else(n, 'nports', '')
- optional = utils.exists_or_else(n, 'optional', '')
+ vlen = n.find('vlen') or '1'
+ nports = n.find('nports') or ''
+ optional = n.find('optional') or ''
#build the port
_Port.__init__(
self,
diff --git a/grc/src/utils/Makefile.am b/grc/src/utils/Makefile.am
index c00102f98..a48904796 100644
--- a/grc/src/utils/Makefile.am
+++ b/grc/src/utils/Makefile.am
@@ -1,5 +1,5 @@
#
-# Copyright 2008 Free Software Foundation, Inc.
+# Copyright 2008, 2009 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -25,5 +25,6 @@ ourpythondir = $(grc_src_prefix)/utils
ourpython_PYTHON = \
converter.py \
+ odict.py \
ParseXML.py \
__init__.py
diff --git a/grc/src/utils/__init__.py b/grc/src/utils/__init__.py
index 73a2ed562..2682db812 100644
--- a/grc/src/utils/__init__.py
+++ b/grc/src/utils/__init__.py
@@ -1,5 +1,5 @@
"""
-Copyright 2008 Free Software Foundation, Inc.
+Copyright 2009 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -17,66 +17,4 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-from UserDict import DictMixin
-
-class odict(DictMixin):
-
- def __init__(self, d={}):
- self._keys = list(d.keys())
- self._data = dict(d.copy())
-
- def __setitem__(self, key, value):
- if key not in self._data:
- self._keys.append(key)
- self._data[key] = value
-
- def __getitem__(self, key):
- return self._data[key]
-
- def __delitem__(self, key):
- del self._data[key]
- self._keys.remove(key)
-
- def keys(self):
- return list(self._keys)
-
- def copy(self):
- copy_dict = odict()
- copy_dict._data = self._data.copy()
- copy_dict._keys = list(self._keys)
- return copy_dict
-
- def insert_after(self, pos_key, key, val):
- """
- Insert the new key, value entry after the entry given by the position key.
- If the positional key is None, insert at the end.
- @param pos_key the positional key
- @param key the key for the new entry
- @param val the value for the new entry
- """
- index = (pos_key is None) and len(self._keys) or self._keys.index(pos_key)
- assert key not in self._keys
- self._keys.insert(index+1, key)
- self._data[key] = val
-
- def insert_before(self, pos_key, key, val):
- """
- Insert the new key, value entry before the entry given by the position key.
- If the positional key is None, insert at the begining.
- @param pos_key the positional key
- @param key the key for the new entry
- @param val the value for the new entry
- """
- index = (pos_key is not None) and self._keys.index(pos_key) or 0
- assert key not in self._keys
- self._keys.insert(index, key)
- self._data[key] = val
-
-def exists_or_else(d, key, alt):
- if d.has_key(key): return d[key]
- else: return alt
-
-def listify(d, key):
- obj = exists_or_else(d, key, [])
- if isinstance(obj, list): return obj
- return [obj]
+from odict import odict
diff --git a/grc/src/utils/odict.py b/grc/src/utils/odict.py
new file mode 100644
index 000000000..ac3cb2070
--- /dev/null
+++ b/grc/src/utils/odict.py
@@ -0,0 +1,93 @@
+"""
+Copyright 2008, 2009 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
+"""
+
+from UserDict import DictMixin
+
+class odict(DictMixin):
+
+ def __init__(self, d={}):
+ self._keys = list(d.keys())
+ self._data = dict(d.copy())
+
+ def __setitem__(self, key, value):
+ if key not in self._data:
+ self._keys.append(key)
+ self._data[key] = value
+
+ def __getitem__(self, key):
+ return self._data[key]
+
+ def __delitem__(self, key):
+ del self._data[key]
+ self._keys.remove(key)
+
+ def keys(self):
+ return list(self._keys)
+
+ def copy(self):
+ copy_dict = odict()
+ copy_dict._data = self._data.copy()
+ copy_dict._keys = list(self._keys)
+ return copy_dict
+
+ def insert_after(self, pos_key, key, val):
+ """
+ Insert the new key, value entry after the entry given by the position key.
+ If the positional key is None, insert at the end.
+ @param pos_key the positional key
+ @param key the key for the new entry
+ @param val the value for the new entry
+ """
+ index = (pos_key is None) and len(self._keys) or self._keys.index(pos_key)
+ assert key not in self._keys
+ self._keys.insert(index+1, key)
+ self._data[key] = val
+
+ def insert_before(self, pos_key, key, val):
+ """
+ Insert the new key, value entry before the entry given by the position key.
+ If the positional key is None, insert at the begining.
+ @param pos_key the positional key
+ @param key the key for the new entry
+ @param val the value for the new entry
+ """
+ index = (pos_key is not None) and self._keys.index(pos_key) or 0
+ assert key not in self._keys
+ self._keys.insert(index, key)
+ self._data[key] = val
+
+ def find(self, key):
+ """
+ Get the value for this key if exists.
+ @param key the key to search for
+ @return the value or None
+ """
+ if self.has_key(key): return self[key]
+ return None
+
+ def findall(self, key):
+ """
+ Get a list of values for this key.
+ @param key the key to search for
+ @return a list of values or empty list
+ """
+ obj = self.find(key)
+ if obj is None: obj = list()
+ if isinstance(obj, list): return obj
+ return [obj]
diff --git a/grc/todo.txt b/grc/todo.txt
index 904128872..33cf58e65 100644
--- a/grc/todo.txt
+++ b/grc/todo.txt
@@ -14,8 +14,6 @@
-search for blocks
-click and drag on whitespace to scroll
-gui grid editor for configuring grid params/placing wxgui plots and controls
--grid param chooser gui
--histogram plot
##################################################
# Problems