def __init__(self): super(PugdebugStatusBar, self).__init__() self.label = QLabel(self) self.light = QLabel(self) layout = QHBoxLayout() layout.addWidget(self.light) layout.addWidget(self.label) self.setLayout(layout) leftMargin, _, rightMargin, _ = layout.getContentsMargins() layout.setContentsMargins(leftMargin, 0, rightMargin, 0)
def __init__(self, parent: QWidget, message: str, func, *args, on_done: WaitingCompletionCallback = None, title: Optional[str] = None, watch_events: bool = False, progress_steps: int = 0, close_delay: int = 0, allow_cancel: bool = False) -> None: assert parent if title is None: title = _("Please wait") # Disable the window close button, not any one we add ourselves. super().__init__(parent, title) # If we do not do this, waiting dialogs get leaked. This can be observed by commenting # out this line and looking for the `__del__` call which should happen after this # dialog is closed. self.setAttribute(Qt.WA_DeleteOnClose) self._title = title self._base_message = message self._close_delay = close_delay self._main_label = QLabel() self._main_label.setAlignment(Qt.AlignCenter) self._main_label.setWordWrap(True) self._secondary_label = QLabel() self._secondary_label.setAlignment(Qt.AlignCenter) self._secondary_label.setWordWrap(True) self._progress_bar: Optional[QProgressBar] = None if progress_steps: progress_bar = self._progress_bar = QProgressBar() progress_bar.setRange(0, progress_steps) progress_bar.setValue(0) progress_bar.setOrientation(Qt.Horizontal) progress_bar.setMinimumWidth(250) # This explicitly needs to be done for the progress bar else it has some RHS space. progress_bar.setAlignment(Qt.AlignCenter) self.advance_progress_signal.connect(self._advance_progress) self._dismiss_button = QPushButton(_("Dismiss")) self._dismiss_button.clicked.connect(self.accept) self._dismiss_button.setEnabled(False) vbox = QVBoxLayout(self) vbox.addWidget(self._main_label) vbox.addWidget(self._secondary_label) if self._progress_bar is not None: vbox.addWidget(self._progress_bar) button_box_1 = QHBoxLayout() lm, tm, rm, bm = button_box_1.getContentsMargins() button_box_1.setContentsMargins(lm, tm + 10, rm, bm) button_box_1.addWidget(self._dismiss_button, False, Qt.AlignHCenter) vbox.addLayout(button_box_1) args = (*args, self._step_progress) # NOTE: The `on_done` callback runs in the GUI thread. self._on_done_callback = on_done self._future = app_state.app.run_in_thread(func, *args, on_done=self._on_run_done) self.accepted.connect(self._on_accepted) self.rejected.connect(self._on_rejected) self.update_message(_("Please wait.")) self.setMinimumSize(250, 100) self.show()
class CodecFrame(QFrame): def __init__(self, parent, context, frame_id, codec_tab, commands, previous_frame, text): super(CodecFrame, self).__init__(parent) self._context = context self._context.shortcutUpdated.connect(self._shortcut_updated_event) self._init_logger(context, frame_id) self._frame_id = frame_id self._codec_tab = codec_tab self._previous_frame = previous_frame if previous_frame: previous_frame.setNext(self) self._next_frame = None self._commands = commands self._flash_event = None self._layout = QHBoxLayout(self) self._status_widget = StatusWidget(self) input_frame = self._init_input_frame(text) button_frame = self._init_button_frame() self._group_box = QGroupBox() group_box_layout = QHBoxLayout() group_box_layout.addWidget(self._status_widget) group_box_layout.addWidget(input_frame) group_box_layout.addWidget(button_frame, 0, Qt.AlignTop) self._group_box.setLayout(group_box_layout) _, top, _, bottom = self._layout.getContentsMargins() self._layout.addWidget(self._group_box) self.setLayout(self._layout) """ Initializes the logger. Encapsulates logger-instance to enhance standard-logging with frame-id. """ def _init_logger(self, context, frame_id): self._logger = context.logger() # BUG: Using logging with custom field frame_id does not work correctly. # WORKAROUND: ??? #self._logger = context.logger(log_format="%(module)s: %(frame_id)d: %(lineno)d: %(msg)s",log_fields={'frame_id': frame_id}) def _init_input_frame(self, text): input_frame = QFrame() frame_layout = QVBoxLayout() self._plain_view_widget = PlainView(text) self._plain_view_widget.textChanged.connect(self._text_changed_event) self._plain_view_widget = self._plain_view_widget frame_layout.addWidget(self._plain_view_widget) frame_layout.setContentsMargins(0, 6, 6, 6) self._hex_view_widget = HexView(self, self._context, self._frame_id, self.getInputText()) self._hex_view_widget.textChanged.connect( self._hex_view_text_changed_event) self._hex_view_widget.setHidden(True) frame_layout.addWidget(self._hex_view_widget) input_frame.setLayout(frame_layout) return input_frame def _init_button_frame(self): button_frame = QFrame() button_frame_layout = QVBoxLayout() self._combo_box_frame = ComboBoxFrame(self, self._context) self._combo_box_frame.titleSelected.connect( self._combo_box_title_selected_event) self._combo_box_frame.commandSelected.connect( self._execute_command_select) button_frame_layout.addWidget(self._combo_box_frame) button_frame_layout.addWidget(self._init_radio_frame()) button_frame.setLayout(button_frame_layout) return button_frame def _init_radio_frame(self): radio_frame = QFrame() radio_frame_layout = QHBoxLayout() self._plain_radio = QRadioButton("Plain") self._plain_radio.setChecked(True) self._plain_radio.toggled.connect(self._view_radio_button_toggle_event) self._hex_radio = QRadioButton("Hex") self._hex_radio.toggled.connect(self._view_radio_button_toggle_event) radio_frame_layout.addWidget(self._plain_radio) radio_frame_layout.addWidget(self._hex_radio) radio_frame.setLayout(radio_frame_layout) return radio_frame def _shortcut_updated_event(self, shortcut): id = shortcut.id() tooltip = self._get_tooltip_by_shortcut(shortcut) if id == Context.Shortcut.FOCUS_DECODER: self._combo_box_frame.decoder().setToolTip(tooltip) elif id == Context.Shortcut.FOCUS_ENCODER: self._combo_box_frame.encoder().setToolTip(tooltip) elif id == Context.Shortcut.FOCUS_HASHER: self._combo_box_frame.hasher().setToolTip(tooltip) elif id == Context.Shortcut.FOCUS_SCRIPT: self._combo_box_frame.script().setToolTip(tooltip) elif id == Context.Shortcut.SELECT_PLAIN_VIEW: self._plain_radio.setToolTip(tooltip) elif id == Context.Shortcut.SELECT_HEX_VIEW: self._hex_radio.setToolTip(tooltip) else: return self._logger.debug( "Updated tooltip within codec-frame for {id} to {tooltip}".format( id=id, tooltip=tooltip)) def _update_tooltip(self, the_widget, the_shortcut_id): tooltip = self._get_tooltip_by_shortcut_id(the_shortcut_id) the_widget.setToolTip(tooltip) def _get_tooltip_by_shortcut_id(self, the_shortcut_id): shortcut = self._context.getShortcutById(the_shortcut_id) return self._get_tooltip_by_shortcut(shortcut) def _get_tooltip_by_shortcut(self, shortcut): return "{description} ({shortcut_key})".format( description=shortcut.name(), shortcut_key=shortcut.key()) def _combo_box_title_selected_event(self): self._codec_tab.removeFrames(self._next_frame) self.focusInputText() def _view_radio_button_toggle_event(self): self._plain_view_widget.setVisible(self._plain_radio.isChecked()) self._hex_view_widget.setVisible(self._hex_radio.isChecked()) # BUG: Performance Issue When Updating Multiple HexView-Frames During Input Text Changes # WORKAROUND: Do only update HexView when it's visible if self._hex_radio.isChecked(): input = self._plain_view_widget.toPlainText() self._hex_view_widget.blockSignals(True) self._hex_view_widget.setData(input) self._hex_view_widget.blockSignals(False) def _text_changed_event(self): # BUG: Performance Issue When Updating Multiple HexView-Frames When Input Text Changes # WORKAROUND: Do only update HexView when it's visible if self._hex_view_widget.isVisible(): input = self._plain_view_widget.toPlainText() self._hex_view_widget.blockSignals(True) self._hex_view_widget.setData(input) self._hex_view_widget.blockSignals(False) self._status_widget.setStatus("DEFAULT") self._execute() def _hex_view_text_changed_event(self, new_text): input = new_text self._plain_view_widget.blockSignals(True) self._plain_view_widget.setPlainText(input) self._plain_view_widget.blockSignals(False) self._status_widget.setStatus("DEFAULT") self._execute() def _execute(self): command = self._combo_box_frame.selectedCommand() if command: self._execute_command_run(command) def _execute_command_run(self, command): input = self.getInputText() output = "" try: output = command.run(input) self._codec_tab.newFrame(output, command.title(), self, status=StatusWidget.SUCCESS) except Exception as e: error = str(e) self._logger.error('{} {}: {}'.format(command.name(), command.type(), str(e))) self._codec_tab.newFrame(output, command.title(), self, status=StatusWidget.ERROR, msg=error) def _execute_command_select(self, command): output = "" try: input = self.getInputText() output = command.select(input) self._codec_tab.newFrame(output, command.title(), self, status=StatusWidget.SUCCESS) except AbortedException as e: # User aborted selection. This usually happens when a user clicks the cancel-button within a codec-dialog. self._logger.debug(str(e)) except Exception as e: error = str(e) self._logger.error('{} {}: {}'.format(command.name(), command.type(), error)) self._codec_tab.newFrame(output, command.title(), self, status=StatusWidget.ERROR, msg=error) def flashStatus(self, status, message): self._status_widget.setStatus(status, message) def selectComboBoxEntryByCommand(self, command): self._combo_box_frame.selectItem(command.type(), command.name(), block_signals=True) self._execute_command_run(command) def selectPlainView(self): self._plain_radio.setChecked(True) def selectHexView(self): self._hex_radio.setChecked(True) def toggleSearchField(self): self._plain_view_widget.toggleSearchField() def hasNext(self): return self._next_frame is not None def hasPrevious(self): return self._previous_frame is not None def setNext(self, next_frame): self._next_frame = next_frame def setPrevious(self, previous_frame): self._previous_frame = previous_frame def next(self): return self._next_frame def previous(self): return self._previous_frame def setTitle(self, title): self._group_box.setTitle(title) def setInputText(self, text, blockSignals=False): self._plain_view_widget.blockSignals(blockSignals) self._plain_view_widget.setPlainText(text) self._plain_view_widget.blockSignals(False) def getInputText(self): return self._plain_view_widget.toPlainText() def getComboBoxes(self): return self._combo_boxes def focusInputText(self): self._plain_view_widget.setFocus() def focusComboBox(self, type): self._combo_box_frame.focusType(type)