class CodecTab(QScrollArea): # BUG: codec_frame should have height 210 but has 480. # WORKAROUND: manually set height to 210 height. # SEE: https://forum.qt.io/topic/42055/qwidget-height-returns-incorrect-value-in-5-3/7 FRAME_HEIGHT = 210 def __init__(self, parent, context, commands): super(QWidget, self).__init__(parent) self._context = context self._logger = context.logger() self._commands = commands self._next_frame_id = 1 self._frames = QSplitter(Qt.Vertical) self._frames.setChildrenCollapsible(False) self._frames.setSizePolicy( QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)) self._frames.setContentsMargins(0, 0, 0, 0) self._main_frame = QFrame(self) self._main_frame_layout = QVBoxLayout() self._main_frame_layout.addWidget(self._frames) self._main_frame_layout.addWidget(VSpacer(self)) self._main_frame.setLayout(self._main_frame_layout) self.newFrame("", "") self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.setWidgetResizable(True) self.setWidget(self._main_frame) def newFrame(self, text, title, previous_frame=None, status=None, msg=None): try: # BUG: Setting complex default values is not possible in python # WORKAROUND: Set default value to None and set real default later. if status is None: status = StatusWidget.DEFAULT if previous_frame and previous_frame.hasNext(): next_frame = previous_frame.next() next_frame.setTitle(title) finished = False if status == StatusWidget.ERROR: while not finished: next_frame.flashStatus(status, msg) # Display error only for the first frame. msg = None finished = not next_frame.hasNext() next_frame = next_frame.next() else: next_frame.setInputText(text, msg is not None and len(msg) > 0) next_frame.flashStatus(status, msg) previous_frame.focusInputText() else: new_frame = CodecFrame(self, self._context, self._next_frame_id, self, self._commands, previous_frame, text) self._next_frame_id += 1 if self._frames.count() > 0: new_frame.flashStatus(status, msg) new_frame.setTitle(title) new_frame.setContentsMargins(0, 0, 0, 0) new_frame.layout().setContentsMargins(0, 0, 0, 0) self._frames.addWidget(new_frame) # BUG: QSplitter does not allow frames to be wider than the surrounding area (here: QScrollArea). # WORKAROUND: Set a fixed size for codec frames and disable handles which prevents users from # trying to resize the codec frames. new_frame.setFixedHeight(self.FRAME_HEIGHT) self._frames.handle(self._frames.count() - 1).setEnabled(False) if previous_frame: previous_frame.focusInputText() else: new_frame.focusInputText() except Exception as e: self._logger.error("Unknown error: {}".format(str(e))) def removeFrames(self, frame): if frame: if frame.previous(): frame.previous().setNext(None) frames_to_remove = [frame] while frame.next(): frames_to_remove.append(frame.next()) frame = frame.next() for frame_to_remove in reversed(frames_to_remove): frame_to_remove.deleteLater() def getFocussedFrame(self): widget = self._frames.focusWidget() while widget: if isinstance(widget, CodecFrame): return widget widget = widget.parent() return self._frames.widget(0)