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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
|
# Copyright 2007-2016 Free Software Foundation, Inc.
# This file is part of GNU Radio
#
# SPDX-License-Identifier: GPL-2.0-or-later
#
import numbers
from .drawable import Drawable
from .. import ParamWidgets, Utils, Constants, Actions
from ...core.params import Param as CoreParam
class Param(CoreParam):
"""The graphical parameter."""
make_cls_with_base = classmethod(Drawable.make_cls_with_base.__func__)
def get_input(self, *args, **kwargs):
"""
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.
Returns:
gtk input class
"""
dtype = self.dtype
if dtype in ('file_open', 'file_save'):
input_widget_cls = ParamWidgets.FileParam
elif dtype == 'dir_select':
input_widget_cls = ParamWidgets.DirectoryParam
elif dtype == 'enum':
input_widget_cls = ParamWidgets.EnumParam
elif self.options:
input_widget_cls = ParamWidgets.EnumEntryParam
elif dtype == '_multiline':
input_widget_cls = ParamWidgets.MultiLineEntryParam
elif dtype == '_multiline_python_external':
input_widget_cls = ParamWidgets.PythonEditorParam
else:
input_widget_cls = ParamWidgets.EntryParam
return input_widget_cls(self, *args, **kwargs)
def format_label_markup(self, have_pending_changes=False):
block = self.parent
# fixme: using non-public attribute here
has_callback = \
hasattr(block, 'templates') and \
any(self.key in callback for callback in block.templates.get('callbacks', ''))
return '<span {underline} {foreground} font_desc="Sans 9">{label}</span>'.format(
underline='underline="low"' if has_callback else '',
foreground='foreground="blue"' if have_pending_changes else
'foreground="red"' if not self.is_valid() else '',
label=Utils.encode(self.name)
)
def format_tooltip_text(self):
errors = self.get_error_messages()
tooltip_lines = ['Key: ' + self.key, 'Type: ' + self.dtype]
if self.is_valid():
value = self.get_evaluated()
if hasattr(value, "__len__"):
tooltip_lines.append('Length: {}'.format(len(value)))
value = str(value)
# ensure that value is a UTF-8 string
# Old PMTs could produce non-UTF-8 strings
value = value.encode('utf-8', 'backslashreplace').decode('utf-8')
if len(value) > 100:
value = '{}...{}'.format(value[:50], value[-50:])
tooltip_lines.append('Value: ' + value)
elif len(errors) == 1:
tooltip_lines.append('Error: ' + errors[0])
elif len(errors) > 1:
tooltip_lines.append('Error:')
tooltip_lines.extend(' * ' + msg for msg in errors)
return '\n'.join(tooltip_lines)
##################################################
# Truncate helper method
##################################################
def truncate(self, string, style=0):
max_len = max(27 - len(self.name), 3)
if len(string) > max_len:
if style < 0: # Front truncate
string = '...' + string[3 - max_len:]
elif style == 0: # Center truncate
string = string[:max_len // 2 - 3] + \
'...' + string[-max_len // 2:]
elif style > 0: # Rear truncate
string = string[:max_len - 3] + '...'
return string
def pretty_print(self):
"""
Get the repr (nice string format) for this param.
Returns:
the string representation
"""
##################################################
# Simple conditions
##################################################
value = self.get_value()
if not self.is_valid():
return self.truncate(value)
if value in self.options:
return self.options[value] # its name
##################################################
# Split up formatting by type
##################################################
# Default center truncate
truncate = 0
e = self.get_evaluated()
t = self.dtype
if isinstance(e, bool):
return str(e)
elif isinstance(e, numbers.Complex):
dt_str = Utils.num_to_str(e)
elif isinstance(e, Constants.VECTOR_TYPES):
# Vector types
if len(e) > 8:
# Large vectors use code
dt_str = self.get_value()
truncate = 1
else:
# Small vectors use eval
dt_str = ', '.join(map(Utils.num_to_str, e))
elif t in ('file_open', 'file_save'):
dt_str = self.get_value()
truncate = -1
else:
# Other types
dt_str = str(e)
# ensure that value is a UTF-8 string
# Old PMTs could produce non-UTF-8 strings
dt_str = dt_str.encode('utf-8', 'backslashreplace').decode('utf-8')
# Done
return self.truncate(dt_str, truncate)
def format_block_surface_markup(self):
"""
Get the markup for this param.
Returns:
a pango markup string
"""
# TODO: is this the correct way to do this?
is_evaluated = self.value != str(self.get_evaluated())
show_value = Actions.TOGGLE_SHOW_PARAMETER_EVALUATION.get_active()
show_expr = Actions.TOGGLE_SHOW_PARAMETER_EXPRESSION.get_active()
display_value = ""
# Include the value defined by the user (after evaluation)
if not is_evaluated or show_value or not show_expr:
display_value += Utils.encode(
self.pretty_print().replace('\n', ' '))
# Include the expression that was evaluated to get the value
if is_evaluated and show_expr:
expr_string = "<i>" + \
Utils.encode(self.truncate(self.value)) + "</i>"
if display_value: # We are already displaying the value
display_value = expr_string + "=" + display_value
else:
display_value = expr_string
return '<span {foreground} font_desc="{font}"><b>{label}:</b> {value}</span>'.format(
foreground='foreground="red"' if not self.is_valid() else '', font=Constants.PARAM_FONT,
label=Utils.encode(self.name), value=display_value)
|