summaryrefslogtreecommitdiff
path: root/grc/src/platforms
diff options
context:
space:
mode:
Diffstat (limited to 'grc/src/platforms')
-rw-r--r--grc/src/platforms/base/Block.py43
-rw-r--r--grc/src/platforms/base/FlowGraph.py37
-rw-r--r--grc/src/platforms/base/Param.py103
-rw-r--r--grc/src/platforms/base/Platform.py35
-rw-r--r--grc/src/platforms/base/Port.py3
-rw-r--r--grc/src/platforms/gui/Block.py33
-rw-r--r--grc/src/platforms/gui/Connection.py6
-rw-r--r--grc/src/platforms/gui/Constants.py51
-rw-r--r--grc/src/platforms/gui/Element.py19
-rw-r--r--grc/src/platforms/gui/FlowGraph.py135
-rw-r--r--grc/src/platforms/gui/Param.py70
-rw-r--r--grc/src/platforms/gui/Port.py18
-rw-r--r--grc/src/platforms/gui/Utils.py13
-rw-r--r--grc/src/platforms/python/Block.py11
-rw-r--r--grc/src/platforms/python/Constants.py.in1
-rw-r--r--grc/src/platforms/python/FlowGraph.py28
-rw-r--r--grc/src/platforms/python/Generator.py2
-rw-r--r--grc/src/platforms/python/Param.py6
-rw-r--r--grc/src/platforms/python/Port.py9
19 files changed, 291 insertions, 332 deletions
diff --git a/grc/src/platforms/base/Block.py b/grc/src/platforms/base/Block.py
index bc9b58a5e..25688472c 100644
--- a/grc/src/platforms/base/Block.py
+++ b/grc/src/platforms/base/Block.py
@@ -1,5 +1,5 @@
"""
-Copyright 2008 Free Software Foundation, Inc.
+Copyright 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -17,7 +17,6 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-from ... import utils
from ... utils import odict
from Element import Element
from Param import Param
@@ -31,7 +30,7 @@ class TemplateArg(UserDict):
A cheetah template argument created from a param.
The str of this class evaluates to the param's to code method.
The use of this class as a dictionary (enum only) will reveal the enum opts.
- The eval method can return the param evaluated to a raw python data type.
+ The __call__ or () method can return the param evaluated to a raw python data type.
"""
def __init__(self, param):
@@ -44,7 +43,7 @@ class TemplateArg(UserDict):
def __str__(self):
return str(self._param.to_code())
- def eval(self):
+ def __call__(self):
return self._param.evaluate()
class Block(Element):
@@ -59,33 +58,33 @@ class Block(Element):
#build the block
Element.__init__(self, flow_graph)
#grab the data
- params = utils.listify(n, 'param')
- sources = utils.listify(n, 'source')
- sinks = utils.listify(n, 'sink')
- self._name = n['name']
- self._key = n['key']
- self._category = utils.exists_or_else(n, 'category', '')
- self._block_wrapper_path = n['block_wrapper_path']
+ params = n.findall('param')
+ sources = n.findall('source')
+ sinks = n.findall('sink')
+ self._name = n.find('name')
+ self._key = n.find('key')
+ self._category = n.find('category') or ''
+ self._block_wrapper_path = n.find('block_wrapper_path')
#create the param objects
self._params = odict()
#add the id param
self._params['id'] = self.get_parent().get_parent().Param(
self,
- {
+ odict({
'name': 'ID',
'key': 'id',
'type': 'id',
- }
+ })
)
self._params['_enabled'] = self.get_parent().get_parent().Param(
self,
- {
+ odict({
'name': 'Enabled',
'key': '_enabled',
'type': 'raw',
'value': 'True',
'hide': 'all',
- }
+ })
)
for param in map(lambda n: self.get_parent().get_parent().Param(self, n), params):
key = param.get_key()
@@ -250,13 +249,11 @@ class Block(Element):
Any param keys that do not exist will be ignored.
@param n the nested data odict
"""
- params_n = utils.listify(n, 'param')
+ params_n = n.findall('param')
for param_n in params_n:
- #key and value must exist in the n data
- if 'key' in param_n.keys() and 'value' in param_n.keys():
- key = param_n['key']
- value = param_n['value']
- #the key must exist in this block's params
- if key in self.get_param_keys():
- self.get_param(key).set_value(value)
+ key = param_n.find('key')
+ value = param_n.find('value')
+ #the key must exist in this block's params
+ if key in self.get_param_keys():
+ self.get_param(key).set_value(value)
self.validate()
diff --git a/grc/src/platforms/base/FlowGraph.py b/grc/src/platforms/base/FlowGraph.py
index aeb66ac7e..747038bfb 100644
--- a/grc/src/platforms/base/FlowGraph.py
+++ b/grc/src/platforms/base/FlowGraph.py
@@ -1,5 +1,5 @@
"""
-Copyright 2008 Free Software Foundation, Inc.
+Copyright 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -17,7 +17,6 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-from ... import utils
from ... utils import odict
from Element import Element
from Block import Block
@@ -37,7 +36,7 @@ class FlowGraph(Element):
#initialize
Element.__init__(self, platform)
#inital blank import
- self.import_data({'flow_graph': {}})
+ self.import_data()
def _get_unique_id(self, base_id=''):
"""
@@ -179,9 +178,9 @@ class FlowGraph(Element):
n['timestamp'] = time.ctime()
n['block'] = [block.export_data() for block in self.get_blocks()]
n['connection'] = [connection.export_data() for connection in self.get_connections()]
- return {'flow_graph': n}
+ return odict({'flow_graph': n})
- def import_data(self, n):
+ def import_data(self, n=None):
"""
Import blocks and connections into this flow graph.
Clear this flowgraph of all previous blocks and connections.
@@ -190,19 +189,16 @@ class FlowGraph(Element):
"""
#remove previous elements
self._elements = list()
- #the flow graph tag must exists, or use blank data
- if 'flow_graph' in n.keys(): fg_n = n['flow_graph']
- else:
- Messages.send_error_load('Flow graph data not found, loading blank flow graph.')
- fg_n = {}
- blocks_n = utils.listify(fg_n, 'block')
- connections_n = utils.listify(fg_n, 'connection')
+ #use blank data if none provided
+ fg_n = n and n.find('flow_graph') or odict()
+ blocks_n = fg_n.findall('block')
+ connections_n = fg_n.findall('connection')
#create option block
self._options_block = self.get_parent().get_new_block(self, 'options')
self._options_block.get_param('id').set_value('options')
#build the blocks
for block_n in blocks_n:
- key = block_n['key']
+ key = block_n.find('key')
if key == 'options': block = self._options_block
else: block = self.get_new_block(key)
#only load the block when the block key was valid
@@ -210,21 +206,14 @@ class FlowGraph(Element):
else: Messages.send_error_load('Block key "%s" not found in %s'%(key, self.get_parent()))
#build the connections
for connection_n in connections_n:
- #test that the data tags exist
- try:
- assert('source_block_id' in connection_n.keys())
- assert('sink_block_id' in connection_n.keys())
- assert('source_key' in connection_n.keys())
- assert('sink_key' in connection_n.keys())
- except AssertionError: continue
#try to make the connection
try:
#get the block ids
- source_block_id = connection_n['source_block_id']
- sink_block_id = connection_n['sink_block_id']
+ source_block_id = connection_n.find('source_block_id')
+ sink_block_id = connection_n.find('sink_block_id')
#get the port keys
- source_key = connection_n['source_key']
- sink_key = connection_n['sink_key']
+ source_key = connection_n.find('source_key')
+ sink_key = connection_n.find('sink_key')
#verify the blocks
block_ids = map(lambda b: b.get_id(), self.get_blocks())
assert(source_block_id in block_ids)
diff --git a/grc/src/platforms/base/Param.py b/grc/src/platforms/base/Param.py
index ebc9977fc..81783c791 100644
--- a/grc/src/platforms/base/Param.py
+++ b/grc/src/platforms/base/Param.py
@@ -1,5 +1,5 @@
"""
-Copyright 2008 Free Software Foundation, Inc.
+Copyright 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -17,13 +17,11 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-from ... import utils
from ... utils import odict
from Element import Element
import pygtk
pygtk.require('2.0')
import gtk
-import gobject
class InputParam(gtk.HBox):
"""The base class for an input parameter inside the input parameters dialog."""
@@ -60,37 +58,60 @@ class EnumParam(InputParam):
def __init__(self, *args, **kwargs):
InputParam.__init__(self, *args, **kwargs)
- input = gtk.ComboBox(gtk.ListStore(gobject.TYPE_STRING))
- cell = gtk.CellRendererText()
- input.pack_start(cell, True)
- input.add_attribute(cell, 'text', 0)
- for option in self.param.get_options(): input.append_text(option.get_name())
- input.set_active(int(self.param.get_option_keys().index(self.param.get_value())))
- input.connect("changed", self._handle_changed)
- self.pack_start(input, False)
- self.get_text = lambda: str(input.get_active()) #the get text parses the selected index to a string
+ self._input = gtk.combo_box_new_text()
+ for option in self.param.get_options(): self._input.append_text(option.get_name())
+ self._input.set_active(self.param.get_option_keys().index(self.param.get_value()))
+ self._input.connect('changed', self._handle_changed)
+ self.pack_start(self._input, False)
+ def get_text(self): return self.param.get_option_keys()[self._input.get_active()]
+
+class EnumEntryParam(InputParam):
+ """Provide an entry box and drop down menu for Raw Enum types."""
+
+ def __init__(self, *args, **kwargs):
+ InputParam.__init__(self, *args, **kwargs)
+ self._input = gtk.combo_box_entry_new_text()
+ for option in self.param.get_options(): self._input.append_text(option.get_name())
+ try: self._input.set_active(self.param.get_option_keys().index(self.param.get_value()))
+ except:
+ self._input.set_active(-1)
+ self._input.get_child().set_text(self.param.get_value())
+ self._input.connect('changed', self._handle_changed)
+ self._input.get_child().connect('changed', self._handle_changed)
+ self.pack_start(self._input, False)
+ def get_text(self):
+ if self._input.get_active() == -1: return self._input.get_child().get_text()
+ return self.param.get_option_keys()[self._input.get_active()]
+ def set_color(self, color):
+ if self._input.get_active() == -1: #custom entry, use color
+ self._input.get_child().modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse(color))
+ else: #from enum, make white background
+ self._input.get_child().modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse('#ffffff'))
class Option(Element):
- def __init__(self, param, name, key, opts):
+ def __init__(self, param, n):
Element.__init__(self, param)
- self._name = name
- self._key = key
+ self._name = n.find('name')
+ self._key = n.find('key')
self._opts = dict()
+ opts = n.findall('opt')
+ #test against opts when non enum
+ try: assert self.get_parent().is_enum() or not opts
+ except AssertionError: self._exit_with_error('Options for non-enum types cannot have sub-options')
+ #extract opts
for opt in opts:
#separate the key:value
try: key, value = opt.split(':')
except: self._exit_with_error('Error separating "%s" into key:value'%opt)
#test against repeated keys
- try: assert(not self._opts.has_key(key))
+ try: assert not self._opts.has_key(key)
except AssertionError: self._exit_with_error('Key "%s" already exists in option'%key)
#store the option
self._opts[key] = value
def __str__(self): return 'Option %s(%s)'%(self.get_name(), self.get_key())
-
def get_name(self): return self._name
-
def get_key(self): return self._key
##############################################
@@ -100,29 +121,6 @@ class Option(Element):
def get_opt(self, key): return self._opts[key]
def get_opts(self): return self._opts.values()
- ##############################################
- ## Static Make Methods
- ##############################################
- def make_option_from_n(param, n):
- """
- Make a new option from nested data.
- @param param the parent element
- @param n the nested odict
- @return a new option
- """
- #grab the data
- name = n['name']
- key = n['key']
- opts = utils.listify(n, 'opt')
- #build the option
- return Option(
- param=param,
- name=name,
- key=key,
- opts=opts,
- )
- make_option_from_n = staticmethod(make_option_from_n)
-
class Param(Element):
##possible param types
@@ -136,21 +134,16 @@ class Param(Element):
@return a new param
"""
#grab the data
- name = n['name']
- key = n['key']
- value = utils.exists_or_else(n, 'value', '')
- type = n['type']
- hide = utils.exists_or_else(n, 'hide', '')
- options = utils.listify(n, 'option')
+ self._name = n.find('name')
+ self._key = n.find('key')
+ value = n.find('value') or ''
+ self._type = n.find('type')
+ self._hide = n.find('hide') or ''
#build the param
Element.__init__(self, block)
- self._name = name
- self._key = key
- self._type = type
- self._hide = hide
#create the Option objects from the n data
self._options = odict()
- for option in map(lambda o: Option.make_option_from_n(self, o), options):
+ for option in map(lambda o: Option(self, o), n.findall('option')):
key = option.get_key()
#test against repeated keys
try: assert(key not in self.get_option_keys())
@@ -226,7 +219,7 @@ class Param(Element):
self._value = str(value) #must be a string
def get_type(self): return self.get_parent().resolve_dependencies(self._type)
- def is_enum(self): return bool(self.get_options())
+ def is_enum(self): return self._type == 'enum'
def __repr__(self):
"""
@@ -241,9 +234,13 @@ class Param(Element):
def get_input_class(self):
"""
Get the graphical gtk class to represent this parameter.
+ An enum requires and combo parameter.
+ A non-enum with options gets a combined entry/combo parameter.
+ All others get a standard entry parameter.
@return gtk input class
"""
if self.is_enum(): return EnumParam
+ if self.get_options(): return EnumEntryParam
return EntryParam
##############################################
diff --git a/grc/src/platforms/base/Platform.py b/grc/src/platforms/base/Platform.py
index 1a96594bb..1f04fa0a6 100644
--- a/grc/src/platforms/base/Platform.py
+++ b/grc/src/platforms/base/Platform.py
@@ -1,5 +1,5 @@
"""
-Copyright 2008 Free Software Foundation, Inc.
+Copyright 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -19,7 +19,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
import os
from ... utils import ParseXML
-from ... import utils
from Element import Element as _Element
from FlowGraph import FlowGraph as _FlowGraph
from Connection import Connection as _Connection
@@ -73,17 +72,17 @@ class Platform(_Element):
"""
try: ParseXML.validate_dtd(f, self._block_dtd)
except ParseXML.XMLSyntaxError, e: self._exit_with_error('Block definition "%s" failed: \n\t%s'%(f, e))
- for n in utils.listify(ParseXML.from_file(f), 'block'):
- #inject block wrapper path
- n['block_wrapper_path'] = f
- block = self.Block(self._flow_graph, n)
- key = block.get_key()
- #test against repeated keys
- try: assert(key not in self.get_block_keys())
- except AssertionError: self._exit_with_error('Key "%s" already exists in blocks'%key)
- #store the block
- self._blocks[key] = block
- self._blocks_n[key] = n
+ n = ParseXML.from_file(f).find('block')
+ #inject block wrapper path
+ n['block_wrapper_path'] = f
+ block = self.Block(self._flow_graph, n)
+ key = block.get_key()
+ #test against repeated keys
+ try: assert(key not in self.get_block_keys())
+ except AssertionError: self._exit_with_error('Key "%s" already exists in blocks'%key)
+ #store the block
+ self._blocks[key] = block
+ self._blocks_n[key] = n
def load_block_tree(self, block_tree):
"""
@@ -93,21 +92,21 @@ class Platform(_Element):
@param block_tree the block tree object
"""
#recursive function to load categories and blocks
- def load_category(cat_n, parent=''):
+ def load_category(cat_n, parent=[]):
#add this category
- parent = '%s/%s'%(parent, cat_n['name'])
+ parent = parent + [cat_n.find('name')]
block_tree.add_block(parent)
#recursive call to load sub categories
- map(lambda c: load_category(c, parent), utils.listify(cat_n, 'cat'))
+ map(lambda c: load_category(c, parent), cat_n.findall('cat'))
#add blocks in this category
- for block_key in utils.listify(cat_n, 'block'):
+ for block_key in cat_n.findall('block'):
block_tree.add_block(parent, self.get_block(block_key))
#load the block tree
f = self._block_tree
try: ParseXML.validate_dtd(f, BLOCK_TREE_DTD)
except ParseXML.XMLSyntaxError, e: self._exit_with_error('Block tree "%s" failed: \n\t%s'%(f, e))
#add all blocks in the tree
- load_category(ParseXML.from_file(f)['cat'])
+ load_category(ParseXML.from_file(f).find('cat'))
#add all other blocks, use the catgory
for block in self.get_blocks():
#blocks with empty categories are in the xml block tree or hidden
diff --git a/grc/src/platforms/base/Port.py b/grc/src/platforms/base/Port.py
index 26ad1fc4a..f46a81195 100644
--- a/grc/src/platforms/base/Port.py
+++ b/grc/src/platforms/base/Port.py
@@ -1,5 +1,5 @@
"""
-Copyright 2008 Free Software Foundation, Inc.
+Copyright 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -17,7 +17,6 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-from ... import utils
from Element import Element
class Port(Element):
diff --git a/grc/src/platforms/gui/Block.py b/grc/src/platforms/gui/Block.py
index ab6a6d0b2..4aa35bf03 100644
--- a/grc/src/platforms/gui/Block.py
+++ b/grc/src/platforms/gui/Block.py
@@ -1,5 +1,5 @@
"""
-Copyright 2007 Free Software Foundation, Inc.
+Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -20,15 +20,19 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
from Element import Element
import Utils
import Colors
-from ... gui.Constants import BORDER_PROXIMITY_SENSITIVITY
+from ... utils import odict
+from Constants import BORDER_PROXIMITY_SENSITIVITY
from Constants import \
- BLOCK_FONT, BLOCK_LABEL_PADDING, \
+ BLOCK_LABEL_PADDING, \
PORT_SEPARATION, LABEL_SEPARATION, \
PORT_BORDER_SEPARATION, POSSIBLE_ROTATIONS
import pygtk
pygtk.require('2.0')
import gtk
-import pango
+
+BLOCK_MARKUP_TMPL="""\
+#set $foreground = $block.is_valid() and 'black' or 'red'
+<span foreground="$foreground" font_desc="Sans 8"><b>$encode($block.get_name())</b></span>"""
class Block(Element):
"""The graphical signal block."""
@@ -41,23 +45,23 @@ class Block(Element):
#add the position param
self._params['_coordinate'] = self.get_parent().get_parent().Param(
self,
- {
+ odict({
'name': 'GUI Coordinate',
'key': '_coordinate',
'type': 'raw',
'value': '(0, 0)',
'hide': 'all',
- }
+ })
)
self._params['_rotation'] = self.get_parent().get_parent().Param(
self,
- {
+ odict({
'name': 'GUI Rotation',
'key': '_rotation',
'type': 'raw',
'value': '0',
'hide': 'all',
- }
+ })
)
Element.__init__(self)
@@ -130,10 +134,7 @@ class Block(Element):
#create the main layout
layout = gtk.DrawingArea().create_pango_layout('')
layouts.append(layout)
- if self.is_valid(): layout.set_markup('<b>'+Utils.xml_encode(self.get_name())+'</b>')
- else: layout.set_markup('<span foreground="red"><b>'+Utils.xml_encode(self.get_name())+'</b></span>')
- desc = pango.FontDescription(BLOCK_FONT)
- layout.set_font_description(desc)
+ layout.set_markup(Utils.parse_template(BLOCK_MARKUP_TMPL, block=self))
self.label_width, self.label_height = layout.get_pixel_size()
#display the params
for param in filter(lambda p: p.get_hide() not in ('all', 'part'), self.get_params()):
@@ -166,22 +167,22 @@ class Block(Element):
for j in range(height): vimage.put_pixel(j, width-i-1, image.get_pixel(i, j))
map(lambda p: p._create_labels(), self.get_ports())
- def draw(self, window):
+ def draw(self, gc, window):
"""
Draw the signal block with label and inputs/outputs.
+ @param gc the graphics context
@param window the gtk window to draw on
"""
x, y = self.get_coordinate()
#draw main block
- Element.draw(self, window, BG_color=self.bg_color)
+ Element.draw(self, gc, window, BG_color=self.bg_color)
#draw label image
- gc = self.get_gc()
if self.is_horizontal():
window.draw_image(gc, self.horizontal_label, 0, 0, x+BLOCK_LABEL_PADDING, y+(self.H-self.label_height)/2, -1, -1)
elif self.is_vertical():
window.draw_image(gc, self.vertical_label, 0, 0, x+(self.H-self.label_height)/2, y+BLOCK_LABEL_PADDING, -1, -1)
#draw ports
- map(lambda p: p.draw(window), self.get_ports())
+ for port in self.get_ports(): port.draw(gc, window)
def what_is_selected(self, coor, coor_m=None):
"""
diff --git a/grc/src/platforms/gui/Connection.py b/grc/src/platforms/gui/Connection.py
index b130611fb..9f243215e 100644
--- a/grc/src/platforms/gui/Connection.py
+++ b/grc/src/platforms/gui/Connection.py
@@ -106,9 +106,10 @@ class Connection(Element):
self.add_line((x1, y1), points[0])
self.add_line((x2, y2), points[0])
- def draw(self, window):
+ def draw(self, gc, window):
"""
Draw the connection.
+ @param gc the graphics context
@param window the gtk window to draw on
"""
sink = self.get_sink()
@@ -123,8 +124,7 @@ class Connection(Element):
self._source_coor = source.get_coordinate()
#draw
fg_color = self.get_enabled() and Colors.FG_COLOR or Colors.DISABLED_FG_COLOR
- Element.draw(self, window, FG_color=fg_color)
- gc = self.get_gc()
+ Element.draw(self, gc, window, FG_color=fg_color)
gc.foreground = self._foreground
#draw arrow on sink port
window.draw_polygon(gc, True, self._arrow)
diff --git a/grc/src/platforms/gui/Constants.py b/grc/src/platforms/gui/Constants.py
index 00899cb78..90c8c1c38 100644
--- a/grc/src/platforms/gui/Constants.py
+++ b/grc/src/platforms/gui/Constants.py
@@ -1,23 +1,21 @@
-#
-# Copyright 2008 Free Software Foundation, Inc.
-#
-# This file is part of GNU Radio
-#
-# GNU Radio is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3, or (at your option)
-# any later version.
-#
-# GNU Radio is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GNU Radio; see the file COPYING. If not, write to
-# the Free Software Foundation, Inc., 51 Franklin Street,
-# Boston, MA 02110-1301, USA.
-#
+"""
+Copyright 2008, 2009 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+"""
#label constraint dimensions
LABEL_SEPARATION = 3
@@ -27,11 +25,6 @@ PORT_LABEL_PADDING = 2
PORT_SEPARATION = 17
PORT_BORDER_SEPARATION = 9
PORT_MIN_WIDTH = 20
-#fonts
-PARAM_LABEL_FONT = 'Sans 9.5'
-PARAM_FONT = 'Sans 7.5'
-BLOCK_FONT = 'Sans 8'
-PORT_FONT = 'Sans 7.5'
#minimal length of connector
CONNECTOR_EXTENSION_MINIMAL = 11
#increment length for connector
@@ -41,3 +34,11 @@ CONNECTOR_ARROW_BASE = 13
CONNECTOR_ARROW_HEIGHT = 17
#possible rotations in degrees
POSSIBLE_ROTATIONS = (0, 90, 180, 270)
+#How close can the mouse get to the window border before mouse events are ignored.
+BORDER_PROXIMITY_SENSITIVITY = 50
+#How close the mouse can get to the edge of the visible window before scrolling is invoked.
+SCROLL_PROXIMITY_SENSITIVITY = 30
+#When the window has to be scrolled, move it this distance in the required direction.
+SCROLL_DISTANCE = 15
+#How close the mouse click can be to a line and register a connection select.
+LINE_SELECT_SENSITIVITY = 5
diff --git a/grc/src/platforms/gui/Element.py b/grc/src/platforms/gui/Element.py
index f97d85ff6..8ef288ed1 100644
--- a/grc/src/platforms/gui/Element.py
+++ b/grc/src/platforms/gui/Element.py
@@ -22,7 +22,7 @@ import pygtk
pygtk.require('2.0')
import gtk
import pango
-from ... gui.Constants import CONNECTION_SELECT_SENSITIVITY
+from Constants import LINE_SELECT_SENSITIVITY
from Constants import POSSIBLE_ROTATIONS
class Element(object):
@@ -61,17 +61,14 @@ class Element(object):
rotation = rotation or self.get_rotation()
return rotation in (90, 270)
- def get_gc(self): return self._gc
-
- def draw(self, window, BG_color=Colors.BG_COLOR, FG_color=Colors.FG_COLOR):
+ def draw(self, gc, window, BG_color=Colors.BG_COLOR, FG_color=Colors.FG_COLOR):
"""
Draw in the given window.
+ @param gc the graphics context
@param window the gtk window to draw on
@param BG_color the background color
@param FG_color the foreground color
"""
- gc = self.get_parent().get_gc()
- self._gc = gc
X,Y = self.get_coordinate()
for (rX,rY),(W,H) in self.areas_dict[self.get_rotation()]:
aX = X + rX
@@ -84,12 +81,12 @@ class Element(object):
gc.foreground = self.is_highlighted() and Colors.H_COLOR or FG_color
window.draw_line(gc, X+x1, Y+y1, X+x2, Y+y2)
- def rotate(self, direction):
+ def rotate(self, rotation):
"""
Rotate all of the areas by 90 degrees.
- @param direction 90 or 270 degrees
+ @param rotation multiple of 90 degrees
"""
- self.set_rotation((self.get_rotation() + direction)%360)
+ self.set_rotation((self.get_rotation() + rotation)%360)
def clear(self):
"""Empty the lines and areas."""
@@ -204,8 +201,8 @@ class Element(object):
if in_between(x, x1, x1+w) and in_between(y, y1, y1+h): return self
#handle horizontal or vertical lines
for (x1, y1), (x2, y2) in self.lines_dict[self.get_rotation()]:
- if x1 == x2: x1, x2 = x1-CONNECTION_SELECT_SENSITIVITY, x2+CONNECTION_SELECT_SENSITIVITY
- if y1 == y2: y1, y2 = y1-CONNECTION_SELECT_SENSITIVITY, y2+CONNECTION_SELECT_SENSITIVITY
+ if x1 == x2: x1, x2 = x1-LINE_SELECT_SENSITIVITY, x2+LINE_SELECT_SENSITIVITY
+ if y1 == y2: y1, y2 = y1-LINE_SELECT_SENSITIVITY, y2+LINE_SELECT_SENSITIVITY
if in_between(x, x1, x2) and in_between(y, y1, y2): return self
return None
diff --git a/grc/src/platforms/gui/FlowGraph.py b/grc/src/platforms/gui/FlowGraph.py
index cc2e27163..31d90984d 100644
--- a/grc/src/platforms/gui/FlowGraph.py
+++ b/grc/src/platforms/gui/FlowGraph.py
@@ -1,5 +1,5 @@
"""
-Copyright 2007 Free Software Foundation, Inc.
+Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -17,25 +17,19 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-from ... gui.Constants import \
- DIR_LEFT, DIR_RIGHT, \
- SCROLL_PROXIMITY_SENSITIVITY, SCROLL_DISTANCE, \
- MOTION_DETECT_REDRAWING_SENSITIVITY
+from Constants import SCROLL_PROXIMITY_SENSITIVITY, SCROLL_DISTANCE
from ... gui.Actions import \
ELEMENT_CREATE, ELEMENT_SELECT, \
BLOCK_PARAM_MODIFY, BLOCK_MOVE, \
ELEMENT_DELETE
import Colors
import Utils
-from ... import utils
-from ... gui.ParamsDialog import ParamsDialog
from Element import Element
from .. base import FlowGraph as _FlowGraph
import pygtk
pygtk.require('2.0')
import gtk
import random
-import time
from ... gui import Messages
class FlowGraph(Element):
@@ -57,7 +51,6 @@ class FlowGraph(Element):
self.element_moved = False
self.mouse_pressed = False
self.unselect()
- self.time = 0
self.press_coor = (0, 0)
#selected ports
self._old_selected_port = None
@@ -67,28 +60,31 @@ class FlowGraph(Element):
# Access Drawing Area
###########################################################################
def get_drawing_area(self): return self.drawing_area
- def get_gc(self): return self.get_drawing_area().gc
- def get_pixmap(self): return self.get_drawing_area().pixmap
+ def queue_draw(self): self.get_drawing_area().queue_draw()
def get_size(self): return self.get_drawing_area().get_size_request()
def set_size(self, *args): self.get_drawing_area().set_size_request(*args)
def get_window(self): return self.get_drawing_area().window
+ def get_pixmap(self): return self.get_drawing_area().pixmap
def get_scroll_pane(self): return self.drawing_area.get_parent()
def get_ctrl_mask(self): return self.drawing_area.ctrl_mask
- def add_new_block(self, key):
+ def add_new_block(self, key, coor=None):
"""
Add a block of the given key to this flow graph.
@param key the block key
+ @param coor an optional coordinate or None for random
"""
id = self._get_unique_id(key)
#calculate the position coordinate
h_adj = self.get_scroll_pane().get_hadjustment()
v_adj = self.get_scroll_pane().get_vadjustment()
- x = int(random.uniform(.25, .75)*h_adj.page_size + h_adj.get_value())
- y = int(random.uniform(.25, .75)*v_adj.page_size + v_adj.get_value())
+ if coor is None: coor = (
+ int(random.uniform(.25, .75)*h_adj.page_size + h_adj.get_value()),
+ int(random.uniform(.25, .75)*v_adj.page_size + v_adj.get_value()),
+ )
#get the new block
block = self.get_new_block(key)
- block.set_coordinate((x, y))
+ block.set_coordinate(coor)
block.set_rotation(0)
block.get_param('id').set_value(id)
self.handle_states(ELEMENT_CREATE)
@@ -137,15 +133,15 @@ class FlowGraph(Element):
y_off = v_adj.get_value() - y_min + v_adj.page_size/4
#create blocks
for block_n in blocks_n:
- block_key = block_n['key']
+ block_key = block_n.find('key')
if block_key == 'options': continue
block = self.get_new_block(block_key)
selected.add(block)
#set params
- params_n = utils.listify(block_n, 'param')
+ params_n = block_n.findall('param')
for param_n in params_n:
- param_key = param_n['key']
- param_value = param_n['value']
+ param_key = param_n.find('key')
+ param_value = param_n.find('value')
#setup id parameter
if param_key == 'id':
old_id2block[param_value] = block
@@ -160,8 +156,8 @@ class FlowGraph(Element):
self.update()
#create connections
for connection_n in connections_n:
- source = old_id2block[connection_n['source_block_id']].get_source(connection_n['source_key'])
- sink = old_id2block[connection_n['sink_block_id']].get_sink(connection_n['sink_key'])
+ source = old_id2block[connection_n.find('source_block_id')].get_source(connection_n.find('source_key'))
+ sink = old_id2block[connection_n.find('sink_block_id')].get_sink(connection_n.find('sink_key'))
self.connect(source, sink)
#set all pasted elements selected
for block in selected: selected = selected.union(set(block.get_connections()))
@@ -186,14 +182,6 @@ class FlowGraph(Element):
"""
return any([sb.port_controller_modify(direction) for sb in self.get_selected_blocks()])
- def param_modify_selected(self):
- """
- Create and show a param modification dialog for the selected block.
- @return true if parameters were changed
- """
- if not self.get_selected_block(): return False
- return ParamsDialog(self.get_selected_block()).run()
-
def enable_selected(self, enable):
"""
Enable/disable the selected blocks.
@@ -216,15 +204,13 @@ class FlowGraph(Element):
selected_block.move(delta_coordinate)
self.element_moved = True
- def rotate_selected(self, direction):
+ def rotate_selected(self, rotation):
"""
- Rotate the selected blocks by 90 degrees.
- @param direction DIR_LEFT or DIR_RIGHT
+ Rotate the selected blocks by multiples of 90 degrees.
+ @param rotation the rotation in degrees
@return true if changed, otherwise false.
"""
if not self.get_selected_blocks(): return False
- #determine the number of degrees to rotate
- rotation = {DIR_LEFT: 90, DIR_RIGHT:270}[direction]
#initialize min and max coordinates
min_x, min_y = self.get_selected_block().get_coordinate()
max_x, max_y = self.get_selected_block().get_coordinate()
@@ -255,55 +241,49 @@ class FlowGraph(Element):
changed = True
return changed
- def draw(self):
+ def draw(self, gc, window):
"""
Draw the background and grid if enabled.
Draw all of the elements in this flow graph onto the pixmap.
Draw the pixmap to the drawable window of this flow graph.
"""
- if self.get_gc():
- W,H = self.get_size()
- #draw the background
- self.get_gc().foreground = Colors.BACKGROUND_COLOR
- self.get_pixmap().draw_rectangle(self.get_gc(), True, 0, 0, W, H)
- #draw multi select rectangle
- if self.mouse_pressed and (not self.get_selected_elements() or self.get_ctrl_mask()):
- #coordinates
- x1, y1 = self.press_coor
- x2, y2 = self.get_coordinate()
- #calculate top-left coordinate and width/height
- x, y = int(min(x1, x2)), int(min(y1, y2))
- w, h = int(abs(x1 - x2)), int(abs(y1 - y2))
- #draw
- self.get_gc().foreground = Colors.H_COLOR
- self.get_pixmap().draw_rectangle(self.get_gc(), True, x, y, w, h)
- self.get_gc().foreground = Colors.TXT_COLOR
- self.get_pixmap().draw_rectangle(self.get_gc(), False, x, y, w, h)
- #draw blocks on top of connections
- for element in self.get_connections() + self.get_blocks():
- element.draw(self.get_pixmap())
- #draw selected blocks on top of selected connections
- for selected_element in self.get_selected_connections() + self.get_selected_blocks():
- selected_element.draw(self.get_pixmap())
- self.get_drawing_area().draw()
+ try: #set the size of the flow graph area (if changed)
+ new_size = self.get_option('window_size')
+ if self.get_size() != tuple(new_size): self.set_size(*new_size)
+ except: pass
+ W,H = self.get_size()
+ #draw the background
+ gc.foreground = Colors.BACKGROUND_COLOR
+ window.draw_rectangle(gc, True, 0, 0, W, H)
+ #draw multi select rectangle
+ if self.mouse_pressed and (not self.get_selected_elements() or self.get_ctrl_mask()):
+ #coordinates
+ x1, y1 = self.press_coor
+ x2, y2 = self.get_coordinate()
+ #calculate top-left coordinate and width/height
+ x, y = int(min(x1, x2)), int(min(y1, y2))
+ w, h = int(abs(x1 - x2)), int(abs(y1 - y2))
+ #draw
+ gc.foreground = Colors.H_COLOR
+ window.draw_rectangle(gc, True, x, y, w, h)
+ gc.foreground = Colors.TXT_COLOR
+ window.draw_rectangle(gc, False, x, y, w, h)
+ #draw blocks on top of connections
+ for element in self.get_connections() + self.get_blocks():
+ element.draw(gc, window)
+ #draw selected blocks on top of selected connections
+ for selected_element in self.get_selected_connections() + self.get_selected_blocks():
+ selected_element.draw(gc, window)
def update(self):
"""
Update highlighting so only the selected is highlighted.
Call update on all elements.
- Resize the window if size changed.
"""
- #update highlighting
- map(lambda e: e.set_highlighted(False), self.get_elements())
- for selected_element in self.get_selected_elements():
- selected_element.set_highlighted(True)
- #update all elements
- map(lambda e: e.update(), self.get_elements())
- #set the size of the flow graph area
- old_x, old_y = self.get_size()
- try: new_x, new_y = self.get_option('window_size')
- except: new_x, new_y = old_x, old_y
- if new_x != old_x or new_y != old_y: self.set_size(new_x, new_y)
+ selected_elements = self.get_selected_elements()
+ for element in self.get_elements():
+ element.set_highlighted(element in selected_elements)
+ element.update()
##########################################################################
## Get Selected
@@ -466,7 +446,6 @@ class FlowGraph(Element):
self.handle_states(BLOCK_MOVE)
self.element_moved = False
self.update_selected_elements()
- self.draw()
def handle_mouse_motion(self, coordinate):
"""
@@ -474,9 +453,8 @@ class FlowGraph(Element):
Move a selected element to the new coordinate.
Auto-scroll the scroll bars at the boundaries.
"""
- #to perform a movement, the mouse must be pressed, timediff large enough
- if not self.mouse_pressed: return
- if time.time() - self.time < MOTION_DETECT_REDRAWING_SENSITIVITY: return
+ #to perform a movement, the mouse must be pressed, no pending events
+ if gtk.events_pending() or not self.mouse_pressed: return
#perform autoscrolling
width, height = self.get_size()
x, y = coordinate
@@ -499,7 +477,6 @@ class FlowGraph(Element):
#move the selected elements and record the new coordinate
X, Y = self.get_coordinate()
if not self.get_ctrl_mask(): self.move_selected((int(x - X), int(y - Y)))
- self.draw()
self.set_coordinate((x, y))
- #update time
- self.time = time.time()
+ #queue draw for animation
+ self.queue_draw()
diff --git a/grc/src/platforms/gui/Param.py b/grc/src/platforms/gui/Param.py
index 2afe18c57..33a9b1f52 100644
--- a/grc/src/platforms/gui/Param.py
+++ b/grc/src/platforms/gui/Param.py
@@ -1,5 +1,5 @@
"""
-Copyright 2007 Free Software Foundation, Inc.
+Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -22,8 +22,30 @@ from Element import Element
import pygtk
pygtk.require('2.0')
import gtk
-import pango
-from Constants import PARAM_LABEL_FONT, PARAM_FONT
+
+PARAM_MARKUP_TMPL="""\
+#set $foreground = $param.is_valid() and 'black' or 'red'
+#set $value = not $param.is_valid() and 'error' or repr($param)
+<span foreground="$foreground" font_desc="Sans 7.5"><b>$encode($param.get_name()): </b>$encode($value)</span>"""
+
+PARAM_LABEL_MARKUP_TMPL="""\
+#set $foreground = $param.is_valid() and 'black' or 'red'
+#set $underline = $has_cb and 'low' or 'none'
+<span underline="$underline" foreground="$foreground" font_desc="Sans 9">$encode($param.get_name())</span>"""
+
+TIP_MARKUP_TMPL="""\
+Key: $param.get_key()
+Type: $param.get_type()
+#if $param.is_valid()
+Value: $param.evaluate()
+#elif len($param.get_error_messages()) == 1
+Error: $(param.get_error_messages()[0])
+#else
+Error:
+ #for $error_msg in $param.get_error_messages()
+ * $error_msg
+ #end for
+#end if"""
class Param(Element):
"""The graphical parameter."""
@@ -52,24 +74,12 @@ class Param(Element):
When the input changes, write the inputs to the data type.
Finish by calling the exteral callback.
"""
- value = self._input.get_text()
- if self.is_enum(): value = self.get_option_keys()[int(value)]
- self.set_value(value)
- #set the markup on the label, red for errors in corresponding data type.
- name = '<span font_desc="%s">%s</span>'%(
- PARAM_LABEL_FONT,
- Utils.xml_encode(self.get_name()),
- )
- #special markups if param is involved in a callback
- if hasattr(self.get_parent(), 'get_callbacks') and \
- filter(lambda c: self.get_key() in c, self.get_parent()._callbacks):
- name = '<span underline="low">%s</span>'%name
- if not self.is_valid():
- self._input.set_markup('<span foreground="red">%s</span>'%name)
- tip = 'Error: ' + ' '.join(self.get_error_messages())
- else:
- self._input.set_markup(name)
- tip = 'Value: %s'%str(self.evaluate())
+ self.set_value(self._input.get_text())
+ #is param is involved in a callback? #FIXME: messy
+ has_cb = \
+ hasattr(self.get_parent(), 'get_callbacks') and \
+ filter(lambda c: self.get_key() in c, self.get_parent()._callbacks)
+ self._input.set_markup(Utils.parse_template(PARAM_LABEL_MARKUP_TMPL, param=self, has_cb=has_cb))
#hide/show
if self.get_hide() == 'all': self._input.hide_all()
else: self._input.show_all()
@@ -78,30 +88,16 @@ class Param(Element):
#set the tooltip
if self._input.tp: self._input.tp.set_tip(
self._input.entry,
- 'Key: %s\nType: %s\n%s'%(self.get_key(), self.get_type(), tip),
+ Utils.parse_template(TIP_MARKUP_TMPL, param=self).strip(),
)
#execute the external callback
if self._callback: self._callback(self)
- def get_markup(self):
- """
- Create a markup to display the param as a label on the block.
- If the param is valid, use the param's repr representation.
- Otherwise, create a markup for error.
- @return pango markup string
- """
- if self.is_valid():
- return '<b>%s:</b> %s'%(Utils.xml_encode(self.get_name()), Utils.xml_encode(repr(self)))
- else:
- return '<span foreground="red"><b>%s:</b> error</span>'%Utils.xml_encode(self.get_name())
-
def get_layout(self):
"""
Create a layout based on the current markup.
@return the pango layout
"""
layout = gtk.DrawingArea().create_pango_layout('')
- layout.set_markup(self.get_markup())
- desc = pango.FontDescription(PARAM_FONT)
- layout.set_font_description(desc)
+ layout.set_markup(Utils.parse_template(PARAM_MARKUP_TMPL, param=self))
return layout
diff --git a/grc/src/platforms/gui/Port.py b/grc/src/platforms/gui/Port.py
index 85d9fea5a..3aec6e4a7 100644
--- a/grc/src/platforms/gui/Port.py
+++ b/grc/src/platforms/gui/Port.py
@@ -20,13 +20,16 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
from Element import Element
from Constants import \
PORT_SEPARATION, CONNECTOR_EXTENSION_MINIMAL, \
- CONNECTOR_EXTENSION_INCREMENT, PORT_FONT, \
+ CONNECTOR_EXTENSION_INCREMENT, \
PORT_LABEL_PADDING, PORT_MIN_WIDTH
+import Utils
import Colors
import pygtk
pygtk.require('2.0')
import gtk
-import pango
+
+PORT_MARKUP_TMPL="""\
+<span foreground="black" font_desc="Sans 7.5">$encode($port.get_name())</span>"""
class Port(Element):
"""The graphical port."""
@@ -83,9 +86,8 @@ class Port(Element):
"""Create the labels for the socket."""
self.BG_color = Colors.get_color(self.get_color())
#create the layout
- layout = gtk.DrawingArea().create_pango_layout(self.get_name())
- desc = pango.FontDescription(PORT_FONT)
- layout.set_font_description(desc)
+ layout = gtk.DrawingArea().create_pango_layout('')
+ layout.set_markup(Utils.parse_template(PORT_MARKUP_TMPL, port=self))
self.w, self.h = layout.get_pixel_size()
self.W, self.H = 2*PORT_LABEL_PADDING+self.w, 2*PORT_LABEL_PADDING+self.h
#create the pixmap
@@ -102,13 +104,13 @@ class Port(Element):
for i in range(self.w):
for j in range(self.h): vimage.put_pixel(j, self.w-i-1, image.get_pixel(i, j))
- def draw(self, window):
+ def draw(self, gc, window):
"""
Draw the socket with a label.
+ @param gc the graphics context
@param window the gtk window to draw on
"""
- Element.draw(self, window, BG_color=self.BG_color)
- gc = self.get_gc()
+ Element.draw(self, gc, window, BG_color=self.BG_color)
gc.foreground = Colors.TXT_COLOR
X,Y = self.get_coordinate()
(x,y),(w,h) = self.areas_dict[self.get_rotation()][0] #use the first area's sizes to place the labels
diff --git a/grc/src/platforms/gui/Utils.py b/grc/src/platforms/gui/Utils.py
index 17750ef45..ee6dc6cdc 100644
--- a/grc/src/platforms/gui/Utils.py
+++ b/grc/src/platforms/gui/Utils.py
@@ -1,5 +1,5 @@
"""
-Copyright 2008 Free Software Foundation, Inc.
+Copyright 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -18,6 +18,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
from Constants import POSSIBLE_ROTATIONS
+from Cheetah.Template import Template
def get_rotated_coordinate(coor, rotation):
"""
@@ -69,3 +70,13 @@ def xml_encode(string):
("'", '&apos;'),
): string = string.replace(char, safe)
return string
+
+def parse_template(tmpl_str, **kwargs):
+ """
+ Parse the template string with the given args.
+ Pass in the xml encode method for pango escape chars.
+ @param tmpl_str the template as a string
+ @return a string of the parsed template
+ """
+ kwargs['encode'] = xml_encode
+ return str(Template(tmpl_str, kwargs))
diff --git a/grc/src/platforms/python/Block.py b/grc/src/platforms/python/Block.py
index 3c45117a3..38a0ce492 100644
--- a/grc/src/platforms/python/Block.py
+++ b/grc/src/platforms/python/Block.py
@@ -19,7 +19,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
from .. base.Block import Block as _Block
from utils import extract_docs
-from ... import utils
class Block(_Block):
@@ -36,11 +35,11 @@ class Block(_Block):
@return block a new block
"""
#grab the data
- doc = utils.exists_or_else(n, 'doc', '')
- imports = map(lambda i: i.strip(), utils.listify(n, 'import'))
- make = n['make']
- checks = utils.listify(n, 'check')
- callbacks = utils.listify(n, 'callback')
+ doc = n.find('doc') or ''
+ imports = map(lambda i: i.strip(), n.findall('import'))
+ make = n.find('make')
+ checks = n.findall('check')
+ callbacks = n.findall('callback')
#build the block
_Block.__init__(
self,
diff --git a/grc/src/platforms/python/Constants.py.in b/grc/src/platforms/python/Constants.py.in
index 199b24223..502f41550 100644
--- a/grc/src/platforms/python/Constants.py.in
+++ b/grc/src/platforms/python/Constants.py.in
@@ -50,3 +50,4 @@ FLOAT_VECTOR_COLOR_SPEC = '#CC8C69'
INT_VECTOR_COLOR_SPEC = '#00CC99'
SHORT_VECTOR_COLOR_SPEC = '#CCCC33'
BYTE_VECTOR_COLOR_SPEC = '#CC66CC'
+ID_COLOR_SPEC = '#DDDDDD'
diff --git a/grc/src/platforms/python/FlowGraph.py b/grc/src/platforms/python/FlowGraph.py
index cd5635b95..95c0b38cb 100644
--- a/grc/src/platforms/python/FlowGraph.py
+++ b/grc/src/platforms/python/FlowGraph.py
@@ -1,5 +1,5 @@
"""
-Copyright 2008 Free Software Foundation, Inc.
+Copyright 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -22,21 +22,15 @@ from .. base.FlowGraph import FlowGraph as _FlowGraph
from Block import Block
from Connection import Connection
-def get_variable_code(variable):
+def _get_value_expr(variable_block):
"""
- Get the code representation for a variable.
- Normally this is the value parameter.
- For the variable chooser, use the index and choices.
- Avoid using the to_code method of the variables,
- as this forces evaluation before the variables are evaluated.
- @param variable the variable block
- @return the code string
+ Get the expression to evaluate from the value param.
+ @param variable_block the variable or parameter block
+ @return the expression string
"""
- if variable.get_key() == 'variable_chooser':
- choices = variable.get_param('choices').get_value()
- value_index = variable.get_param('value_index').get_value()
- return "(%s)[%s]"%(choices, value_index)
- return variable.get_param('value').get_value()
+ value_param = variable_block.get_param('value')
+ value_param.evaluate() #evaluate prior to code
+ return value_param.to_code()
class FlowGraph(_FlowGraph):
@@ -117,7 +111,7 @@ class FlowGraph(_FlowGraph):
id2var = dict([(var.get_id(), var) for var in variables])
#map var id to variable code
#variable code is a concatenation of all param code (without the id param)
- id2expr = dict([(var.get_id(), get_variable_code(var)) for var in variables])
+ id2expr = dict([(var.get_id(), var.get_param('value').get_value()) for var in variables])
#sort according to dependency
sorted_ids = expr_utils.sort_variables(id2expr)
#create list of sorted variable blocks
@@ -151,14 +145,14 @@ class FlowGraph(_FlowGraph):
np = dict()
for parameter in self.get_parameters():
try:
- e = self._eval(parameter.get_param('value').to_code(), n)
+ e = self._eval(_get_value_expr(parameter), n)
np[parameter.get_id()] = e
except: pass
n.update(np) #merge param namespace
#load variables
for variable in self.get_variables():
try:
- e = self._eval(get_variable_code(variable), n)
+ e = self._eval(_get_value_expr(variable), n)
n[variable.get_id()] = e
except: pass
#make namespace public
diff --git a/grc/src/platforms/python/Generator.py b/grc/src/platforms/python/Generator.py
index 83dd186c3..93321404a 100644
--- a/grc/src/platforms/python/Generator.py
+++ b/grc/src/platforms/python/Generator.py
@@ -53,7 +53,7 @@ class Generator(object):
def write(self):
#do throttle warning
all_keys = ' '.join(map(lambda b: b.get_key(), self._flow_graph.get_enabled_blocks()))
- if ('usrp' not in all_keys) and ('audio' not in all_keys) and ('throttle' not in all_keys):
+ if ('usrp' not in all_keys) and ('audio' not in all_keys) and ('throttle' not in all_keys) and self._generate_options != 'hb':
Messages.send_warning('''\
This flow graph may not have flow control: no audio or usrp blocks found. \
Add a Misc->Throttle block to your flow graph to avoid CPU congestion.''')
diff --git a/grc/src/platforms/python/Param.py b/grc/src/platforms/python/Param.py
index efebe92e5..e75a882a4 100644
--- a/grc/src/platforms/python/Param.py
+++ b/grc/src/platforms/python/Param.py
@@ -1,5 +1,5 @@
"""
-Copyright 2008 Free Software Foundation, Inc.
+Copyright 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -94,7 +94,7 @@ class Param(_Param):
Get the repr (nice string format) for this param.
@return the string representation
"""
- if self.is_enum(): return _Param.__repr__(self)
+ if self.get_value() in self.get_option_keys(): return self.get_option(self.get_value()).get_name()
##################################################
# display logic for numbers
##################################################
@@ -158,7 +158,7 @@ class Param(_Param):
#special
'hex': Constants.INT_COLOR_SPEC,
'string': Constants.BYTE_VECTOR_COLOR_SPEC,
- 'id': '#DDDDDD',
+ 'id': Constants.ID_COLOR_SPEC,
'grid_pos': Constants.INT_VECTOR_COLOR_SPEC,
}[self.get_type()]
except: return _Param.get_color(self)
diff --git a/grc/src/platforms/python/Port.py b/grc/src/platforms/python/Port.py
index 109eecb62..b5bc9696b 100644
--- a/grc/src/platforms/python/Port.py
+++ b/grc/src/platforms/python/Port.py
@@ -1,5 +1,5 @@
"""
-Copyright 2008 Free Software Foundation, Inc.
+Copyright 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -18,7 +18,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
from .. base.Port import Port as _Port
-from ... import utils
import Constants
class Port(_Port):
@@ -33,9 +32,9 @@ class Port(_Port):
@param n the nested odict
@return a new port
"""
- vlen = utils.exists_or_else(n, 'vlen', '1')
- nports = utils.exists_or_else(n, 'nports', '')
- optional = utils.exists_or_else(n, 'optional', '')
+ vlen = n.find('vlen') or '1'
+ nports = n.find('nports') or ''
+ optional = n.find('optional') or ''
#build the port
_Port.__init__(
self,