ColinKennedy
ColinKennedy

Reputation: 998

Make a graph of Qt widgets that extend outside its parent window

I'm trying to create a basic Qt solution for the image below:

enter image description here

(At the bottom of the post, I've included a nested dict that could be used to generate the widget-graph, if anyone would like to use it)

Basically, I need some kind of widget / tree of widgets that can ...

At first I thought maybe a QTreeWidget or QTreeView could do this but I could not get those classes to extend outside of the main window like shown.

I also tried messing around with QMenu and QMenuBar and then QMenu widgets inside a QListWidget. None of those produced good results. But I could have been creating those incorrectly.

Here is some data that I would need to display in Qt:

[
    {
        'name': 'foo',
        'dependencies': [
            {
                'name': 'bar',
                'dependencies': [],
            },
            {
                'name': 'when',
                'dependencies': [
                    {
                        'name': 'subitem',
                        'dependencies': [],
                    },
                    {
                        'name': 'will',
                        'dependencies': [
                            {
                                'name': 'it',
                                'dependencies': [
                                    {
                                        'name': 'end',
                                        'dependencies': [],
                                        'version': 8,
                                        'latest': 10,
                                    },
                                ],
                            },
                        ],
                    },
                    {
                        'name': 'another',
                        'dependencies': [],
                    },
                ],
            },
            {
                'name': 'thing',
                'dependencies': [],
            },
        ],
    },
    {
        'name': 'some_other_thing',
        'dependencies': [],
    },
    {
        'name': 'an_asset_with_data',
        'dependencies': [],
    },
    {
        'name': 'more_things',
        'dependencies': [],
    },
]

Any help would be appreciated.

Upvotes: 1

Views: 230

Answers (1)

eyllanesc
eyllanesc

Reputation: 243887

The solution I propose is using QListWidget with a QMenu.

import sys

from PyQt4.QtCore import Qt
from PyQt4.QtGui import QApplication, QListWidget, QListWidgetItem, QMenu


class MenuWidget(QListWidget):
    DependenciesRole = Qt.UserRole

    def __init__(self, items, parent=None):
        QListWidget.__init__(self, parent)
        for it in items:
            name = it["name"]
            dependencies = it["dependencies"]
            it = QListWidgetItem(name)
            self.addItem(it)
            it.setData(MenuWidget.DependenciesRole, dependencies)

    def mousePressEvent(self, event):
        QListWidget.mousePressEvent(self, event)
        it = self.itemAt(event.pos())
        if it is not None:
            dependencies = it.data(MenuWidget.DependenciesRole)
            if dependencies:
                menu = QMenu(self)
                MenuWidget.add_submenu(menu, dependencies)
                p = self.visualRect(self.indexAt(event.pos())).topRight()
                menu.popup(self.mapToGlobal(p))

    @staticmethod
    def add_submenu(menu, items):
        for it in items:
            name = it["name"]
            dependencies = it["dependencies"]
            if dependencies:
                mn = menu.addMenu(name)
                MenuWidget.add_submenu(mn, dependencies)
            else:
                menu.addAction(name)


d = [
    {
        'name': 'foo',
        'dependencies': [
            {
                'name': 'bar',
                'dependencies': [],
            },
            {
                'name': 'when',
                'dependencies': [
                    {
                        'name': 'subitem',
                        'dependencies': [],
                    },
                    {
                        'name': 'will',
                        'dependencies': [
                            {
                                'name': 'it',
                                'dependencies': [
                                    {
                                        'name': 'end',
                                        'dependencies': [],
                                        'version': 8,
                                        'latest': 10,
                                    },
                                ],
                            },
                        ],
                    },
                    {
                        'name': 'another',
                        'dependencies': [],
                    },
                ],
            },
            {
                'name': 'thing',
                'dependencies': [],
            },
        ],
    },
    {
        'name': 'some_other_thing',
        'dependencies': [],
    },
    {
        'name': 'an_asset_with_data',
        'dependencies': [],
    },
    {
        'name': 'more_things',
        'dependencies': [],
    },
]

if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = MenuWidget(d)
    w.show()
    sys.exit(app.exec_())

enter image description here

Upvotes: 1

Related Questions