Example #1
0
    def loadXbelNode(self, element, model, parent=None):
        """Recursively load an XBEL ElementTree node and its children.

        Arguments:
            element -- an XBEL ElementTree node
            model -- a ref to the TreeLine model
            parent  -- the parent TreeNode (None for the root node only)
        """
        if element.tag in ('xbel', 'folder'):
            node = treenode.TreeNode(parent, bookmarkFolderTypeName, model)
            if parent:
                parent.childList.append(node)
            else:
                model.root = node
            for child in element:
                self.loadXbelNode(child, model, node)
        elif element.tag == 'bookmark':
            node = treenode.TreeNode(parent, bookmarkLinkTypeName, model)
            parent.childList.append(node)
            link = element.get('href').strip()
            if link:
                node.data[bookmarkLinkFieldName] = (
                    '<a href="{0}">{1}</a>'.format(link, link))
            for child in element:
                self.loadXbelNode(child, model, node)
        elif element.tag == 'title':
            parent.setTitle(element.text)
        elif element.tag == 'separator':
            node = treenode.TreeNode(parent, bookmarkSeparatorTypeName, model)
            parent.childList.append(node)
            node.setUniqueId(True)
        else:  # unsupported tags
            pass
Example #2
0
 def __init__(self, newFile=False, parent=None):
     """Initialize a TreeModel.
     
     Arguments:
         newFile -- if true, adds default root node and formats
         parent -- optional QObject parent for the model
     """
     super().__init__(parent)
     self.root = None
     self.configDialogFormats = None
     self.undoList = None
     self.redoList = None
     self.nodeIdDict = {}
     self.linkRefCollect = linkref.LinkRefCollection()
     self.mathZeroBlanks = True
     if newFile:
         self.formats = treeformats.TreeFormats(True)
         self.root = treenode.TreeNode(None, treeformats.defaultTypeName,
                                       self)
         self.root.setTitle(defaultRootName)
     else:
         self.formats = treeformats.TreeFormats()
     self.fileInfoNode = treenode.TreeNode(None,
                                           self.formats.fileInfoFormat.name,
                                           self)
Example #3
0
def prune_tree(original_sub_tree, values_to_discard):
    '''
    Returns a tree with any node whose label is in the list values_to_discard
    (and thus all of its children) pruned. This function should return a copy
    of the original tree and should not destructively modify the original tree.
    The pruning step must be recursive.

    Inputs:
        original_sub_tree: (TreeNode) a tree of type TreeNode whose internal
                  counts have been computed. That is, compute_internal_counts()
                  must have been run on this tree.
        values_to_discard: (list of strings) A list of strings specifying the
                  labels of nodes to discard

    Variables:
        t: (TreeNode) variable representation of original_sub_tree
        child_array: (list of TreeNodes) holds the list of children for a given
                  node of the tree 

    Returns: a new TreeNode representing the pruned tree
    '''
    t = original_sub_tree
    if t.num_children() == 0:
        return treenode.TreeNode(t.label, count=t.count)
    child_array = []
    for child in t.children:
        if child.label not in values_to_discard:
            child_array.append(prune_tree(child, values_to_discard))
    return treenode.TreeNode(t.label, t.count, child_array)
Example #4
0
    def __init__(self, fileData=None, topNodes=None, addDefaults=False,
                 addSpots=True):
        """Create and store a tree structure from file data.

        If no file data is given, create an empty or a default new structure.
        Arguments:
            fileData -- a dict in JSON file format of a structure
            topNodes -- existing top-level nodes to add to a structure
            addDefaults -- if True, adds default new structure
            addSpots -- if True, adds parent spot references
        """
        super().__init__(None)  # init TreeNode, with no formatRef
        self.nodeDict = {}
        self.undoList = None
        self.redoList = None
        self.configDialogFormats = None
        self.mathZeroBlanks = True
        self.childRefErrorNodes = []
        if fileData:
            self.treeFormats = treeformats.TreeFormats(fileData['formats'])
            self.treeFormats.loadGlobalSavedConditions(fileData['properties'])
            for nodeInfo in fileData['nodes']:
                formatRef = self.treeFormats[nodeInfo['format']]
                node = treenode.TreeNode(formatRef, nodeInfo)
                self.nodeDict[node.uId] = node
            for node in self.nodeDict.values():
                node.assignRefs(self.nodeDict)
                if node.tmpChildRefs:
                    self.childRefErrorNodes.append(node)
                    node.tmpChildRefs = []
            for uId in fileData['properties']['topnodes']:
                node = self.nodeDict[uId]
                self.childList.append(node)
            if 'zeroblanks' in fileData['properties']:
                self.mathZeroBlanks = fileData['properties']['zeroblanks']
            if addSpots:
                self.generateSpots(None)
        elif topNodes:
            self.childList = topNodes
            self.treeFormats = treeformats.TreeFormats()
            for topNode in topNodes:
                for node in topNode.descendantGen():
                    self.nodeDict[node.uId] = node
                    self.treeFormats.addTypeIfMissing(node.formatRef)
            if addSpots:
                self.generateSpots(None)
        elif addDefaults:
            self.treeFormats = treeformats.TreeFormats(setDefault=True)
            node = treenode.TreeNode(self.treeFormats[treeformats.
                                                      defaultTypeName])
            node.setTitle(defaultRootTitle)
            self.nodeDict[node.uId] = node
            self.childList.append(node)
            if addSpots:
                self.generateSpots(None)
        else:
            self.treeFormats = treeformats.TreeFormats()
        self.fileInfoNode = treenode.TreeNode(self.treeFormats.fileInfoFormat)
 def _put(self, key, val, current_node):
     if key < current_node.key:
         if current_node.has_left_child():
             self._put(key, val, current_node.left_child)
         else:
             current_node.left_child = tn.TreeNode(key,
                                                   val,
                                                   parent=current_node)
     else:
         if current_node.has_right_child():
             self._put(key, val, current_node.right_child)
         else:
             current_node.right_child = tn.TreeNode(key,
                                                    val,
                                                    parent=current_node)
Example #6
0
def prune_tree(original_sub_tree, values_to_discard):
    '''
    Returns a tree with any node whose label is in the list values_to_discard
    (and thus all of its children) pruned. This function should return a copy
    of the original tree and should not destructively modify the original tree.
    The pruning step must be recursive.

    Inputs:
        original_sub_tree: (TreeNode) a tree of type TreeNode whose internal
                  counts have been computed. That is, compute_internal_counts()
                  must have been run on this tree.
        values_to_discard: (list of strings) A list of strings specifying the
                  labels of nodes to discard

    Returns: a new TreeNode representing the pruned tree
    '''

    good_child_list = []
    t = original_sub_tree

    if t.num_children() == 0:
        if t.label not in values_to_discard:
            return t

    for child in t.children:
        if child.label not in values_to_discard:
            good_child = prune_tree(child, values_to_discard)
            good_child_list.append(good_child)

    pruned_tree = treenode.TreeNode(t.label, None, good_child_list)

    return pruned_tree
Example #7
0
    def loadL5XNode(self, element, model, parent=None):
        """Recursively load a generic XML ElementTree node and its children.

        Arguments:
            element -- an XML ElementTree node
            model -- a ref to the TreeLine model
            parent -- the parent TreeNode (None for the root node only)
        """
        elemFormat = model.formats.get(element.tag, None)
        if not elemFormat:
            elemFormat = nodeformat.NodeFormat(element.tag, model.formats)
            model.formats[element.tag] = elemFormat
        node = treenode.TreeNode(parent, elemFormat.name, model)
        if parent:
            parent.childList.append(node)
        elif model.root:
            raise ElementTree.ParseError  # invalid with two roots
        else:
            model.root = node
        if element.text and element.text.strip():
            if genericXmlTextFieldName not in elemFormat.fieldDict:
                elemFormat.addFieldList([genericXmlTextFieldName], True, True)
            node.setTitle(element.text.strip())
        for key, value in element.items():
            elemFormat.addFieldIfNew(key)
            node.data[key] = value
        for child in element:
            self.loadL5XNode(child, model, node)
Example #8
0
    def loadXmlNode(self, element, structure, parent=None):
        """Recursively load a generic XML ElementTree node and its children.

        Arguments:
            element -- an XML ElementTree node
            structure -- a ref to the TreeLine structure
            parent -- the parent TreeNode (None for the root node only)
        """
        elemFormat = structure.treeFormats.get(element.tag, None)
        if not elemFormat:
            elemFormat = nodeformat.NodeFormat(element.tag,
                                               structure.treeFormats)
            structure.treeFormats[element.tag] = elemFormat
        node = treenode.TreeNode(elemFormat)
        structure.addNodeDictRef(node)
        if not parent:
            parent = structure
        parent.childList.append(node)
        if element.text and element.text.strip():
            if genericXmlTextFieldName not in elemFormat.fieldDict:
                elemFormat.addFieldList([genericXmlTextFieldName], True, True)
            node.setTitle(element.text.strip())
        for key, value in element.items():
            elemFormat.addFieldIfNew(key)
            node.data[key] = value
        for child in element:
            self.loadXmlNode(child, structure, node)
Example #9
0
    def importTableText(self):
        """Import a file with a tab-delimited table with header row.

        Return the model if import is successful, otherwise None.
        """
        model = treemodel.TreeModel(True)
        typeName = _('TABLE')
        tableFormat = nodeformat.NodeFormat(typeName, model.formats)
        model.formats.addTypeIfMissing(tableFormat)
        with open(self.filePath, 'r',
                  encoding=globalref.localTextEncoding) as f:
            headings = [
                self.correctFieldName(name)
                for name in f.readline().split('\t')
            ]
            tableFormat.addFieldList(headings, True, True)
            lineNum = 1
            for line in f:
                lineNum += 1
                if line.strip():
                    entries = line.split('\t')
                    node = treenode.TreeNode(model.root, typeName, model)
                    model.root.childList.append(node)
                    try:
                        for heading in headings:
                            node.data[heading] = entries.pop(0)
                    except IndexError:
                        pass  # fewer entries than headings is OK
                    if entries:
                        self.errorMessage = (
                            _('Too many entries on Line {0}').format(lineNum))
                        return None  # abort if too few headings
                    node.setUniqueId(True)
        return model
Example #10
0
 def _insert(self, data, curr_node):
     # If entry node < current node, add as left child if null, or recursively call method on left child if not null
     if data < curr_node.data:
         if curr_node.left is None:
             curr_node.left = treenode.TreeNode(data)
         else:
             self._insert(data, curr_node.left)
     # If entry node > current node, same as above but for right side of tree
     elif data > curr_node.data:
         if curr_node.right is None:
             curr_node.right = treenode.TreeNode(data)
         else:
             self._insert(data, curr_node.right)
     # Otherwise value equals current tree node, and we do not add it to avoid duplicates
     else:
         print("Value is already present in BST")
Example #11
0
    def mimeData(self, indexList):
        """Return a mime data object for the given node index branches.

        Arguments:
            indexList -- a list of node indexes to convert
        """
        allNodes = [index.internalPointer() for index in indexList]
        nodes = []
        # accept only nodes on top of unique branches
        for node in allNodes:
            parent = node.parent
            while parent and parent not in allNodes:
                parent = parent.parent
            if not parent:
                nodes.append(node)
        TreeModel.storedDragNodes = nodes
        TreeModel.storedDragModel = self
        dummyFormat = None
        if len(nodes) > 1:
            dummyFormat = self.formats.addDummyRootType()
            root = treenode.TreeNode(None, dummyFormat.name, self)
            for node in nodes:
                root.childList.append(copy.copy(node))
                root.childList[-1].parent = root
        else:
            root = nodes[0]
        text = ElementTree.tostring(
            root.elementXml({dummyFormat}, True, False), 'utf-8')
        self.formats.removeDummyRootType()
        mime = QtCore.QMimeData()
        mime.setData('text/xml', text)
        return mime
Example #12
0
    def importTableTabbed(self):
        """Import a file with a tab-delimited table with header row.

        Return the structure if import is successful, otherwise None.
        """
        structure = treestructure.TreeStructure(addDefaults=True,
                                                addSpots=False)
        tableFormat = nodeformat.NodeFormat(_('TABLE'), structure.treeFormats)
        structure.treeFormats.addTypeIfMissing(tableFormat)
        with self.pathObj.open(encoding=globalref.localTextEncoding) as f:
            headings = [
                self.correctFieldName(name)
                for name in f.readline().split('\t')
            ]
            tableFormat.addFieldList(headings, True, True)
            lineNum = 1
            for line in f:
                lineNum += 1
                if line.strip():
                    entries = line.split('\t')
                    node = treenode.TreeNode(tableFormat)
                    structure.childList[0].childList.append(node)
                    structure.addNodeDictRef(node)
                    try:
                        for heading in headings:
                            node.data[heading] = entries.pop(0)
                    except IndexError:
                        pass  # fewer entries than headings is OK
                    if entries:
                        self.errorMessage = (
                            _('Too many entries on Line {0}').format(lineNum))
                        return None  # abort if too few headings
        structure.generateSpots(None)
        return structure
Example #13
0
    def loadOldTreeLineNode(self,
                            element,
                            structure,
                            idRefDict,
                            linkList,
                            parent=None):
        """Recursively load an old TreeLine ElementTree node and its children.

        Arguments:
            element -- an ElementTree node
            structure -- a ref to the new tree structure
            idRefDict -- a dict to relate old to new unique node IDs
            linkList -- internal link list ref with (node, fieldname) tuples
            parent  -- the parent TreeNode (None for the root node only)
        """
        try:
            typeFormat = structure.treeFormats[element.tag]
        except KeyError:
            formatData = self.convertOldNodeFormat(element.attrib)
            typeFormat = nodeformat.NodeFormat(element.tag,
                                               structure.treeFormats,
                                               formatData)
            structure.treeFormats[element.tag] = typeFormat
            self.treeLineOldFieldAttr[typeFormat.name] = {}
        if element.get('item') == 'y':
            node = treenode.TreeNode(typeFormat)
            oldId = element.attrib.get('uniqueid', '')
            if oldId:
                idRefDict[oldId] = node.uId
            if parent:
                parent.childList.append(node)
            else:
                structure.childList.append(node)
            structure.nodeDict[node.uId] = node
            cloneAttr = element.attrib.get('clones', '')
            if cloneAttr:
                for cloneId in cloneAttr.split(','):
                    if cloneId in idRefDict:
                        cloneNode = structure.nodeDict[idRefDict[cloneId]]
                        node.data = cloneNode.data.copy()
                        break
        else:  # bare format (no nodes)
            node = None
        for child in element:
            if child.get('item') and node:
                self.loadOldTreeLineNode(child, structure, idRefDict, linkList,
                                         node)
            else:
                if node and child.text:
                    node.data[child.tag] = child.text
                    if child.get('linkcount'):
                        linkList.append((node, child.tag))
                if child.tag not in typeFormat.fieldDict:
                    fieldData = self.convertOldFieldFormat(child.attrib)
                    oldFormatDict = self.treeLineOldFieldAttr[typeFormat.name]
                    oldFormatDict[child.tag] = fieldData
                    typeFormat.addField(child.tag, fieldData)
Example #14
0
def create_st(relevant_rows, hierarchy, hierarchy_labels, level_label):
    '''
	Recursively creates subtrees

	'''
    if len(hierarchy) == 0:
        # Return leaf node with count of relevant rows
        return treenode.TreeNode(level_label,
                                 count=relevant_rows["count"].sum())
    else:
        curr_children = []
        curr_level = hierarchy[0]
        hierarchy = list(hierarchy[1:])
        for level_value in hierarchy_labels[curr_level]:
            curr_rows = relevant_rows[relevant_rows[curr_level] == level_value]
            curr_children.append(
                create_st(curr_rows, hierarchy, hierarchy_labels, level_value))
        return treenode.TreeNode(level_label, children=curr_children)
Example #15
0
    def importOdfText(self):
        """Import an ODF format text file outline.

        Return the structure if import is successful, otherwise None.
        """
        structure = treestructure.TreeStructure(addDefaults=True,
                                                addSpots=False)
        structure.removeNodeDictRef(structure.childList[0])
        structure.childList = []
        odfFormat = structure.treeFormats[treeformats.defaultTypeName]
        odfFormat.addField(textFieldName)
        odfFormat.changeOutputLines([
            '<b>{{*{0}*}}</b>'.format(nodeformat.defaultFieldName),
            '{{*{0}*}}'.format(textFieldName)
        ])
        odfFormat.formatHtml = True
        try:
            with zipfile.ZipFile(str(self.pathObj), 'r') as f:
                text = f.read('content.xml')
        except (zipfile.BadZipFile, KeyError):
            return None
        try:
            rootElement = ElementTree.fromstring(text)
        except ElementTree.ParseError:
            return None
        nameSpace = '{urn:oasis:names:tc:opendocument:xmlns:text:1.0}'
        headerTag = '{0}h'.format(nameSpace)
        paraTag = '{0}p'.format(nameSpace)
        numRegExp = re.compile(r'.*?(\d+)$')
        parents = [structure]
        prevLevel = 0
        for elem in rootElement.iter():
            if elem.tag == headerTag:
                style = elem.get('{0}style-name'.format(nameSpace), '')
                try:
                    level = int(numRegExp.match(style).group(1))
                except AttributeError:
                    return None
                if level < 1 or level > prevLevel + 1:
                    return None
                parents = parents[:level]
                node = treenode.TreeNode(odfFormat)
                structure.addNodeDictRef(node)
                parents[-1].childList.append(node)
                node.data[nodeformat.defaultFieldName] = ''.join(
                    elem.itertext())
                parents.append(node)
                prevLevel = level
            elif elem.tag == paraTag:
                text = ''.join(elem.itertext())
                origText = node.data.get(textFieldName, '')
                if origText:
                    text = '{0}<br />{1}'.format(origText, text)
                node.data[textFieldName] = text
        structure.generateSpots(None)
        return structure
Example #16
0
    def importOdfText(self):
        """Import an ODF format text file outline.

        Return the model if import is successful, otherwise None.
        """
        model = treemodel.TreeModel(True)
        odfFormat = model.formats[treeformats.defaultTypeName]
        odfFormat.addField(textFieldName)
        odfFormat.changeOutputLines([
            '<b>{{*{0}*}}</b>'.format(nodeformat.defaultFieldName),
            '{{*{0}*}}'.format(textFieldName)
        ])
        odfFormat.formatHtml = True
        try:
            with zipfile.ZipFile(self.filePath, 'r') as f:
                text = f.read('content.xml')
        except (zipfile.BadZipFile, KeyError):
            return None
        try:
            rootElement = ElementTree.fromstring(text)
        except ElementTree.ParseError:
            return None
        nameSpace = '{urn:oasis:names:tc:opendocument:xmlns:text:1.0}'
        headerTag = '{0}h'.format(nameSpace)
        paraTag = '{0}p'.format(nameSpace)
        numRegExp = re.compile(r'.*?(\d+)$')
        currentNode = model.root
        currentLevel = 0
        for elem in rootElement.iter():
            if elem.tag == headerTag:
                style = elem.get('{0}style-name'.format(nameSpace), '')
                try:
                    level = int(numRegExp.match(style).group(1))
                except AttributeError:
                    return None
                if level < 1 or level > currentLevel + 1:
                    return None
                while (currentLevel >= level):
                    currentNode = currentNode.parent
                    currentLevel -= 1
                node = treenode.TreeNode(currentNode, odfFormat.name, model)
                currentNode.childList.append(node)
                node.data[nodeformat.defaultFieldName] = ''.join(
                    elem.itertext())
                node.setUniqueId(True)
                currentNode = node
                currentLevel = level
            elif elem.tag == paraTag:
                text = ''.join(elem.itertext())
                origText = currentNode.data.get(textFieldName, '')
                if origText:
                    text = '{0}<br />{1}'.format(origText, text)
                node.data[textFieldName] = text
        return model
Example #17
0
 def handle_starttag(self, tag, attrs):
     """Called by the reader at each open tag.
     
     Arguments:
         tag -- the tag label
         attrs -- any tag attributes
     """
     if tag == 'dt' or tag == 'h1':  # start any entry
         self.text = ''
     elif tag == 'dl':  # start indent
         self.currentParent = self.currentNode
         self.currentNode = None
     elif tag == 'h3':  # start folder
         if not self.currentParent:
             raise html.parser.HTMLParseError
         self.currentNode = treenode.TreeNode(self.currentParent,
                                              bookmarkFolderTypeName,
                                              self.model)
         self.currentParent.childList.append(self.currentNode)
     elif tag == 'a':  # start link
         if not self.currentParent:
             raise html.parser.HTMLParseError
         self.currentNode = treenode.TreeNode(self.currentParent,
                                              bookmarkLinkTypeName,
                                              self.model)
         self.currentParent.childList.append(self.currentNode)
         for name, value in attrs:
             if name == 'href':
                 link = '<a href="{0}">{0}</a>'.format(value)
                 self.currentNode.data[bookmarkLinkFieldName] = link
     elif tag == 'hr':  # separator
         if not self.currentParent:
             raise html.parser.HTMLParseError
         node = treenode.TreeNode(self.currentParent,
                                  bookmarkSeparatorTypeName, self.model)
         node.setUniqueId(True)
         self.currentParent.childList.append(node)
         self.currentNode = None
Example #18
0
    def handle_starttag(self, tag, attrs):
        """Called by the reader at each open tag.

        Arguments:
            tag -- the tag label
            attrs -- any tag attributes
        """
        if tag == 'dt' or tag == 'h1':  # start any entry
            self.text = ''
        elif tag == 'dl':  # start indent
            self.parents.append(self.currentNode)
            self.currentNode = None
        elif tag == 'h3':  # start folder
            if not self.parents:
                raise ValueError
            self.currentNode = treenode.TreeNode(
                self.structure.treeFormats[bookmarkFolderTypeName])
            self.structure.addNodeDictRef(self.currentNode)
            self.parents[-1].childList.append(self.currentNode)
        elif tag == 'a':  # start link
            if not self.parents:
                raise ValueError
            self.currentNode = treenode.TreeNode(
                self.structure.treeFormats[bookmarkLinkTypeName])
            self.structure.addNodeDictRef(self.currentNode)
            self.parents[-1].childList.append(self.currentNode)
            for name, value in attrs:
                if name == 'href':
                    link = '<a href="{0}">{0}</a>'.format(value)
                    self.currentNode.data[bookmarkLinkFieldName] = link
        elif tag == 'hr':  # separator
            if not self.parents:
                raise ValueError
            node = treenode.TreeNode(
                self.structure.treeFormats[bookmarkSeparatorTypeName])
            self.structure.addNodeDictRef(node)
            self.parents[-1].childList.append(node)
            self.currentNode = None
Example #19
0
    def __init__(self, model):
        """Initialize the HTML parser object.

        Arguments:
            model -- a reference to the tree model
        """
        super().__init__()
        self.model = model
        self.model.root = treenode.TreeNode(None, bookmarkFolderTypeName,
                                            self.model)
        self.model.root.data[nodeformat.defaultFieldName] = _('Bookmarks')
        self.currentNode = self.model.root
        self.currentParent = None
        self.text = ''
Example #20
0
    def importTableCsvLevels(self):
        """Import a CSV-delimited table file with level column, header row.

        Return the structure if import is successful, otherwise None.
        """
        structure = treestructure.TreeStructure(addSpots=False)
        tableFormat = nodeformat.NodeFormat(_('TABLE'), structure.treeFormats)
        structure.treeFormats.addTypeIfMissing(tableFormat)
        nodeList = []
        with self.pathObj.open(newline='',
                               encoding=globalref.localTextEncoding) as f:
            reader = csv.reader(f)
            try:
                headings = [
                    self.correctFieldName(name) for name in next(reader)
                ][1:]
                tableFormat.addFieldList(headings, True, True)
                for entries in reader:
                    if entries:
                        node = treenode.TreeNode(tableFormat)
                        structure.addNodeDictRef(node)
                        try:
                            level = int(entries.pop(0))
                        except ValueError:
                            self.errorMessage = (_('Invalid level number on '
                                                   'line {0}').format(
                                                       reader.line_num))
                            return None  # abort
                        nodeList.append((node, level))
                        try:
                            for heading in headings:
                                node.data[heading] = entries.pop(0)
                        except IndexError:
                            pass  # fewer entries than headings is OK
                        if entries:
                            self.errorMessage = (_('Too many entries on '
                                                   'Line {0}').format(
                                                       reader.line_num))
                            return None  # abort if too few headings
            except csv.Error:
                self.errorMessage = (_('Bad CSV format on Line {0}').format(
                    reader.line_num))
                return None  # abort
        if nodeList:
            if structure.loadChildNodeLevels(nodeList):
                structure.generateSpots(None)
                return structure
            self.errorMessage = (_('Invalid level structure'))
        return None
Example #21
0
    def importTreePad(self):
        """Import a Treepad file, text nodes only.

        Return the model if import is successful, otherwise None.
        """
        structure = treestructure.TreeStructure(addDefaults=True,
                                                addSpots=False)
        structure.removeNodeDictRef(structure.childList[0])
        structure.childList = []
        tpFormat = structure.treeFormats[treeformats.defaultTypeName]
        tpFormat.addFieldList([textFieldName], False, True)
        tpFormat.fieldDict[textFieldName].changeType('SpacedText')
        try:
            with self.pathObj.open(encoding=globalref.localTextEncoding) as f:
                textList = f.read().split('<end node> 5P9i0s8y19Z')
        except UnicodeDecodeError:
            with self.pathObj.open(encoding='latin-1') as f:
                textList = f.read().split('<end node> 5P9i0s8y19Z')
        except UnicodeDecodeError:
            return None
        nodeList = []
        for text in textList:
            text = text.strip()
            if text:
                try:
                    text = text.split('<node>', 1)[1].lstrip()
                    lines = text.split('\n')
                    title = lines[0]
                    level = int(lines[1])
                    lines = lines[2:]
                except (ValueError, IndexError):
                    return None
                node = treenode.TreeNode(tpFormat)
                node.data[nodeformat.defaultFieldName] = title
                node.data[textFieldName] = '\n'.join(lines)
                node.level = level
                nodeList.append(node)
                structure.addNodeDictRef(node)
        parentList = []
        for node in nodeList:
            if node.level != 0:
                parentList = parentList[:node.level]
                node.parent = parentList[-1]
                parentList[-1].childList.append(node)
            parentList.append(node)
        structure.childList = [nodeList[0]]
        structure.generateSpots(None)
        return structure
Example #22
0
    def __init__(self, structure):
        """Initialize the HTML parser object.

        Arguments:
            structure -- a reference to the tree structure
        """
        super().__init__()
        self.structure = structure
        rootNode = treenode.TreeNode(
            self.structure.treeFormats[bookmarkFolderTypeName])
        rootNode.data[nodeformat.defaultFieldName] = _('Bookmarks')
        self.structure.addNodeDictRef(rootNode)
        self.structure.childList = [rootNode]
        self.currentNode = rootNode
        self.parents = []
        self.text = ''
Example #23
0
    def importTextLines(self):
        """Import a text file, creating one node per line.

        Return the model if import is successful, otherwise None.
        """
        model = treemodel.TreeModel(True)
        with open(self.filePath, 'r',
                  encoding=globalref.localTextEncoding) as f:
            for line in f:
                line = line.strip()
                if line:
                    node = treenode.TreeNode(model.root, model.root.formatName,
                                             model)
                    model.root.childList.append(node)
                    node.data[nodeformat.defaultFieldName] = line
                    node.setUniqueId(True)
        return model
Example #24
0
    def exportHtmlPages(self, filePath=''):
        """Export multiple web pages with navigation, use ExportDialog options.

        Prompt user for path if not given in argument.
        Return True on successful export.
        Arguments:
            filePath -- use if given, otherwise prompt user
        """
        if not filePath:
            filePath = QtGui.QFileDialog.getExistingDirectory(
                QtGui.QApplication.activeWindow(), _('TreeLine - Export HTML'),
                self.defaultFilePath)
            if not filePath:
                return False
        QtGui.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor)
        oldDir = os.getcwd()
        os.chdir(filePath)
        indent = globalref.genOptions.getValue('IndentOffset')
        cssLines = [
            '#sidebar {', '   width: 16em;', '   float: left;',
            '   border-right: 1px solid black;', '}',
            '#sidebar div {{margin-left: {0}em;}}'.format(indent),
            '#content {', '   margin-left: 16em;',
            '   border-left: 1px solid black;', '   padding-left: 6px;', '}'
        ]
        with open('default.css', 'w', encoding='utf-8') as f:
            f.writelines([(line + '\n') for line in cssLines])
        if ExportDialog.exportWhat == ExportDialog.entireTree:
            self.selectedNodes = [self.rootNode]
        if len(self.selectedNodes) > 1:
            modelRef = self.selectedNodes[0].modelRef
            dummyFormat = modelRef.formats.addDummyRootType()
            root = treenode.TreeNode(None, dummyFormat.name, modelRef)
            name = os.path.basename(self.defaultFilePath)
            if not name:
                name = treemodel.defaultRootName
            root.setTitle(name)
            for node in self.selectedNodes:
                root.childList.append(copy.copy(node))
                root.childList[-1].parent = root
        else:
            root = self.selectedNodes[0]
        root.exportHtmlPage()
        root.modelRef.formats.removeDummyRootType()
        os.chdir(oldDir)
        return True
Example #25
0
    def importTextPara(self):
        """Import a text file, creating one node per paragraph.

        Blank line delimited.
        Return the model if import is successful, otherwise None.
        """
        model = treemodel.TreeModel(True)
        with open(self.filePath, 'r',
                  encoding=globalref.localTextEncoding) as f:
            text = f.read()
        paraList = text.split('\n\n')
        for para in paraList:
            para = para.strip()
            if para:
                node = treenode.TreeNode(model.root, model.root.formatName,
                                         model)
                model.root.childList.append(node)
                node.data[nodeformat.defaultFieldName] = para
                node.setUniqueId(True)
        return model
Example #26
0
    def importTextLines(self):
        """Import a text file, creating one node per line.

        Return the structure if import is successful, otherwise None.
        """
        structure = treestructure.TreeStructure(addDefaults=True,
                                                addSpots=False)
        nodeFormat = structure.childList[0].formatRef
        structure.removeNodeDictRef(structure.childList[0])
        structure.childList = []
        with self.pathObj.open(encoding=globalref.localTextEncoding) as f:
            for line in f:
                line = line.strip()
                if line:
                    node = treenode.TreeNode(nodeFormat)
                    structure.childList.append(node)
                    structure.addNodeDictRef(node)
                    node.data[nodeformat.defaultFieldName] = line
        structure.generateSpots(None)
        return structure
Example #27
0
 def loadNode(self, element, parent=None):
     """Recursively load an ElementTree node and its children.
     
     Arguments:
         element -- an ElementTree node
         parent  -- the parent TreeNode (None for the root node only)
     """
     try:
         typeFormat = self.model.formats[element.tag]
     except KeyError:
         typeFormat = nodeformat.NodeFormat(element.tag, self.model.formats,
                                            element.attrib)
         self.model.formats[element.tag] = typeFormat
     if element.get('item') == 'y':
         node = treenode.TreeNode(parent, element.tag, self.model,
                                  element.attrib)
         if parent:
             parent.childList.append(node)
         else:
             self.model.root = node
     else:     # bare format (no nodes)
         node = None
     for child in element:
         if child.get('item') and node:
             self.loadNode(child, node)
         else:
             if node and child.text:
                 node.data[child.tag] = child.text
                 if child.get('linkcount'):
                     self.model.linkRefCollect.searchForLinks(node,
                                                              child.tag)
             typeFormat.addFieldIfNew(child.tag, child.attrib)
     if node and typeFormat.fieldDict:
         try:
             node.setUniqueId()
         except ValueError:
             oldId = node.uniqueId
             node.setUniqueId(True)
             self.duplicateIdList.append('{0} -> {1}'.format(oldId,
                                                             node.uniqueId))
Example #28
0
    def importTreePad(self):
        """Import a Treepad file, text nodes only.

        Return the model if import is successful, otherwise None.
        """
        model = treemodel.TreeModel(True)
        tpFormat = model.formats[treeformats.defaultTypeName]
        tpFormat.addFieldList([textFieldName], False, True)
        tpFormat.fieldDict[textFieldName].changeType('SpacedText')
        with open(self.filePath, 'r',
                  encoding=globalref.localTextEncoding) as f:
            textList = f.read().split('<end node> 5P9i0s8y19Z')
        nodeList = []
        for text in textList:
            text = text.strip()
            if text:
                try:
                    text = text.split('<node>', 1)[1].lstrip()
                    lines = text.split('\n')
                    title = lines[0]
                    level = int(lines[1])
                    lines = lines[2:]
                except (ValueError, IndexError):
                    return None
                node = treenode.TreeNode(None, tpFormat.name, model)
                node.data[nodeformat.defaultFieldName] = title
                node.data[textFieldName] = '\n'.join(lines)
                node.level = level
                node.setUniqueId(True)
                nodeList.append(node)
        parentList = []
        for node in nodeList:
            if node.level != 0:
                parentList = parentList[:node.level]
                node.parent = parentList[-1]
                parentList[-1].childList.append(node)
            parentList.append(node)
        model.root = nodeList[0]
        return model
Example #29
0
    def importTableCsv(self):
        """Import a file with a CSV-delimited table with header row.

        Return the structure if import is successful, otherwise None.
        """
        structure = treestructure.TreeStructure(addDefaults=True,
                                                addSpots=False)
        tableFormat = nodeformat.NodeFormat(_('TABLE'), structure.treeFormats)
        structure.treeFormats.addTypeIfMissing(tableFormat)
        with self.pathObj.open(newline='',
                               encoding=globalref.localTextEncoding) as f:
            reader = csv.reader(f)
            try:
                headings = [
                    self.correctFieldName(name) for name in next(reader)
                ]
                tableFormat.addFieldList(headings, True, True)
                for entries in reader:
                    if entries:
                        node = treenode.TreeNode(tableFormat)
                        structure.childList[0].childList.append(node)
                        structure.addNodeDictRef(node)
                        try:
                            for heading in headings:
                                node.data[heading] = entries.pop(0)
                        except IndexError:
                            pass  # fewer entries than headings is OK
                        if entries:
                            self.errorMessage = (_('Too many entries on '
                                                   'Line {0}').format(
                                                       reader.line_num))
                            return None  # abort if too few headings
            except csv.Error:
                self.errorMessage = (_('Bad CSV format on Line {0}').format(
                    reader.line_num))
                return None  # abort
        structure.generateSpots(None)
        return structure
Example #30
0
    def exportXmlSubtree(self, filePath=''):
        """Export TreeLine subtree, use ExportDialog options.

        Prompt user for path if not given in argument.
        Return True on successful export.
        Arguments:
            filePath -- use if given, otherwise prompt user
        """
        if not filePath:
            filePath = self.getFileName(
                _('TreeLine - Export TreeLine '
                  'Subtree'), 'trl')
            if not filePath:
                return False
        QtGui.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor)
        if ExportDialog.exportWhat == ExportDialog.entireTree:
            self.selectedNodes = [self.rootNode]
        addBranches = ExportDialog.exportWhat != ExportDialog.selectNode
        if len(self.selectedNodes) > 1:
            modelRef = self.selectedNodes[0].modelRef
            dummyFormat = modelRef.formats.addDummyRootType()
            root = treenode.TreeNode(None, dummyFormat.name, modelRef)
            name = os.path.basename(self.defaultFilePath)
            if not name:
                name = treemodel.defaultRootName
            root.setTitle(name)
            for node in self.selectedNodes:
                root.childList.append(copy.copy(node))
                root.childList[-1].parent = root
        else:
            root = self.selectedNodes[0]
        rootElement = root.elementXml(addChildren=addBranches)
        rootElement.attrib.update(
            globalref.mainControl.activeControl.printData.xmlAttr())
        elementTree = ElementTree.ElementTree(rootElement)
        elementTree.write(filePath, 'utf-8', True)
        root.modelRef.formats.removeDummyRootType()
        return True