Merged grc developer branch r10679:10938
authorjblum <jblum@221aa14e-8319-0410-a670-987f0aec2ac5>
Fri, 1 May 2009 20:28:04 +0000 (20:28 +0000)
committerjblum <jblum@221aa14e-8319-0410-a670-987f0aec2ac5>
Fri, 1 May 2009 20:28:04 +0000 (20:28 +0000)
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

81 files changed:
config/grc_grc.m4
grc/Makefile.inc
grc/data/platforms/python/blocks/audio_sink.xml
grc/data/platforms/python/blocks/audio_source.xml
grc/data/platforms/python/blocks/blks2_rational_resampler_xxx.xml
grc/data/platforms/python/blocks/gr_fft_vxx.xml
grc/data/platforms/python/blocks/gr_mute_xx.xml
grc/data/platforms/python/blocks/gr_noise_source_x.xml
grc/data/platforms/python/blocks/gr_sig_source_x.xml
grc/data/platforms/python/blocks/gr_vector_sink_x.xml
grc/data/platforms/python/blocks/gr_vector_source_x.xml
grc/data/platforms/python/blocks/options.xml
grc/data/platforms/python/blocks/parameter.xml
grc/data/platforms/python/blocks/probe_function.xml
grc/data/platforms/python/blocks/usrp2_sink_xxxx.xml
grc/data/platforms/python/blocks/usrp2_source_xxxx.xml
grc/data/platforms/python/blocks/usrp_dual_source_x.xml
grc/data/platforms/python/blocks/usrp_simple_sink_x.xml
grc/data/platforms/python/blocks/usrp_simple_source_x.xml
grc/data/platforms/python/blocks/variable_chooser.xml
grc/data/platforms/python/blocks/variable_sink.xml
grc/data/platforms/python/blocks/variable_slider.xml
grc/data/platforms/python/blocks/variable_text_box.xml
grc/data/platforms/python/blocks/wxgui_constellationsink2.xml
grc/data/platforms/python/blocks/wxgui_fftsink2.xml
grc/data/platforms/python/blocks/wxgui_histosink2.xml
grc/data/platforms/python/blocks/wxgui_numbersink2.xml
grc/data/platforms/python/blocks/wxgui_scopesink2.xml
grc/data/platforms/python/blocks/wxgui_waterfallsink2.xml
grc/data/platforms/python/blocks/xmlrpc_client.xml
grc/data/platforms/python/flow_graph.tmpl
grc/examples/Makefile.am
grc/examples/audio/Makefile.am [deleted file]
grc/examples/simple/Makefile.am [deleted file]
grc/examples/trellis/Makefile.am [deleted file]
grc/examples/usrp/Makefile.am [deleted file]
grc/examples/usrp/usrp2_const_wave.grc
grc/examples/usrp/usrp2_dpsk_mod.grc [new file with mode: 0644]
grc/examples/usrp/usrp2_fft.grc
grc/examples/usrp/usrp_two_tone_loopback.grc
grc/examples/usrp/usrp_wbfm_receive.grc
grc/examples/xmlrpc/Makefile.am [deleted file]
grc/scripts/grc
grc/src/grc_gnuradio/wxgui/Makefile.am
grc/src/grc_gnuradio/wxgui/__init__.py
grc/src/grc_gnuradio/wxgui/callback_controls.py [deleted file]
grc/src/grc_gnuradio/wxgui/forms/__init__.py [new file with mode: 0644]
grc/src/grc_gnuradio/wxgui/forms/converters.py [new file with mode: 0644]
grc/src/grc_gnuradio/wxgui/forms/forms.py [new file with mode: 0644]
grc/src/grc_gnuradio/wxgui/top_block_gui.py
grc/src/gui/ActionHandler.py
grc/src/gui/Actions.py
grc/src/gui/Bars.py
grc/src/gui/BlockTreeWindow.py
grc/src/gui/Constants.py
grc/src/gui/Dialogs.py
grc/src/gui/DrawingArea.py
grc/src/gui/ParamsDialog.py
grc/src/platforms/base/Block.py
grc/src/platforms/base/FlowGraph.py
grc/src/platforms/base/Param.py
grc/src/platforms/base/Platform.py
grc/src/platforms/base/Port.py
grc/src/platforms/gui/Block.py
grc/src/platforms/gui/Connection.py
grc/src/platforms/gui/Constants.py
grc/src/platforms/gui/Element.py
grc/src/platforms/gui/FlowGraph.py
grc/src/platforms/gui/Param.py
grc/src/platforms/gui/Port.py
grc/src/platforms/gui/Utils.py
grc/src/platforms/python/Block.py
grc/src/platforms/python/Constants.py.in
grc/src/platforms/python/FlowGraph.py
grc/src/platforms/python/Generator.py
grc/src/platforms/python/Param.py
grc/src/platforms/python/Port.py
grc/src/utils/Makefile.am
grc/src/utils/__init__.py
grc/src/utils/odict.py [new file with mode: 0644]
grc/todo.txt

index 07463a52c60da091ce4084e8bdf97a6369888a12..d8bc02a24df476b81a0cc4c4e60229b51faf899e 100644 (file)
@@ -60,11 +60,6 @@ AC_DEFUN([GRC_GRC],[
         grc/src/utils/Makefile \
         grc/src/gui/Makefile \
         grc/examples/Makefile \
-        grc/examples/xmlrpc/Makefile \
-        grc/examples/usrp/Makefile \
-        grc/examples/audio/Makefile \
-        grc/examples/simple/Makefile \
-        grc/examples/trellis/Makefile \
         grc/Makefile \
         grc/data/Makefile \
         grc/data/platforms/Makefile \
index 8acd4e1075d75030a4b7f27c1754f86c5180a1ff..4d78070da674d5b43be0b165aacb89f9af1d07dd 100644 (file)
@@ -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
index decaf2a08d6e869ccc31f6ab6a409207644be5c3..75d5834709862016b94336c787500db545e9ef1c 100644 (file)
@@ -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>
index 21407dccdecc3028c9aff15912a1b0066ce33023..1f5d1033e5c3ebe4e96f34ac8e4e00fb1e952f74 100644 (file)
@@ -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>
index 2f81a50e5c26db2f9eedb604ea54036ad270b270..b92ec8ec207f8106deed753f3a40fec5b3d8b3c7 100644 (file)
        <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,
index c2c13d0aefa76f4b1e45240c3077018b7ed8f1fd..d398486efac6f9594f96570fe95b33c06be765bb 100644 (file)
@@ -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)
index 668d7c59927187ddb55c118925e8920af7915264..a9a857c6a1d54a9e9eef23746bdf638fc92f1f39 100644 (file)
                <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>
index 664a108d32f1c91378dccc054c98eb76c161918c..4fcef5148d53e167627f2d76e5f892238d2426e5 100644 (file)
@@ -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>
index 53434c4304c5e1a76d2a97899a6da69645d78e1b..c329dba67fb0e34790fcc0fe93f44c4c5717f089 100644 (file)
@@ -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>
index d901b1d789d75dbd64a354313e8576da2c3535ea..3bd998698f41a78b82fe57757dd836ece477e016 100644 (file)
@@ -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>
                        <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>
index 240273e42df11d54d4e975a1c5a7191ed171dbb5..7a6a3aeff8bf6a9795d10399880d44bc4a76b248 100644 (file)
@@ -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>
                        <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>
index 11e46bbe6595602715f962c8eefdd1e7782cea35..07f659af9b662aaed0c1cfc9fc3fa7290497058a 100644 (file)
        <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
index de2085011bbab1961d0553168b6ac34b6f1ae55e..e7bf615640ead989eb8278060faa5c0871d4a144 100644 (file)
@@ -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>
                </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>
index d4687852612cd84f5d2b0147d0e26a9ad2989937..ac0b3dcde8d71ce55eee5f2428a809fe7bd24b49 100644 (file)
@@ -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>
index e6e315786c9f05d603467a79cc7c91935c3ffd28..264ed4f20cf623a884f506e60da4831dfbdf763a 100644 (file)
@@ -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)
index 8b8ae3248bf9f241050183500e57b09593b16649..54bea7a499c35dd007e8526d5af092c67b938ada 100644 (file)
@@ -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)
index 823850b52c3a02b1569461b89a8f37199599738c..cb75fceadfef84458ad72d756b5118a7af07a001 100644 (file)
@@ -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>
index ca887997a16ba9f98f9ecd9a5febdca1f33cbb80..0c7fc53da19e19dc296cb23cfdfb0f28d9ecbec9 100644 (file)
@@ -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>
index d7f5475a6921ca7e6340e3e17dd4062350886a66..8d7b9533d027bd1dd894353a5224c1675bf0fe00 100644 (file)
@@ -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>
index 2a00a1cf2e1a1ecd6a4cbdb5d4991bb50e0cbcbd..6827c3675e56b8ebd5e53e0589695e108b136872 100644 (file)
@@ -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,25 +69,36 @@ 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>
                        <key>button</key>
                </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. \
index 87575ae1b74a25f442b21ece2e1cc4d80e97ff9a..426bd34fb17cc810186d3fd11a9a9853630d34f4 100644 (file)
@@ -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>
index 635f3ed4cb26bac336ed62556375bdbcf3564581..9c8e7ece92e95e3d0e5e295e05516f2fdbb1add2 100644 (file)
@@ -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>
index 97c6aa0d98c908f843b83db85c1212f499ed3a29..2857fa3666614f61b33bec92dcb1b44a3719a6ee 100644 (file)
@@ -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>
@@ -36,6 +42,28 @@ self.GridAdd(_$(id)_control, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos
                <value>0</value>
                <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>
index 69869904fcbd092bba1442ec0a2e8073fe5a99ae..471c9f4a89470585062e18ed931e56902c2c3921 100644 (file)
@@ -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
index c729bea4b73375bd8476e5faceb6a70b1b1495bb..31680f7bd9fe31764b20b755302eb298e121a204 100644 (file)
        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>
index 3d694aedc2a93cdeb46b713e2637aaab6ed007a2..4de57b1c4f47c010eae6b2d2d482de332d1695f7 100644 (file)
@@ -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
index 1b32993e16b88d0b89229514e52d1d9e8eb2005e..af0281f6a9fb1afd45933f6dc33695051578235f 100644 (file)
        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>
index 1af0afb35fb2f7a23a5368d573776228bd587809..78c39f80d8f80fb1511a08368e0d5fbcf6e05165 100644 (file)
@@ -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>
index 68d84dbba3e51a7602e53e4f29807d4e5c09402f..6d76ee86751531307be765587ec66c6e992cf771 100644 (file)
        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
index f132a7865308661272e54a9258051c7d7e39d8dc..dc4d154d14001643ef6e3c13c0fd536a2e35dd6c 100644 (file)
@@ -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>
index a84b4eb0ae8f73855946ad395d18a993669b8b2e..4c481dce4fe1cfcc2e464d7e0943f00fa4f9ec33 100644 (file)
@@ -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'
index d129cf6baf49f7fd47e770d53c47b2a9aed68fd2..9a2fbd53d8a9eb0f718920fdbe1e7840aab40f21 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Copyright 2008 Free Software Foundation, Inc.
+# Copyright 2009 Free Software Foundation, Inc.
 #
 # This file is part of GNU Radio
 #
 # 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 (file)
index f9604c3..0000000
+++ /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 (file)
index a56f98b..0000000
+++ /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 (file)
index 5677730..0000000
+++ /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 (file)
index 4e969eb..0000000
+++ /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
index ac9570349f11cb7cf024e8b4055d0cb37c973d94..fdbd7c1f398eacd1054d22118f782398f90ed6ba 100644 (file)
@@ -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>
     </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>
     </param>
     <param>
       <key>_coordinate</key>
-      <value>(12, 144)</value>
+      <value>(30, 376)</value>
     </param>
     <param>
       <key>_rotation</key>
     </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>
     </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>
     </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 (file)
index 0000000..e9f9b41
--- /dev/null
@@ -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>
index e7e93b3ff331c266f0d40102d980d5857c166c36..134bd46146e2fae65dc48fe93629ba434719f3a1 100644 (file)
@@ -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>
       <key>category</key>
       <value>Custom</value>
     </param>
+    <param>
+      <key>realtime_scheduling</key>
+      <value></value>
+    </param>
     <param>
       <key>_coordinate</key>
       <value>(10, 10)</value>
       <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/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>
     </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>
     </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>
     </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>
       <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>
     </param>
     <param>
       <key>_coordinate</key>
-      <value>(384, 72)</value>
+      <value>(466, 100)</value>
     </param>
     <param>
       <key>_rotation</key>
     </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>
index e3c635d467dfb9972d34db42303272060708db54..3df9770444acb83b094464408949ab84bad541b8 100644 (file)
@@ -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>
     </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>
       <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>
     </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>
       <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>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>
     </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>
     </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>
     </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>
     </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>
     </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>
     </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>
     </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>
     </param>
     <param>
       <key>_coordinate</key>
-      <value>(257, 337)</value>
+      <value>(276, 312)</value>
     </param>
     <param>
       <key>_rotation</key>
     </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>
     </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>
     <key>variable_slider</key>
     <param>
       <key>id</key>
-      <value>tone_ampl</value>
+      <value>tone2</value>
     </param>
     <param>
       <key>_enabled</key>
     </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>
       <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>
index 7fb621241d6cef28f7a104db5b0c265dfda9d0f4..8f53475ab57762457fd4c5fa2fffe8c358c3928b 100644 (file)
@@ -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>
       <key>category</key>
       <value>Custom</value>
     </param>
+    <param>
+      <key>realtime_scheduling</key>
+      <value></value>
+    </param>
     <param>
       <key>_coordinate</key>
       <value>(10, 10)</value>
     </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>
     <key>variable_slider</key>
     <param>
       <key>id</key>
-      <value>fine</value>
+      <value>volume</value>
     </param>
     <param>
       <key>_enabled</key>
     </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>
     </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>
     </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>
       <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>
     <key>variable_slider</key>
     <param>
       <key>id</key>
-      <value>volume</value>
+      <value>freq</value>
     </param>
     <param>
       <key>_enabled</key>
     </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>
     <key>variable_slider</key>
     <param>
       <key>id</key>
-      <value>freq</value>
+      <value>fine</value>
     </param>
     <param>
       <key>_enabled</key>
     </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>
     </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>
     <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 (file)
index cfe04a5..0000000
+++ /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
index e74d98616982fed87d187ef38ba3abe47430dd05..70c7ad1adf6eda6875d2a10ea1700c282a41be25 100755 (executable)
@@ -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
 
index 6f731f2cb533f1213a04f4a20de0ead5d0d6357b..b82ca4c909bb2329cd70d68cd243b6e3a7f9156a 100644 (file)
 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
index 0b13ead9e2ee732a14fc7d0ea7e2bffb46d21a84..94a0adb8a1a44a8a6a5e3e4854c7972682ee16ea 100644 (file)
 # 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 (file)
index 32e5d88..0000000
+++ /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 (file)
index 0000000..0722666
--- /dev/null
@@ -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 (file)
index 0000000..5971cfc
--- /dev/null
@@ -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 (file)
index 0000000..5c5b6ba
--- /dev/null
@@ -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)
index fef9d18ceb7d395d5b6e816421cec1e622c7abdd..f3305d7c5505f8c20be5a5a61d4994557322330e 100644 (file)
 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
index 91dd0fb454e89fb038ef53bd245bf5e34bf4f2b7..da0909a647eb7c4697989edd6e91da936536210c 100644 (file)
@@ -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):
                """
index 16f12dd4c05e36d1d3833b29fccfe57056066fd1..9b687df7e18d0a242bfe06e33a21d0cd1378c277 100644 (file)
@@ -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
index c89aea580919b9afecb68df5c072ede9398e9ba3..52e7ba1f88894a612a400a9a09239f2f233b642d 100644 (file)
@@ -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,
        ]),
 )
index 94b9476c5b63bbc82d2126def76ff697905ba114..9e4bec3f9ae7d84f9ac26f3fc108954c3e070949 100644 (file)
@@ -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.
index 70e6b6b6edcb5c8927b2cd6a403b99139aa8d366..f23ab8b1384694f11ed73cd8a63013921ae52a4d 100644 (file)
@@ -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)]
index e15f8c574123ebe56966ed3ceb70c3f6c746babb..d526b97b432341ea05312f335b02f24e944119d6 100644 (file)
@@ -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.""")
index 3588e122d21ec9e4e17fcc44581e2aec829247c3..5258979d82fc26c6362bda6b85a7aeff54f110c7 100644 (file)
@@ -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)
index 5837ab7c4291882fd4cd1f39643e75455a8a8c2d..6cc42e8fca1715d9853fafabc59dfd44e3bf3cbf 100644 (file)
@@ -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
index bc9b58a5e13a0b6977bf7a9a6557ceb94194ac17..25688472cad48fa4536c3944cfa152679357b2be 100644 (file)
@@ -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()
index aeb66ac7e870685967e2f6d4ab084d30e52b94d9..747038bfbc446d0b97defcd4d834e9c3e7fa8541 100644 (file)
@@ -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)
index ebc9977fc9c693ff9064ffba3c4ec25cb31001cf..81783c791eb579e283417e07c83ce4b4be6da402 100644 (file)
@@ -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
 
        ##############################################
index 1a96594bbaa391db3cc9a49893851b424209731a..1f04fa0a6bc5ee6f2c030c8cfc103a96dc45126d 100644 (file)
@@ -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
index 26ad1fc4ae795ec3daae4c796ca8dda5959a253b..f46a81195b8f793a2d36433d13e744ad2f173101 100644 (file)
@@ -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):
index ab6a6d0b2242168317fc9f1b5cf2354ed008d459..4aa35bf03bc4dd702c7c6ce9ca9a7b9ae79dc868 100644 (file)
@@ -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):
                """
index b130611fbfe610dea246d7df6c994a0816ac4c3f..9f243215e07b416e121db37c26ae8eb4a71ee8a8 100644 (file)
@@ -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)
index 00899cb7881212cc4149afaf4ce0657862151d26..90c8c1c3896c2424cee0c071f68fb9da6fa4a243 100644 (file)
@@ -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
index f97d85ff69e58649dac2d2890dbdec015b500ad2..8ef288ed152498424ff78b1690a7b08b3007b8ba 100644 (file)
@@ -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
 
index cc2e271635466280e1bee92c28673b2a1da064fa..31d90984de74a15c4e2cbc6bbe3dfac60e8a36a8 100644 (file)
@@ -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()
index 2afe18c571b5199c82efc295bd07256a0d8d5da3..33a9b1f529cccf9a7c7ecbfb90a039150abfd079 100644 (file)
@@ -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
index 85d9fea5aa946872890e5d97c1a50e4431c0b2a1..3aec6e4a72a8a900edddc3c949e23adb3b73d7ad 100644 (file)
@@ -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
index 17750ef45b13e1dad9a22d44369354ae791f820c..ee6dc6cdc4aa2a62cddc7bc5d6a1ecce71bba496 100644 (file)
@@ -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))
index 3c45117a3fa2d82136419b5625bacd1ddf3e2387..38a0ce492327cabac479167a779021969ba4c2ba 100644 (file)
@@ -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,
index 199b242236aa9d93c93a4a2aec549f0941b3bdd8..502f4155051cd28294935e738a8b368f77a8fa0f 100644 (file)
@@ -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'
index cd5635b95d8325608e4d8b7bbaf9871eb668359b..95c0b38cb8dd3ac29d3beb72b39e35f9ff34fde0 100644 (file)
@@ -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
index 83dd186c397b47dff1c6a51a3938b52b5d955abc..93321404a1086ed7aa1be5e85f2053ea77e3946c 100644 (file)
@@ -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.''')
index efebe92e5d209ff4463896bd328706eea90da134..e75a882a47b531f5b01ff1c27606ef6f637ee62c 100644 (file)
@@ -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)
index 109eecb62c02f59b2f7eea39ddb9c95f045caf75..b5bc9696b5a7e7d5cad1247346f1a6959f103be5 100644 (file)
@@ -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,
index c00102f98b50781780176ef9325cc99d97047443..a4890479660c4cac570c73561cf7eb0e26cfd188 100644 (file)
@@ -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
index 73a2ed562f10ccdbb81baf2317d35da104c0467c..2682db8125724ce123916a42d0fdb3b8f35f4385 100644 (file)
@@ -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 (file)
index 0000000..ac3cb20
--- /dev/null
@@ -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]
index 904128872eb4a0b64202d480e1385b1941d88772..33cf58e657d607e7abb1d18ead77b87fcbe077c3 100644 (file)
@@ -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