示例#1
0
 def __reload_nodes(self, node: QTreeWidgetItem, _: int):
     """Mark edited node as unsaved."""
     name = node.text(0)
     code = int(node.text(2))
     if name.startswith('@'):
         self.__add_macro(name[1:], code)
     self.__root_unsaved()
示例#2
0
 def new_pointer(node: QTreeWidgetItem):
     """Give a new pointer code for node."""
     code = self.data.new_num()
     self.data[code] = self.data[int(node.text(2))]
     node.setText(2, str(code))
     for i in range(node.childCount()):
         new_pointer(node.child(i))
示例#3
0
def getpath(node: QTreeWidgetItem) -> str:
    """Get the path of current node."""
    parent = node.parent()
    file_name = node.text(1)
    if parent:
        return QFileInfo(QDir(
            node_getpath(parent)).filePath(file_name)).absoluteFilePath()
    return file_name
示例#4
0
def node_getpath(node: QTreeWidgetItem) -> str:
    """Recursive return the path of the node."""
    path = node.text(1)
    parent = node.parent()
    if parent is None:
        if file_suffix(path) == 'kmol':
            return QFileInfo(path).absolutePath()
        else:
            return path
    return QDir(node_getpath(parent)).filePath(path)
示例#5
0
 def __delete_node_data(self, node: QTreeWidgetItem):
     """Delete data from data structure."""
     name = node.text(0)
     if name.startswith('@'):
         for action in self.macros_toolbar.actions():
             if action.text() == name[1:]:
                 self.macros_toolbar.removeAction(action)
     del self.data[int(node.text(2))]
     for i in range(node.childCount()):
         self.__delete_node_data(node.child(i))
示例#6
0
 def find_in_nodes(node: QTreeWidgetItem, last_name: str = ''):
     """Find the word in all nodes."""
     last_name += node.text(0)
     if node.childCount():
         last_name += '->'
     code = int(node.text(2))
     doc = self.data[code]
     pattern = re.compile(text, flags)
     for m in pattern.finditer(doc):
         add_find_result(code, last_name, *m.span())
     for i in range(node.childCount()):
         find_in_nodes(node.child(i), last_name)
示例#7
0
def _get_root(node: QTreeWidgetItem) -> QTreeWidgetItem:
    """Return the top-level parent if exist."""
    parent = node.parent()
    if parent is not None:
        return _get_root(parent)
    else:
        return node
示例#8
0
 def find_in_nodes(node: QTreeWidgetItem, last_name: str = ''):
     """Find the word in all nodes."""
     last_name += node.text(0)
     if node.childCount():
         last_name += '->'
     code = int(node.text(2))
     doc = self.data[code]
     pattern = re.compile(text.encode('utf-8'), flags)
     for m in pattern.finditer(doc.encode('utf-8')):
         start, end = m.span()
         item = QListWidgetItem(last_name)
         item.setToolTip(f"{code}:{start}:{end}")
         self.find_list_node[code] = node
         self.find_list.addItem(item)
     for i in range(node.childCount()):
         find_in_nodes(node.child(i), last_name)
示例#9
0
def _write_tree(proj_name: str, root_node: QTreeWidgetItem, data: DataDict):
    """Write to YAML file."""
    yml_data: YMLData = {}
    my_codes: List[int] = []

    def add_node(node: QTreeWidgetItem) -> NodeDict:
        code_int = int(node.text(2))
        node_dict: NodeDict = {
            'code': code_int,
            'name': node.text(0),
            'path': node.text(1),
            'sub': [],
        }
        if file_suffix(node.text(1)) not in _SUPPORTED_FILE_SUFFIX:
            my_codes.append(code_int)
        if QFileInfo(QDir(node_getpath(node.parent())).filePath(node.text(1))).isFile():
            # Files do not need to make a copy.
            return node_dict
        for j in range(node.childCount()):
            node_dict['sub'].append(add_node(node.child(j)))
        return node_dict

    root_code = int(root_node.text(2))
    yml_data['description'] = root_code

    yml_data['node'] = []
    for i in range(root_node.childCount()):
        yml_data['node'].append(add_node(root_node.child(i)))

    yml_data['data'] = {root_code: _LiteralDoc(data[root_code]) or ''}
    for code in my_codes:
        yml_data['data'][code] = _LiteralDoc(data[code]) or ''

    data.save_all()

    yml_str = (
        f"# Generated by Kmol editor {__version__}\n\n" +
        yaml.dump(yml_data, default_flow_style=False)
    )
    with open(proj_name, 'w', encoding='utf-8') as f:
        f.write(yml_str)

    print("Saved: {}".format(proj_name))
示例#10
0
def _parse_tree(root_node: QTreeWidgetItem, data: DataDict):
    """Parse in to tree widget."""
    try:
        with open(root_node.text(1), encoding='utf-8') as f:
            yaml_script = f.read()
    except FileNotFoundError:
        return

    yml_data: YMLData = yaml.load(yaml_script, Loader=yaml.FullLoader)
    parse_list: List[QTreeWidgetItem] = []

    root_node.setText(2, str(yml_data['description']))
    data.update(yml_data['data'])

    def add_node(node_dict: NodeDict) -> QTreeWidgetItem:
        """Add node in to tree widget."""
        name: str = node_dict['name']
        code_int: int = node_dict['code']
        path: str = node_dict['path']
        node = QTreeItem(name, path, str(code_int))
        if name.startswith('@'):
            node.setIcon(0, file_icon("python"))
            data.add_macro(name[1:], code_int)
        suffix_text = file_suffix(path)
        if suffix_text:
            parse_list.append(node)
        elif path:
            node.setIcon(0, file_icon("directory"))
        subs: List[NodeDict] = node_dict['sub']
        for sub in subs:
            node.addChild(add_node(sub))
        return node

    child_node_dicts: List[NodeDict] = yml_data['node']
    for child_node_dict in child_node_dicts:
        root_node.addChild(add_node(child_node_dict))

    for node_item in parse_list:
        parse(node_item, data)

    data.save_all()
示例#11
0
    def __switch_data(self, current: QTreeWidgetItem,
                      previous: QTreeWidgetItem):
        """Switch node function.

        + Auto collapse and expand function.
        + Important: Store the string data.
        """
        if self.auto_expand_option.isChecked():
            self.tree_main.expandItem(current)
        self.tree_main.scrollToItem(current)

        bar: QScrollBar = self.text_editor.verticalScrollBar()
        if previous:
            key = int(previous.text(2))
            self.data[key] = self.text_editor.text()
            self.data.set_pos(key, bar.value())
        if current:
            # Auto highlight.
            path = current.text(1)
            file_name = QFileInfo(path).fileName()
            suffix = QFileInfo(file_name).suffix()
            if current.text(0).startswith('@'):
                self.highlighter_option.setCurrentText("Python")
            else:
                self.highlighter_option.setCurrentText("Markdown")
            if path:
                for name_m, suffix_m in HIGHLIGHTER_SUFFIX.items():
                    if suffix in suffix_m:
                        self.highlighter_option.setCurrentText(name_m)
                        break
                else:
                    for name_m, filename_m in HIGHLIGHTER_FILENAME.items():
                        if file_name in filename_m:
                            self.highlighter_option.setCurrentText(name_m)
                            break
            key = int(current.text(2))
            self.text_editor.setText(self.data[key])
            bar.setValue(self.data.pos(key))

        self.reload_html_viewer()
        self.__action_changed()
示例#12
0
 def add_node(node_dict: NodeDict) -> QTreeWidgetItem:
     """Add node in to tree widget."""
     name: str = node_dict['name']
     code_int: int = node_dict['code']
     path: str = node_dict['path']
     node = QTreeWidgetItem([name, path, str(code_int)])
     if name.startswith('@'):
         node.setIcon(0, file_icon("python"))
         data.add_macro(name[1:], code_int)
     suffix_text = file_suffix(path)
     if suffix_text:
         parse_list.append(node)
     elif path:
         node.setIcon(0, file_icon("directory"))
     subs: List[NodeDict] = node_dict['sub']
     for sub in subs:
         node.addChild(add_node(sub))
     return node
示例#13
0
 def add_node(node: QTreeWidgetItem) -> NodeDict:
     code_int = int(node.text(2))
     node_dict: NodeDict = {
         'code': code_int,
         'name': node.text(0),
         'path': node.text(1),
         'sub': [],
     }
     if file_suffix(node.text(1)) not in _SUPPORTED_FILE_SUFFIX:
         my_codes.append(code_int)
     if QFileInfo(QDir(node_getpath(node.parent())).filePath(node.text(1))).isFile():
         # Files do not need to make a copy.
         return node_dict
     for j in range(node.childCount()):
         node_dict['sub'].append(add_node(node.child(j)))
     return node_dict
示例#14
0
def save_file(node: QTreeWidgetItem, data: DataDict) -> Tuple[str, bool]:
    """Recursive to all the contents of nodes."""
    text_data = []
    all_saved = data.is_saved(int(node.text(2)))
    for i in range(node.childCount()):
        doc, saved = save_file(node.child(i), data)
        text_data.append(doc)
        all_saved &= saved
    my_content = data[int(node.text(2))].splitlines()
    for i in range(len(my_content)):
        content_text = my_content[i]
        if content_text.endswith("@others"):
            preffix = content_text[:-len("@others")]
            my_content[i] = '\n\n'.join(preffix + t for t in text_data)
    my_content = '\n'.join(my_content)
    path_text = QFileInfo(node.text(1)).fileName()
    if path_text and not all_saved:
        suffix_text = QFileInfo(path_text).suffix()
        if suffix_text == 'kmol':
            # Save project.
            _write_tree(node.text(1), node, data)
        else:
            # File path.
            file_path = QDir(QFileInfo(node_getpath(node)).absolutePath())
            if not file_path.exists():
                file_path.mkpath('.')
                print("Create Folder: {}".format(file_path.absolutePath()))
            file_name = file_path.filePath(path_text)

            if suffix_text in _SUPPORTED_FILE_SUFFIX:
                # Add end new line.
                if my_content and (my_content[-1] != '\n'):
                    my_content += '\n'
                try:
                    with open(file_name, 'w', encoding='utf-8') as f:
                        f.write(my_content)
                except UnicodeError:
                    print(f"Unicode Error in: {file_name}")
                else:
                    print(f"Saved: {file_name}")
            elif suffix_text:
                print(f"Ignore file: {file_name}")

    return my_content, all_saved
示例#15
0
def _expand_recursive(node: QTreeWidgetItem):
    """Expand node and its children."""
    node.setExpanded(True)
    for i in range(node.childCount()):
        _expand_recursive(node.child(i))
示例#16
0
def _grand_parent(node: QTreeWidgetItem) -> QTreeWidgetItem:
    """Return the grand parent if exist."""
    parent = node.parent()
    return (parent.parent() if parent else node.treeWidget()) or node.treeWidget()
示例#17
0
def _get_root(node: QTreeWidgetItem) -> QTreeWidgetItem:
    """Return the top-level parent if exist."""
    parent = node.parent()
    return _get_root(parent) if parent else node
示例#18
0
 def expand(node: QTreeWidgetItem, level: int):
     not_target = level != target_level
     node.setExpanded(not_target)
     if not_target:
         for i in range(node.childCount()):
             expand(node.child(i), level + 1)
示例#19
0
def parse(node: QTreeWidgetItem, data: DataDict):
    """Parse file to tree format."""
    node.takeChildren()
    file_name = getpath(node)
    suffix_text = file_suffix(file_name)
    if node.text(2):
        code = int(node.text(2))
    else:
        code = data.new_num()
        node.setText(2, str(code))
    if node not in LOADED_FILES and suffix_text in _SUPPORTED_FILE_SUFFIX:
        LOADED_FILES.append(node)

    if suffix_text == 'md':
        # Markdown
        node.setIcon(0, file_icon("markdown"))
        parse_markdown(file_name, node, code, data)
    elif suffix_text == 'py':
        # Python script
        node.setIcon(0, file_icon("python"))
        parse_text(file_name, code, data)
    elif suffix_text == 'html':
        # TODO: Need to parse HTML (reveal.js index.html)
        node.setIcon(0, file_icon("html"))
        parse_text(file_name, code, data)
    elif suffix_text == 'kmol':
        # Kmol project
        node.setIcon(0, file_icon("kmol"))
        _parse_tree(node, data)
    else:
        # Text files and Python scripts.
        node.setIcon(0, file_icon("txt"))
        parse_text(file_name, code, data)
    print("Loaded: {}".format(node.text(1)))