diff -r 4958dd72c937 -r 606ac0e26533 src/eric7/MicroPython/MicroPythonWidget.py --- a/src/eric7/MicroPython/MicroPythonWidget.py Thu Feb 09 09:55:57 2023 +0100 +++ b/src/eric7/MicroPython/MicroPythonWidget.py Sat Feb 11 16:59:50 2023 +0100 @@ -202,6 +202,7 @@ DevicePortRole = Qt.ItemDataRole.UserRole + 2 DeviceVidRole = Qt.ItemDataRole.UserRole + 3 DevicePidRole = Qt.ItemDataRole.UserRole + 4 + DeviceSerNoRole = Qt.ItemDataRole.UserRole + 5 dataReceived = pyqtSignal(bytes) @@ -282,6 +283,8 @@ self.__linkConnected = False self.__setConnected(False) + self.__replBuffer = b"" + if not HAS_QTSERIALPORT: self.replEdit.setHtml( self.tr( @@ -336,6 +339,7 @@ portName, vid, pid, + serialNumber, ) in enumerate(sorted(devices), 1): self.deviceTypeComboBox.addItem( self.tr( @@ -353,6 +357,9 @@ ) self.deviceTypeComboBox.setItemData(index, vid, self.DeviceVidRole) self.deviceTypeComboBox.setItemData(index, pid, self.DevicePidRole) + self.deviceTypeComboBox.setItemData( + index, serialNumber, self.DeviceSerNoRole + ) else: supportedMessage = self.tr("No supported devices detected.") @@ -386,6 +393,7 @@ if self.__linkConnected: # we are still connected, so disconnect self.on_connectButton_clicked() + self.__device = None self.on_deviceTypeComboBox_activated(index) self.deviceTypeComboBox.setCurrentIndex(index) @@ -500,14 +508,17 @@ boardName = self.deviceTypeComboBox.itemData(index, self.DeviceBoardRole) vid = self.deviceTypeComboBox.itemData(index, self.DeviceVidRole) pid = self.deviceTypeComboBox.itemData(index, self.DevicePidRole) + serNo = self.deviceTypeComboBox.itemData(index, self.DeviceSerNoRole) if deviceType or (pid is not None and pid is not None): self.__device = MicroPythonDevices.getDevice( - deviceType, self, vid, pid, boardName + deviceType, self, vid, pid, boardName=boardName, serialNumber=serNo ) self.__device.setButtons() self.connectButton.setEnabled(bool(deviceType)) + else: + self.__device = None @pyqtSlot() def on_checkButton_clicked(self): @@ -844,6 +855,9 @@ 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 @@ -891,7 +905,7 @@ tc.removeSelectedText() self.replEdit.setTextCursor(tc) elif match.group("count") == "1": - # delete to beinning of line + # delete to beginning of line tc.movePosition( QTextCursor.MoveOperation.StartOfLine, mode=QTextCursor.MoveMode.KeepAnchor, @@ -909,6 +923,24 @@ 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 + tc.deleteChar() + self.replEdit.setTextCursor(tc) + self.replEdit.insertPlainText(title) + else: + # data is incomplete; buffer and stop processing + self.__replBuffer = data[index:] + return else: tc.deleteChar() self.replEdit.setTextCursor(tc) @@ -917,6 +949,7 @@ index += 1 self.replEdit.ensureCursorVisible() + self.__replBuffer = b"" def __setCharFormat(self, formatCodes, textCursor): """ @@ -1127,6 +1160,7 @@ if self.__interface.connectToDevice(port): deviceResponding = self.__interface.probeDevice() self.__setConnected(deviceResponding) + self.__device.setConnected(deviceResponding) if deviceResponding: if ( Preferences.getMicroPython("SyncTimeAfterConnect") @@ -1161,6 +1195,7 @@ """ Private method to disconnect from the device. """ + self.__device.setConnected(False) self.__interface.disconnectFromDevice() self.__setConnected(False) @@ -1423,34 +1458,28 @@ # populate the super menu hasTime = self.__device.hasTimeCommands() if self.__device else False - act = self.__superMenu.addAction( + self.__superMenu.addAction( self.tr("Show Version"), self.__showDeviceVersion - ) - act.setEnabled(self.__connected) - act = self.__superMenu.addAction( + ).setEnabled(self.__connected) + self.__superMenu.addAction( self.tr("Show Implementation"), self.__showImplementation - ) - act.setEnabled(self.__connected) - act = self.__superMenu.addAction( + ).setEnabled(self.__connected) + self.__superMenu.addAction( self.tr("Show Board Data"), self.__showBoardInformation - ) - act.setEnabled(self.__connected) + ).setEnabled(self.__connected) self.__superMenu.addSeparator() if hasTime: - act = self.__superMenu.addAction( + self.__superMenu.addAction( self.tr("Synchronize Time"), self.__synchronizeTime - ) - act.setEnabled(self.__connected) - act = self.__superMenu.addAction( + ).setEnabled(self.__connected) + self.__superMenu.addAction( self.tr("Show Device Time"), self.__showDeviceTime - ) - act.setEnabled(self.__connected) + ).setEnabled(self.__connected) self.__superMenu.addAction(self.tr("Show Local Time"), self.__showLocalTime) if hasTime: - act = self.__superMenu.addAction( + self.__superMenu.addAction( self.tr("Show Time"), self.__showLocalAndDeviceTime - ) - act.setEnabled(self.__connected) + ).setEnabled(self.__connected) self.__superMenu.addSeparator() self.__superMenu.addAction( self.tr("Show Builtin Modules"), self.__showBuiltinModules @@ -1458,35 +1487,32 @@ self.__superMenu.addSeparator() if not OSUtilities.isWindowsPlatform(): available = self.__mpyCrossAvailable() - act = self.__superMenu.addAction( + self.__superMenu.addAction( self.tr("Compile Python File"), self.__compileFile2Mpy - ) - act.setEnabled(available) - act = self.__superMenu.addAction( + ).setEnabled(available) + aw = ericApp().getObject("ViewManager").activeWindow() + self.__superMenu.addAction( self.tr("Compile Current Editor"), self.__compileEditor2Mpy - ) - aw = ericApp().getObject("ViewManager").activeWindow() - act.setEnabled(available and bool(aw)) + ).setEnabled(available and bool(aw)) self.__superMenu.addSeparator() if self.__device: self.__device.addDeviceMenuEntries(self.__superMenu) self.__superMenu.addSeparator() if downloadMenu is None: # generic download action - act = self.__superMenu.addAction( + self.__superMenu.addAction( self.tr("Download Firmware"), self.__downloadFirmware - ) - act.setEnabled(self.__device.hasFirmwareUrl()) + ).setEnabled(self.__device.hasFirmwareUrl()) else: # download sub-menu self.__superMenu.addMenu(downloadMenu) self.__superMenu.addSeparator() - act = self.__superMenu.addAction( + self.__superMenu.addAction( self.tr("Show Documentation"), self.__showDocumentation - ) - act.setEnabled(self.__device.hasDocumentationUrl()) + ).setEnabled(self.__device.hasDocumentationUrl()) self.__superMenu.addSeparator() - if self.__device is not None and not self.__device.hasFlashMenuEntry(): + ##if self.__device is not None and not self.__device.hasFlashMenuEntry(): + if bool(UF2FlashDialog.getFoundDevices()): self.__superMenu.addAction(self.tr("Flash UF2 Device"), self.__flashUF2) self.__superMenu.addSeparator() self.__superMenu.addAction( @@ -1503,46 +1529,46 @@ """ Private slot to show some version info about MicroPython of the device. """ - try: - versionInfo = self.__interface.version() - if versionInfo: - msg = self.tr("<h3>Device Version Information</h3>") - msg += "<table>" - for key, value in versionInfo.items(): - msg += "<tr><td><b>{0}</b></td><td>{1}</td></tr>".format( - key.capitalize(), value - ) - msg += "</table>" - else: - msg = self.tr("No version information available.") - + data = self.__device.getDeviceData() + if data: + msg = self.tr("<h3>Device Version Information</h3>") + msg += "<table>" + for key in ("sysname", "nodename", "release", "version", "machine"): + msg += "<tr><td><b>{0}</b></td><td>{1}</td></tr>".format( + key.capitalize(), data[key] + ) + msg += "</table>" EricMessageBox.information(self, self.tr("Device Version Information"), msg) - except Exception as exc: - self.__showError("version()", str(exc)) + else: + EricMessageBox.critical( + self, + self.tr("Device Version Information"), + self.tr("No version information available."), + ) @pyqtSlot() def __showImplementation(self): """ Private slot to show some implementation related information. """ - try: - impInfo = self.__interface.getImplementation() - if impInfo["name"] == "micropython": + data = self.__device.getDeviceData() + if data: + if data["mpy_name"] == "micropython": name = "MicroPython" - elif impInfo["name"] == "circuitpython": + elif data["mpy_name"] == "circuitpython": name = "CircuitPython" - elif impInfo["name"] == "unknown": + elif data["mpy_name"] == "unknown": name = self.tr("unknown") else: - name = impInfo["name"] + name = data["mpy_name"] version = ( self.tr("unknown") - if impInfo["version"] == "unknown" - else impInfo["version"] + if data["mpy_version"] == "unknown" + else data["mpy_version"] ) variant = ( - self.tr(" ({0})").format(impInfo["variant"]) - if impInfo["variant"] + self.tr(" ({0})").format(data["mpy_variant"]) + if data["mpy_variant"] else "" ) @@ -1554,8 +1580,12 @@ "<p>This device contains <b>{0} {1}{2}</b>.</p>" ).format(name, version, variant), ) - except Exception as exc: - self.__showError("getImplementation()", str(exc)) + else: + EricMessageBox.critical( + self, + self.tr("Device Implementation Information"), + self.tr("No device implementation information available."), + ) @pyqtSlot() def __showBoardInformation(self): @@ -1582,8 +1612,12 @@ @type bool """ if self.__device and self.__device.hasTimeCommands(): + hasCPy = ( + self.__device.checkDeviceData() + and self.__device.getDeviceData()["mpy_name"] == "circuitpython" + ) try: - self.__interface.syncTime(self.__device.getDeviceType()) + self.__interface.syncTime(self.__device.getDeviceType(), hasCPy=hasCPy) if not quiet: with EricOverridenCursor():