summaryrefslogtreecommitdiff
path: root/gr-wxgui/src/python/forms/converters.py
blob: 9f757aa8410eb24b7d226e9c828da4caa8a2fd6c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#
# 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):
		#choices must be a list because tuple does not have .index() in python2.5
		self._choices = list(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 __init__(self, formatter=lambda x: '%s'%(x)):
		self._formatter = formatter
	def external_to_internal(self, v):
		return self._formatter(v)
	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 __init__(self, formatter=lambda x: '%s'%(x)):
		self._formatter = formatter
	def external_to_internal(self, v):
		return self._formatter(v)
	def internal_to_external(self, s):
		return str(s)

class int_converter(abstract_converter):
	def __init__(self, formatter=lambda x: '%d'%round(x)):
		self._formatter = formatter
	def external_to_internal(self, v):
		return self._formatter(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 __init__(self, formatter=eng_notation.num_to_str):
		self._formatter = formatter
	def external_to_internal(self, v):
		return self._formatter(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):
		#slider's internal representation is an integer
		return int(round((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)