diff options
-rw-r--r-- | grc/core/Block.py | 151 | ||||
-rw-r--r-- | grc/core/Connection.py | 22 | ||||
-rw-r--r-- | grc/core/FlowGraph.py | 49 | ||||
-rw-r--r-- | grc/core/Messages.py | 4 | ||||
-rw-r--r-- | grc/gui/Block.py | 51 | ||||
-rw-r--r-- | grc/gui/Connection.py | 2 | ||||
-rw-r--r-- | grc/gui/Constants.py | 1 | ||||
-rw-r--r-- | grc/gui/FlowGraph.py | 4 | ||||
-rw-r--r-- | grc/gui/Port.py | 20 |
9 files changed, 152 insertions, 152 deletions
diff --git a/grc/core/Block.py b/grc/core/Block.py index 9572982bf7..e7e4a8215a 100644 --- a/grc/core/Block.py +++ b/grc/core/Block.py @@ -178,17 +178,20 @@ class Block(Element): port.key = str(domain_specific_port_index[domain]) domain_specific_port_index[domain] += 1 - # Adjust nports, disconnect hidden ports + # Adjust nports for ports in (self.sources, self.sinks): self._rewrite_nports(ports) self.back_ofthe_bus(ports) rekey(ports) + self._rewrite_bus_ports() + # disconnect hidden ports for port in itertools.chain(self.sources, self.sinks): if port.get_hide(): for connection in port.get_connections(): - self.parent.remove_element(connection) + self.parent_flowgraph.remove_element(connection) + self.active_sources = [p for p in self.get_sources_gui() if not p.get_hide()] self.active_sinks = [p for p in self.get_sinks_gui() if not p.get_hide()] @@ -201,7 +204,7 @@ class Block(Element): for clone in port.clones[nports-1:]: # Remove excess connections for connection in clone.get_connections(): - self.parent.remove_element(connection) + self.parent_flowgraph.remove_element(connection) port.remove_clone(clone) ports.remove(clone) # Add more cloned ports @@ -256,8 +259,56 @@ class Block(Element): self.add_error_message('Value "{}" cannot be evaluated:\n{}'.format(value, err)) ############################################## - # Getters + # props + ############################################## + + @lazy_property + def is_throtteling(self): + return BLOCK_FLAG_THROTTLE in self.flags + + @lazy_property + def is_deprecated(self): + return BLOCK_FLAG_DEPRECATED in self.flags + + @property + def documentation(self): + documentation = self.parent_platform.block_docstrings.get(self.key, {}) + from_xml = self._doc.strip() + if from_xml: + documentation[''] = from_xml + return documentation + + @property + def comment(self): + return self.params['comment'].get_value() + + @property + def state(self): + """Gets the block's current state.""" + try: + return self.STATE_LABELS[int(self.states['_enabled'])] + except ValueError: + return 'enabled' + + @state.setter + def state(self, value): + """Sets the state for the block.""" + try: + encoded = self.STATE_LABELS.index(value) + except ValueError: + encoded = 1 + self.states['_enabled'] = encoded + + # Enable/Disable Aliases + @property + def enabled(self): + """Get the enabled state of the block""" + return self.state != 'disabled' + + ############################################## + # Getters (old) ############################################## + def get_imports(self, raw=False): """ Resolve all import statements. @@ -304,39 +355,6 @@ class Block(Element): def is_virtual_source(self): return self.key == 'virtual_source' - @property - def documentation(self): - documentation = self.parent_platform.block_docstrings.get(self.key, {}) - from_xml = self._doc.strip() - if from_xml: - documentation[''] = from_xml - return documentation - - # Main functions to get and set the block state - # Also kept get_enabled and set_enabled to keep compatibility - @property - def state(self): - """Gets the block's current state.""" - try: - return self.STATE_LABELS[int(self.states['_enabled'])] - except ValueError: - return 'enabled' - - @state.setter - def state(self, value): - """Sets the state for the block.""" - try: - encoded = self.STATE_LABELS.index(value) - except ValueError: - encoded = 1 - self.states['_enabled'] = encoded - - # Enable/Disable Aliases - @property - def enabled(self): - """Get the enabled state of the block""" - return self.state != 'disabled' - # Block bypassing def get_bypassed(self): """ @@ -389,17 +407,6 @@ class Block(Element): def get_children_gui(self): return self.get_ports_gui() + self.params.values() - def get_comment(self): - return self.params['comment'].get_value() - - @lazy_property - def is_throtteling(self): - return BLOCK_FLAG_THROTTLE in self.flags - - @lazy_property - def is_deprecated(self): - return BLOCK_FLAG_DEPRECATED in self.flags - ############################################## # Access ############################################## @@ -597,6 +604,44 @@ class Block(Element): if self._bussify_source: self.bussify('source') + def _rewrite_bus_ports(self): + return # fixme: probably broken + + def doit(ports, ports_gui, direc): + if not self.current_bus_structure[direc]: + return + + bus_structure = self.form_bus_structure(direc) + for port in ports_gui[len(bus_structure):]: + for connect in port.get_connections(): + self.parent_flowgraph.remove_element(connect) + ports.remove(port) + + port_factory = self.parent_platform.get_new_port + + if len(ports_gui) < len(bus_structure): + for i in range(len(ports_gui), len(bus_structure)): + port = port_factory(self, direction=direc, key=str(1 + i), + name='bus', type='bus') + ports.append(port) + + doit(self.sources, self.get_sources_gui(), 'source') + doit(self.sinks, self.get_sinks_gui(), 'sink') + + if 'bus' in [a.get_type() for a in self.get_sources_gui()]: + for i in range(len(self.get_sources_gui())): + if not self.get_sources_gui()[i].get_connections(): + continue + source = self.get_sources_gui()[i] + sink = [] + + for j in range(len(source.get_connections())): + sink.append(source.get_connections()[j].sink_port) + for elt in source.get_connections(): + self.parent_flowgraph.remove_element(elt) + for j in sink: + self.parent_flowgraph.connect(source, j) + class EPyBlock(Block): @@ -711,11 +756,11 @@ class DummyBlock(Block): build_in_param_keys = 'id alias affinity minoutbuf maxoutbuf comment' def __init__(self, parent, key, missing_key, params_n): - params = [{'key': p['key'], 'name': p['key'], 'type': 'string'} - for p in params_n if p['key'] not in self.build_in_param_keys] - super(DummyBlock, self).__init__( - parent=parent, key=missing_key, name='Missing Block', param=params, - ) + super(DummyBlock, self).__init__(parent=parent, key=missing_key, name='Missing Block') + param_factory = self.parent_platform.get_new_param + for param_n in params_n: + key = param_n['key'] + self.params.setdefault(key, param_factory(self, key=key, name=key, type='string')) def is_valid(self): return False diff --git a/grc/core/Connection.py b/grc/core/Connection.py index 6be1ccb2aa..63c6a94571 100644 --- a/grc/core/Connection.py +++ b/grc/core/Connection.py @@ -31,7 +31,7 @@ class Connection(Element): is_connection = True - def __init__(self, flow_graph, porta, portb): + def __init__(self, parent, porta, portb): """ Make a new connection given the parent and 2 ports. @@ -44,7 +44,7 @@ class Connection(Element): Returns: a new connection """ - Element.__init__(self, flow_graph) + Element.__init__(self, parent) source, sink = self._get_sink_source(porta, portb) @@ -52,14 +52,16 @@ class Connection(Element): self.sink_port = sink # Ensure that this connection (source -> sink) is unique - for connection in flow_graph.connections: - if connection.source_port is source and connection.sink_port is sink: - raise LookupError('This connection between source and sink is not unique.') + if self in self.parent_flowgraph.connections: + raise LookupError('This connection between source and sink is not unique.') if self.is_bus(): self._make_bus_connect() - else: - self.parent_flowgraph.connect(source, sink) + + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return self.source_port == other.source_port and self.sink_port == other.sink_port @staticmethod def _get_sink_source(porta, portb): @@ -68,7 +70,7 @@ class Connection(Element): for port in (porta, portb): if port.is_source: source = port - else: + if port.is_sink: sink = port if not source: raise ValueError('Connection could not isolate source') @@ -110,10 +112,6 @@ class Connection(Element): Validate the connections. The ports must match in io size. """ - """ - Validate the connections. - The ports must match in type. - """ Element.validate(self) platform = self.parent_platform diff --git a/grc/core/FlowGraph.py b/grc/core/FlowGraph.py index 97a4c37353..8246d86f44 100644 --- a/grc/core/FlowGraph.py +++ b/grc/core/FlowGraph.py @@ -20,7 +20,6 @@ from __future__ import absolute_import, print_function import imp import time import re -from itertools import chain from operator import methodcaller import collections @@ -201,10 +200,7 @@ class FlowGraph(Element): Flag the namespace to be renewed. """ self.renew_namespace() - for child in chain(self.blocks, self.connections): - child.rewrite() - - self.bus_ports_rewrite() + Element.rewrite(self) def renew_namespace(self): namespace = {} @@ -299,7 +295,7 @@ class FlowGraph(Element): """ connection = self.parent_platform.Connection( - flow_graph=self, porta=porta, portb=portb) + parent=self, porta=porta, portb=portb) self.connections.append(connection) return connection @@ -453,47 +449,6 @@ class FlowGraph(Element): self.rewrite() # global rewrite return errors - ############################################## - # Needs to go - ############################################## - def bus_ports_rewrite(self): - # todo: move to block.rewrite() - def doit(block, ports, ports_gui, direc): - bus_structure = block.form_bus_structure(direc) - - if any('bus' == a.get_type() for a in ports_gui): - if len(ports_gui) > len(bus_structure): - for _ in range(len(bus_structure), len(ports_gui)): - for connect in ports_gui[-1].get_connections(): - block.parent.remove_element(connect) - ports.remove(ports_gui[-1]) - elif len(ports_gui) < len(bus_structure): - n = {'name': 'bus', 'type': 'bus'} - if any(isinstance(a.get_nports(), int) for a in ports): - n['nports'] = str(1) - for _ in range(len(ports_gui), len(bus_structure)): - n['key'] = str(len(ports)) - port = block.parent.parent.Port(block=block, n=dict(n), dir=direc) - ports.append(port) - - if 'bus' in [a.get_type() for a in block.get_sources_gui()]: - for i in range(len(block.get_sources_gui())): - if not block.get_sources_gui()[i].get_connections(): - continue - source = block.get_sources_gui()[i] - sink = [] - - for j in range(len(source.get_connections())): - sink.append(source.get_connections()[j].sink_port) - for elt in source.get_connections(): - self.remove_element(elt) - for j in sink: - self.connect(source, j) - - for blk in self.blocks: - doit(blk, blk.sources, blk.get_sources_gui(), 'source') - doit(blk, blk.sinks, blk.get_sinks_gui(), 'sink') - def _update_old_message_port_keys(source_key, sink_key, source_block, sink_block): """ diff --git a/grc/core/Messages.py b/grc/core/Messages.py index 596b6197d8..c2d216ef61 100644 --- a/grc/core/Messages.py +++ b/grc/core/Messages.py @@ -125,8 +125,8 @@ def send_fail_save(file_path): send('>>> Error: Cannot save: %s\n' % file_path) -def send_fail_connection(): - send('>>> Error: Cannot create connection.\n') +def send_fail_connection(msg=''): + send('>>> Error: Cannot create connection.\n' + ('\t' + str(msg) if msg else '')) def send_fail_load_preferences(prefs_file_path): diff --git a/grc/gui/Block.py b/grc/gui/Block.py index db147738b6..d1f67d6586 100644 --- a/grc/gui/Block.py +++ b/grc/gui/Block.py @@ -55,8 +55,9 @@ class Block(CoreBlock, Element): self._surface_layout_offsets = 0, 0 self._comment_layout = None + self._border_color = (Colors.MISSING_BLOCK_BORDER_COLOR if self.is_dummy_block else + Colors.BORDER_COLOR) self._bg_color = Colors.BLOCK_ENABLED_COLOR - self.has_busses = [False, False] # source, sink @property def coordinate(self): @@ -113,7 +114,8 @@ class Block(CoreBlock, Element): elif self.is_vertical(): self.areas.append([0, 0, self.height, self.width]) - for ports, has_busses in zip((self.active_sources, self.active_sinks), self.has_busses): + bussified = self.current_bus_structure['source'], self.current_bus_structure['sink'] + for ports, has_busses in zip((self.active_sources, self.active_sinks), bussified): if not ports: continue port_separation = PORT_SEPARATION if not has_busses else ports[0].height + PORT_SPACING @@ -177,25 +179,26 @@ class Block(CoreBlock, Element): self.create_port_labels() - def get_min_height_for_ports(): + def get_min_height_for_ports(ports): min_height = 2 * PORT_BORDER_SEPARATION + len(ports) * PORT_SEPARATION if ports: min_height -= ports[-1].height return min_height - height = max( - [ # labels - height - ] + - [ # ports - get_min_height_for_ports() for ports in (self.active_sources, self.active_sinks) - ] + - [ # bus ports only - 2 * PORT_BORDER_SEPARATION + - sum([port.height + PORT_SPACING for port in ports if port.get_type() == 'bus']) - PORT_SPACING - for ports in (self.get_sources_gui(), self.get_sinks_gui()) - ] - ) + height = max(height, + get_min_height_for_ports(self.active_sinks), + get_min_height_for_ports(self.active_sources)) + + def get_min_height_for_bus_ports(ports): + return 2 * PORT_BORDER_SEPARATION + sum( + port.height + PORT_SPACING for port in ports if port.get_type() == 'bus' + ) - PORT_SPACING + + if self.current_bus_structure['sink']: + height = max(height, get_min_height_for_bus_ports(self.active_sinks)) + if self.current_bus_structure['source']: + height = max(height, get_min_height_for_bus_ports(self.active_sources)) + self.width, self.height = width, height = Utils.align_to_grid((width, height)) self._surface_layout_offsets = [ @@ -203,10 +206,6 @@ class Block(CoreBlock, Element): (height - label_height) / 2.0 ] - self.has_busses = [ - any(port.get_type() == 'bus' for port in ports) - for ports in (self.get_sources_gui(), self.get_sinks_gui()) - ] self.create_comment_layout() def create_port_labels(self): @@ -226,9 +225,9 @@ class Block(CoreBlock, Element): complexity = utils.calculate_flowgraph_complexity(self.parent) markups.append( '<span foreground="#444" size="medium" font_desc="{font}">' - '<b>Complexity: {num}bal</b></span>'.format(num=utils.num_to_str(complexity), font=BLOCK_FONT) + '<b>Complexity: {num}bal</b></span>'.format(num=Utils.num_to_str(complexity), font=BLOCK_FONT) ) - comment = self.get_comment() # Returns None if there are no comments + comment = self.comment # Returns None if there are no comments if comment: if markups: markups.append('<span></span>') @@ -242,16 +241,12 @@ class Block(CoreBlock, Element): else: self._comment_layout = None - def draw(self, widget, cr): + def draw(self, widget, cr, border_color=None, bg_color=None): """ Draw the signal block with label and inputs/outputs. """ bg_color = self._bg_color - border_color = ( - Colors.HIGHLIGHT_COLOR if self.highlighted else - Colors.MISSING_BLOCK_BORDER_COLOR if self.is_dummy_block else - Colors.BORDER_COLOR - ) + border_color = Colors.HIGHLIGHT_COLOR if self.highlighted else self._border_color # draw main block Element.draw(self, widget, cr, border_color, bg_color) for port in self.active_ports(): diff --git a/grc/gui/Connection.py b/grc/gui/Connection.py index b6e84f8c89..9b483383ac 100644 --- a/grc/gui/Connection.py +++ b/grc/gui/Connection.py @@ -152,7 +152,7 @@ class Connection(Element, _Connection): # create right-angled connector self.lines.append([p0, p1, point, p2, p3]) - def draw(self, widget, cr): + def draw(self, widget, cr, border_color=None, bg_color=None): """ Draw the connection. """ diff --git a/grc/gui/Constants.py b/grc/gui/Constants.py index 5c55c4180e..516aaf92f4 100644 --- a/grc/gui/Constants.py +++ b/grc/gui/Constants.py @@ -72,6 +72,7 @@ PORT_SEPARATION = 32 PORT_MIN_WIDTH = 20 PORT_LABEL_HIDDEN_WIDTH = 10 +PORT_EXTRA_BUS_HEIGHT = 40 # minimal length of connector CONNECTOR_EXTENSION_MINIMAL = 11 diff --git a/grc/gui/FlowGraph.py b/grc/gui/FlowGraph.py index a3dd379074..6ff4507df2 100644 --- a/grc/gui/FlowGraph.py +++ b/grc/gui/FlowGraph.py @@ -153,8 +153,8 @@ class FlowGraph(Element, _Flowgraph): try: self.connect(self._old_selected_port, self._new_selected_port) Actions.ELEMENT_CREATE() - except: - Messages.send_fail_connection() + except Exception as e: + Messages.send_fail_connection(e) self._old_selected_port = None self._new_selected_port = None return True diff --git a/grc/gui/Port.py b/grc/gui/Port.py index 991036cb99..6776963c63 100644 --- a/grc/gui/Port.py +++ b/grc/gui/Port.py @@ -42,8 +42,9 @@ class Port(_Port, Element): self._connector_coordinate = (0, 0) self._hovering = False self.force_show_label = False - self._bg_color = (0, 0, 0) + self._bg_color = 0, 0, 0 self._line_width_factor = 1.0 + self._label_layout_offsets = 0, 0 self.width_with_label = self.height = 0 self.connector_length = 0 @@ -109,8 +110,10 @@ class Port(_Port, Element): self.width = 2 * Constants.PORT_LABEL_PADDING + label_width self.height = 2 * Constants.PORT_LABEL_PADDING + label_height + self._label_layout_offsets = [0, Constants.PORT_LABEL_PADDING] if self.get_type() == 'bus': - self.height += 2 * label_height + self.height += Constants.PORT_EXTRA_BUS_HEIGHT + self._label_layout_offsets[1] += Constants.PORT_EXTRA_BUS_HEIGHT / 2 self.height += self.height % 2 # uneven height def draw(self, widget, cr, border_color, bg_color): @@ -126,7 +129,7 @@ class Port(_Port, Element): if self.is_vertical(): cr.rotate(-math.pi / 2) cr.translate(-self.width, 0) - cr.translate(0, Constants.PORT_LABEL_PADDING) + cr.translate(*self._label_layout_offsets) PangoCairo.update_layout(cr, self.label_layout) PangoCairo.show_layout(cr, self.label_layout) @@ -138,8 +141,11 @@ class Port(_Port, Element): Returns: the connector coordinate (x, y) tuple """ - return [sum(c) for c in zip(self._connector_coordinate, self.coordinate, - self.parent_block.coordinate)] + return [sum(c) for c in zip( + self._connector_coordinate, # relative to port + self.coordinate, # relative to block + self.parent_block.coordinate # abs + )] def get_connector_direction(self): """ @@ -167,7 +173,7 @@ class Port(_Port, Element): Args: direction: degrees to rotate """ - self.parent.rotate(direction) + self.parent_block.rotate(direction) def move(self, delta_coor): """ @@ -176,7 +182,7 @@ class Port(_Port, Element): Args: delta_corr: the (delta_x, delta_y) tuple """ - self.parent.move(delta_coor) + self.parent_block.move(delta_coor) @property def highlighted(self): |