Home > Enterprise >  Converting a QTreeWidget to a nested dictionary in PyQt
Converting a QTreeWidget to a nested dictionary in PyQt

Time:11-01

The reason I want to do this is to allow the user to create a file tree using a QTreeWidget, then I want to extract that tree in to a nested dict structure, and save it some how. I've thought about using a txt file and eval aproach to simply load all the saved schemes into some array or just another dict where the key is the name of the scheme, so the user can then simply select a scheme or edit it if they wish. This naturally leads to me having to then convert that saved dict back into a QTreeWidget after the user has selected edit.

For now though here's my problem.

I've been able to successfully navigate the QTreeWidget using a recursive a function. What I struggle with is the logic behind creating the nested dict.

Below is what i have come up with so far:

def tree_to_dict(self, parent, key):
    for i in range(parent.childCount()):
        cur_par = parent.child(i)
        if cur_par.childCount() == 0:
            try:
                if type(self.scheme[key]) is dict :
                    self.scheme[key][cur_par.text(0)] = 'E'
            except KeyError:
                key = cur_par.text(0)
                self.scheme[key] = 'E'
        else:
            key = cur_par.text(0)
            self.scheme[key] = {}
            self.tree_to_dict(cur_par, key)

I know this is wrong. It's why I need help.

The above code generates the following dict form the following QTreeWidget

a
b
    a
c

{'a':'E', 'b':{'a':'E', 'c':'E'}}

But it should be:

{'a':'E', 'b':{'a':'E'}, 'c':'E'}

The E simply means that there will be no further subdirectories.

I've seen some other implementations of this but their horribly confusing and I don't quite get their logic. This is a near duplicate of the question I'm asking here, but it's yet to be answered. I've tried adapting his implementation but it's (to me anyway) convoluted and hard to fit into the structure of my program.

CodePudding user response:

Your implementation is probably too complex than required.

Since each item is the key, you need to iterate recursively and return the values for that key.

If the item has no children, it will return 'E', otherwise will it will call the function again with the given child, and so on.
The function doesn't need the key argument, as it will be created by the recursive call.

    def tree_to_dict(parent):
        childCount = parent.childCount()
        if not childCount:
            return 'E'
        content = {}
        for row in range(childCount):
            child = parent.child(row)
            content[child.text(0)] = tree_to_dict(child)
        return content

Then, just call the function using the invisibleRootItem().

  • Related