class ConsoleWidget(QWidget): def __init__(self, exc_info, parent=None): QWidget.__init__(self, parent) self.compiler = code.CommandCompiler() # for console self.tb = exc_info[2] self.entries = traceback.extract_tb(self.tb) self.console = QLineEdit() self.console.setPlaceholderText(">>> Python Console") self.console.returnPressed.connect(self.exec_console) self.console.setFont(QFont("Courier")) self.console_out = QTextEdit() self.console_out.setReadOnly(True) self.console_out.setFont(QFont("Courier")) self.console_out.setVisible(False) # initially hidden self.console_outs = [''] * len(self.entries) self.frame_vars = [None] * len(self.entries) l = QVBoxLayout() l.addWidget(self.console_out) l.addWidget(self.console) l.setContentsMargins(0, 0, 0, 0) self.setLayout(l) def go_to_frame(self, index): self.console_out.setPlainText(self.console_outs[index]) self.current_frame_index = index def exec_console(self): index = self.current_frame_index if index < 0: return # cache frame variables (globals and locals) # because every time we ask for frame.f_locals, a new dict instance # is created - we keep our local cache that may contain some changes if self.frame_vars[index] is None: #print "init", index frame = frame_from_traceback(self.tb, index) self.frame_vars[index] = (dict(frame.f_globals), dict(frame.f_locals)) frame_vars = self.frame_vars[index] #print frame_vars[1] line = self.console.text() try: c = self.compiler(line, "<console>", "single") except (OverflowError, SyntaxError, ValueError) as e: QMessageBox.critical(self, "Error", str(e)) return if c is None: QMessageBox.critical(self, "Error", "Code not complete") return import io io = io.StringIO() if sys.version_info.major >= 3 else io.BytesIO() try: with stdout_redirected(io): exec(c, frame_vars[0], frame_vars[1]) except: etype, value, tb = sys.exc_info() QMessageBox.critical(self, "Error", etype.__name__ + "\n" + str(value)) return stuff = self.console_outs[index] stuff += ">>> " + line + "\n" stuff += io.getvalue() self.console_outs[index] = stuff self.console_out.setPlainText(stuff) self.console_out.setVisible(True) # make sure we are at the end c = self.console_out.textCursor() c.movePosition(QTextCursor.End) self.console_out.setTextCursor(c) self.console_out.ensureCursorVisible() self.console.setText('')
class CodeValueWidget(QWidget): """Widget for specifying barcode or QR code values.""" value_changed = pyqtSignal(str) def __init__(self, item_widget): super().__init__(item_widget) self._item_widget = item_widget self._value_text_edit = QTextEdit() self._value_text_edit.setLineWrapMode(QTextEdit.WidgetWidth) self._value_text_edit.textChanged.connect(self._on_code_value_changed) self._exp_btn = QPushButton(self.tr('Insert expression...')) self._exp_btn.setIcon( QgsApplication.getThemeIcon('/mIconExpression.svg')) self._exp_btn.clicked.connect(self._on_insert_expression) layout = QVBoxLayout() layout.addWidget(self._value_text_edit) layout.addWidget(self._exp_btn) self.setLayout(layout) @property def value_text_edit(self): """ :return: Returns text edit widget for entering code values. :rtype: QPlainTextEdit """ return self._value_text_edit @property def code_value(self): """ :return: Returns the value in the text widget. :rtype: str """ return self._value_text_edit.toPlainText() @code_value.setter def code_value(self, val): """ Sets the text widget to the given value. :param val: Value to set in the text widget. :type val: str """ if self.code_value == val: return self._value_text_edit.setPlainText(val) def highlight_invalid_data(self, invalid): """ Highlights barcode data in red to indicate invalidity. :param invalid: True to highlight in red, else False to restore default color. :type invalid: bool """ if invalid: stylesheet = 'color:#ff0000; font-weight: bold;' else: stylesheet = '' self._value_text_edit.setStyleSheet(stylesheet) def _on_code_value_changed(self): # Slot raised when the code value changes. code_txt = self.code_value self.value_changed.emit(code_txt) def _on_insert_expression(self): # Slot raised to insert an expression. if not isinstance(self._item_widget, QgsLayoutItemBaseWidget): return qrcode_item = self._item_widget.layoutObject() if not qrcode_item: return sel_txt = self._value_text_edit.textCursor().selectedText() # Edit expression text if specified if sel_txt.startswith('[%') and sel_txt.endswith('%]'): sel_txt = sel_txt.lstrip('[%') sel_txt = sel_txt.rstrip('%]') cov_layer = self._item_widget.coverageLayer() exp_ctx = qrcode_item.createExpressionContext() exp_dlg = QgsExpressionBuilderDialog(cov_layer, sel_txt, self, 'generic', exp_ctx) exp_dlg.setWindowTitle(self.tr('Insert Expression for Barcode Data')) exp_dlg.setAllowEvalErrors(False) if exp_dlg.exec_() == QDialog.Accepted: exp = exp_dlg.expressionText() if exp: self._value_text_edit.setPlainText('[%{0}%]'.format(exp)) def block_value_widget_signals(self, status): """ Set True to block all signals emitted by the code value widget, else False to restore. :param status: True to block signals, False to restore. :type status: bool """ self._value_text_edit.blockSignals(status)