diff options
-rw-r--r-- | grc/gui/Block.py | 56 | ||||
-rw-r--r-- | grc/gui/BlockTreeWindow.py | 57 | ||||
-rw-r--r-- | grc/gui/Dialogs.py | 48 | ||||
-rw-r--r-- | grc/gui/FileDialogs.py | 12 | ||||
-rw-r--r-- | grc/gui/MainWindow.py | 69 | ||||
-rw-r--r-- | grc/gui/Param.py | 68 | ||||
-rw-r--r-- | grc/gui/Port.py | 10 | ||||
-rw-r--r-- | grc/gui/PropsDialog.py | 12 | ||||
-rw-r--r-- | grc/gui/Utils.py | 24 |
9 files changed, 136 insertions, 220 deletions
diff --git a/grc/gui/Block.py b/grc/gui/Block.py index 57fb69c448..f8687be42f 100644 --- a/grc/gui/Block.py +++ b/grc/gui/Block.py @@ -32,28 +32,9 @@ from .Constants import ( ) from . Element import Element from ..core.Param import num_to_str -from ..core.utils import odict from ..core.utils.complexity import calculate_flowgraph_complexity from ..core.Block import Block as _Block -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>""" - -# Includes the additional complexity markup if enabled -COMMENT_COMPLEXITY_MARKUP_TMPL="""\ -#set $foreground = $block.get_enabled() and '#444' or '#888' -#if $complexity -<span foreground="#444" size="medium" font_desc="$font"><b>$encode($complexity)</b></span>#slurp -#end if -#if $complexity and $comment -<span></span> -#end if -#if $comment -<span foreground="$foreground" font_desc="$font">$encode($comment)</span>#slurp -#end if -""" - class Block(Element, _Block): """The graphical signal block.""" @@ -188,14 +169,16 @@ class Block(Element, _Block): del self.layouts[:] #create the main layout layout = Gtk.DrawingArea().create_pango_layout('') - self.layouts.append(layout) - layout.set_markup(Utils.parse_template(BLOCK_MARKUP_TMPL, block=self, font=BLOCK_FONT)) + layout.set_markup('<span foreground="{foreground}" font_desc="{font}"><b>{name}</b></span>'.format( + foreground='black' if self.is_valid() else 'red', font=BLOCK_FONT, name=Utils.encode(self.get_name()) + )) self.label_width, self.label_height = layout.get_pixel_size() + self.layouts.append(layout) #display the params if self.is_dummy_block: - markups = [ - '<span foreground="black" font_desc="{font}"><b>key: </b>{key}</span>'.format(font=PARAM_FONT, key=self._key) - ] + markups = ['<span foreground="black" font_desc="{font}"><b>key: </b>{key}</span>'.format( + font=PARAM_FONT, key=self._key + )] else: markups = [param.get_markup() for param in self.get_params() if param.get_hide() not in ('all', 'part')] if markups: @@ -237,20 +220,25 @@ class Block(Element, _Block): self.create_comment_label() def create_comment_label(self): - comment = self.get_comment() # Returns None if there are no comments - complexity = None + markups = [] - # Show the flowgraph complexity on the top block if enabled + # Show the flow graph complexity on the top block if enabled if Actions.TOGGLE_SHOW_FLOWGRAPH_COMPLEXITY.get_active() and self.get_key() == "options": complexity = calculate_flowgraph_complexity(self.get_parent()) - complexity = "Complexity: {}bal".format(num_to_str(complexity)) - + markups.append( + '<span foreground="#444" size="medium" font_desc="{font}">' + '<b>Complexity: {num}bal</b></span>'.format(num=num_to_str(complexity), font=BLOCK_FONT) + ) + comment = self.get_comment() # Returns None if there are no comments + if comment: + if markups: + markups.append('<span></span>') + + markups.append('<span foreground="{foreground}" font_desc="{font}">{comment}</span>'.format( + foreground='#444' if self.get_enabled() else '#888', font=BLOCK_FONT, comment=Utils.encode(comment) + )) 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)) + layout.set_markup(''.join(markups)) # Setup the pixel map. Make sure that layout not empty width, height = layout.get_pixel_size() diff --git a/grc/gui/BlockTreeWindow.py b/grc/gui/BlockTreeWindow.py index a68d0938fc..e8de6e9277 100644 --- a/grc/gui/BlockTreeWindow.py +++ b/grc/gui/BlockTreeWindow.py @@ -26,36 +26,26 @@ from gi.repository import GObject from . import Actions, Utils from .Constants import DEFAULT_BLOCKS_WINDOW_WIDTH, DND_TARGETS -NAME_INDEX = 0 -KEY_INDEX = 1 -DOC_INDEX = 2 - -DOC_MARKUP_TMPL = """\ -#set $docs = [] -#if $doc.get('') - #set $docs += $doc.pop('').splitlines() + [''] -#end if -#for b, d in $doc.iteritems() - #set $docs += ['--- {0} ---'.format(b)] + d.splitlines() + [''] -#end for -#set $len_out = 0 -#for $n, $line in $enumerate($docs[:-1]) -#if $n - -#end if -$encode($line)#slurp -#set $len_out += $len($line) -#if $n > 10 or $len_out > 500 - -...#slurp -#break -#end if -#end for -#if $len_out == 0 -undocumented#slurp -#end if""" - -CAT_MARKUP_TMPL = """Category: $cat""" +NAME_INDEX, KEY_INDEX, DOC_INDEX = range(3) + + +def _format_doc(doc): + docs = [] + if doc.get(''): + docs += doc.pop('').splitlines() + [''] + for block_name, docstring in doc.iteritems(): + docs.append('--- {0} ---'.format(block_name)) + docs += docstring.splitlines() + docs.append('') + out = '' + for n, line in enumerate(docs[:-1]): + if n: + out += '\n' + out += Utils.encode(line) + if n > 10 or len(out) > 500: + out += '\n...' + break + return out or 'undocumented' class BlockTreeWindow(Gtk.VBox): @@ -159,7 +149,7 @@ class BlockTreeWindow(Gtk.VBox): iter_ = treestore.insert_before(categories[sub_category[:-1]], None) treestore.set_value(iter_, NAME_INDEX, cat_name) treestore.set_value(iter_, KEY_INDEX, '') - treestore.set_value(iter_, DOC_INDEX, Utils.parse_template(CAT_MARKUP_TMPL, cat=cat_name)) + treestore.set_value(iter_, DOC_INDEX, 'Category: ' + Utils.encode(cat_name)) categories[sub_category] = iter_ # add block if block is None: @@ -167,7 +157,7 @@ class BlockTreeWindow(Gtk.VBox): iter_ = treestore.insert_before(categories[category], None) treestore.set_value(iter_, NAME_INDEX, block.get_name()) treestore.set_value(iter_, KEY_INDEX, block.get_key()) - treestore.set_value(iter_, DOC_INDEX, Utils.parse_template(DOC_MARKUP_TMPL, doc=block.get_doc())) + treestore.set_value(iter_, DOC_INDEX, _format_doc(block.get_doc())) def update_docs(self): """Update the documentation column of every block""" @@ -177,8 +167,7 @@ class BlockTreeWindow(Gtk.VBox): return # category node, no doc string key = model.get_value(iter_, KEY_INDEX) block = self.platform.blocks[key] - doc = Utils.parse_template(DOC_MARKUP_TMPL, doc=block.get_doc()) - model.set_value(iter_, DOC_INDEX, doc) + model.set_value(iter_, DOC_INDEX, _format_doc(block.get_doc())) self.treestore.foreach(update_doc) self.treestore_search.foreach(update_doc) diff --git a/grc/gui/Dialogs.py b/grc/gui/Dialogs.py index a7bc121e40..953373ee24 100644 --- a/grc/gui/Dialogs.py +++ b/grc/gui/Dialogs.py @@ -161,20 +161,16 @@ def MessageDialogHelper(type, buttons, title=None, markup=None, default_response return response -ERRORS_MARKUP_TMPL="""\ -#for $i, $err_msg in enumerate($errors) -<b>Error $i:</b> -$encode($err_msg.replace('\t', ' ')) - -#end for""" - - -def ErrorsDialog(flowgraph): MessageDialogHelper( - type=Gtk.MessageType.ERROR, - buttons=Gtk.ButtonsType.CLOSE, - title='Flow Graph Errors', - markup=Utils.parse_template(ERRORS_MARKUP_TMPL, errors=flowgraph.get_error_messages()), -) +def ErrorsDialog(flowgraph): + MessageDialogHelper( + type=Gtk.MessageType.ERROR, + buttons=Gtk.ButtonsType.CLOSE, + title='Flow Graph Errors', + markup='\n\n'.join( + '<b>Error {num}:</b>\n{msg}'.format(num=i, msg=Utils.encode(msg.replace('\t', ' '))) + for i, msg in enumerate(flowgraph.get_error_messages()) + ), + ) class AboutDialog(Gtk.AboutDialog): @@ -208,25 +204,21 @@ def HelpDialog(): MessageDialogHelper( * See the menu for other keyboard shortcuts.""") -COLORS_DIALOG_MARKUP_TMPL = """\ -<b>Color Mapping</b> - -#if $colors - #set $max_len = max([len(color[0]) for color in $colors]) + 10 - #for $title, $color_spec in $colors -<span background="$color_spec"><tt>$($encode($title).center($max_len))</tt></span> - #end for -#end if -""" - def TypesDialog(platform): + colors = platform.get_colors() + max_len = 10 + max(len(name) for name, code in colors) + + message = '\n'.join( + '<span background="{color}"><tt>{name}</tt></span>' + ''.format(color=color, name=Utils.encode(name).center(max_len)) + for name, color in colors + ) MessageDialogHelper( type=Gtk.MessageType.INFO, buttons=Gtk.ButtonsType.CLOSE, - title='Types', - markup=Utils.parse_template(COLORS_DIALOG_MARKUP_TMPL, - colors=platform.get_colors()) + title='Types - Color Mapping', + markup=message ) diff --git a/grc/gui/FileDialogs.py b/grc/gui/FileDialogs.py index 479f13bbd7..63d4a397a8 100644 --- a/grc/gui/FileDialogs.py +++ b/grc/gui/FileDialogs.py @@ -39,13 +39,6 @@ SAVE_CONSOLE = 'save console' SAVE_IMAGE = 'save image' OPEN_QSS_THEME = 'open qss theme' -FILE_OVERWRITE_MARKUP_TMPL="""\ -File <b>$encode($filename)</b> Exists!\nWould you like to overwrite the existing file?""" - -FILE_DNE_MARKUP_TMPL="""\ -File <b>$encode($filename)</b> Does not Exist!""" - - # File Filters def get_flow_graph_files_filter(): @@ -179,7 +172,8 @@ class FileDialog(FileDialogHelper): if path.exists(filename): #ask the user to confirm overwrite if MessageDialogHelper( Gtk.MessageType.QUESTION, Gtk.ButtonsType.YES_NO, 'Confirm Overwrite!', - Utils.parse_template(FILE_OVERWRITE_MARKUP_TMPL, filename=filename), + 'File <b>{filename}</b> Exists!\nWould you like to overwrite the existing file?' + ''.format(filename=Utils.encode(filename)), ) == Gtk.ResponseType.NO: return self.get_rectified_filename() return filename ############################################# @@ -191,7 +185,7 @@ class FileDialog(FileDialogHelper): if not path.exists(filename): #show a warning and re-run MessageDialogHelper( Gtk.MessageType.WARNING, Gtk.ButtonsType.CLOSE, 'Cannot Open!', - Utils.parse_template(FILE_DNE_MARKUP_TMPL, filename=filename), + 'File <b>{filename}</b> Does not Exist!'.format(filename=Utils.encode(filename)), ) return self.get_rectified_filename() return filenames diff --git a/grc/gui/MainWindow.py b/grc/gui/MainWindow.py index 95a5c89867..751e0d9b3f 100644 --- a/grc/gui/MainWindow.py +++ b/grc/gui/MainWindow.py @@ -36,34 +36,6 @@ from .NotebookPage import NotebookPage from ..core import Messages - -MAIN_WINDOW_TITLE_TMPL = """\ -#if not $saved -*#slurp -#end if -#if $basename -$basename#slurp -#else -$new_flowgraph_title#slurp -#end if -#if $read_only - (read only)#slurp -#end if -#if $dirname - - $dirname#slurp -#end if - - $platform_name#slurp -""" - -PAGE_TITLE_MARKUP_TMPL = """\ -#set $foreground = $saved and 'black' or 'red' -<span foreground="$foreground">$encode($title or $new_flowgraph_title)</span>#slurp -#if $read_only - (ro)#slurp -#end if -""" - - ############################################################ # Main window ############################################################ @@ -351,32 +323,27 @@ class MainWindow(Gtk.Window): Set the title of the main window. Set the titles on the page tabs. Show/hide the console window. + """ + page = self.get_page() - Args: - title: the window title - """ - Gtk.Window.set_title(self, Utils.parse_template(MAIN_WINDOW_TITLE_TMPL, - basename=os.path.basename(self.get_page().get_file_path()), - dirname=os.path.dirname(self.get_page().get_file_path()), - new_flowgraph_title=NEW_FLOGRAPH_TITLE, - read_only=self.get_page().get_read_only(), - saved=self.get_page().get_saved(), - platform_name=self._platform.config.name, - ) - ) - #set tab titles - for page in self.get_pages(): page.set_markup( - Utils.parse_template(PAGE_TITLE_MARKUP_TMPL, - #get filename and strip out file extension - title=os.path.splitext(os.path.basename(page.get_file_path()))[0], - read_only=page.get_read_only(), saved=page.get_saved(), - new_flowgraph_title=NEW_FLOGRAPH_TITLE, - ) - ) - #show/hide notebook tabs + basename = os.path.basename(page.get_file_path()) + dirname = os.path.dirname(page.get_file_path()) + Gtk.Window.set_title(self, ''.join(( + '*' if not page.get_saved() else '', basename if basename else NEW_FLOGRAPH_TITLE, + '(read only)' if page.get_read_only() else '', ' - ', + dirname if dirname else self._platform.config.name, + ))) + # set tab titles + for page in self.get_pages(): + file_name = os.path.splitext(os.path.basename(page.get_file_path()))[0] + page.set_markup('<span foreground="{foreground}">{title}{ro}</span>'.format( + foreground='black' if page.get_saved() else 'red', ro=' (ro)' if page.get_read_only() else '', + title=Utils.encode(file_name or NEW_FLOGRAPH_TITLE), + )) + # show/hide notebook tabs self.notebook.set_show_tabs(len(self.get_pages()) > 1) - # Need to update the variable window when changing + # Need to update the variable window when changing self.vars.update_gui() def update_pages(self): diff --git a/grc/gui/Param.py b/grc/gui/Param.py index fe5da8ba84..a0ca6b66c3 100644 --- a/grc/gui/Param.py +++ b/grc/gui/Param.py @@ -63,22 +63,39 @@ class InputParam(Gtk.HBox): """ Set the markup, color, tooltip, show/hide. """ - #set the markup - has_cb = \ - hasattr(self.param.get_parent(), 'get_callbacks') and \ - filter(lambda c: self.param.get_key() in c, self.param.get_parent()._callbacks) - self.set_markup(Utils.parse_template(PARAM_LABEL_MARKUP_TMPL, - param=self.param, has_cb=has_cb, - modified=self._have_pending_changes)) - #set the color + param = self.param + + has_callback = \ + hasattr(param.get_parent(), 'get_callbacks') and \ + any(param.get_key() in callback for callback in param.get_parent()._callbacks) + + self.set_markup('<span underline="{line}" foreground="{color}" font_desc="Sans 9">{label}</span>'.format( + line='low' if has_callback else 'none', + color='blue' if self._have_pending_changes else + 'black' if param.is_valid() else + 'red', + label=Utils.encode(self.param.get_name()) + )) self.set_color(self.param.get_color()) - #set the tooltip - self.set_tooltip_text( - Utils.parse_template(TIP_MARKUP_TMPL, param=self.param).strip(), - ) - #show/hide - if self.param.get_hide() == 'all': self.hide_all() - else: self.show_all() + + errors = param.get_error_messages() + tooltip_lines = ['Key: ' + param.get_key(), 'Type: ' + param.get_type()] + if param.is_valid(): + value = str(param.get_evaluated()) + 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) + self.set_tooltip_text('\n'.join(tooltip_lines)) + + if self.param.get_hide() == 'all': + self.hide_all() + else: + self.show_all() def _mark_changed(self, *args): """ @@ -135,13 +152,13 @@ class EntryParam(InputParam): need_status_color = self.label not in self.get_children() text_color = ( Colors.PARAM_ENTRY_TEXT_COLOR if not need_status_color else - gtk.gdk.color_parse('blue') if self._have_pending_changes else - gtk.gdk.color_parse('red') if not self.param.is_valid() else + Gtk.gdk.color_parse('blue') if self._have_pending_changes else + Gtk.gdk.color_parse('red') if not self.param.is_valid() else Colors.PARAM_ENTRY_TEXT_COLOR) base_color = ( Colors.BLOCK_DISABLED_COLOR if need_status_color and not self.param.get_parent().get_enabled() - else gtk.gdk.color_parse(color) + else Gtk.gdk.color_parse(color) ) self._input.modify_base(Gtk.StateType.NORMAL, base_color) self._input.modify_text(Gtk.StateType.NORMAL, text_color) @@ -361,15 +378,6 @@ class FileParam(EntryParam): file_dialog.destroy() #destroy the dialog -PARAM_MARKUP_TMPL="""\ -#set $foreground = $param.is_valid() and 'black' or 'red' -<span foreground="$foreground" font_desc="$font"><b>$encode($param.get_name()): </b>$encode(repr($param).replace('\\n',' '))</span>""" - -PARAM_LABEL_MARKUP_TMPL="""\ -#set $foreground = $modified and 'blue' or $param.is_valid() and 'black' or 'red' -#set $underline = $has_cb and 'low' or 'none' -<span underline="$underline" foreground="$foreground" font_desc="Sans 9">$encode($param.get_name())</span>""" - TIP_MARKUP_TMPL="""\ ######################################## #def truncate(string) @@ -440,5 +448,7 @@ class Param(Element, _Param): Returns: a pango markup string """ - return Utils.parse_template(PARAM_MARKUP_TMPL, - param=self, font=Constants.PARAM_FONT) + return '<span foreground="{color}" font_desc="{font}"><b>{label}:</b> {value}</span>'.format( + color='black' if self.is_valid() else 'red', font=Constants.PARAM_FONT, + label=Utils.encode(self.get_name()), value=Utils.encode(repr(self).replace('\n', ' ')) + ) diff --git a/grc/gui/Port.py b/grc/gui/Port.py index eb15f6c788..fb1cd678cd 100644 --- a/grc/gui/Port.py +++ b/grc/gui/Port.py @@ -25,16 +25,14 @@ from gi.repository import Gtk, PangoCairo from . import Actions, Colors, Utils from .Constants import ( PORT_SEPARATION, PORT_SPACING, CONNECTOR_EXTENSION_MINIMAL, - CONNECTOR_EXTENSION_INCREMENT, PORT_LABEL_PADDING, PORT_MIN_WIDTH, PORT_LABEL_HIDDEN_WIDTH, PORT_FONT + CONNECTOR_EXTENSION_INCREMENT, PORT_LABEL_PADDING, PORT_MIN_WIDTH, + PORT_LABEL_HIDDEN_WIDTH, PORT_FONT ) from .Element import Element from ..core.Constants import DEFAULT_DOMAIN, GR_MESSAGE_DOMAIN from ..core.Port import Port as _Port -PORT_MARKUP_TMPL="""\ -<span foreground="black" font_desc="$font">$encode($port.get_name())</span>""" - class Port(_Port, Element): """The graphical port.""" @@ -117,7 +115,9 @@ class Port(_Port, Element): def create_labels(self): """Create the labels for the socket.""" - self.layout.set_markup(Utils.parse_template(PORT_MARKUP_TMPL, port=self, font=PORT_FONT)) + self.layout.set_markup("""<span foreground="black" font_desc="{font}">{name}</span>""".format( + name=Utils.encode(self.get_name()), font=PORT_FONT + )) def draw(self, widget, cr): """ diff --git a/grc/gui/PropsDialog.py b/grc/gui/PropsDialog.py index 8367f8740a..d6f3cb4efe 100644 --- a/grc/gui/PropsDialog.py +++ b/grc/gui/PropsDialog.py @@ -29,10 +29,6 @@ from Constants import MIN_DIALOG_WIDTH, MIN_DIALOG_HEIGHT, FONT_SIZE import Utils from gi.repository import Pango -TAB_LABEL_MARKUP_TMPL="""\ -#set $foreground = $valid and 'black' or 'red' -<span foreground="$foreground">$encode($tab)</span>""" - def get_title_label(title): """ @@ -46,7 +42,7 @@ def get_title_label(title): a gtk object """ label = Gtk.Label() - label.set_markup('\n<b><span underline="low">%s</span>:</b>\n'%title) + label.set_markup('\n<b><span underline="low">{title}</span>:</b>\n'.format(title)) hbox = Gtk.HBox() hbox.pack_start(label, False, False, padding=11) return hbox @@ -192,7 +188,11 @@ class PropsDialog(Gtk.Dialog): box_all_valid = box_all_valid and param.is_valid() input_widget = param.get_input(self._handle_changed, self._activate_apply) vbox.pack_start(input_widget, input_widget.expand) - label.set_markup(Utils.parse_template(TAB_LABEL_MARKUP_TMPL, valid=box_all_valid, tab=tab)) + label.set_markup( + '<span foreground="{color}">{name}</span>'.format( + color='black' if box_all_valid else 'red', name=Utils.encode(tab) + ) + ) # show params box with new params vbox.show_all() # update the errors box diff --git a/grc/gui/Utils.py b/grc/gui/Utils.py index 054af57c51..e5d69bcf54 100644 --- a/grc/gui/Utils.py +++ b/grc/gui/Utils.py @@ -25,8 +25,6 @@ from gi.repository import GdkPixbuf from gi.repository import GObject from gi.repository import GLib -from Cheetah.Template import Template - from Constants import POSSIBLE_ROTATIONS, CANVAS_GRID_SIZE @@ -104,28 +102,6 @@ def encode(value): return GLib.markup_escape_text(valid_utf8) -class TemplateParser(object): - def __init__(self): - self.cache = {} - - def __call__(self, tmpl_str, **kwargs): - """ - Parse the template string with the given args. - Pass in the xml encode method for pango escape chars. - - Args: - tmpl_str: the template as a string - - Returns: - a string of the parsed template - """ - kwargs['encode'] = encode - template = self.cache.setdefault(tmpl_str, Template.compile(tmpl_str)) - return str(template(namespaces=kwargs)) - -parse_template = TemplateParser() - - def align_to_grid(coor, mode=round): def align(value): return int(mode(value / (1.0 * CANVAS_GRID_SIZE)) * CANVAS_GRID_SIZE) |