I could get it to work by first copying the folder structure, then inserting each files in the proper nest. The result is a dict, which is then converted into a QMenu/QAction structure with a resursive fonction. All items are stored in a set to survive the garbage collection.
Quote:# First loop:
{'collision': {}, 'sub1': {'sub2': {'collision': {}}}}
# Second loop:
{'collision': {'collision': '/home/user/.config/qtpad-vim/notes/collision/collision.txt'}, 'sub1': {'sub2': {'collision': {'action3': '/home/user/.config/qtpad-vim/notes/sub1/sub2/collision/action3.txt'}, 'action2': '/home/user/.config/qtpad-vim/notes/sub1/sub2/action2.txt'}, 'action1': '/home/user/.config/qtpad-vim/notes/sub1/action1.txt'}, 'lvl0 with spaces': '/home/user/.config/qtpad-vim/notes/lvl0 with spaces.txt'}
def _fill(self, current, dest): for part in current: if type(current[part]) is dict: item = QtWidgets.QMenu(part) dest.addMenu(item) self._fill(current=current[part], dest=item) else: item = QtWidgets.QAction(part, checkable=True) item.triggered.connect(lambda checked, path=current[part]: print(path)) dest.addAction(item) self.items.add(item) def refresh(self): folder = Path(CFG_DIR / "notes") dirs = [x for x in folder.rglob("*") if x.is_dir()] files = [x for x in folder.rglob("*.txt") if x.is_file()] struct = {} for path in dirs: folders = path.relative_to(CFG_DIR / "notes") folders = PurePath(folders).parts last = struct for f in folders: last.setdefault(f, {}) last = last[f] for path in files: folders = path.relative_to(CFG_DIR / "notes") folders = PurePath(folders).parts[:-1] last = struct for f in folders: last = last[f] last[path.stem] = str(path) self.clear() self.items = set() self._fill(struct, dest=self)If someone think of a better way I would still like to know :)