class CollapsibleDialog(QDialog): """a dialog to which collapsible sections can be added; reimplement define_sections() to define sections and add them as (title, widget) tuples to self.sections reimplemented from http://www.fancyaddress.com/blog/qt-2/create-something-like-the-widget-box-as-in-the-qt-designer/ """ def __init__(self, parent = None): super().__init__(parent) self.tree = QTreeWidget() self.tree.setHeaderHidden(True) layout = QVBoxLayout() layout.addWidget(self.tree) self.setLayout(layout) self.tree.setIndentation(0) self.sections = [] self.section_dic = {} self.define_sections() self.add_sections() def add_sections(self): """adds a collapsible sections for every (title, widget) tuple in self.sections """ for (i, (title, widget)) in enumerate(self.sections): button = self.add_button(title) section = self.add_widget(button, widget) button.addChild(section) if i == 0: button.setExpanded(True) self.section_dic[i] = (button, section) def define_sections(self): """reimplement this to define all your sections and add them as (title, widget) tuples to self.sections """ widget = QFrame(self.tree) layout = QHBoxLayout(widget) layout.addWidget(QLabel("Bla")) layout.addWidget(QLabel("Blubb")) title = "Section 1" self.sections.append((title, widget)) def add_button(self, title): """creates a QTreeWidgetItem containing a button to expand or collapse its section """ item = QTreeWidgetItem() self.tree.addTopLevelItem(item) self.tree.setItemWidget(item, 0, SectionExpandButton(item, text = title)) return item def add_widget(self, button, widget): """creates a QWidgetItem containing the widget, as child of the button-QWidgetItem """ section = QTreeWidgetItem(button) section.setDisabled(True) self.tree.setItemWidget(section, 0, widget) return section @pyqtSlot(int, int) def proceed_sections(self, old_section, new_section): """collapses old section and expands next section """ (button_new, _) = self.section_dic[new_section] (button_old, _) = self.section_dic[old_section] button_new.setExpanded(True) button_old.setExpanded(False) try: self.sender().setChecked(False) # if sent from a button, un-press it except: pass