src/eric7/MicroPython/MicroPythonWidget.py

branch
mpy_network
changeset 10011
26a7d607b8f6
parent 10010
8a68a7a7ab88
child 10012
d649d500a9a1
diff -r 8a68a7a7ab88 -r 26a7d607b8f6 src/eric7/MicroPython/MicroPythonWidget.py
--- a/src/eric7/MicroPython/MicroPythonWidget.py	Wed May 03 10:12:03 2023 +0200
+++ b/src/eric7/MicroPython/MicroPythonWidget.py	Thu May 04 11:22:11 2023 +0200
@@ -7,28 +7,17 @@
 Module implementing the MicroPython REPL widget.
 """
 
-# TODO: refactor the code such to have the MicroPythonWidget as the top level
-#       container and a MicroPythonReplWidget containing the REPL related stuff
-#       (incl. device status line and zoom widget ?)
-
 import contextlib
 import functools
 import os
-import re
 import time
 
-from PyQt6.QtCore import QEvent, QPoint, Qt, pyqtSignal, pyqtSlot
-from PyQt6.QtGui import QBrush, QClipboard, QColor, QKeySequence, QTextCursor
+from PyQt6.QtCore import Qt, pyqtSignal, pyqtSlot
 from PyQt6.QtWidgets import (
-    QApplication,
     QDialog,
-    QHBoxLayout,
     QInputDialog,
-    QLabel,
     QLineEdit,
     QMenu,
-    QSizePolicy,
-    QTextEdit,
     QToolButton,
     QWidget,
 )
@@ -41,7 +30,6 @@
 from eric7.EricWidgets.EricListSelectionDialog import EricListSelectionDialog
 from eric7.EricWidgets.EricPlainTextDialog import EricPlainTextDialog
 from eric7.EricWidgets.EricProcessDialog import EricProcessDialog
-from eric7.EricWidgets.EricZoomWidget import EricZoomWidget
 from eric7.SystemUtilities import FileSystemUtilities, OSUtilities
 from eric7.UI.Info import BugAddress
 
@@ -68,136 +56,6 @@
 except ImportError:
     HAS_QTSERIALPORT = False
 
-# ANSI Colors (see https://en.wikipedia.org/wiki/ANSI_escape_code)
-AnsiColorSchemes = {
-    "Windows 7": {
-        0: QBrush(QColor(0, 0, 0)),
-        1: QBrush(QColor(128, 0, 0)),
-        2: QBrush(QColor(0, 128, 0)),
-        3: QBrush(QColor(128, 128, 0)),
-        4: QBrush(QColor(0, 0, 128)),
-        5: QBrush(QColor(128, 0, 128)),
-        6: QBrush(QColor(0, 128, 128)),
-        7: QBrush(QColor(192, 192, 192)),
-        10: QBrush(QColor(128, 128, 128)),
-        11: QBrush(QColor(255, 0, 0)),
-        12: QBrush(QColor(0, 255, 0)),
-        13: QBrush(QColor(255, 255, 0)),
-        14: QBrush(QColor(0, 0, 255)),
-        15: QBrush(QColor(255, 0, 255)),
-        16: QBrush(QColor(0, 255, 255)),
-        17: QBrush(QColor(255, 255, 255)),
-    },
-    "Windows 10": {
-        0: QBrush(QColor(12, 12, 12)),
-        1: QBrush(QColor(197, 15, 31)),
-        2: QBrush(QColor(19, 161, 14)),
-        3: QBrush(QColor(193, 156, 0)),
-        4: QBrush(QColor(0, 55, 218)),
-        5: QBrush(QColor(136, 23, 152)),
-        6: QBrush(QColor(58, 150, 221)),
-        7: QBrush(QColor(204, 204, 204)),
-        10: QBrush(QColor(118, 118, 118)),
-        11: QBrush(QColor(231, 72, 86)),
-        12: QBrush(QColor(22, 198, 12)),
-        13: QBrush(QColor(249, 241, 165)),
-        14: QBrush(QColor(59, 12, 255)),
-        15: QBrush(QColor(180, 0, 158)),
-        16: QBrush(QColor(97, 214, 214)),
-        17: QBrush(QColor(242, 242, 242)),
-    },
-    "PuTTY": {
-        0: QBrush(QColor(0, 0, 0)),
-        1: QBrush(QColor(187, 0, 0)),
-        2: QBrush(QColor(0, 187, 0)),
-        3: QBrush(QColor(187, 187, 0)),
-        4: QBrush(QColor(0, 0, 187)),
-        5: QBrush(QColor(187, 0, 187)),
-        6: QBrush(QColor(0, 187, 187)),
-        7: QBrush(QColor(187, 187, 187)),
-        10: QBrush(QColor(85, 85, 85)),
-        11: QBrush(QColor(255, 85, 85)),
-        12: QBrush(QColor(85, 255, 85)),
-        13: QBrush(QColor(255, 255, 85)),
-        14: QBrush(QColor(85, 85, 255)),
-        15: QBrush(QColor(255, 85, 255)),
-        16: QBrush(QColor(85, 255, 255)),
-        17: QBrush(QColor(255, 255, 255)),
-    },
-    "xterm": {
-        0: QBrush(QColor(0, 0, 0)),
-        1: QBrush(QColor(205, 0, 0)),
-        2: QBrush(QColor(0, 205, 0)),
-        3: QBrush(QColor(205, 205, 0)),
-        4: QBrush(QColor(0, 0, 238)),
-        5: QBrush(QColor(205, 0, 205)),
-        6: QBrush(QColor(0, 205, 205)),
-        7: QBrush(QColor(229, 229, 229)),
-        10: QBrush(QColor(127, 127, 127)),
-        11: QBrush(QColor(255, 0, 0)),
-        12: QBrush(QColor(0, 255, 0)),
-        13: QBrush(QColor(255, 255, 0)),
-        14: QBrush(QColor(0, 0, 255)),
-        15: QBrush(QColor(255, 0, 255)),
-        16: QBrush(QColor(0, 255, 255)),
-        17: QBrush(QColor(255, 255, 255)),
-    },
-    "Ubuntu": {
-        0: QBrush(QColor(1, 1, 1)),
-        1: QBrush(QColor(222, 56, 43)),
-        2: QBrush(QColor(57, 181, 74)),
-        3: QBrush(QColor(255, 199, 6)),
-        4: QBrush(QColor(0, 11, 184)),
-        5: QBrush(QColor(118, 38, 113)),
-        6: QBrush(QColor(44, 181, 233)),
-        7: QBrush(QColor(204, 204, 204)),
-        10: QBrush(QColor(128, 128, 128)),
-        11: QBrush(QColor(255, 0, 0)),
-        12: QBrush(QColor(0, 255, 0)),
-        13: QBrush(QColor(255, 255, 0)),
-        14: QBrush(QColor(0, 0, 255)),
-        15: QBrush(QColor(255, 0, 255)),
-        16: QBrush(QColor(0, 255, 255)),
-        17: QBrush(QColor(255, 255, 255)),
-    },
-    "Ubuntu (dark)": {
-        0: QBrush(QColor(96, 96, 96)),
-        1: QBrush(QColor(235, 58, 45)),
-        2: QBrush(QColor(57, 181, 74)),
-        3: QBrush(QColor(255, 199, 29)),
-        4: QBrush(QColor(25, 56, 230)),
-        5: QBrush(QColor(200, 64, 193)),
-        6: QBrush(QColor(48, 200, 255)),
-        7: QBrush(QColor(204, 204, 204)),
-        10: QBrush(QColor(128, 128, 128)),
-        11: QBrush(QColor(255, 0, 0)),
-        12: QBrush(QColor(0, 255, 0)),
-        13: QBrush(QColor(255, 255, 0)),
-        14: QBrush(QColor(0, 0, 255)),
-        15: QBrush(QColor(255, 0, 255)),
-        16: QBrush(QColor(0, 255, 255)),
-        17: QBrush(QColor(255, 255, 255)),
-    },
-    "Breeze (dark)": {
-        0: QBrush(QColor(35, 38, 39)),
-        1: QBrush(QColor(237, 21, 21)),
-        2: QBrush(QColor(17, 209, 22)),
-        3: QBrush(QColor(246, 116, 0)),
-        4: QBrush(QColor(29, 153, 243)),
-        5: QBrush(QColor(155, 89, 182)),
-        6: QBrush(QColor(26, 188, 156)),
-        7: QBrush(QColor(252, 252, 252)),
-        10: QBrush(QColor(127, 140, 141)),
-        11: QBrush(QColor(192, 57, 43)),
-        12: QBrush(QColor(28, 220, 154)),
-        13: QBrush(QColor(253, 188, 75)),
-        14: QBrush(QColor(61, 174, 233)),
-        15: QBrush(QColor(142, 68, 173)),
-        16: QBrush(QColor(22, 160, 133)),
-        17: QBrush(QColor(255, 255, 255)),
-    },
-}
-
 
 class MicroPythonWidget(QWidget, Ui_MicroPythonWidget):
     """
@@ -207,9 +65,6 @@
         connection for further processing
     """
 
-    ZoomMin = -10
-    ZoomMax = 20
-
     DeviceTypeRole = Qt.ItemDataRole.UserRole
     DeviceBoardRole = Qt.ItemDataRole.UserRole + 1
     DevicePortRole = Qt.ItemDataRole.UserRole + 2
@@ -269,27 +124,6 @@
         self.chartButton.setIcon(EricPixmapCache.getIcon("chart"))
         self.connectButton.setIcon(EricPixmapCache.getIcon("linkConnect"))
 
-        self.__zoomLayout = QHBoxLayout()
-        self.__osdLabel = QLabel()
-        self.__osdLabel.setSizePolicy(
-            QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Preferred
-        )
-        self.__zoomLayout.addWidget(self.__osdLabel)
-
-        self.__zoom0 = self.replEdit.fontPointSize()
-        self.__zoomWidget = EricZoomWidget(
-            EricPixmapCache.getPixmap("zoomOut"),
-            EricPixmapCache.getPixmap("zoomIn"),
-            EricPixmapCache.getPixmap("zoomReset"),
-            self,
-        )
-        self.__zoomLayout.addWidget(self.__zoomWidget)
-        self.layout().insertLayout(self.layout().count() - 1, self.__zoomLayout)
-        self.__zoomWidget.setMinimum(self.ZoomMin)
-        self.__zoomWidget.setMaximum(self.ZoomMax)
-        self.__zoomWidget.valueChanged.connect(self.__doZoom)
-        self.__currentZoom = 0
-
         self.__fileManager = None
         self.__fileManagerWidget = None
         self.__chartWidget = None
@@ -306,10 +140,8 @@
         self.__linkConnected = False
         self.__setConnected(False)
 
-        self.__replBuffer = b""
-
         if not HAS_QTSERIALPORT:
-            self.replEdit.setHtml(
+            self.replWidget.replEdit().setHtml(
                 self.tr(
                     "<h3>The QtSerialPort package is not available.<br/>"
                     "MicroPython support is deactivated.</h3>"
@@ -318,29 +150,14 @@
             self.setEnabled(False)
             return
 
-        self.__vt100Re = re.compile(
-            r"(?P<count>\d*)(?P<color>(?:;?\d*)*)(?P<action>[ABCDKm])"
-        )
-
         self.__populateDeviceTypeComboBox()
 
         self.repopulateButton.clicked.connect(self.__populateDeviceTypeComboBox)
         self.webreplConfigButton.clicked.connect(self.__configureWebreplUrls)
-
-        self.replEdit.installEventFilter(self)
-        # Hack to intercept middle button paste
-        self.__origReplEditMouseReleaseEvent = self.replEdit.mouseReleaseEvent
-        self.replEdit.mouseReleaseEvent = self.__replEditMouseReleaseEvent
-
-        self.replEdit.customContextMenuRequested.connect(self.__showContextMenu)
         self.__ui.preferencesChanged.connect(self.__handlePreferencesChanged)
 
         self.__handlePreferencesChanged()
 
-        charFormat = self.replEdit.currentCharFormat()
-        self.DefaultForeground = charFormat.foreground()
-        self.DefaultBackground = charFormat.background()
-
     def __populateDeviceTypeComboBox(self):
         """
         Private method to populate the device type selector.
@@ -431,9 +248,7 @@
                 index, webreplUrlsDict[name]["url"], self.DeviceWebreplUrlRole
             )
         webreplMessage = (
-            self.tr(
-                "\n%n WebREPL connection(s) defined.", "", len(webreplUrlsDict)
-            )
+            self.tr("\n%n WebREPL connection(s) defined.", "", len(webreplUrlsDict))
             if webreplUrlsDict
             else ""
         )
@@ -507,16 +322,7 @@
         """
         Private slot to handle a change in preferences.
         """
-        self.__colorScheme = Preferences.getMicroPython("ColorScheme")
-
-        self.__font = Preferences.getEditorOtherFonts("MonospacedFont")
-        self.replEdit.setFontFamily(self.__font.family())
-        self.replEdit.setFontPointSize(self.__font.pointSize())
-
-        if Preferences.getMicroPython("ReplLineWrap"):
-            self.replEdit.setLineWrapMode(QTextEdit.LineWrapMode.WidgetWidth)
-        else:
-            self.replEdit.setLineWrapMode(QTextEdit.LineWrapMode.NoWrap)
+        self.replWidget.replEdit().handlePreferencesChanged()
 
         if self.__interface is not None:
             self.__interface.handlePreferencesChanged
@@ -623,50 +429,6 @@
                 kwargs["chart"] and HAS_QTCHART and self.__connected
             )
 
-    @pyqtSlot(QPoint)
-    def __showContextMenu(self, pos):
-        """
-        Private slot to show the REPL context menu.
-
-        @param pos position to show the menu at
-        @type QPoint
-        """
-        if OSUtilities.isMacPlatform():
-            copyKeys = QKeySequence("Ctrl+C")
-            pasteKeys = QKeySequence("Ctrl+V")
-            selectAllKeys = QKeySequence("Ctrl+A")
-        else:
-            copyKeys = QKeySequence("Ctrl+Shift+C")
-            pasteKeys = QKeySequence("Ctrl+Shift+V")
-            selectAllKeys = QKeySequence("Ctrl+Shift+A")
-
-        menu = QMenu(self)
-        menu.addAction(
-            EricPixmapCache.getIcon("editDelete"), self.tr("Clear"), self.__clear
-        ).setEnabled(bool(self.replEdit.toPlainText()))
-        menu.addSeparator()
-        menu.addAction(
-            EricPixmapCache.getIcon("editCopy"),
-            self.tr("Copy"),
-            copyKeys,
-            self.replEdit.copy,
-        ).setEnabled(self.replEdit.textCursor().hasSelection())
-        menu.addAction(
-            EricPixmapCache.getIcon("editPaste"),
-            self.tr("Paste"),
-            pasteKeys,
-            self.__paste,
-        ).setEnabled(self.replEdit.canPaste() and self.__connected)
-        menu.addSeparator()
-        menu.addAction(
-            EricPixmapCache.getIcon("editSelectAll"),
-            self.tr("Select All"),
-            selectAllKeys,
-            self.replEdit.selectAll,
-        ).setEnabled(bool(self.replEdit.toPlainText()))
-
-        menu.exec(self.replEdit.mapToGlobal(pos))
-
     def __setConnected(self, connected):
         """
         Private method to set the connection status LED.
@@ -761,8 +523,10 @@
                 )
                 return
 
-            self.replEdit.clear()
-            self.__interface.dataReceived.connect(self.__processData)
+            self.replWidget.replEdit().clear()
+            self.__interface.dataReceived.connect(
+                self.replWidget.replEdit().processData
+            )
 
             if not self.__interface.isConnected():
                 self.__connectToDevice()
@@ -773,11 +537,13 @@
                     self.__interface.write(b"\x03")
 
             self.__device.setRepl(True)
-            self.replEdit.setFocus(Qt.FocusReason.OtherFocusReason)
+            self.replWidget.replEdit().setFocus(Qt.FocusReason.OtherFocusReason)
         else:
             with contextlib.suppress(TypeError):
                 if self.__interface is not None:
-                    self.__interface.dataReceived.disconnect(self.__processData)
+                    self.__interface.dataReceived.disconnect(
+                        self.replWidget.replEdit().processData
+                    )
             if not self.chartButton.isChecked() and not self.filesButton.isChecked():
                 self.__disconnectFromDevice()
             self.__device.setRepl(False)
@@ -789,7 +555,7 @@
         Private slot to connect to the selected device or disconnect from the
         currently connected device.
         """
-        self.__osdLabel.clear()
+        self.replWidget.clearOSD()
         if self.__linkConnected:
             with EricOverrideCursor():
                 self.__disconnectFromDevice()
@@ -804,374 +570,6 @@
             with EricOverrideCursor():
                 self.__connectToDevice(withAutostart=True)
 
-    @pyqtSlot()
-    def __clear(self):
-        """
-        Private slot to clear the REPL pane.
-        """
-        self.replEdit.clear()
-        if bool(self.__interface) and self.__interface.isConnected():
-            self.__interface.write(b"\r")
-
-    @pyqtSlot()
-    def __paste(self, mode=QClipboard.Mode.Clipboard):
-        """
-        Private slot to perform a paste operation.
-
-        @param mode paste mode (defaults to QClipboard.Mode.Clipboard)
-        @type QClipboard.Mode (optional)
-        """
-        # add support for paste by mouse middle button
-        clipboard = QApplication.clipboard()
-        if clipboard:
-            pasteText = clipboard.text(mode=mode)
-            if pasteText:
-                pasteText = pasteText.replace("\n\r", "\r")
-                pasteText = pasteText.replace("\n", "\r")
-                if bool(self.__interface) and self.__interface.isConnected():
-                    self.__interface.write(b"\x05")
-                    self.__interface.write(pasteText.encode("utf-8"))
-                    self.__interface.write(b"\x04")
-
-    def eventFilter(self, obj, evt):
-        """
-        Public method to process events for the REPL pane.
-
-        @param obj reference to the object the event was meant for
-        @type QObject
-        @param evt reference to the event object
-        @type QEvent
-        @return flag to indicate that the event was handled
-        @rtype bool
-        """
-        if obj is self.replEdit and evt.type() == QEvent.Type.KeyPress:
-            # handle the key press event on behalf of the REPL pane
-            key = evt.key()
-            msg = bytes(evt.text(), "utf8")
-            if key == Qt.Key.Key_Backspace:
-                msg = b"\b"
-            elif key == Qt.Key.Key_Delete:
-                msg = b"\x1B[\x33\x7E"
-            elif key == Qt.Key.Key_Up:
-                msg = b"\x1B[A"
-            elif key == Qt.Key.Key_Down:
-                msg = b"\x1B[B"
-            elif key == Qt.Key.Key_Right:
-                msg = b"\x1B[C"
-            elif key == Qt.Key.Key_Left:
-                msg = b"\x1B[D"
-            elif key == Qt.Key.Key_Home:
-                msg = b"\x1B[H"
-            elif key == Qt.Key.Key_End:
-                msg = b"\x1B[F"
-            elif (
-                OSUtilities.isMacPlatform()
-                and evt.modifiers() == Qt.KeyboardModifier.MetaModifier
-            ) or (
-                not OSUtilities.isMacPlatform()
-                and evt.modifiers() == Qt.KeyboardModifier.ControlModifier
-            ):
-                if Qt.Key.Key_A <= key <= Qt.Key.Key_Z:
-                    # devices treat an input of \x01 as Ctrl+A, etc.
-                    msg = bytes([1 + key - Qt.Key.Key_A])
-            elif evt.modifiers() == (
-                Qt.KeyboardModifier.ControlModifier | Qt.KeyboardModifier.ShiftModifier
-            ) or (
-                OSUtilities.isMacPlatform()
-                and evt.modifiers() == Qt.KeyboardModifier.ControlModifier
-            ):
-                if key == Qt.Key.Key_C:
-                    self.replEdit.copy()
-                    msg = b""
-                elif key == Qt.Key.Key_V:
-                    self.__paste()
-                    msg = b""
-                elif key == Qt.Key.Key_A:
-                    self.replEdit.selectAll()
-                    msg = b""
-            elif key in (Qt.Key.Key_Return, Qt.Key.Key_Enter):
-                tc = self.replEdit.textCursor()
-                tc.movePosition(QTextCursor.MoveOperation.EndOfLine)
-                self.replEdit.setTextCursor(tc)
-            if bool(self.__interface) and self.__interface.isConnected():
-                self.__interface.write(msg)
-            return True
-        else:
-            # standard event processing
-            return super().eventFilter(obj, evt)
-
-    def __replEditMouseReleaseEvent(self, evt):
-        """
-        Private method handling mouse release events for the replEdit widget.
-
-        Note: this is a hack because QTextEdit does not allow filtering of
-        QEvent.Type.MouseButtonRelease. To make middle button paste work, we
-        had to intercept the protected event method (some kind of
-        reimplementing it).
-
-        @param evt reference to the event object
-        @type QMouseEvent
-        """
-        if evt.button() == Qt.MouseButton.MiddleButton:
-            self.__paste(mode=QClipboard.Mode.Selection)
-            msg = b""
-            if bool(self.__interface) and self.__interface.isConnected():
-                self.__interface.write(msg)
-            evt.accept()
-        else:
-            self.__origReplEditMouseReleaseEvent(evt)
-
-    def __processData(self, data):
-        """
-        Private slot to process bytes received from the device.
-
-        @param data bytes received from the device
-        @type bytes
-        """
-        tc = self.replEdit.textCursor()
-        # the text cursor must be on the last line
-        while tc.movePosition(QTextCursor.MoveOperation.Down):
-            pass
-
-        # set the font
-        charFormat = tc.charFormat()
-        charFormat.setFontFamilies([self.__font.family()])
-        charFormat.setFontPointSize(self.__font.pointSize())
-        tc.setCharFormat(charFormat)
-
-        # add received data to the buffered one
-        data = self.__replBuffer + data
-
-        index = 0
-        while index < len(data):
-            if data[index] == 8:  # \b
-                tc.movePosition(QTextCursor.MoveOperation.Left)
-                self.replEdit.setTextCursor(tc)
-            elif data[index] in (4, 13):  # EOT, \r
-                pass
-            elif len(data) > index + 1 and data[index] == 27 and data[index + 1] == 91:
-                # VT100 cursor command detected: <Esc>[
-                index += 2  # move index to after the [
-                match = self.__vt100Re.search(
-                    data[index:].decode("utf-8", errors="replace")
-                )
-                if match:
-                    # move to last position in control sequence
-                    # ++ will be done at end of loop
-                    index += match.end() - 1
-
-                    action = match.group("action")
-                    if action in "ABCD":
-                        if match.group("count") == "":
-                            count = 1
-                        else:
-                            count = int(match.group("count"))
-
-                        if action == "A":  # up
-                            tc.movePosition(QTextCursor.MoveOperation.Up, n=count)
-                            self.replEdit.setTextCursor(tc)
-                        elif action == "B":  # down
-                            tc.movePosition(QTextCursor.MoveOperation.Down, n=count)
-                            self.replEdit.setTextCursor(tc)
-                        elif action == "C":  # right
-                            tc.movePosition(QTextCursor.MoveOperation.Right, n=count)
-                            self.replEdit.setTextCursor(tc)
-                        elif action == "D":  # left
-                            tc.movePosition(QTextCursor.MoveOperation.Left, n=count)
-                            self.replEdit.setTextCursor(tc)
-                    elif action == "K":  # delete things
-                        if match.group("count") in ("", "0"):
-                            # delete to end of line
-                            tc.movePosition(
-                                QTextCursor.MoveOperation.EndOfLine,
-                                mode=QTextCursor.MoveMode.KeepAnchor,
-                            )
-                            tc.removeSelectedText()
-                            self.replEdit.setTextCursor(tc)
-                        elif match.group("count") == "1":
-                            # delete to beginning of line
-                            tc.movePosition(
-                                QTextCursor.MoveOperation.StartOfLine,
-                                mode=QTextCursor.MoveMode.KeepAnchor,
-                            )
-                            tc.removeSelectedText()
-                            self.replEdit.setTextCursor(tc)
-                        elif match.group("count") == "2":
-                            # delete whole line
-                            tc.movePosition(QTextCursor.MoveOperation.EndOfLine)
-                            tc.movePosition(
-                                QTextCursor.MoveOperation.StartOfLine,
-                                mode=QTextCursor.MoveMode.KeepAnchor,
-                            )
-                            tc.removeSelectedText()
-                            self.replEdit.setTextCursor(tc)
-                    elif action == "m":
-                        self.__setCharFormat(match.group(0)[:-1].split(";"), tc)
-            elif (
-                len(data) > index + 1
-                and data[index] == 27
-                and data[index + 1 : index + 4] == b"]0;"
-            ):
-                if b"\x1b\\" in data[index + 4 :]:
-                    # 'set window title' command detected: <Esc>]0;...<Esc>\
-                    # __IGNORE_WARNING_M891__
-                    titleData = data[index + 4 :].split(b"\x1b\\")[0]
-                    title = titleData.decode()
-                    index += len(titleData) + 5  # one more is done at the end
-                    self.__osdLabel.setText(title)
-                else:
-                    # data is incomplete; buffer and stop processing
-                    self.__replBuffer = data[index:]
-                    return
-            else:
-                tc.deleteChar()
-                self.replEdit.setTextCursor(tc)
-                self.replEdit.insertPlainText(chr(data[index]))
-
-            index += 1
-
-        self.replEdit.ensureCursorVisible()
-        self.__replBuffer = b""
-
-    def __setCharFormat(self, formatCodes, textCursor):
-        """
-        Private method setting the current text format of the REPL pane based
-        on the passed ANSI codes.
-
-        Following codes are used:
-        <ul>
-        <li>0: Reset</li>
-        <li>1: Bold font (weight 75)</li>
-        <li>2: Light font (weight 25)</li>
-        <li>3: Italic font</li>
-        <li>4: Underlined font</li>
-        <li>9: Strikeout font</li>
-        <li>21: Bold off (weight 50)</li>
-        <li>22: Light off (weight 50)</li>
-        <li>23: Italic off</li>
-        <li>24: Underline off</li>
-        <li>29: Strikeout off</li>
-        <li>30: foreground Black</li>
-        <li>31: foreground Dark Red</li>
-        <li>32: foreground Dark Green</li>
-        <li>33: foreground Dark Yellow</li>
-        <li>34: foreground Dark Blue</li>
-        <li>35: foreground Dark Magenta</li>
-        <li>36: foreground Dark Cyan</li>
-        <li>37: foreground Light Gray</li>
-        <li>39: reset foreground to default</li>
-        <li>40: background Black</li>
-        <li>41: background Dark Red</li>
-        <li>42: background Dark Green</li>
-        <li>43: background Dark Yellow</li>
-        <li>44: background Dark Blue</li>
-        <li>45: background Dark Magenta</li>
-        <li>46: background Dark Cyan</li>
-        <li>47: background Light Gray</li>
-        <li>49: reset background to default</li>
-        <li>53: Overlined font</li>
-        <li>55: Overline off</li>
-        <li>90: bright foreground Dark Gray</li>
-        <li>91: bright foreground Red</li>
-        <li>92: bright foreground Green</li>
-        <li>93: bright foreground Yellow</li>
-        <li>94: bright foreground Blue</li>
-        <li>95: bright foreground Magenta</li>
-        <li>96: bright foreground Cyan</li>
-        <li>97: bright foreground White</li>
-        <li>100: bright background Dark Gray</li>
-        <li>101: bright background Red</li>
-        <li>102: bright background Green</li>
-        <li>103: bright background Yellow</li>
-        <li>104: bright background Blue</li>
-        <li>105: bright background Magenta</li>
-        <li>106: bright background Cyan</li>
-        <li>107: bright background White</li>
-        </ul>
-
-        @param formatCodes list of format codes
-        @type list of str
-        @param textCursor reference to the text cursor
-        @type QTextCursor
-        """
-        if not formatCodes:
-            # empty format codes list is treated as a reset
-            formatCodes = ["0"]
-
-        charFormat = textCursor.charFormat()
-        for formatCode in formatCodes:
-            try:
-                formatCode = int(formatCode)
-            except ValueError:
-                # ignore non digit values
-                continue
-
-            if formatCode == 0:
-                charFormat.setFontWeight(50)
-                charFormat.setFontItalic(False)
-                charFormat.setFontUnderline(False)
-                charFormat.setFontStrikeOut(False)
-                charFormat.setFontOverline(False)
-                charFormat.setForeground(self.DefaultForeground)
-                charFormat.setBackground(self.DefaultBackground)
-            elif formatCode == 1:
-                charFormat.setFontWeight(75)
-            elif formatCode == 2:
-                charFormat.setFontWeight(25)
-            elif formatCode == 3:
-                charFormat.setFontItalic(True)
-            elif formatCode == 4:
-                charFormat.setFontUnderline(True)
-            elif formatCode == 9:
-                charFormat.setFontStrikeOut(True)
-            elif formatCode in (21, 22):
-                charFormat.setFontWeight(50)
-            elif formatCode == 23:
-                charFormat.setFontItalic(False)
-            elif formatCode == 24:
-                charFormat.setFontUnderline(False)
-            elif formatCode == 29:
-                charFormat.setFontStrikeOut(False)
-            elif formatCode == 53:
-                charFormat.setFontOverline(True)
-            elif formatCode == 55:
-                charFormat.setFontOverline(False)
-            elif formatCode in (30, 31, 32, 33, 34, 35, 36, 37):
-                charFormat.setForeground(
-                    AnsiColorSchemes[self.__colorScheme][formatCode - 30]
-                )
-            elif formatCode in (40, 41, 42, 43, 44, 45, 46, 47):
-                charFormat.setBackground(
-                    AnsiColorSchemes[self.__colorScheme][formatCode - 40]
-                )
-            elif formatCode in (90, 91, 92, 93, 94, 95, 96, 97):
-                charFormat.setForeground(
-                    AnsiColorSchemes[self.__colorScheme][formatCode - 80]
-                )
-            elif formatCode in (100, 101, 102, 103, 104, 105, 106, 107):
-                charFormat.setBackground(
-                    AnsiColorSchemes[self.__colorScheme][formatCode - 90]
-                )
-            elif formatCode == 39:
-                charFormat.setForeground(self.DefaultForeground)
-            elif formatCode == 49:
-                charFormat.setBackground(self.DefaultBackground)
-
-        textCursor.setCharFormat(charFormat)
-
-    def __doZoom(self, value):
-        """
-        Private slot to zoom the REPL pane.
-
-        @param value zoom value
-        @type int
-        """
-        if value < self.__currentZoom:
-            self.replEdit.zoomOut(self.__currentZoom - value)
-        elif value > self.__currentZoom:
-            self.replEdit.zoomIn(value - self.__currentZoom)
-        self.__currentZoom = value
-
     def getCurrentPort(self):
         """
         Public method to determine the port path of the selected device.
@@ -1287,6 +685,7 @@
                         return
 
             self.__interface = MicroPythonWebreplDeviceInterface(self)
+        self.replWidget.replEdit().setInterface(self.__interface)
 
         if self.__interface.connectToDevice(port):
             deviceResponding = self.__interface.probeDevice()
@@ -1340,6 +739,7 @@
             self.__interface.disconnectFromDevice()
             self.__interface.deleteLater()
             self.__interface = None
+            self.replWidget.replEdit().setInterface(None)
 
     @pyqtSlot()
     def on_runButton_clicked(self):

eric ide

mercurial