summaryrefslogtreecommitdiff
path: root/grc/model/Param.py
diff options
context:
space:
mode:
Diffstat (limited to 'grc/model/Param.py')
-rw-r--r--grc/model/Param.py199
1 files changed, 179 insertions, 20 deletions
diff --git a/grc/model/Param.py b/grc/model/Param.py
index b627e5eec8..c8da6a5b58 100644
--- a/grc/model/Param.py
+++ b/grc/model/Param.py
@@ -1,5 +1,5 @@
"""
-Copyright 2008-2011 Free Software Foundation, Inc.
+Copyright 2008-2015 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -25,17 +25,23 @@ from gnuradio import gr
import Constants
from Constants import VECTOR_TYPES, COMPLEX_TYPES, REAL_TYPES, INT_TYPES
-from .base.Param import Param as _Param
+
_check_id_matcher = re.compile('^[a-z|A-Z]\w*$')
_show_id_matcher = re.compile('^(variable\w*|parameter|options|notebook|epy_module)$')
+from .odict import odict
+from .Element import Element
#blacklist certain ids, its not complete, but should help
import __builtin__
ID_BLACKLIST = ['self', 'options', 'gr', 'blks2', 'wxgui', 'wx', 'math', 'forms', 'firdes'] + \
filter(lambda x: not x.startswith('_'), dir(gr.top_block())) + dir(__builtin__)
+def _get_keys(lst): return [elem.get_key() for elem in lst]
+def _get_elem(lst, key):
+ try: return lst[_get_keys(lst).index(key)]
+ except ValueError: raise ValueError, 'Key "%s" not found in %s.'%(key, _get_keys(lst))
def num_to_str(num):
""" Display logic for numbers """
@@ -48,24 +54,110 @@ def num_to_str(num):
else: return '%s+%sj'%(eng_notation.num_to_str(num.real), eng_notation.num_to_str(num.imag))
else: return str(num)
+class Option(Element):
+
+ def __init__(self, param, n):
+ Element.__init__(self, param)
+ self._name = n.find('name')
+ self._key = n.find('key')
+ self._opts = dict()
+ opts = n.findall('opt')
+ #test against opts when non enum
+ if not self.get_parent().is_enum() and opts:
+ raise Exception, '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: raise Exception, 'Error separating "%s" into key:value'%opt
+ #test against repeated keys
+ if self._opts.has_key(key):
+ raise Exception, '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
+
+ ##############################################
+ # Access Opts
+ ##############################################
+ def get_opt_keys(self): return self._opts.keys()
+ def get_opt(self, key): return self._opts[key]
+ def get_opts(self): return self._opts.values()
+
+
+class Param(Element):
+
+ def __init__(self, block, n):
+ """
+ Make a new param from nested data.
-class Param(_Param):
-
- def __init__(self, **kwargs):
- _Param.__init__(self, **kwargs)
+ Args:
+ block: the parent element
+ n: the nested odict
+ """
+ # if the base key is a valid param key, copy its data and overlay this params data
+ base_key = n.find('base_key')
+ if base_key and base_key in block.get_param_keys():
+ n_expanded = block.get_param(base_key)._n.copy()
+ n_expanded.update(n)
+ n = n_expanded
+ # save odict in case this param will be base for another
+ self._n = n
+ # parse the data
+ self._name = n.find('name')
+ self._key = n.find('key')
+ value = n.find('value') or ''
+ self._type = n.find('type') or 'raw'
+ self._hide = n.find('hide') or ''
+ self._tab_label = n.find('tab') or block.get_param_tab_labels()[0]
+ if not self._tab_label in block.get_param_tab_labels():
+ block.get_param_tab_labels().append(self._tab_label)
+ #build the param
+ Element.__init__(self, block)
+ #create the Option objects from the n data
+ self._options = list()
+ self._evaluated = None
+ for option in map(lambda o: Option(param=self, n=o), n.findall('option')):
+ key = option.get_key()
+ #test against repeated keys
+ if key in self.get_option_keys():
+ raise Exception, 'Key "%s" already exists in options'%key
+ #store the option
+ self.get_options().append(option)
+ #test the enum options
+ if self.is_enum():
+ #test against options with identical keys
+ if len(set(self.get_option_keys())) != len(self.get_options()):
+ raise Exception, 'Options keys "%s" are not unique.'%self.get_option_keys()
+ #test against inconsistent keys in options
+ opt_keys = self.get_options()[0].get_opt_keys()
+ for option in self.get_options():
+ if set(opt_keys) != set(option.get_opt_keys()):
+ raise Exception, 'Opt keys "%s" are not identical across all options.'%opt_keys
+ #if a value is specified, it must be in the options keys
+ self._value = value if value or value in self.get_option_keys() else self.get_option_keys()[0]
+ if self.get_value() not in self.get_option_keys():
+ raise Exception, 'The value "%s" is not in the possible values of "%s".'%(self.get_value(), self.get_option_keys())
+ else:
+ self._value = value or ''
+ self._default = value
self._init = False
self._hostage_cells = list()
- def get_types(self): return (
- 'raw', 'enum',
- 'complex', 'real', 'float', 'int',
- 'complex_vector', 'real_vector', 'float_vector', 'int_vector',
- 'hex', 'string', 'bool',
- 'file_open', 'file_save', '_multiline', '_multiline_python_external',
- 'id', 'stream_id',
- 'grid_pos', 'notebook', 'gui_hint',
- 'import',
- )
+ def get_types(self):
+ return (
+ 'raw', 'enum',
+ 'complex', 'real', 'float', 'int',
+ 'complex_vector', 'real_vector', 'float_vector', 'int_vector',
+ 'hex', 'string', 'bool',
+ 'file_open', 'file_save', '_multiline', '_multiline_python_external',
+ 'id', 'stream_id',
+ 'grid_pos', 'notebook', 'gui_hint',
+ 'import',
+ )
def __repr__(self):
"""
@@ -115,6 +207,19 @@ class Param(_Param):
##################################################
return _truncate(dt_str, truncate)
+ def __repr2__(self):
+ """
+ Get the repr (nice string format) for this param.
+
+ Returns:
+ the string representation
+ """
+ if self.is_enum():
+ return self.get_option(self.get_value()).get_name()
+ return self.get_value()
+
+ def __str__(self): return 'Param - %s(%s)'%(self.get_name(), self.get_key())
+
def get_color(self):
"""
Get the color that represents this param's type.
@@ -144,7 +249,8 @@ class Param(_Param):
'notebook': Constants.INT_VECTOR_COLOR_SPEC,
'raw': Constants.WILDCARD_COLOR_SPEC,
}[self.get_type()]
- except: return _Param.get_color(self)
+ except:
+ return '#FFFFFF'
def get_hide(self):
"""
@@ -157,7 +263,7 @@ class Param(_Param):
Returns:
hide the hide property string
"""
- hide = _Param.get_hide(self)
+ hide = self.get_parent().resolve_dependencies(self._hide).strip()
if hide: return hide
#hide ID in non variable blocks
if self.get_key() == 'id' and not _show_id_matcher.match(self.get_parent().get_key()): return 'part'
@@ -179,9 +285,12 @@ class Param(_Param):
def validate(self):
"""
Validate the param.
- A test evaluation is performed
+ The value must be evaluated and type must a possible type.
"""
- _Param.validate(self) #checks type
+ Element.validate(self)
+ if self.get_type() not in self.get_types():
+ self.add_error_message('Type "%s" is not a possible type.'%self.get_type())
+
self._evaluated = None
try: self._evaluated = self.evaluate()
except Exception, e: self.add_error_message(str(e))
@@ -427,3 +536,53 @@ class Param(_Param):
a list of params
"""
return sum([filter(lambda p: p.get_type() == type, block.get_params()) for block in self.get_parent().get_parent().get_enabled_blocks()], [])
+
+ def is_enum(self): return self._type == 'enum'
+
+ def get_value(self):
+ value = self._value
+ if self.is_enum() and value not in self.get_option_keys():
+ value = self.get_option_keys()[0]
+ self.set_value(value)
+ return value
+
+ def set_value(self, value): self._value = str(value) #must be a string
+
+ def value_is_default(self):
+ return self._default == self._value
+
+ def get_type(self): return self.get_parent().resolve_dependencies(self._type)
+ def get_tab_label(self): return self._tab_label
+
+ def is_param(self): return True
+ def get_name(self): return self.get_parent().resolve_dependencies(self._name).strip()
+ def get_key(self): return self._key
+
+ ##############################################
+ # Access Options
+ ##############################################
+ def get_option_keys(self): return _get_keys(self.get_options())
+ def get_option(self, key): return _get_elem(self.get_options(), key)
+ def get_options(self): return self._options
+
+ ##############################################
+ # Access Opts
+ ##############################################
+ def get_opt_keys(self): return self.get_option(self.get_value()).get_opt_keys()
+ def get_opt(self, key): return self.get_option(self.get_value()).get_opt(key)
+ def get_opts(self): return self.get_option(self.get_value()).get_opts()
+
+ ##############################################
+ ## Import/Export Methods
+ ##############################################
+ def export_data(self):
+ """
+ Export this param's key/value.
+
+ Returns:
+ a nested data odict
+ """
+ n = odict()
+ n['key'] = self.get_key()
+ n['value'] = self.get_value()
+ return n