summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Koslowski <sebastian.koslowski@gmail.com>2017-10-25 20:56:18 +0200
committerSebastian Koslowski <sebastian.koslowski@gmail.com>2017-10-25 20:56:18 +0200
commit06acc2eb6a3caee1aa26506935877da15eeec1b6 (patch)
tree1dd2a8367f86a6dd28ae70f9ae9050264174f378
parent7199e7811261af93203a6f207fd21927ea8304a3 (diff)
parent52a333e05e6336616ca4de61b8c37e7e405e6f6e (diff)
Merge branch 'merges/next' into merges/python3
-rw-r--r--gr-qtgui/grc/qtgui_ber_sink_b.xml2
-rw-r--r--gr-qtgui/grc/qtgui_check_box.xml3
-rw-r--r--gr-qtgui/grc/qtgui_chooser.xml3
-rw-r--r--gr-qtgui/grc/qtgui_const_sink_x.xml3
-rw-r--r--gr-qtgui/grc/qtgui_edit_box_msg.xml2
-rw-r--r--gr-qtgui/grc/qtgui_entry.xml5
-rw-r--r--gr-qtgui/grc/qtgui_freq_sink_x.xml3
-rw-r--r--gr-qtgui/grc/qtgui_histogram_sink_x.xml4
-rw-r--r--gr-qtgui/grc/qtgui_label.xml3
-rw-r--r--gr-qtgui/grc/qtgui_number_sink.xml3
-rw-r--r--gr-qtgui/grc/qtgui_push_button.xml4
-rw-r--r--gr-qtgui/grc/qtgui_range.xml3
-rw-r--r--gr-qtgui/grc/qtgui_sink_x.xml2
-rw-r--r--gr-qtgui/grc/qtgui_tab_widget.xml3
-rw-r--r--gr-qtgui/grc/qtgui_time_raster_x.xml3
-rw-r--r--gr-qtgui/grc/qtgui_time_sink_x.xml3
-rw-r--r--gr-qtgui/grc/qtgui_vector_sink_f.xml3
-rw-r--r--gr-qtgui/grc/qtgui_waterfall_sink_x.xml3
-rw-r--r--grc/core/Param.py166
-rw-r--r--grc/core/generator/hier_block.py4
20 files changed, 172 insertions, 53 deletions
diff --git a/gr-qtgui/grc/qtgui_ber_sink_b.xml b/gr-qtgui/grc/qtgui_ber_sink_b.xml
index 05a36dfbc0..75e43bb703 100644
--- a/gr-qtgui/grc/qtgui_ber_sink_b.xml
+++ b/gr-qtgui/grc/qtgui_ber_sink_b.xml
@@ -47,7 +47,7 @@ for i in xrange($num_curves):
self.$(id).set_line_alpha(i, alphas[i])
self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget)
-$(gui_hint()($win))</make>
+$(gui_hint() % $win)</make>
<param>
<name>esno</name>
diff --git a/gr-qtgui/grc/qtgui_check_box.xml b/gr-qtgui/grc/qtgui_check_box.xml
index ccee59dd92..26e0116600 100644
--- a/gr-qtgui/grc/qtgui_check_box.xml
+++ b/gr-qtgui/grc/qtgui_check_box.xml
@@ -20,7 +20,8 @@ self._$(id)_choices_inv = dict((v,k) for k,v in self._$(id)_choices.iteritems())
self._$(id)_callback = lambda i: Qt.QMetaObject.invokeMethod($(win), "setChecked", Qt.Q_ARG("bool", self._$(id)_choices_inv[i]))
self._$(id)_callback(self.$id)
$(win).stateChanged.connect(lambda i: self.set_$(id)(self._$(id)_choices[bool(i)]))
-$(gui_hint()($win))</make>
+$(gui_hint() % $win)</make>
+
<callback>self.set_$(id)($value)</callback>
<callback>self._$(id)_callback($id)</callback>
<param>
diff --git a/gr-qtgui/grc/qtgui_chooser.xml b/gr-qtgui/grc/qtgui_chooser.xml
index f79bb8ccb3..ae34e57be0 100644
--- a/gr-qtgui/grc/qtgui_chooser.xml
+++ b/gr-qtgui/grc/qtgui_chooser.xml
@@ -86,7 +86,8 @@ self._$(id)_callback(self.$id)
self._$(id)_button_group.buttonClicked[int].connect(
lambda i: self.set_$(id)(self._$(id)_options[i]))
#end if
-$(gui_hint()($win))</make>
+$(gui_hint() % $win)</make>
+
<callback>self.set_$(id)($value)</callback>
<callback>self._$(id)_callback($id)</callback>
<param>
diff --git a/gr-qtgui/grc/qtgui_const_sink_x.xml b/gr-qtgui/grc/qtgui_const_sink_x.xml
index 10f82cce82..301a69b298 100644
--- a/gr-qtgui/grc/qtgui_const_sink_x.xml
+++ b/gr-qtgui/grc/qtgui_const_sink_x.xml
@@ -51,7 +51,8 @@ for i in xrange(#if $type.t == 'message' then 1 else $nconnections#):
self.$(id).set_line_alpha(i, alphas[i])
self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget)
-$(gui_hint()($win))</make>
+$(gui_hint() % $win)</make>
+
<callback>set_resize($width, $height)</callback>
<callback>set_update_time($update_time)</callback>
<callback>set_title($which, $title)</callback>
diff --git a/gr-qtgui/grc/qtgui_edit_box_msg.xml b/gr-qtgui/grc/qtgui_edit_box_msg.xml
index d77a4b3e1b..bf5dbb4cdd 100644
--- a/gr-qtgui/grc/qtgui_edit_box_msg.xml
+++ b/gr-qtgui/grc/qtgui_edit_box_msg.xml
@@ -13,7 +13,7 @@
<make>#set $win = 'self._%s_win'%$id
qtgui.edit_box_msg($(type.t), $value, $label, $is_pair, $is_static, $key)
self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget)
-$(gui_hint()($win))</make>
+$(gui_hint() % $win)</make>
<param>
<name>Type</name>
diff --git a/gr-qtgui/grc/qtgui_entry.xml b/gr-qtgui/grc/qtgui_entry.xml
index fc0f4089d1..0d2192b8b6 100644
--- a/gr-qtgui/grc/qtgui_entry.xml
+++ b/gr-qtgui/grc/qtgui_entry.xml
@@ -21,9 +21,12 @@ self._$(id)_line_edit = Qt.QLineEdit(str(self.$id))
self._$(id)_tool_bar.addWidget(self._$(id)_line_edit)
self._$(id)_line_edit.returnPressed.connect(
lambda: self.set_$(id)($(type.conv)(str(self._$(id)_line_edit.text().toAscii()))))
-$(gui_hint()($win))</make>
+$(gui_hint() % $win)</make>
+
<callback>self.set_$(id)($value)</callback>
+
<callback>Qt.QMetaObject.invokeMethod(self._$(id)_line_edit, "setText", Qt.Q_ARG("QString", $(type.str)($id)))</callback>
+
<param>
<name>Label</name>
<key>label</key>
diff --git a/gr-qtgui/grc/qtgui_freq_sink_x.xml b/gr-qtgui/grc/qtgui_freq_sink_x.xml
index ed39db7781..36d4270f7d 100644
--- a/gr-qtgui/grc/qtgui_freq_sink_x.xml
+++ b/gr-qtgui/grc/qtgui_freq_sink_x.xml
@@ -54,7 +54,8 @@ for i in xrange(#if $type.t == 'message' then 1 else $nconnections#):
self.$(id).set_line_alpha(i, alphas[i])
self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget)
-$(gui_hint()($win))</make>
+$(gui_hint() % $win)</make>
+
<callback>set_frequency_range($fc, $bw)</callback>
<callback>set_update_time($update_time)</callback>
<callback>set_title($which, $title)</callback>
diff --git a/gr-qtgui/grc/qtgui_histogram_sink_x.xml b/gr-qtgui/grc/qtgui_histogram_sink_x.xml
index 9e3dcb104f..a2d21b22a6 100644
--- a/gr-qtgui/grc/qtgui_histogram_sink_x.xml
+++ b/gr-qtgui/grc/qtgui_histogram_sink_x.xml
@@ -53,8 +53,8 @@ for i in xrange(#if $type.t == 'message' then 1 else $nconnections#):
self.$(id).set_line_alpha(i, alphas[i])
self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget)
-$(gui_hint()($win))
- </make>
+$(gui_hint() % $win)</make>
+
<callback>set_update_time($update_time)</callback>
<callback>set_title($which, $title)</callback>
<callback>set_color($which, $color)</callback>
diff --git a/gr-qtgui/grc/qtgui_label.xml b/gr-qtgui/grc/qtgui_label.xml
index 946cee36ab..777e3fcc1f 100644
--- a/gr-qtgui/grc/qtgui_label.xml
+++ b/gr-qtgui/grc/qtgui_label.xml
@@ -26,8 +26,7 @@ else:
$(win).addWidget(Qt.QLabel($label+": "))
self._$(id)_label = Qt.QLabel(str(self._$(id)_formatter(self.$id)))
self._$(id)_tool_bar.addWidget(self._$(id)_label)
-$(gui_hint()($win))
- </make>
+$(gui_hint() % $win)</make>
<callback>self.set_$(id)(self._$(id)_formatter($value))</callback>
<callback>Qt.QMetaObject.invokeMethod(self._$(id)_label, "setText", Qt.Q_ARG("QString", $id))</callback>
diff --git a/gr-qtgui/grc/qtgui_number_sink.xml b/gr-qtgui/grc/qtgui_number_sink.xml
index 06837493c3..7f883eb2de 100644
--- a/gr-qtgui/grc/qtgui_number_sink.xml
+++ b/gr-qtgui/grc/qtgui_number_sink.xml
@@ -41,7 +41,8 @@ for i in xrange($nconnections):
self.$(id).enable_autoscale($autoscale)
self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget)
-$(gui_hint()($win))</make>
+$(gui_hint() % $win)</make>
+
<callback>set_update_time($update_time)</callback>
<param_tab_order>
diff --git a/gr-qtgui/grc/qtgui_push_button.xml b/gr-qtgui/grc/qtgui_push_button.xml
index 49c2e9d6f0..62d44c9ca1 100644
--- a/gr-qtgui/grc/qtgui_push_button.xml
+++ b/gr-qtgui/grc/qtgui_push_button.xml
@@ -18,8 +18,10 @@ $win = Qt.QPushButton($label)
self._$(id)_choices = {'Pressed': $pressed, 'Released': $released}
$(win).pressed.connect(lambda: self.set_$(id)(self._$(id)_choices['Pressed']))
$(win).released.connect(lambda: self.set_$(id)(self._$(id)_choices['Released']))
-$(gui_hint()($win))</make>
+$(gui_hint() % $win)</make>
+
<callback>self.set_$(id)($value)</callback>
+
<param>
<name>Label</name>
<key>label</key>
diff --git a/gr-qtgui/grc/qtgui_range.xml b/gr-qtgui/grc/qtgui_range.xml
index 71b614cc5e..0999311a0b 100644
--- a/gr-qtgui/grc/qtgui_range.xml
+++ b/gr-qtgui/grc/qtgui_range.xml
@@ -17,7 +17,8 @@
#end if
$(range) = Range($start, $stop, $step, $value, $min_len)
$(win) = RangeWidget($range, self.set_$(id), $label, "$widget", $rangeType)
-$(gui_hint()($win))</make>
+$(gui_hint() % $win)</make>
+
<callback>self.set_$(id)($value)</callback>
<param>
diff --git a/gr-qtgui/grc/qtgui_sink_x.xml b/gr-qtgui/grc/qtgui_sink_x.xml
index a9bc469cd2..e8af2f0c10 100644
--- a/gr-qtgui/grc/qtgui_sink_x.xml
+++ b/gr-qtgui/grc/qtgui_sink_x.xml
@@ -25,7 +25,7 @@ qtgui.$(type.fcn)(
)
self.$(id).set_update_time(1.0/$rate)
self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget)
-$(gui_hint()($win))
+$(gui_hint() % $win)
self.$(id).enable_rf_freq($showrf)
diff --git a/gr-qtgui/grc/qtgui_tab_widget.xml b/gr-qtgui/grc/qtgui_tab_widget.xml
index 805542cc8b..7bb5b55e12 100644
--- a/gr-qtgui/grc/qtgui_tab_widget.xml
+++ b/gr-qtgui/grc/qtgui_tab_widget.xml
@@ -21,7 +21,8 @@ self.$(id)_grid_layout_$(i) = Qt.QGridLayout()
self.$(id)_layout_$(i).addLayout(self.$(id)_grid_layout_$(i))
$(win).addTab(self.$(id)_widget_$(i), $label)
#end for
-$(gui_hint()($win))</make>
+$(gui_hint() % $win)</make>
+
<param>
<name>Num Tabs</name>
<key>num_tabs</key>
diff --git a/gr-qtgui/grc/qtgui_time_raster_x.xml b/gr-qtgui/grc/qtgui_time_raster_x.xml
index d458f67eb9..6177b01cad 100644
--- a/gr-qtgui/grc/qtgui_time_raster_x.xml
+++ b/gr-qtgui/grc/qtgui_time_raster_x.xml
@@ -41,7 +41,8 @@ for i in xrange(#if $type.t == 'message' then 1 else $nconnections#):
self.$(id).set_line_alpha(i, alphas[i])
self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget)
-$(gui_hint()($win))</make>
+$(gui_hint() % $win)</make>
+
<callback>set_num_rows($nrows)</callback>
<callback>set_num_cols($ncols)</callback>
<callback>set_multiplier($mult)</callback>
diff --git a/gr-qtgui/grc/qtgui_time_sink_x.xml b/gr-qtgui/grc/qtgui_time_sink_x.xml
index d4347950ea..8a0d460491 100644
--- a/gr-qtgui/grc/qtgui_time_sink_x.xml
+++ b/gr-qtgui/grc/qtgui_time_sink_x.xml
@@ -74,7 +74,8 @@ for i in xrange(#if $type.t == 'message' then 1 else $nconnections#):
#end if
self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget)
-$(gui_hint()($win))</make>
+$(gui_hint() % $win)</make>
+
<callback>set_time_domain_axis($min, $max)</callback>
<callback>set_update_time($update_time)</callback>
<callback>set_title($which, $title)</callback>
diff --git a/gr-qtgui/grc/qtgui_vector_sink_f.xml b/gr-qtgui/grc/qtgui_vector_sink_f.xml
index 0f456323bf..3b12369bb1 100644
--- a/gr-qtgui/grc/qtgui_vector_sink_f.xml
+++ b/gr-qtgui/grc/qtgui_vector_sink_f.xml
@@ -46,7 +46,8 @@ for i in xrange($nconnections):
self.$(id).set_line_alpha(i, alphas[i])
self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget)
-$(gui_hint()($win))</make>
+$(gui_hint() % $win)</make>
+
<callback>set_update_time($update_time)</callback>
<callback>set_title($title)</callback>
<callback>set_color($which, $color)</callback>
diff --git a/gr-qtgui/grc/qtgui_waterfall_sink_x.xml b/gr-qtgui/grc/qtgui_waterfall_sink_x.xml
index a684492246..a4fb37bd6e 100644
--- a/gr-qtgui/grc/qtgui_waterfall_sink_x.xml
+++ b/gr-qtgui/grc/qtgui_waterfall_sink_x.xml
@@ -47,7 +47,8 @@ for i in xrange(#if $type.t == 'message' then 1 else $nconnections#):
self.$(id).set_intensity_range($int_min, $int_max)
self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget)
-$(gui_hint()($win))</make>
+$(gui_hint() % $win)</make>
+
<callback>set_frequency_range($fc, $bw)</callback>
<callback>set_update_time($update_time)</callback>
<callback>set_title($which, $title)</callback>
diff --git a/grc/core/Param.py b/grc/core/Param.py
index 56855908ea..13439f43b4 100644
--- a/grc/core/Param.py
+++ b/grc/core/Param.py
@@ -23,9 +23,10 @@ import ast
import numbers
import re
import collections
+import textwrap
import six
-from six.moves import builtins, filter, map, range, zip
+from six.moves import builtins, range
from . import Constants, blocks
from .base import Element
@@ -102,6 +103,7 @@ class Param(Element):
self._evaluated = None
self._stringify_flag = False
self._lisitify_flag = False
+ self.hostage_cells = set()
self._init = False
@property
@@ -299,38 +301,11 @@ class Param(Element):
# GUI Position/Hint
#########################
elif dtype == 'gui_hint':
- if ':' in expr:
- tab, pos = expr.split(':')
- elif '@' in expr:
- tab, pos = expr, ''
+ if self.parent_block.state == 'disabled':
+ return ''
else:
- tab, pos = '', expr
+ return self.parse_gui_hint(expr)
- if '@' in tab:
- tab, index = tab.split('@')
- else:
- index = '?'
-
- # TODO: Problem with this code. Produces bad tabs
- widget_str = ({
- (True, True): 'self.%(tab)s_grid_layout_%(index)s.addWidget(%(widget)s, %(pos)s)',
- (True, False): 'self.%(tab)s_layout_%(index)s.addWidget(%(widget)s)',
- (False, True): 'self.top_grid_layout.addWidget(%(widget)s, %(pos)s)',
- (False, False): 'self.top_layout.addWidget(%(widget)s)',
- }[bool(tab), bool(pos)]) % {'tab': tab, 'index': index, 'widget': '%s', 'pos': pos}
-
- # FIXME: Move replace(...) into the make template of the qtgui blocks
- # Return a string here
- class GuiHint(object):
- def __init__(self, ws):
- self._ws = ws
-
- def __call__(self, w):
- return (self._ws.replace('addWidget', 'addLayout') if 'layout' in w else self._ws) % w
-
- def __str__(self):
- return self._ws
- return GuiHint(widget_str)
#########################
# Import Type
#########################
@@ -411,3 +386,132 @@ class Param(Element):
def get_opt(self, item):
return self.options.attributes[self.get_value()][item]
+
+ ##############################################
+ # GUI Hint
+ ##############################################
+ def parse_gui_hint(self, expr):
+ """
+ Parse/validate gui hint value.
+
+ Args:
+ expr: gui_hint string from a block's 'gui_hint' param
+
+ Returns:
+ string of python code for positioning GUI elements in pyQT
+ """
+ self.hostage_cells.clear()
+
+ # Parsing
+ if ':' in expr:
+ tab, pos = expr.split(':')
+ elif ',' in expr:
+ tab, pos = '', expr
+ else:
+ tab, pos = expr, ''
+
+ if '@' in tab:
+ tab, index = tab.split('@')
+ else:
+ index = '0'
+ index = int(index)
+
+ # Validation
+ def parse_pos():
+ e = self.parent_flowgraph.evaluate(pos)
+
+ if not isinstance(e, (list, tuple)) or len(e) not in (2, 4) or not all(isinstance(ei, int) for ei in e):
+ raise Exception('Invalid GUI Hint entered: {e!r} (Must be a list of {{2,4}} non-negative integers).'.format(e=e))
+
+ if len(e) == 2:
+ row, col = e
+ row_span = col_span = 1
+ else:
+ row, col, row_span, col_span = e
+
+ if (row < 0) or (col < 0):
+ raise Exception('Invalid GUI Hint entered: {e!r} (non-negative integers only).'.format(e=e))
+
+ if (row_span < 1) or (col_span < 1):
+ raise Exception('Invalid GUI Hint entered: {e!r} (positive row/column span required).'.format(e=e))
+
+ return row, col, row_span, col_span
+
+ def validate_tab():
+ tabs = (block for block in self.parent_flowgraph.iter_enabled_blocks()
+ if block.key == 'qtgui_tab_widget' and block.name == tab)
+ tab_block = next(iter(tabs), None)
+ if not tab_block:
+ raise Exception('Invalid tab name entered: {tab} (Tab name not found).'.format(tab=tab))
+
+ tab_index_size = int(tab_block.params['num_tabs'].value)
+ if index >= tab_index_size:
+ raise Exception('Invalid tab index entered: {tab}@{index} (Index out of range).'.format(
+ tab=tab, index=index))
+
+ # Collision Detection
+ def collision_detection(row, col, row_span, col_span):
+ my_parent = '{tab}@{index}'.format(tab=tab, index=index) if tab else 'main'
+ # Calculate hostage cells
+ for r in range(row, row + row_span):
+ for c in range(col, col + col_span):
+ self.hostage_cells.add((my_parent, (r, c)))
+
+ for other in self.get_all_params('gui_hint'):
+ if other is self:
+ continue
+ collision = next(iter(self.hostage_cells & other.hostage_cells), None)
+ if collision:
+ raise Exception('Block {block!r} is also using parent {parent!r}, cell {cell!r}.'.format(
+ block=other.parent_block.name, parent=collision[0], cell=collision[1]
+ ))
+
+ # Code Generation
+ if tab:
+ validate_tab()
+ layout = '{tab}_grid_layout_{index}'.format(tab=tab, index=index)
+ else:
+ layout = 'top_grid_layout'
+
+ widget = '%s' # to be fill-out in the mail template
+
+ if pos:
+ row, col, row_span, col_span = parse_pos()
+ collision_detection(row, col, row_span, col_span)
+
+ widget_str = textwrap.dedent("""
+ self.{layout}.addWidget({widget}, {row}, {col}, {row_span}, {col_span})
+ for r in range({row}, {row_end}):
+ self.{layout}.setRowStretch(r, 1)
+ for c in range({col}, {col_end}):
+ self.{layout}.setColumnStretch(c, 1)
+ """.strip('\n')).format(
+ layout=layout, widget=widget,
+ row=row, row_span=row_span, row_end=row+row_span,
+ col=col, col_span=col_span, col_end=col+col_span,
+ )
+
+ else:
+ widget_str = 'self.{layout}.addWidget({widget})'.format(layout=layout, widget=widget)
+
+ return widget_str
+
+ def get_all_params(self, dtype, key=None):
+ """
+ Get all the params from the flowgraph that have the given type and
+ optionally a given key
+
+ Args:
+ type: the specified type
+ key: the key to match against
+
+ Returns:
+ a list of params
+ """
+ params = []
+ for block in self.parent_flowgraph.iter_enabled_blocks():
+ params.extend(
+ param for param in block.params.values()
+ if param.dtype == dtype and (key is None or key == param.name)
+ )
+ return params
diff --git a/grc/core/generator/hier_block.py b/grc/core/generator/hier_block.py
index 237fd71377..31cd198c01 100644
--- a/grc/core/generator/hier_block.py
+++ b/grc/core/generator/hier_block.py
@@ -149,8 +149,8 @@ class QtHierBlockGenerator(HierBlockGenerator):
block_n['param'].append(gui_hint_param)
block_n['make'] += (
- "\n#set $win = 'self.%s' % $id"
- "\n${gui_hint()($win)}"
+ "\n<% win = 'self.' + id %>"
+ "\n${ gui_hint % win }"
)
return {'block': block_n}