diff options
-rw-r--r-- | grc/base/FlowGraph.py | 54 | ||||
-rw-r--r-- | grc/gui/ActionHandler.py | 43 | ||||
-rw-r--r-- | grc/gui/Actions.py | 6 | ||||
-rw-r--r-- | grc/gui/Bars.py | 2 | ||||
-rw-r--r-- | grc/gui/Block.py | 35 | ||||
-rw-r--r-- | grc/gui/Constants.py | 1 | ||||
-rw-r--r-- | grc/gui/FlowGraph.py | 2 | ||||
-rw-r--r-- | grc/python/Constants.py | 11 | ||||
-rw-r--r-- | grc/python/Param.py | 40 |
9 files changed, 141 insertions, 53 deletions
diff --git a/grc/base/FlowGraph.py b/grc/base/FlowGraph.py index 217c4d7302..f61542c712 100644 --- a/grc/base/FlowGraph.py +++ b/grc/base/FlowGraph.py @@ -67,6 +67,58 @@ class FlowGraph(Element): def __str__(self): return 'FlowGraph - %s(%s)' % (self.get_option('title'), self.get_option('id')) + def get_complexity(self): + """ + Determines the complexity of a flowgraph + """ + dbal = 0 + block_list = self.get_blocks() + for block in block_list: + # Skip options block + if block.get_key() == 'options': + continue + + # Don't worry about optional sinks? + sink_list = filter(lambda c: not c.get_optional(), block.get_sinks()) + source_list = filter(lambda c: not c.get_optional(), block.get_sources()) + sinks = float(len(sink_list)) + sources = float(len(source_list)) + base = max(min(sinks, sources), 1) + + # Port ratio multiplier + if min(sinks, sources) > 0: + multi = sinks / sources + multi = (1 / multi) if multi > 1 else multi + else: + multi = 1 + + # Connection ratio multiplier + sink_multi = max(float(sum(map(lambda c: len(c.get_connections()), sink_list)) / max(sinks, 1.0)), 1.0) + source_multi = max(float(sum(map(lambda c: len(c.get_connections()), source_list)) / max(sources, 1.0)), 1.0) + dbal = dbal + (base * multi * sink_multi * source_multi) + + elements = float(len(self.get_elements())) + connections = float(len(self.get_connections())) + disabled_connections = len(filter(lambda c: not c.get_enabled(), self.get_connections())) + blocks = float(len(block_list)) + variables = elements - blocks - connections + enabled = float(len(self.get_enabled_blocks())) + + # Disabled multiplier + if enabled > 0: + disabled_multi = 1 / (max(1 - ((blocks - enabled) / max(blocks, 1)), 0.05)) + else: + disabled_multi = 1 + + # Connection multiplier (How many connections ) + if (connections - disabled_connections) > 0: + conn_multi = 1 / (max(1 - (disabled_connections / max(connections, 1)), 0.05)) + else: + conn_multi = 1 + + final = round(max((dbal - 1) * disabled_multi * conn_multi * connections, 0.0) / 1000000, 6) + return final + def rewrite(self): def refactor_bus_structure(): @@ -102,7 +154,7 @@ class FlowGraph(Element): get_p().append(port); for child in self.get_children(): child.rewrite() - refactor_bus_structure(); + refactor_bus_structure() def get_option(self, key): """ diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py index 19c6edc914..e6ffe9c5e7 100644 --- a/grc/gui/ActionHandler.py +++ b/grc/gui/ActionHandler.py @@ -113,21 +113,6 @@ class ActionHandler: # Initialize/Quit ################################################## if action == Actions.APPLICATION_INITIALIZE: - for action in Actions.get_all_actions(): action.set_sensitive(False) #set all actions disabled - #enable a select few actions - for action in ( - Actions.APPLICATION_QUIT, Actions.FLOW_GRAPH_NEW, - Actions.FLOW_GRAPH_OPEN, Actions.FLOW_GRAPH_SAVE_AS, - Actions.FLOW_GRAPH_CLOSE, Actions.ABOUT_WINDOW_DISPLAY, - Actions.FLOW_GRAPH_SCREEN_CAPTURE, Actions.HELP_WINDOW_DISPLAY, - Actions.TYPES_WINDOW_DISPLAY, Actions.TOGGLE_BLOCKS_WINDOW, - Actions.TOGGLE_REPORTS_WINDOW, Actions.TOGGLE_HIDE_DISABLED_BLOCKS, - Actions.TOOLS_RUN_FDESIGN, Actions.TOGGLE_SCROLL_LOCK, - Actions.CLEAR_REPORTS, Actions.SAVE_REPORTS, - Actions.TOGGLE_AUTO_HIDE_PORT_LABELS, Actions.TOGGLE_SNAP_TO_GRID, - Actions.TOGGLE_SHOW_BLOCK_COMMENTS, - Actions.TOGGLE_SHOW_CODE_PREVIEW_TAB, - ): action.set_sensitive(True) if ParseXML.xml_failures: Messages.send_xml_errors_if_any(ParseXML.xml_failures) Actions.XML_PARSER_ERRORS_DISPLAY.set_sensitive(True) @@ -142,15 +127,27 @@ class ActionHandler: if not self.get_page(): self.main_window.new_page() #ensure that at least a blank page exists self.main_window.btwin.search_entry.hide() + + # Disable all actions, then re-enable a few + for action in Actions.get_all_actions(): action.set_sensitive(False) #set all actions disabled for action in ( - Actions.TOGGLE_REPORTS_WINDOW, - Actions.TOGGLE_BLOCKS_WINDOW, - Actions.TOGGLE_AUTO_HIDE_PORT_LABELS, - Actions.TOGGLE_SCROLL_LOCK, - Actions.TOGGLE_SNAP_TO_GRID, + Actions.APPLICATION_QUIT, Actions.FLOW_GRAPH_NEW, + Actions.FLOW_GRAPH_OPEN, Actions.FLOW_GRAPH_SAVE_AS, + Actions.FLOW_GRAPH_CLOSE, Actions.ABOUT_WINDOW_DISPLAY, + Actions.FLOW_GRAPH_SCREEN_CAPTURE, Actions.HELP_WINDOW_DISPLAY, + Actions.TYPES_WINDOW_DISPLAY, Actions.TOGGLE_BLOCKS_WINDOW, + Actions.TOGGLE_REPORTS_WINDOW, Actions.TOGGLE_HIDE_DISABLED_BLOCKS, + Actions.TOOLS_RUN_FDESIGN, Actions.TOGGLE_SCROLL_LOCK, + Actions.CLEAR_REPORTS, Actions.SAVE_REPORTS, + Actions.TOGGLE_AUTO_HIDE_PORT_LABELS, Actions.TOGGLE_SNAP_TO_GRID, Actions.TOGGLE_SHOW_BLOCK_COMMENTS, Actions.TOGGLE_SHOW_CODE_PREVIEW_TAB, - ): action.load_from_preferences() + Actions.TOGGLE_SHOW_FLOWGRAPH_COMPLEXITY, + ): + action.set_sensitive(True) + if hasattr(action, 'load_from_preferences'): + action.load_from_preferences() + elif action == Actions.APPLICATION_QUIT: if self.main_window.close_pages(): gtk.main_quit() @@ -416,6 +413,10 @@ class ActionHandler: action.save_to_preferences() elif action == Actions.TOGGLE_SHOW_CODE_PREVIEW_TAB: action.save_to_preferences() + elif action == Actions.TOGGLE_SHOW_FLOWGRAPH_COMPLEXITY: + action.save_to_preferences() + for page in self.main_window.get_pages(): + page.get_flow_graph().update() ################################################## # Param Modifications ################################################## diff --git a/grc/gui/Actions.py b/grc/gui/Actions.py index ce1f2cf873..00184d5cf5 100644 --- a/grc/gui/Actions.py +++ b/grc/gui/Actions.py @@ -284,6 +284,12 @@ TOGGLE_SHOW_CODE_PREVIEW_TAB = ToggleAction( preference_name='show_generated_code_tab', default=False, ) +TOGGLE_SHOW_FLOWGRAPH_COMPLEXITY = ToggleAction( + label='Show Flowgraph Complexity', + tooltip="How many Balints is the flowgraph...", + preference_name='show_flowgraph_complexity', + default=False, +) BLOCK_CREATE_HIER = Action( label='C_reate Hier', tooltip='Create hier block from selected blocks', diff --git a/grc/gui/Bars.py b/grc/gui/Bars.py index f0f8dac7fb..f1f90e4af2 100644 --- a/grc/gui/Bars.py +++ b/grc/gui/Bars.py @@ -116,6 +116,8 @@ MENU_BAR_LIST = ( (gtk.Action('Tools', '_Tools', None, None), [ Actions.TOOLS_RUN_FDESIGN, None, + Actions.TOGGLE_SHOW_FLOWGRAPH_COMPLEXITY, + None, Actions.TOOLS_MORE_TO_COME, ]), (gtk.Action('Help', '_Help', None, None), [ diff --git a/grc/gui/Block.py b/grc/gui/Block.py index 11273a537b..94ed5802d1 100644 --- a/grc/gui/Block.py +++ b/grc/gui/Block.py @@ -21,6 +21,7 @@ from Element import Element import Utils import Colors from .. base import odict +from .. python.Param import num_to_str from Constants import BORDER_PROXIMITY_SENSITIVITY from Constants import ( BLOCK_LABEL_PADDING, PORT_SPACING, PORT_SEPARATION, LABEL_SEPARATION, @@ -35,9 +36,17 @@ import pango BLOCK_MARKUP_TMPL="""\ #set $foreground = $block.is_valid() and 'black' or 'red' <span foreground="$foreground" font_desc="$font"><b>$encode($block.get_name())</b></span>""" -COMMENT_MARKUP_TMPL="""\ + +# Includes the additional complexity markup if enabled +COMMENT_COMPLEXITY_MARKUP_TMPL="""\ #set $foreground = $block.get_enabled() and '#444' or '#888' -<span foreground="$foreground" font_desc="$font">$encode($block.get_comment())</span>""" +#if $complexity +<span foreground="#444" size="medium" font_desc="$font"><b>$encode($complexity)</b></span> +#end if +#if $comment +<span foreground="$foreground" font_desc="$font">$encode($comment)</span>#slurp +#end if""" + class Block(Element): """The graphical signal block.""" @@ -218,11 +227,23 @@ class Block(Element): self.create_comment_label() def create_comment_label(self): - comment = self.get_comment() - if comment: - layout = gtk.DrawingArea().create_pango_layout('') - layout.set_markup(Utils.parse_template(COMMENT_MARKUP_TMPL, block=self, font=BLOCK_FONT)) - width, height = layout.get_pixel_size() + comment = self.get_comment() # Returns None if there are no comments + complexity = None + + # Show the flowgraph complexity on the top block if enabled + if Actions.TOGGLE_SHOW_FLOWGRAPH_COMPLEXITY.get_active() and self.get_key() == "options": + complexity = "Complexity: {}bal".format(num_to_str(self.get_parent().get_complexity())) + + layout = gtk.DrawingArea().create_pango_layout('') + layout.set_markup(Utils.parse_template(COMMENT_COMPLEXITY_MARKUP_TMPL, + block=self, + comment=comment, + complexity=complexity, + font=BLOCK_FONT)) + + # Setup the pixel map. Make sure that layout is valid + width, height = layout.get_pixel_size() + if layout and width > 0 and height > 0: pixmap = self.get_parent().new_pixmap(width, height) gc = pixmap.new_gc() gc.set_foreground(Colors.COMMENT_BACKGROUND_COLOR) diff --git a/grc/gui/Constants.py b/grc/gui/Constants.py index a8395f631e..32d69604de 100644 --- a/grc/gui/Constants.py +++ b/grc/gui/Constants.py @@ -118,4 +118,3 @@ SCROLL_DISTANCE = 15 # How close the mouse click can be to a line and register a connection select. LINE_SELECT_SENSITIVITY = 5 - diff --git a/grc/gui/FlowGraph.py b/grc/gui/FlowGraph.py index b1e88aae8e..fc6a711572 100644 --- a/grc/gui/FlowGraph.py +++ b/grc/gui/FlowGraph.py @@ -285,10 +285,12 @@ class FlowGraph(Element): Draw all of the elements in this flow graph onto the pixmap. Draw the pixmap to the drawable window of this flow graph. """ + W,H = self.get_size() #draw the background gc.set_foreground(Colors.FLOWGRAPH_BACKGROUND_COLOR) window.draw_rectangle(gc, True, 0, 0, W, H) + # draw comments first if Actions.TOGGLE_SHOW_BLOCK_COMMENTS.get_active(): for block in self.iter_blocks(): diff --git a/grc/python/Constants.py b/grc/python/Constants.py index 02be22a441..b7a370cad7 100644 --- a/grc/python/Constants.py +++ b/grc/python/Constants.py @@ -19,6 +19,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import os from os.path import expanduser +import numpy import stat from gnuradio import gr @@ -53,6 +54,16 @@ FLOW_GRAPH_TEMPLATE = os.path.join(DATA_DIR, 'flow_graph.tmpl') BLOCK_DTD = os.path.join(DATA_DIR, 'block.dtd') DEFAULT_FLOW_GRAPH = os.path.join(DATA_DIR, 'default_flow_graph.grc') +#define types, native python + numpy +VECTOR_TYPES = (tuple, list, set, numpy.ndarray) +COMPLEX_TYPES = [complex, numpy.complex, numpy.complex64, numpy.complex128] +REAL_TYPES = [float, numpy.float, numpy.float32, numpy.float64] +INT_TYPES = [int, long, numpy.int, numpy.int8, numpy.int16, numpy.int32, numpy.uint64, + numpy.uint, numpy.uint8, numpy.uint16, numpy.uint32, numpy.uint64] +#cast to tuple for isinstance, concat subtypes +COMPLEX_TYPES = tuple(COMPLEX_TYPES + REAL_TYPES + INT_TYPES) +REAL_TYPES = tuple(REAL_TYPES + INT_TYPES) +INT_TYPES = tuple(INT_TYPES) # Updating colors. Using the standard color pallette from: # http://www.google.com/design/spec/style/color.html#color-color-palette diff --git a/grc/python/Param.py b/grc/python/Param.py index 0e72fcbfb2..27e5b76320 100644 --- a/grc/python/Param.py +++ b/grc/python/Param.py @@ -19,8 +19,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA from .. base.Param import Param as _Param from .. gui.Param import Param as _GUIParam + import Constants -import numpy +from Constants import VECTOR_TYPES, COMPLEX_TYPES, REAL_TYPES, INT_TYPES + from gnuradio import eng_notation import re from gnuradio import gr @@ -33,16 +35,19 @@ _show_id_matcher = re.compile('^(variable\w*|parameter|options|notebook)$') 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__) -#define types, native python + numpy -VECTOR_TYPES = (tuple, list, set, numpy.ndarray) -COMPLEX_TYPES = [complex, numpy.complex, numpy.complex64, numpy.complex128] -REAL_TYPES = [float, numpy.float, numpy.float32, numpy.float64] -INT_TYPES = [int, long, numpy.int, numpy.int8, numpy.int16, numpy.int32, numpy.uint64, - numpy.uint, numpy.uint8, numpy.uint16, numpy.uint32, numpy.uint64] -#cast to tuple for isinstance, concat subtypes -COMPLEX_TYPES = tuple(COMPLEX_TYPES + REAL_TYPES + INT_TYPES) -REAL_TYPES = tuple(REAL_TYPES + INT_TYPES) -INT_TYPES = tuple(INT_TYPES) + + +def num_to_str(num): + """ Display logic for numbers """ + if isinstance(num, COMPLEX_TYPES): + num = complex(num) #cast to python complex + if num == 0: return '0' #value is zero + elif num.imag == 0: return '%s'%eng_notation.num_to_str(num.real) #value is real + elif num.real == 0: return '%sj'%eng_notation.num_to_str(num.imag) #value is imaginary + elif num.imag < 0: return '%s-%sj'%(eng_notation.num_to_str(num.real), eng_notation.num_to_str(abs(num.imag))) + else: return '%s+%sj'%(eng_notation.num_to_str(num.real), eng_notation.num_to_str(num.imag)) + else: return str(num) + class Param(_Param, _GUIParam): @@ -88,18 +93,7 @@ class Param(_Param, _GUIParam): ################################################## if not self.is_valid(): return _truncate(self.get_value()) if self.get_value() in self.get_option_keys(): return self.get_option(self.get_value()).get_name() - ################################################## - # display logic for numbers - ################################################## - def num_to_str(num): - if isinstance(num, COMPLEX_TYPES): - num = complex(num) #cast to python complex - if num == 0: return '0' #value is zero - elif num.imag == 0: return '%s'%eng_notation.num_to_str(num.real) #value is real - elif num.real == 0: return '%sj'%eng_notation.num_to_str(num.imag) #value is imaginary - elif num.imag < 0: return '%s-%sj'%(eng_notation.num_to_str(num.real), eng_notation.num_to_str(abs(num.imag))) - else: return '%s+%sj'%(eng_notation.num_to_str(num.real), eng_notation.num_to_str(num.imag)) - else: return str(num) + ################################################## # split up formatting by type ################################################## |