Exemple #1
0
class KConfigTree(JTree, CellEditorListener):
    """Custom Swing JTree based tree that visualizes a KConfig configuration.
        The full KConfig menu structure is put into a shadow tree model. From the shadow model,
        a real model is built (updateModel), where hidden nodes are not included. This update model
        is what the tree uses to visualize the configuration menu.
        Both the shadow and the updated model has the same TreeNodeData with KConfig data.
        The expanded state and search result state is kept in the TreeNodeData.
    """
    shadowModel = None
    isUpdating = False
    showAll = False
    isSearching = False

    def __init__(self, kconf):
        self.setCellRenderer(CustomCellRenderer())
        self.setCellEditor(CustomCellEditor(self))
        self.createKconfShadowModel(kconf)
        self.setModel(self.createUpdatedModel())
        self.expandRow(0)
        self.setEditable(True)
        self.setRootVisible(False)
        self.setShowsRootHandles(True)
        self.setRowHeight(0)
        self.addTreeExpansionListener(KConfigTreeExpansionListener())
        self.getCellEditor().addCellEditorListener(self)

    def editingCanceled(self, event):
        """From CellEditorListener """
        # log.info("editingCanceled", self.cellEditor.getCellEditorValue())
        pass

    def editingStopped(self, event):
        """From CellEditorListener."""
        # log.info("editingStopped", self.cellEditor.getCellEditorValue())
        self.stopEditing()

    def createKconfShadowModel(self, kconf):
        """Create the one and only shadow data model"""
        rootNode = DefaultMutableTreeNode(kconf.mainmenu_text)
        self.addNodes(rootNode, kconf.top_node.list)
        self.shadowModel = DefaultTreeModel(rootNode)

    def addNodes(self, parent, node):
        """Recursively traverse the KConfig structure and add to the shadow model"""
        while node:
            newUiNode = DefaultMutableTreeNode(TreeNodeData(node, self))
            parent.add(newUiNode)

            if node.list:
                self.addNodes(newUiNode, node.list)

            node = node.next

    def createUpdatedModel(self):
        """When the user does any changes in the tree, the underlaying kconfig structure
        will change. Nodes may change visibility and value. The tree control cannot hide nodes,
        so a new datamodel must be generated that does not include invisible nodes."""
        shadowTreeRoot = self.shadowModel.getRoot()
        rootNode = DefaultMutableTreeNode("Root")
        self.addVisibleNodes(rootNode, shadowTreeRoot)
        return DefaultTreeModel(rootNode)

    def addVisibleNodes(self, visibleParent, shadowParent):
        """Adds visible nodes from the shadow tree model to the update tree model.
        If there is an active search operation, only search matches will be added.
        If showAll is set, all nodes are added regardless of visibility."""
        childrenEnum = shadowParent.children()
        while childrenEnum.hasMoreElements():
            shadowChild = childrenEnum.nextElement()

            if shadowChild.getUserObject().getVisible() > 0 or self.showAll:
                if not self.isSearching or shadowChild.getUserObject(
                ).isSearchMatch():
                    visibleChild = DefaultMutableTreeNode(
                        shadowChild.getUserObject())
                    visibleParent.add(visibleChild)

                    if shadowChild.getChildCount() > 0:
                        self.addVisibleNodes(visibleChild, shadowChild)

    def isPathEditable(self, path):
        comp = path.getLastPathComponent()
        if isinstance(comp, DefaultMutableTreeNode):
            nodeData = comp.getUserObject()
            if isinstance(nodeData, TreeNodeData):
                return True
        return False

    def updateTree(self):
        """Call to create a new updated tree model"""
        if not self.isUpdating:
            # log.info("updateTree()")
            self.isUpdating = True
            self.setModel(self.createUpdatedModel())
            self.updateExpandedState(self.getModel().getRoot())
            self.isUpdating = False

    def updateExpandedState(self, parent):
        """Scan through the whole tree and expand the tree node
        if the node data has the expanded field set to True."""
        childrenEnum = parent.children()
        while childrenEnum.hasMoreElements():
            child = childrenEnum.nextElement()

            if child.getUserObject().isExpanded():
                self.expandPath(TreePath(child.getPath()))

            if child.getChildCount() > 0:
                self.updateExpandedState(child)

    def setShowAll(self, show):
        self.showAll = show
        self.updateTree()

    def doSearch(self, searchText):
        """Perform a search in the data model with the supplied text."""
        if len(searchText) > 0:
            self.isSearching = True
            self.doSearchBranch(self.shadowModel.getRoot(), searchText)
        else:
            self.isSearching = False
        self.updateTree()

    def doSearchBranch(self, shadowParent, searchText):
        """Traverse the tree model searching for the search text"""
        match = False

        childrenEnum = shadowParent.children()
        while childrenEnum.hasMoreElements():
            shadowChild = childrenEnum.nextElement()

            if shadowChild.getUserObject().search(searchText, self.showAll):
                match = True

            if shadowChild.getChildCount() > 0:
                if self.doSearchBranch(shadowChild, searchText):
                    shadowChild.getUserObject().setSearchMatch(True)
                    match = True

        return match