eric6/MicroPython/MicroPythonReplWidget.py

branch
micropython
changeset 7095
8e10acb1cd85
parent 7094
d5f340dfb986
child 7103
aea236dc8002
equal deleted inserted replaced
7094:d5f340dfb986 7095:8e10acb1cd85
9 9
10 from __future__ import unicode_literals 10 from __future__ import unicode_literals
11 11
12 import re 12 import re
13 13
14 from PyQt5.QtCore import ( 14 from PyQt5.QtCore import pyqtSlot, pyqtSignal, Qt, QPoint, QEvent
15 pyqtSlot, pyqtSignal, Qt, QPoint, QEvent, QIODevice, QTimer 15 from PyQt5.QtGui import QColor, QKeySequence, QTextCursor, QBrush
16 )
17 from PyQt5.QtGui import (
18 QColor, QKeySequence, QTextCursor, QBrush
19 )
20 from PyQt5.QtWidgets import ( 16 from PyQt5.QtWidgets import (
21 QWidget, QMenu, QApplication, QHBoxLayout, QSpacerItem, QSizePolicy 17 QWidget, QMenu, QApplication, QHBoxLayout, QSpacerItem, QSizePolicy
22 ) 18 )
23 try:
24 from PyQt5.QtSerialPort import QSerialPort
25 HAS_QTSERIALPORT = True
26 except ImportError:
27 HAS_QTSERIALPORT = False
28 19
29 from E5Gui.E5ZoomWidget import E5ZoomWidget 20 from E5Gui.E5ZoomWidget import E5ZoomWidget
30 from E5Gui import E5MessageBox, E5FileDialog 21 from E5Gui import E5MessageBox, E5FileDialog
31 from E5Gui.E5Application import e5App 22 from E5Gui.E5Application import e5App
32 23
37 from .MicroPythonGraphWidget import MicroPythonGraphWidget 28 from .MicroPythonGraphWidget import MicroPythonGraphWidget
38 HAS_QTCHART = True 29 HAS_QTCHART = True
39 except ImportError: 30 except ImportError:
40 HAS_QTCHART = False 31 HAS_QTCHART = False
41 from .MicroPythonFileManagerWidget import MicroPythonFileManagerWidget 32 from .MicroPythonFileManagerWidget import MicroPythonFileManagerWidget
33 try:
34 from .MicroPythonCommandsInterface import MicroPythonCommandsInterface
35 HAS_QTSERIALPORT = True
36 except ImportError:
37 HAS_QTSERIALPORT = False
42 38
43 import Globals 39 import Globals
44 import UI.PixmapCache 40 import UI.PixmapCache
45 import Preferences 41 import Preferences
46 42
137 17: QBrush(QColor(255, 255, 255)), 133 17: QBrush(QColor(255, 255, 255)),
138 }, 134 },
139 } 135 }
140 136
141 137
138 # TODO: make wrapping an option for the repl edit
139 # TODO: add a connect button or make the disconnect button with changing icon (see IRC)
142 class MicroPythonReplWidget(QWidget, Ui_MicroPythonReplWidget): 140 class MicroPythonReplWidget(QWidget, Ui_MicroPythonReplWidget):
143 """ 141 """
144 Class implementing the MicroPython REPL widget. 142 Class implementing the MicroPython REPL widget.
145 143
146 @signal dataReceived(data) emitted to send data received via the serial 144 @signal dataReceived(data) emitted to send data received via the serial
196 self.__zoomWidget.setMinimum(self.ZoomMin) 194 self.__zoomWidget.setMinimum(self.ZoomMin)
197 self.__zoomWidget.setMaximum(self.ZoomMax) 195 self.__zoomWidget.setMaximum(self.ZoomMax)
198 self.__zoomWidget.valueChanged.connect(self.__doZoom) 196 self.__zoomWidget.valueChanged.connect(self.__doZoom)
199 self.__currentZoom = 0 197 self.__currentZoom = 0
200 198
201 self.__serial = None 199 self.__fileManagerWidget = None
200
201 self.__interface = MicroPythonCommandsInterface(self)
202 self.__device = None 202 self.__device = None
203 self.__connected = False
203 self.setConnected(False) 204 self.setConnected(False)
204 205
206 # TODO: replace these by checking the button states
205 self.__replRunning = False 207 self.__replRunning = False
206 self.__plotterRunning = False 208 self.__plotterRunning = False
207 self.__fileManagerRunning = False 209 self.__fileManagerRunning = False
208 210
209 if not HAS_QTSERIALPORT: 211 if not HAS_QTSERIALPORT:
221 self.replEdit.installEventFilter(self) 223 self.replEdit.installEventFilter(self)
222 224
223 self.replEdit.customContextMenuRequested.connect( 225 self.replEdit.customContextMenuRequested.connect(
224 self.__showContextMenu) 226 self.__showContextMenu)
225 self.__ui.preferencesChanged.connect(self.__handlePreferencesChanged) 227 self.__ui.preferencesChanged.connect(self.__handlePreferencesChanged)
228 self.__ui.preferencesChanged.connect(
229 self.__interface.handlePreferencesChanged)
226 230
227 self.__handlePreferencesChanged() 231 self.__handlePreferencesChanged()
228 232
229 charFormat = self.replEdit.currentCharFormat() 233 charFormat = self.replEdit.currentCharFormat()
230 self.DefaultForeground = charFormat.foreground() 234 self.DefaultForeground = charFormat.foreground()
267 271
268 self.__font = Preferences.getEditorOtherFonts("MonospacedFont") 272 self.__font = Preferences.getEditorOtherFonts("MonospacedFont")
269 273
270 self.replEdit.setFontFamily(self.__font.family()) 274 self.replEdit.setFontFamily(self.__font.family())
271 self.replEdit.setFontPointSize(self.__font.pointSize()) 275 self.replEdit.setFontPointSize(self.__font.pointSize())
276
277 def commandsInterface(self):
278 """
279 Public method to get a reference to the commands interface object.
280
281 @return reference to the commands interface object
282 @rtype MicroPythonCommandsInterface
283 """
284 return self.__interface
272 285
273 @pyqtSlot(int) 286 @pyqtSlot(int)
274 def on_deviceTypeComboBox_activated(self, index): 287 def on_deviceTypeComboBox_activated(self, index):
275 """ 288 """
276 Private slot handling the selection of a device type. 289 Private slot handling the selection of a device type.
344 Public method to set the connection status LED. 357 Public method to set the connection status LED.
345 358
346 @param connected connection state 359 @param connected connection state
347 @type bool 360 @type bool
348 """ 361 """
349 if connected: 362 self.__connected = connected
350 self.deviceConnectedLed.setColor(QColor(Qt.green)) 363
351 else: 364 self.deviceConnectedLed.setOn(connected)
352 self.deviceConnectedLed.setColor(QColor(Qt.red)) 365 if self.__fileManagerWidget:
366 self.__fileManagerWidget.deviceConnectedLed.setOn(connected)
353 367
354 self.deviceTypeComboBox.setEnabled(not connected) 368 self.deviceTypeComboBox.setEnabled(not connected)
355 369
356 self.disconnectButton.setEnabled(connected) 370 self.disconnectButton.setEnabled(connected)
357 371
367 """ of MicroPython (or CircuitPython) flashed onto""" 381 """ of MicroPython (or CircuitPython) flashed onto"""
368 """ it before anything will work.\n\nFinally press""" 382 """ it before anything will work.\n\nFinally press"""
369 """ the device's reset button and wait a few seconds""" 383 """ the device's reset button and wait a few seconds"""
370 """ before trying again.""")) 384 """ before trying again."""))
371 385
372 @pyqtSlot() 386 @pyqtSlot(bool)
373 def on_replButton_clicked(self): 387 def on_replButton_clicked(self, checked):
374 """ 388 """
375 Private slot to connect to the selected device and start a REPL. 389 Private slot to connect to enable or disable the REPL widget connecting
390 or disconnecting from the device.
391
392 @param checked state of the button
393 @type bool
376 """ 394 """
377 if not self.__device: 395 if not self.__device:
378 self.__showNoDeviceMessage() 396 self.__showNoDeviceMessage()
379 return 397 return
380 398
381 if self.__replRunning: 399 if checked:
382 self.dataReceived.disconnect(self.__processData)
383 if not self.__plotterRunning:
384 self.__disconnectSerial()
385 self.__replRunning = False
386 self.__device.setRepl(False)
387 else:
388 ok, reason = self.__device.canStartRepl() 400 ok, reason = self.__device.canStartRepl()
389 if not ok: 401 if not ok:
390 E5MessageBox.warning( 402 E5MessageBox.warning(
391 self, 403 self,
392 self.tr("Start REPL"), 404 self.tr("Start REPL"),
393 self.tr("""<p>The REPL cannot be started.</p><p>Reason:""" 405 self.tr("""<p>The REPL cannot be started.</p><p>Reason:"""
394 """ {0}</p>""").format(reason)) 406 """ {0}</p>""").format(reason))
395 return 407 return
396 408
397 self.replEdit.clear() 409 self.replEdit.clear()
398 self.dataReceived.connect(self.__processData) 410 self.__interface.dataReceived.connect(self.__processData)
399 411
400 if not self.__serial: 412 if not self.__interface.isConnected():
401 self.__openSerialLink() 413 self.__connectToDevice()
402 if self.__serial: 414 if self.__device.forceInterrupt():
403 if self.__device.forceInterrupt(): 415 # send a Ctrl-B (exit raw mode)
404 # send a Ctrl-B (exit raw mode) 416 self.__interface.write(b'\x02')
405 self.__serial.write(b'\x02') 417 # send Ctrl-C (keyboard interrupt)
406 # send Ctrl-C (keyboard interrupt) 418 self.__interface.write(b'\x03')
407 self.__serial.write(b'\x03')
408 419
409 self.__replRunning = True 420 self.__replRunning = True
410 self.__device.setRepl(True) 421 self.__device.setRepl(True)
411 self.replEdit.setFocus(Qt.OtherFocusReason) 422 self.replEdit.setFocus(Qt.OtherFocusReason)
423 else:
424 self.__interface.dataReceived.disconnect(self.__processData)
425 if not self.__plotterRunning and not self.__fileManagerRunning:
426 self.__disconnectFromDevice()
427 self.__replRunning = False
428 self.__device.setRepl(False)
429 self.replButton.setChecked(checked)
412 430
413 @pyqtSlot() 431 @pyqtSlot()
414 def on_disconnectButton_clicked(self): 432 def on_disconnectButton_clicked(self):
415 """ 433 """
416 Private slot to disconnect from the currently connected device. 434 Private slot to disconnect from the currently connected device.
417 """ 435 """
418 if self.__replRunning: 436 self.__disconnectFromDevice()
419 self.on_replButton_clicked()
420
421 if self.__plotterRunning:
422 self.on_chartButton_clicked()
423
424 def __disconnectSerial(self):
425 """
426 Private slot to disconnect the serial connection.
427 """
428 self.__closeSerialLink()
429 self.setConnected(False)
430 437
431 @pyqtSlot() 438 @pyqtSlot()
432 def __clear(self): 439 def __clear(self):
433 """ 440 """
434 Private slot to clear the REPL pane. 441 Private slot to clear the REPL pane.
435 """ 442 """
436 self.replEdit.clear() 443 self.replEdit.clear()
437 self.__serial and self.__serial.write(b"\r") 444 self.__interface.isConnected() and self.__interface.write(b"\r")
438 445
439 @pyqtSlot() 446 @pyqtSlot()
440 def __paste(self): 447 def __paste(self):
441 """ 448 """
442 Private slot to perform a paste operation. 449 Private slot to perform a paste operation.
445 if clipboard: 452 if clipboard:
446 pasteText = clipboard.text() 453 pasteText = clipboard.text()
447 if pasteText: 454 if pasteText:
448 pasteText = pasteText.replace('\n\r', '\r') 455 pasteText = pasteText.replace('\n\r', '\r')
449 pasteText = pasteText.replace('\n', '\r') 456 pasteText = pasteText.replace('\n', '\r')
450 self.__serial and self.__serial.write( 457 self.__interface.isConnected() and self.__interface.write(
451 pasteText.encode("utf-8")) 458 pasteText.encode("utf-8"))
452 459
453 def eventFilter(self, obj, evt): 460 def eventFilter(self, obj, evt):
454 """ 461 """
455 Public method to process events for the REPL pane. 462 Public method to process events for the REPL pane.
499 msg = b'' 506 msg = b''
500 elif key in (Qt.Key_Return, Qt.Key_Enter): 507 elif key in (Qt.Key_Return, Qt.Key_Enter):
501 tc = self.replEdit.textCursor() 508 tc = self.replEdit.textCursor()
502 tc.movePosition(QTextCursor.EndOfLine) 509 tc.movePosition(QTextCursor.EndOfLine)
503 self.replEdit.setTextCursor(tc) 510 self.replEdit.setTextCursor(tc)
504 self.__serial and self.__serial.write(msg) 511 self.__interface.isConnected() and self.__interface.write(msg)
505 return True 512 return True
506 513
507 else: 514 else:
508 # standard event processing 515 # standard event processing
509 return super(MicroPythonReplWidget, self).eventFilter(obj, evt) 516 return super(MicroPythonReplWidget, self).eventFilter(obj, evt)
584 tc.removeSelectedText() 591 tc.removeSelectedText()
585 self.replEdit.setTextCursor(tc) 592 self.replEdit.setTextCursor(tc)
586 elif action == "m": 593 elif action == "m":
587 self.__setCharFormat(match.group(0)[:-1].split(";"), 594 self.__setCharFormat(match.group(0)[:-1].split(";"),
588 tc) 595 tc)
589 ## elif data[index] == 10: # \n
590 ## tc.movePosition(QTextCursor.End)
591 ## self.replEdit.setTextCursor(tc)
592 ## self.replEdit.insertPlainText(chr(data[index]))
593 ## self.__setCharFormat(["0"], tc) # reset format after a \n
594 else: 596 else:
595 tc.deleteChar() 597 tc.deleteChar()
596 self.replEdit.setTextCursor(tc) 598 self.replEdit.setTextCursor(tc)
597 self.replEdit.insertPlainText(chr(data[index])) 599 self.replEdit.insertPlainText(chr(data[index]))
598 600
751 return portName 753 return portName
752 else: 754 else:
753 # return with device path prepended 755 # return with device path prepended
754 return "/dev/{0}".format(portName) 756 return "/dev/{0}".format(portName)
755 757
756 def __openSerialLink(self): 758 def __connectToDevice(self):
757 """ 759 """
758 Private method to open a serial link to the selected device. 760 Private method to connect to the selected device.
759 """ 761 """
760 port = self.__getCurrentPort() 762 port = self.__getCurrentPort()
761 self.__serial = QSerialPort() 763 if self.__interface.connectToDevice(port):
762 self.__serial.setPortName(port)
763 if self.__serial.open(QIODevice.ReadWrite):
764 self.__serial.setDataTerminalReady(True)
765 # 115.200 baud, 8N1
766 self.__serial.setBaudRate(115200)
767 self.__serial.setDataBits(QSerialPort.Data8)
768 self.__serial.setParity(QSerialPort.NoParity)
769 self.__serial.setStopBits(QSerialPort.OneStop)
770 self.__serial.readyRead.connect(self.__readSerial)
771 self.setConnected(True) 764 self.setConnected(True)
772 else: 765 else:
773 E5MessageBox.warning( 766 E5MessageBox.warning(
774 self, 767 self,
775 self.tr("Serial Device Connect"), 768 self.tr("Serial Device Connect"),
776 self.tr("""<p>Cannot connect to device at serial port""" 769 self.tr("""<p>Cannot connect to device at serial port"""
777 """ <b>{0}</b>.</p>""").format(port)) 770 """ <b>{0}</b>.</p>""").format(port))
778 self.__serial = None 771
779 772 def __disconnectFromDevice(self):
780 def __closeSerialLink(self): 773 """
781 """ 774 Private method to disconnect from the device.
782 Private method to close the open serial connection. 775 """
783 """ 776 self.__interface.disconnectFromDevice()
784 if self.__serial: 777 self.setConnected(False)
785 self.__serial.close()
786 self.__serial = None
787
788 @pyqtSlot()
789 def __readSerial(self):
790 """
791 Private slot to read all available serial data and emit it with the
792 "dataReceived" signal for further processing.
793 """
794 data = bytes(self.__serial.readAll())
795 self.dataReceived.emit(data)
796
797 def execute(self, commandsList):
798 """
799 Public method to execute a series of commands over a period of time.
800
801 @param commandsList list of commands to be execute on the device
802 @type list of bytes
803 """
804 def remainingTask(commands):
805 self.execute(commands)
806
807 if commandsList:
808 command = commandsList[0]
809 self.__serial.write(command)
810 remainder = commandsList[1:]
811 QTimer.singleShot(2, lambda: remainingTask(remainder))
812 778
813 @pyqtSlot() 779 @pyqtSlot()
814 def on_runButton_clicked(self): 780 def on_runButton_clicked(self):
815 """ 781 """
816 Private slot to execute the script of the active editor on the 782 Private slot to execute the script of the active editor on the
845 self.tr("""<p>Cannot run script.</p><p>Reason:""" 811 self.tr("""<p>Cannot run script.</p><p>Reason:"""
846 """ {0}</p>""").format(reason)) 812 """ {0}</p>""").format(reason))
847 return 813 return
848 814
849 if not self.__replRunning: 815 if not self.__replRunning:
850 self.on_replButton_clicked() 816 # switch on the REPL
817 self.on_replButton_clicked(True)
851 if self.__replRunning: 818 if self.__replRunning:
852 self.__device.runScript(script) 819 self.__device.runScript(script)
853 820
854 @pyqtSlot() 821 @pyqtSlot()
855 def on_openButton_clicked(self): 822 def on_openButton_clicked(self):
881 workspace = self.__device.getWorkspace() 848 workspace = self.__device.getWorkspace()
882 aw = e5App().getObject("ViewManager").activeWindow() 849 aw = e5App().getObject("ViewManager").activeWindow()
883 if aw: 850 if aw:
884 aw.saveFileAs(workspace) 851 aw.saveFileAs(workspace)
885 852
886 @pyqtSlot() 853 @pyqtSlot(bool)
887 def on_chartButton_clicked(self): 854 def on_chartButton_clicked(self, checked):
888 """ 855 """
889 Private slot to open a chart view to plot data received from the 856 Private slot to open a chart view to plot data received from the
890 connected device. 857 connected device.
858
859 @param checked state of the button
860 @type bool
891 """ 861 """
892 if not HAS_QTCHART: 862 if not HAS_QTCHART:
893 # QtChart not available => fail silently 863 # QtChart not available => fail silently
894 return 864 return
895 865
896 if not self.__device: 866 if not self.__device:
897 self.__showNoDeviceMessage() 867 self.__showNoDeviceMessage()
898 return 868 return
899 869
900 if self.__plotterRunning: 870 if checked:
871 ok, reason = self.__device.canStartPlotter()
872 if not ok:
873 E5MessageBox.warning(
874 self,
875 self.tr("Start Chart"),
876 self.tr("""<p>The Chart cannot be started.</p><p>Reason:"""
877 """ {0}</p>""").format(reason))
878 return
879
880 self.__chartWidget = MicroPythonGraphWidget(self)
881 self.__interface.dataReceived.connect(
882 self.__chartWidget.processData)
883 self.__chartWidget.dataFlood.connect(
884 self.handleDataFlood)
885
886 self.__ui.addSideWidget(self.__ui.BottomSide, self.__chartWidget,
887 UI.PixmapCache.getIcon("chart"),
888 self.tr("μPy Chart"))
889 self.__ui.showSideWidget(self.__chartWidget)
890
891 if not self.__interface.isConnected():
892 self.__connectToDevice()
893 if self.__device.forceInterrupt():
894 # send a Ctrl-B (exit raw mode)
895 self.__interface.write(b'\x02')
896 # send Ctrl-C (keyboard interrupt)
897 self.__interface.write(b'\x03')
898
899 self.__plotterRunning = True
900 self.__device.setPlotter(True)
901 else:
901 if self.__chartWidget.isDirty(): 902 if self.__chartWidget.isDirty():
902 res = E5MessageBox.okToClearData( 903 res = E5MessageBox.okToClearData(
903 self, 904 self,
904 self.tr("Unsaved Chart Data"), 905 self.tr("Unsaved Chart Data"),
905 self.tr("""The chart contains unsaved data."""), 906 self.tr("""The chart contains unsaved data."""),
906 self.__chartWidget.saveData) 907 self.__chartWidget.saveData)
907 if not res: 908 if not res:
908 # abort 909 # abort
909 return 910 return
910 911
911 self.dataReceived.disconnect(self.__chartWidget.processData) 912 self.__interface.dataReceived.disconnect(
912 self.__chartWidget.dataFlood.disconnect(self.handleDataFlood) 913 self.__chartWidget.processData)
913 914 self.__chartWidget.dataFlood.disconnect(
914 if not self.__replRunning: 915 self.handleDataFlood)
915 self.__disconnectSerial() 916
917 if not self.__replRunning and not self.__fileManagerRunning:
918 self.__disconnectFromDevice()
916 919
917 self.__plotterRunning = False 920 self.__plotterRunning = False
918 self.__device.setPlotter(False) 921 self.__device.setPlotter(False)
919 self.__ui.removeSideWidget(self.__chartWidget) 922 self.__ui.removeSideWidget(self.__chartWidget)
920 else: 923
921 ok, reason = self.__device.canStartPlotter() 924 self.__chartWidget.deleteLater()
922 if not ok: 925 self.__chartWidget = None
923 E5MessageBox.warning( 926
924 self, 927 self.chartButton.setChecked(checked)
925 self.tr("Start Chart"),
926 self.tr("""<p>The Chart cannot be started.</p><p>Reason:"""
927 """ {0}</p>""").format(reason))
928 return
929
930 self.__chartWidget = MicroPythonGraphWidget(self)
931 self.dataReceived.connect(self.__chartWidget.processData)
932 self.__chartWidget.dataFlood.connect(self.handleDataFlood)
933
934 self.__ui.addSideWidget(self.__ui.BottomSide, self.__chartWidget,
935 UI.PixmapCache.getIcon("chart"),
936 self.tr("μPy Chart"))
937 self.__ui.showSideWidget(self.__chartWidget)
938
939 if not self.__serial:
940 self.__openSerialLink()
941 if self.__serial:
942 if self.__device.forceInterrupt():
943 # send a Ctrl-B (exit raw mode)
944 self.__serial.write(b'\x02')
945 # send Ctrl-C (keyboard interrupt)
946 self.__serial.write(b'\x03')
947
948 self.__plotterRunning = True
949 self.__device.setPlotter(True)
950 928
951 @pyqtSlot() 929 @pyqtSlot()
952 def handleDataFlood(self): 930 def handleDataFlood(self):
953 """ 931 """
954 Public slot handling a data flood from the device. 932 Public slot handling a data flood from the device.
955 """ 933 """
956 self.on_disconnectButton_clicked() 934 self.on_disconnectButton_clicked()
957 self.__device.handleDataFlood() 935 self.__device.handleDataFlood()
958 936
959 @pyqtSlot() 937 @pyqtSlot(bool)
960 def on_filesButton_clicked(self): 938 def on_filesButton_clicked(self, checked):
961 """ 939 """
962 Private slot to open a file manager window to the connected device. 940 Private slot to open a file manager window to the connected device.
941
942 @param checked state of the button
943 @type bool
963 """ 944 """
964 if not self.__device: 945 if not self.__device:
965 self.__showNoDeviceMessage() 946 self.__showNoDeviceMessage()
966 return 947 return
967 948
968 if self.__fileManagerRunning: 949 if checked:
969 self.__fileManagerWidget.stop()
970 self.__ui.removeSideWidget(self.__fileManagerWidget)
971
972 self.__device.setFileManager(False)
973 self.__fileManagerRunning = False
974 else:
975 ok, reason = self.__device.canStartFileManager() 950 ok, reason = self.__device.canStartFileManager()
976 if not ok: 951 if not ok:
977 E5MessageBox.warning( 952 E5MessageBox.warning(
978 self, 953 self,
979 self.tr("Start File Manager"), 954 self.tr("Start File Manager"),
980 self.tr("""<p>The File Manager cannot be started.</p>""" 955 self.tr("""<p>The File Manager cannot be started.</p>"""
981 """<p>Reason: {0}</p>""").format(reason)) 956 """<p>Reason: {0}</p>""").format(reason))
982 return 957 return
983 958
984 port = self.__getCurrentPort() 959 if not self.__interface.isConnected():
985 self.__fileManagerWidget = MicroPythonFileManagerWidget(port, self) 960 self.__connectToDevice()
961 self.__fileManagerWidget = MicroPythonFileManagerWidget(
962 self.__interface, self)
986 963
987 self.__ui.addSideWidget(self.__ui.BottomSide, 964 self.__ui.addSideWidget(self.__ui.BottomSide,
988 self.__fileManagerWidget, 965 self.__fileManagerWidget,
989 UI.PixmapCache.getIcon("filemanager"), 966 UI.PixmapCache.getIcon("filemanager"),
990 self.tr("μPy Files")) 967 self.tr("μPy Files"))
992 969
993 self.__device.setFileManager(True) 970 self.__device.setFileManager(True)
994 self.__fileManagerRunning = True 971 self.__fileManagerRunning = True
995 972
996 self.__fileManagerWidget.start() 973 self.__fileManagerWidget.start()
974 else:
975 self.__fileManagerWidget.stop()
976 self.__ui.removeSideWidget(self.__fileManagerWidget)
977
978 self.__device.setFileManager(False)
979 self.__fileManagerRunning = False
980 self.__fileManagerWidget.deleteLater()
981 self.__fileManagerWidget = None

eric ide

mercurial