from ..Qt import QtWidgets, QtCore class ExpandableWidget(QtWidgets.QWidget): expansionChanged = QtCore.pyqtSignal() def __init__(self, parent=None): super().__init__(parent=parent) self._init_ui() self._widget = None self._expanded = False self.toolButton.clicked.connect(self.changeVisibility) def _init_ui(self): self.verticalLayout = QtWidgets.QVBoxLayout(self) self.verticalLayout.setContentsMargins(0, 0, 0, 0) self.verticalLayout.setSpacing(0) self.horizontalLayout = QtWidgets.QHBoxLayout() self.horizontalLayout.setSpacing(0) self.toolButton = QtWidgets.QToolButton(self) self.toolButton.setArrowType(QtCore.Qt.RightArrow) self.toolButton.setStyleSheet('border: 0') self.toolButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) self.horizontalLayout.addWidget(self.toolButton) self.line = QtWidgets.QFrame(self) self.line.setFrameShape(QtWidgets.QFrame.HLine) self.horizontalLayout.addWidget(self.line) self.verticalLayout.addLayout(self.horizontalLayout) def addWidget(self, widget: QtWidgets.QWidget): self._widget = widget self._widget.setVisible(self._expanded) self.layout().addWidget(widget) def setText(self, text: str): self.toolButton.setText(text) def isExpanded(self): return self._expanded def changeVisibility(self): if not self._widget: return self.setExpansion(not self._expanded) self.expansionChanged.emit() def setExpansion(self, state: bool): self.blockSignals(True) if state: self.toolButton.setArrowType(QtCore.Qt.DownArrow) else: self.toolButton.setArrowType(QtCore.Qt.RightArrow) self._expanded = state if self._widget is not None: self._widget.setVisible(state) self.blockSignals(False)