commit-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Commit-gnuradio] [gnuradio] 01/03: grc: separate core and OOT block tre


From: git
Subject: [Commit-gnuradio] [gnuradio] 01/03: grc: separate core and OOT block trees via the category of each block
Date: Fri, 27 May 2016 20:18:57 +0000 (UTC)

This is an automated email from the git hooks/post-receive script.

jcorgan pushed a commit to branch master
in repository gnuradio.

commit 1937f756fd4027ace86316fc6fb1433cd832e6eb
Author: Sebastian Koslowski <address@hidden>
Date:   Tue Apr 5 22:03:43 2016 +0200

    grc: separate core and OOT block trees via the category of each block
    
    Each block get assigned a module based on the root of its category.
    The category is set via a block_tree.xml or else from its <category> tag.
    The category root is only interpreted as module name if it is in square 
brackets.
    Else the default module 'Others' is used.
---
 grc/core/Block.py          |  9 ++---
 grc/core/Constants.py      |  1 +
 grc/core/Platform.py       | 82 ++++++++++++++++++++--------------------------
 grc/core/utils/odict.py    |  4 +++
 grc/gui/ActionHandler.py   |  5 ++-
 grc/gui/BlockTreeWindow.py | 41 +++++++++++++----------
 6 files changed, 68 insertions(+), 74 deletions(-)

diff --git a/grc/core/Block.py b/grc/core/Block.py
index f67d990..8a683a2 100644
--- a/grc/core/Block.py
+++ b/grc/core/Block.py
@@ -79,7 +79,8 @@ class Block(Element):
         sinks = n.findall('sink')
         self._name = n.find('name')
         self._key = n.find('key')
-        self._category = n.find('category') or ''
+        category = (n.find('category') or '').split('/')
+        self.category = [cat.strip() for cat in category if cat.strip()]
         self._flags = n.find('flags') or ''
         # Backwards compatibility
         if n.find('throttle') and BLOCK_FLAG_THROTTLE not in self._flags:
@@ -594,12 +595,6 @@ class Block(Element):
     def get_key(self):
         return self._key
 
-    def get_category(self):
-        return self._category
-
-    def set_category(self, cat):
-        self._category = cat
-
     def get_ports(self):
         return self.get_sources() + self.get_sinks()
 
diff --git a/grc/core/Constants.py b/grc/core/Constants.py
index 462049c..eeb1d7f 100644
--- a/grc/core/Constants.py
+++ b/grc/core/Constants.py
@@ -37,6 +37,7 @@ FLOW_GRAPH_FILE_FORMAT_VERSION = 1
 # Param tabs
 DEFAULT_PARAM_TAB = "General"
 ADVANCED_PARAM_TAB = "Advanced"
+DEFAULT_BLOCK_MODULE_NAME = '(no module specified)'
 
 # Port domains
 GR_STREAM_DOMAIN = "gr_stream"
diff --git a/grc/core/Platform.py b/grc/core/Platform.py
index 5bcf79c..9b25e67 100644
--- a/grc/core/Platform.py
+++ b/grc/core/Platform.py
@@ -67,15 +67,15 @@ class Platform(Element):
         self._flow_graph = Element(self)
         self._flow_graph.connections = []
 
-        self.blocks = None
-        self._blocks_n = None
-        self._category_trees_n = None
+        self.blocks = odict()
+        self._blocks_n = odict()
+        self._block_categories = {}
         self.domains = {}
         self.connection_templates = {}
 
         self._auto_hier_block_generate_chain = set()
 
-        self.load_blocks()
+        self.build_block_library()
 
     def __str__(self):
         return 'Platform - {}({})'.format(self.config.key, self.config.name)
@@ -133,16 +133,17 @@ class Platform(Element):
         self.load_block_xml(generator.get_file_path_xml())
         return True
 
-    def load_blocks(self):
+    def build_block_library(self):
         """load the blocks and block tree from the search paths"""
         self._docstring_extractor.start()
         # Reset
-        self.blocks = odict()
-        self._blocks_n = odict()
-        self._category_trees_n = list()
+        self.blocks.clear()
+        self._blocks_n.clear()
+        self._block_categories.clear()
         self.domains.clear()
         self.connection_templates.clear()
         ParseXML.xml_failures.clear()
+
         # Try to parse and load blocks
         for xml_file in self.iter_xml_files():
             try:
@@ -158,6 +159,19 @@ class Platform(Element):
             except Exception as e:
                 print >> sys.stderr, 'Warning: XML parsing 
failed:\n\t%r\n\tIgnoring: %s' % (e, xml_file)
 
+        # Add blocks to block tree
+        for key, block in self.blocks.iteritems():
+            category = self._block_categories.get(key, block.category)
+            # Blocks with empty categories are hidden
+            if not category:
+                continue
+            root = category[0]
+            if root.startswith('[') and root.endswith(']'):
+                category[0] = root[1:-1]
+            else:
+                category.insert(0, Constants.DEFAULT_BLOCK_MODULE_NAME)
+            block.category = category
+
         self._docstring_extractor.finish()
         # self._docstring_extractor.wait()
 
@@ -195,8 +209,19 @@ class Platform(Element):
     def load_category_tree_xml(self, xml_file):
         """Validate and parse category tree file and add it to list"""
         ParseXML.validate_dtd(xml_file, Constants.BLOCK_TREE_DTD)
-        n = ParseXML.from_file(xml_file).find('cat')
-        self._category_trees_n.append(n)
+        xml = ParseXML.from_file(xml_file)
+        path = []
+
+        def load_category(cat_n):
+            path.append(cat_n.find('name').strip())
+            for block_key in cat_n.findall('block'):
+                if block_key not in self._block_categories:
+                    self._block_categories[block_key] = list(path)
+            for sub_cat_n in cat_n.findall('cat'):
+                load_category(sub_cat_n)
+            path.pop()
+
+        load_category(xml.find('cat'))
 
     def load_domain_xml(self, xml_file):
         """Load a domain properties and connection templates from XML"""
@@ -241,43 +266,6 @@ class Platform(Element):
             else:
                 self.connection_templates[key] = connection_n.find('make') or 
''
 
-    def load_block_tree(self, block_tree):
-        """
-        Load a block tree with categories and blocks.
-        Step 1: Load all blocks from the xml specification.
-        Step 2: Load blocks with builtin category specifications.
-
-        Args:
-            block_tree: the block tree object
-        """
-        # Recursive function to load categories and blocks
-        def load_category(cat_n, parent=None):
-            # Add this category
-            parent = (parent or []) + [cat_n.find('name')]
-            block_tree.add_block(parent)
-            # Recursive call to load sub categories
-            map(lambda c: load_category(c, parent), cat_n.findall('cat'))
-            # Add blocks in this category
-            for block_key in cat_n.findall('block'):
-                if block_key not in self.blocks:
-                    print >> sys.stderr, 'Warning: Block key "{}" not found 
when loading category tree.'.format(block_key)
-                    continue
-                block = self.blocks[block_key]
-                # If it exists, the block's category shall not be overridden 
by the xml tree
-                if not block.get_category():
-                    block.set_category(parent)
-
-        # Recursively load the category trees and update the categories for 
each block
-        for category_tree_n in self._category_trees_n:
-            load_category(category_tree_n)
-
-        # Add blocks to block tree
-        for block in self.blocks.itervalues():
-            # Blocks with empty categories are hidden
-            if not block.get_category():
-                continue
-            block_tree.add_block(block.get_category(), block)
-
     def _save_docstring_extraction_result(self, key, docstrings):
         docs = {}
         for match, docstring in docstrings.iteritems():
diff --git a/grc/core/utils/odict.py b/grc/core/utils/odict.py
index 20970e9..85927e8 100644
--- a/grc/core/utils/odict.py
+++ b/grc/core/utils/odict.py
@@ -109,3 +109,7 @@ class odict(DictMixin):
         if isinstance(obj, list):
             return obj
         return [obj]
+
+    def clear(self):
+        self._data.clear()
+        del self._keys[:]
\ No newline at end of file
diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py
index 2b39079..11e81c4 100644
--- a/grc/gui/ActionHandler.py
+++ b/grc/gui/ActionHandler.py
@@ -607,9 +607,8 @@ class ActionHandler:
         elif action == Actions.PAGE_CHANGE:  # pass and run the global actions
             pass
         elif action == Actions.RELOAD_BLOCKS:
-            self.platform.load_blocks()
-            main.btwin.clear()
-            self.platform.load_block_tree(main.btwin)
+            self.platform.build_block_library()
+            main.btwin.repopulate()
             Actions.XML_PARSER_ERRORS_DISPLAY.set_sensitive(bool(
                 ParseXML.xml_failures))
             Messages.send_xml_errors_if_any(ParseXML.xml_failures)
diff --git a/grc/gui/BlockTreeWindow.py b/grc/gui/BlockTreeWindow.py
index 4279e8c..6ba5144 100644
--- a/grc/gui/BlockTreeWindow.py
+++ b/grc/gui/BlockTreeWindow.py
@@ -124,33 +124,42 @@ class BlockTreeWindow(gtk.VBox):
         # map categories to iters, automatic mapping for root
         self._categories = {tuple(): None}
         self._categories_search = {tuple(): None}
-        # add blocks and categories
-        self.platform.load_block_tree(self)
         self.platform.block_docstrings_loaded_callback = self.update_docs
+        self.repopulate()
 
     def clear(self):
-        self.treestore.clear();
-        self._categories = {tuple(): None}
+        self.treestore.clear()
+        self._categories = {(): None}
+
+    def repopulate(self):
+        self.clear()
+        for block in self.platform.blocks.itervalues():
+            if block.category:
+                self.add_block(block)
+        self.expand_module_in_tree()
+
+    def expand_module_in_tree(self, module_name='Core'):
+        self.treeview.collapse_all()
+        core_module_iter = self._categories.get((module_name,))
+        if core_module_iter:
+            
self.treeview.expand_row(self.treestore.get_path(core_module_iter), False)
 
     ############################################################
     ## Block Tree Methods
     ############################################################
-    def add_block(self, category, block=None, treestore=None, categories=None):
+    def add_block(self, block, treestore=None, categories=None):
         """
         Add a block with category to this selection window.
         Add only the category when block is None.
 
         Args:
-            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
+        treestore = treestore or self.treestore
+        categories = categories or self._categories
+
+        category = tuple(filter(str, block.category))  # tuple is hashable, 
remove empty cats
 
-        if isinstance(category, (str, unicode)): category = category.split('/')
-        category = tuple(filter(lambda x: x, category))  # tuple is hashable
         # add category and all sub categories
         for i, cat_name in enumerate(category):
             sub_category = category[:i+1]
@@ -160,9 +169,8 @@ class BlockTreeWindow(gtk.VBox):
                 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())
@@ -226,7 +234,7 @@ class BlockTreeWindow(gtk.VBox):
         key = widget.get_text().lower()
         if not key:
             self.treeview.set_model(self.treestore)
-            self.treeview.collapse_all()
+            self.expand_module_in_tree()
         else:
             matching_blocks = filter(lambda b: key in b.get_key().lower() or 
key in b.get_name().lower(),
                                      self.platform.blocks.values())
@@ -234,8 +242,7 @@ class BlockTreeWindow(gtk.VBox):
             self.treestore_search.clear()
             self._categories_search = {tuple(): None}
             for block in matching_blocks:
-                self.add_block(block.get_category() or 'None', block,
-                               self.treestore_search, self._categories_search)
+                self.add_block(block, self.treestore_search, 
self._categories_search)
             self.treeview.set_model(self.treestore_search)
             self.treeview.expand_all()
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]