diff options
Diffstat (limited to 'grc')
-rw-r--r-- | grc/gui/ActionHandler.py | 6 | ||||
-rw-r--r-- | grc/gui/Actions.py | 2 | ||||
-rw-r--r-- | grc/gui/BlockTreeWindow.py | 52 | ||||
-rw-r--r-- | grc/gui/Colors.py | 3 | ||||
-rw-r--r-- | grc/gui/DrawingArea.py | 27 | ||||
-rw-r--r-- | grc/gui/FileDialogs.py | 15 | ||||
-rw-r--r-- | grc/gui/Preferences.py | 4 | ||||
-rw-r--r-- | grc/gui/PropsDialog.py | 38 | ||||
-rw-r--r-- | grc/python/Block.py | 7 | ||||
-rw-r--r-- | grc/python/Platform.py | 25 | ||||
-rw-r--r-- | grc/python/extract_docs.py | 2 |
11 files changed, 137 insertions, 44 deletions
diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py index 7766a0a853..0f227d08f5 100644 --- a/grc/gui/ActionHandler.py +++ b/grc/gui/ActionHandler.py @@ -34,7 +34,7 @@ from .ParserErrorsDialog import ParserErrorsDialog from .MainWindow import MainWindow from .PropsDialog import PropsDialog from .FileDialogs import (OpenFlowGraphFileDialog, SaveFlowGraphFileDialog, - SaveReportsFileDialog, SaveImageFileDialog, + SaveReportsFileDialog, SaveScreenShotDialog, OpenQSSFileDialog) from .Constants import DEFAULT_CANVAS_SIZE, IMAGE_FILE_EXTENSION, GR_PREFIX @@ -521,9 +521,9 @@ class ActionHandler: self.main_window.tool_bar.refresh_submenus() self.main_window.menu_bar.refresh_submenus() elif action == Actions.FLOW_GRAPH_SCREEN_CAPTURE: - file_path = SaveImageFileDialog(self.get_page().get_file_path()).run() + file_path, background_transparent = SaveScreenShotDialog(self.get_page().get_file_path()).run() if file_path is not None: - pixbuf = self.get_flow_graph().get_drawing_area().get_pixbuf() + pixbuf = self.get_flow_graph().get_drawing_area().get_screenshot(background_transparent) pixbuf.save(file_path, IMAGE_FILE_EXTENSION[1:]) ################################################## # Gen/Exec/Stop diff --git a/grc/gui/Actions.py b/grc/gui/Actions.py index 9b32b3e601..d53375f291 100644 --- a/grc/gui/Actions.py +++ b/grc/gui/Actions.py @@ -386,7 +386,7 @@ FLOW_GRAPH_KILL = Action( keypresses=(gtk.keysyms.F7, NO_MODS_MASK), ) FLOW_GRAPH_SCREEN_CAPTURE = Action( - label='Sc_reen Capture', + label='Screen Ca_pture', tooltip='Create a screen capture of the flow graph', stock_id=gtk.STOCK_PRINT, keypresses=(gtk.keysyms.Print, NO_MODS_MASK), diff --git a/grc/gui/BlockTreeWindow.py b/grc/gui/BlockTreeWindow.py index 6b3ebf7807..8a29120102 100644 --- a/grc/gui/BlockTreeWindow.py +++ b/grc/gui/BlockTreeWindow.py @@ -30,12 +30,27 @@ KEY_INDEX = 1 DOC_INDEX = 2 DOC_MARKUP_TMPL = """\ -#if $doc -#if len($doc) > 1000 -#set $doc = $doc[:1000] + '...' +#set $docs = [] +#if $doc.get('') + #set $docs += $doc.pop('').splitlines() + [''] #end if -$encode($doc)#slurp -#else +#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""" @@ -129,8 +144,10 @@ class BlockTreeWindow(gtk.VBox): category: the category list or path string block: the block object or None """ - if treestore is None: treestore = self.treestore - if categories is None: categories = self._categories + if treestore is None: + treestore = self.treestore + if categories is None: + categories = self._categories if isinstance(category, (str, unicode)): category = category.split('/') category = tuple(filter(lambda x: x, category)) # tuple is hashable @@ -138,17 +155,18 @@ class BlockTreeWindow(gtk.VBox): for i, cat_name in enumerate(category): sub_category = category[:i+1] if sub_category not in categories: - iter = treestore.insert_before(categories[sub_category[:-1]], None) - treestore.set_value(iter, NAME_INDEX, '[ %s ]'%cat_name) - treestore.set_value(iter, KEY_INDEX, '') - treestore.set_value(iter, DOC_INDEX, Utils.parse_template(CAT_MARKUP_TMPL, cat=cat_name)) - categories[sub_category] = iter + 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)) + categories[sub_category] = iter_ # add block - if block is None: return - 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())) + if block is None: + return + 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())) def update_docs(self): """Update the documentation column of every block""" diff --git a/grc/gui/Colors.py b/grc/gui/Colors.py index 52c95e8edf..050b363cdd 100644 --- a/grc/gui/Colors.py +++ b/grc/gui/Colors.py @@ -33,8 +33,9 @@ try: PARAM_ENTRY_TEXT_COLOR = get_color('black') ENTRYENUM_CUSTOM_COLOR = get_color('#EEEEEE') #flow graph color constants - FLOWGRAPH_BACKGROUND_COLOR = get_color('#FFF9FF') + FLOWGRAPH_BACKGROUND_COLOR = get_color('#FFFFFF') COMMENT_BACKGROUND_COLOR = get_color('#F3F3F3') + FLOWGRAPH_EDGE_COLOR = COMMENT_BACKGROUND_COLOR #block color constants BLOCK_ENABLED_COLOR = get_color('#F1ECFF') BLOCK_DISABLED_COLOR = get_color('#CCCCCC') diff --git a/grc/gui/DrawingArea.py b/grc/gui/DrawingArea.py index 4412129809..6a1df27a8c 100644 --- a/grc/gui/DrawingArea.py +++ b/grc/gui/DrawingArea.py @@ -20,7 +20,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import pygtk pygtk.require('2.0') import gtk + from Constants import MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT, DND_TARGETS +import Colors + class DrawingArea(gtk.DrawingArea): """ @@ -68,13 +71,21 @@ class DrawingArea(gtk.DrawingArea): self.set_flags(gtk.CAN_FOCUS) # self.set_can_focus(True) self.connect('focus-out-event', self._handle_focus_lost_event) - def new_pixmap(self, width, height): return gtk.gdk.Pixmap(self.window, width, height, -1) - def get_pixbuf(self): - width, height = self._pixmap.get_size() - pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, 0, 8, width, height) - pixbuf.get_from_drawable(self._pixmap, self._pixmap.get_colormap(), 0, 0, 0, 0, width, height) + def new_pixmap(self, width, height): + return gtk.gdk.Pixmap(self.window, width, height, -1) + + def get_screenshot(self, transparent_bg=False): + pixmap = self._pixmap + W, H = pixmap.get_size() + pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, 0, 8, W, H) + pixbuf.fill(0xFF + Colors.FLOWGRAPH_BACKGROUND_COLOR.pixel << 8) + pixbuf.get_from_drawable(pixmap, pixmap.get_colormap(), 0, 0, 0, 0, W-1, H-1) + if transparent_bg: + bgc = Colors.FLOWGRAPH_BACKGROUND_COLOR + pixbuf = pixbuf.add_alpha(True, bgc.red, bgc.green, bgc.blue) return pixbuf + ########################################################################## ## Handlers ########################################################################## @@ -149,6 +160,12 @@ class DrawingArea(gtk.DrawingArea): gc = self.window.new_gc() self._flow_graph.draw(gc, self._pixmap) self.window.draw_drawable(gc, self._pixmap, 0, 0, 0, 0, -1, -1) + # draw a light grey line on the bottom and right end of the canvas. + # this is useful when the theme uses the same panel bg color as the canvas + W, H = self._pixmap.get_size() + gc.set_foreground(Colors.FLOWGRAPH_EDGE_COLOR) + self.window.draw_line(gc, 0, H-1, W, H-1) + self.window.draw_line(gc, W-1, 0, W-1, H) def _handle_focus_lost_event(self, widget, event): # don't clear selection while context menu is active diff --git a/grc/gui/FileDialogs.py b/grc/gui/FileDialogs.py index 730ac6fba0..4b5770ad21 100644 --- a/grc/gui/FileDialogs.py +++ b/grc/gui/FileDialogs.py @@ -210,3 +210,18 @@ class SaveFlowGraphFileDialog(FileDialog): type = SAVE_FLOW_GRAPH class OpenQSSFileDialog(FileDialog): type = OPEN_QSS_THEME class SaveReportsFileDialog(FileDialog): type = SAVE_REPORTS class SaveImageFileDialog(FileDialog): type = SAVE_IMAGE + + +class SaveScreenShotDialog(SaveImageFileDialog): + + def __init__(self, current_file_path=''): + SaveImageFileDialog.__init__(self, current_file_path) + self._button = button = gtk.CheckButton('_Background transparent') + self._button.set_active(Preferences.screen_shot_background_transparent()) + self.set_extra_widget(button) + + def run(self): + filename = SaveImageFileDialog.run(self) + bg_transparent = self._button.get_active() + Preferences.screen_shot_background_transparent(bg_transparent) + return filename, bg_transparent diff --git a/grc/gui/Preferences.py b/grc/gui/Preferences.py index 3ebee24345..ad2206ca29 100644 --- a/grc/gui/Preferences.py +++ b/grc/gui/Preferences.py @@ -150,3 +150,7 @@ def blocks_window_position(pos=None): def xterm_missing(cmd=None): return entry('xterm_missing', cmd, default='INVALID_XTERM_SETTING') + + +def screen_shot_background_transparent(transparent=None): + return entry('screen_shot_background_transparent', transparent, default=False) diff --git a/grc/gui/PropsDialog.py b/grc/gui/PropsDialog.py index bf7d31d391..7c66a77a54 100644 --- a/grc/gui/PropsDialog.py +++ b/grc/gui/PropsDialog.py @@ -97,7 +97,8 @@ class PropsDialog(gtk.Dialog): self._params_boxes.append((tab, label, vbox)) # Docs for the block - self._docs_text_display = SimpleTextDisplay() + self._docs_text_display = doc_view = SimpleTextDisplay() + doc_view.get_buffer().create_tag('b', weight=pango.WEIGHT_BOLD) self._docs_box = gtk.ScrolledWindow() self._docs_box.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self._docs_box.add_with_viewport(self._docs_text_display) @@ -200,10 +201,43 @@ class PropsDialog(gtk.Dialog): messages = '\n\n'.join(self._block.get_error_messages()) self._error_messages_text_display.set_text(messages) # update the docs box - self._docs_text_display.set_text(self._block.get_doc()) + self._update_docs_page() # update the generated code self._update_generated_code_page() + def _update_docs_page(self): + """Show documentation from XML and try to display best matching docstring""" + buffer = self._docs_text_display.get_buffer() + buffer.delete(buffer.get_start_iter(), buffer.get_end_iter()) + pos = buffer.get_end_iter() + + docstrings = self._block.get_doc() + if not docstrings: + return + + # show documentation string from block xml + from_xml = docstrings.pop('', '') + for line in from_xml.splitlines(): + if line.lstrip() == line and line.endswith(':'): + buffer.insert_with_tags_by_name(pos, line + '\n', 'b') + else: + buffer.insert(pos, line + '\n') + if from_xml: + buffer.insert(pos, '\n') + + # if given the current parameters an exact match can be made + block_constructor = self._block.get_make().rsplit('.', 2)[-1] + block_class = block_constructor.partition('(')[0].strip() + if block_class in docstrings: + docstrings = {block_class: docstrings[block_class]} + + # show docstring(s) extracted from python sources + for cls_name, docstring in docstrings.iteritems(): + buffer.insert_with_tags_by_name(pos, cls_name + '\n', 'b') + buffer.insert(pos, docstring + '\n\n') + pos.backward_chars(2) + buffer.delete(pos, buffer.get_end_iter()) + def _update_generated_code_page(self): if not self._code_text_display: return # user disabled code preview diff --git a/grc/python/Block.py b/grc/python/Block.py index f5c994dc05..f43b006e5f 100644 --- a/grc/python/Block.py +++ b/grc/python/Block.py @@ -185,8 +185,11 @@ class Block(_Block, _GUIBlock): def get_doc(self): platform = self.get_parent().get_parent() - extracted_docs = platform.block_docstrings.get(self._key, '') - return (self._doc + '\n\n' + extracted_docs).strip() + documentation = platform.block_docstrings.get(self._key, {}) + from_xml = self._doc.strip() + if from_xml: + documentation[''] = from_xml + return documentation def get_category(self): return _Block.get_category(self) diff --git a/grc/python/Platform.py b/grc/python/Platform.py index 1d932761d8..5932818c1e 100644 --- a/grc/python/Platform.py +++ b/grc/python/Platform.py @@ -38,8 +38,6 @@ from .Constants import ( PREFS_FILE, PREFS_FILE_OLD, CORE_TYPES ) -COLORS = [(name, color) for name, key, sizeof, color in CORE_TYPES] - class Platform(_Platform, _GUIPlatform): def __init__(self): @@ -52,17 +50,11 @@ class Platform(_Platform, _GUIPlatform): if not os.path.exists(os.path.dirname(PREFS_FILE)): os.mkdir(os.path.dirname(PREFS_FILE)) - self.block_docstrings = block_docstrings = dict() - self.block_docstrings_loaded_callback = lambda: None - - def setter(key, docs): - block_docstrings[key] = '\n\n'.join( - '--- {0} ---\n{1}\n'.format(b, d.replace('\n\n', '\n')) - for b, d in docs.iteritems() if d is not None - ) + self.block_docstrings = {} + self.block_docstrings_loaded_callback = lambda: None # dummy to be replaced by BlockTreeWindow self._docstring_extractor = extract_docs.SubprocessLoader( - callback_query_result=setter, + callback_query_result=self._save_docstring_extraction_result, callback_finished=lambda: self.block_docstrings_loaded_callback() ) @@ -78,7 +70,7 @@ class Platform(_Platform, _GUIPlatform): block_dtd=BLOCK_DTD, default_flow_graph=DEFAULT_FLOW_GRAPH, generator=Generator, - colors=COLORS, + colors=[(name, color) for name, key, sizeof, color in CORE_TYPES], ) self._move_old_pref_file() _GUIPlatform.__init__( @@ -87,6 +79,15 @@ class Platform(_Platform, _GUIPlatform): ) self._auto_hier_block_generate_chain = set() + def _save_docstring_extraction_result(self, key, docstrings): + docs = {} + for match, docstring in docstrings.iteritems(): + if not docstring or match.endswith('_sptr'): + continue + docstring = docstring.replace('\n\n', '\n').strip() + docs[match] = docstring + self.block_docstrings[key] = docs + @staticmethod def _move_old_pref_file(): if PREFS_FILE == PREFS_FILE_OLD: diff --git a/grc/python/extract_docs.py b/grc/python/extract_docs.py index d8dc4f4e8f..7c149ce593 100644 --- a/grc/python/extract_docs.py +++ b/grc/python/extract_docs.py @@ -70,7 +70,7 @@ def docstring_guess_from_key(key): ) for match in filter(pattern.match, dir(module)): try: - doc_strings[match] = getattr(module, match).__doc__.strip() + doc_strings[match] = getattr(module, match).__doc__ except AttributeError: continue |