Ejemplo n.º 1
0
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('')
Ejemplo n.º 2
0
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)