|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2019 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing the device interface class for PyBoard boards. |
|
8 """ |
|
9 |
|
10 from E5Gui import E5MessageBox |
|
11 from E5Gui.E5Application import e5App |
|
12 |
|
13 from .MicroPythonDevices import MicroPythonDevice |
|
14 from .MicroPythonWidget import HAS_QTCHART |
|
15 |
|
16 import Utilities |
|
17 import Preferences |
|
18 |
|
19 |
|
20 class PyBoardDevice(MicroPythonDevice): |
|
21 """ |
|
22 Class implementing the device for PyBoard boards. |
|
23 """ |
|
24 DeviceVolumeName = "PYBFLASH" |
|
25 |
|
26 FlashInstructionsURL = ( |
|
27 "https://github.com/micropython/micropython/wiki/" |
|
28 "Pyboard-Firmware-Update" |
|
29 ) |
|
30 |
|
31 def __init__(self, microPythonWidget, parent=None): |
|
32 """ |
|
33 Constructor |
|
34 |
|
35 @param microPythonWidget reference to the main MicroPython widget |
|
36 @type MicroPythonWidget |
|
37 @param parent reference to the parent object |
|
38 @type QObject |
|
39 """ |
|
40 super(PyBoardDevice, self).__init__(microPythonWidget, parent) |
|
41 |
|
42 def setButtons(self): |
|
43 """ |
|
44 Public method to enable the supported action buttons. |
|
45 """ |
|
46 super(PyBoardDevice, self).setButtons() |
|
47 self.microPython.setActionButtons( |
|
48 run=True, repl=True, files=True, chart=HAS_QTCHART) |
|
49 |
|
50 if self.__deviceVolumeMounted(): |
|
51 self.microPython.setActionButtons(open=True, save=True) |
|
52 |
|
53 def forceInterrupt(self): |
|
54 """ |
|
55 Public method to determine the need for an interrupt when opening the |
|
56 serial connection. |
|
57 |
|
58 @return flag indicating an interrupt is needed |
|
59 @rtype bool |
|
60 """ |
|
61 return False |
|
62 |
|
63 def deviceName(self): |
|
64 """ |
|
65 Public method to get the name of the device. |
|
66 |
|
67 @return name of the device |
|
68 @rtype str |
|
69 """ |
|
70 return self.tr("PyBoard") |
|
71 |
|
72 def canStartRepl(self): |
|
73 """ |
|
74 Public method to determine, if a REPL can be started. |
|
75 |
|
76 @return tuple containing a flag indicating it is safe to start a REPL |
|
77 and a reason why it cannot. |
|
78 @rtype tuple of (bool, str) |
|
79 """ |
|
80 return True, "" |
|
81 |
|
82 def canStartPlotter(self): |
|
83 """ |
|
84 Public method to determine, if a Plotter can be started. |
|
85 |
|
86 @return tuple containing a flag indicating it is safe to start a |
|
87 Plotter and a reason why it cannot. |
|
88 @rtype tuple of (bool, str) |
|
89 """ |
|
90 return True, "" |
|
91 |
|
92 def canRunScript(self): |
|
93 """ |
|
94 Public method to determine, if a script can be executed. |
|
95 |
|
96 @return tuple containing a flag indicating it is safe to start a |
|
97 Plotter and a reason why it cannot. |
|
98 @rtype tuple of (bool, str) |
|
99 """ |
|
100 return True, "" |
|
101 |
|
102 def runScript(self, script): |
|
103 """ |
|
104 Public method to run the given Python script. |
|
105 |
|
106 @param script script to be executed |
|
107 @type str |
|
108 """ |
|
109 pythonScript = script.split("\n") |
|
110 self.sendCommands(pythonScript) |
|
111 |
|
112 def canStartFileManager(self): |
|
113 """ |
|
114 Public method to determine, if a File Manager can be started. |
|
115 |
|
116 @return tuple containing a flag indicating it is safe to start a |
|
117 File Manager and a reason why it cannot. |
|
118 @rtype tuple of (bool, str) |
|
119 """ |
|
120 return True, "" |
|
121 |
|
122 def supportsLocalFileAccess(self): |
|
123 """ |
|
124 Public method to indicate file access via a local directory. |
|
125 |
|
126 @return flag indicating file access via local directory |
|
127 @rtype bool |
|
128 """ |
|
129 return self.__deviceVolumeMounted() |
|
130 |
|
131 def __deviceVolumeMounted(self): |
|
132 """ |
|
133 Private method to check, if the device volume is mounted. |
|
134 |
|
135 @return flag indicated a mounted device |
|
136 @rtype bool |
|
137 """ |
|
138 return self.getWorkspace(silent=True).endswith(self.DeviceVolumeName) |
|
139 |
|
140 def getWorkspace(self, silent=False): |
|
141 """ |
|
142 Public method to get the workspace directory. |
|
143 |
|
144 @param silent flag indicating silent operations |
|
145 @type bool |
|
146 @return workspace directory used for saving files |
|
147 @rtype str |
|
148 """ |
|
149 # Attempts to find the path on the filesystem that represents the |
|
150 # plugged in PyBoard board. |
|
151 deviceDirectory = Utilities.findVolume(self.DeviceVolumeName) |
|
152 |
|
153 if deviceDirectory: |
|
154 return deviceDirectory |
|
155 else: |
|
156 # return the default workspace and give the user a warning (unless |
|
157 # silent mode is selected) |
|
158 if not silent: |
|
159 E5MessageBox.warning( |
|
160 self.microPython, |
|
161 self.tr("Workspace Directory"), |
|
162 self.tr("Python files for PyBoard devices are stored" |
|
163 " on the device. Therefore, to edit these files" |
|
164 " you need to have the device plugged in. Until" |
|
165 " you plug in a device, the standard directory" |
|
166 " will be used.")) |
|
167 |
|
168 return super(PyBoardDevice, self).getWorkspace() |
|
169 |
|
170 def getDocumentationUrl(self): |
|
171 """ |
|
172 Public method to get the device documentation URL. |
|
173 |
|
174 @return documentation URL of the device |
|
175 @rtype str |
|
176 """ |
|
177 return Preferences.getMicroPython("MicroPythonDocuUrl") |
|
178 |
|
179 def addDeviceMenuEntries(self, menu): |
|
180 """ |
|
181 Public method to add device specific entries to the given menu. |
|
182 |
|
183 @param menu reference to the context menu |
|
184 @type QMenu |
|
185 """ |
|
186 menu.addAction( |
|
187 self.tr("MicroPython Install Instructions"), |
|
188 self.__showInstallInstructions) |
|
189 |
|
190 def __showInstallInstructions(self): |
|
191 """ |
|
192 Private slot to open the URL containing instructions for installing |
|
193 MicroPython on the pyboard. |
|
194 """ |
|
195 e5App().getObject("UserInterface").launchHelpViewer( |
|
196 PyBoardDevice.FlashInstructionsURL) |