src/eric7/MicroPython/MicroPythonFileManagerWidget.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9238
a7cbf3d61498
equal deleted inserted replaced
9220:e9e7eca7efee 9221:bf71ee032bb4
10 import os 10 import os
11 import shutil 11 import shutil
12 12
13 from PyQt6.QtCore import pyqtSlot, Qt, QPoint 13 from PyQt6.QtCore import pyqtSlot, Qt, QPoint
14 from PyQt6.QtWidgets import ( 14 from PyQt6.QtWidgets import (
15 QWidget, QTreeWidgetItem, QHeaderView, QMenu, QInputDialog, QLineEdit, 15 QWidget,
16 QDialog 16 QTreeWidgetItem,
17 QHeaderView,
18 QMenu,
19 QInputDialog,
20 QLineEdit,
21 QDialog,
17 ) 22 )
18 23
19 from EricWidgets import EricMessageBox, EricPathPickerDialog 24 from EricWidgets import EricMessageBox, EricPathPickerDialog
20 from EricWidgets.EricPathPicker import EricPathPickerModes 25 from EricWidgets.EricPathPicker import EricPathPickerModes
21 from EricWidgets.EricFileSaveConfirmDialog import confirmOverwrite 26 from EricWidgets.EricFileSaveConfirmDialog import confirmOverwrite
23 28
24 from .Ui_MicroPythonFileManagerWidget import Ui_MicroPythonFileManagerWidget 29 from .Ui_MicroPythonFileManagerWidget import Ui_MicroPythonFileManagerWidget
25 30
26 from .MicroPythonFileManager import MicroPythonFileManager 31 from .MicroPythonFileManager import MicroPythonFileManager
27 from .MicroPythonFileSystemUtilities import ( 32 from .MicroPythonFileSystemUtilities import (
28 mtime2string, mode2string, decoratedName, listdirStat 33 mtime2string,
34 mode2string,
35 decoratedName,
36 listdirStat,
29 ) 37 )
30 38
31 from UI.DeleteFilesConfirmationDialog import DeleteFilesConfirmationDialog 39 from UI.DeleteFilesConfirmationDialog import DeleteFilesConfirmationDialog
32 40
33 import UI.PixmapCache 41 import UI.PixmapCache
38 46
39 class MicroPythonFileManagerWidget(QWidget, Ui_MicroPythonFileManagerWidget): 47 class MicroPythonFileManagerWidget(QWidget, Ui_MicroPythonFileManagerWidget):
40 """ 48 """
41 Class implementing a file manager for MicroPython devices. 49 Class implementing a file manager for MicroPython devices.
42 """ 50 """
51
43 def __init__(self, commandsInterface, deviceWithLocalAccess, parent=None): 52 def __init__(self, commandsInterface, deviceWithLocalAccess, parent=None):
44 """ 53 """
45 Constructor 54 Constructor
46 55
47 @param commandsInterface reference to the commands interface object 56 @param commandsInterface reference to the commands interface object
48 @type MicroPythonCommandsInterface 57 @type MicroPythonCommandsInterface
49 @param deviceWithLocalAccess flag indicating the device supports file 58 @param deviceWithLocalAccess flag indicating the device supports file
50 access via a local directory 59 access via a local directory
51 @type bool 60 @type bool
52 @param parent reference to the parent widget 61 @param parent reference to the parent widget
53 @type QWidget 62 @type QWidget
54 """ 63 """
55 super().__init__(parent) 64 super().__init__(parent)
56 self.setupUi(self) 65 self.setupUi(self)
57 66
58 self.__repl = parent 67 self.__repl = parent
59 self.__deviceWithLocalAccess = deviceWithLocalAccess 68 self.__deviceWithLocalAccess = deviceWithLocalAccess
60 69
61 self.syncButton.setIcon(UI.PixmapCache.getIcon("2rightarrow")) 70 self.syncButton.setIcon(UI.PixmapCache.getIcon("2rightarrow"))
62 self.putButton.setIcon(UI.PixmapCache.getIcon("1rightarrow")) 71 self.putButton.setIcon(UI.PixmapCache.getIcon("1rightarrow"))
63 self.putAsButton.setIcon(UI.PixmapCache.getIcon("putAs")) 72 self.putAsButton.setIcon(UI.PixmapCache.getIcon("putAs"))
64 self.getButton.setIcon(UI.PixmapCache.getIcon("1leftarrow")) 73 self.getButton.setIcon(UI.PixmapCache.getIcon("1leftarrow"))
65 self.getAsButton.setIcon(UI.PixmapCache.getIcon("getAs")) 74 self.getAsButton.setIcon(UI.PixmapCache.getIcon("getAs"))
67 self.localHomeButton.setIcon(UI.PixmapCache.getIcon("home")) 76 self.localHomeButton.setIcon(UI.PixmapCache.getIcon("home"))
68 self.localReloadButton.setIcon(UI.PixmapCache.getIcon("reload")) 77 self.localReloadButton.setIcon(UI.PixmapCache.getIcon("reload"))
69 self.deviceUpButton.setIcon(UI.PixmapCache.getIcon("1uparrow")) 78 self.deviceUpButton.setIcon(UI.PixmapCache.getIcon("1uparrow"))
70 self.deviceHomeButton.setIcon(UI.PixmapCache.getIcon("home")) 79 self.deviceHomeButton.setIcon(UI.PixmapCache.getIcon("home"))
71 self.deviceReloadButton.setIcon(UI.PixmapCache.getIcon("reload")) 80 self.deviceReloadButton.setIcon(UI.PixmapCache.getIcon("reload"))
72 81
73 self.deviceUpButton.setEnabled(not self.__repl.isMicrobit()) 82 self.deviceUpButton.setEnabled(not self.__repl.isMicrobit())
74 self.deviceHomeButton.setEnabled(not self.__repl.isMicrobit()) 83 self.deviceHomeButton.setEnabled(not self.__repl.isMicrobit())
75 84
76 self.putButton.setEnabled(False) 85 self.putButton.setEnabled(False)
77 self.putAsButton.setEnabled(False) 86 self.putAsButton.setEnabled(False)
78 self.getButton.setEnabled(False) 87 self.getButton.setEnabled(False)
79 self.getAsButton.setEnabled(False) 88 self.getAsButton.setEnabled(False)
80 89
81 self.localFileTreeWidget.header().setSortIndicator( 90 self.localFileTreeWidget.header().setSortIndicator(
82 0, Qt.SortOrder.AscendingOrder) 91 0, Qt.SortOrder.AscendingOrder
92 )
83 self.deviceFileTreeWidget.header().setSortIndicator( 93 self.deviceFileTreeWidget.header().setSortIndicator(
84 0, Qt.SortOrder.AscendingOrder) 94 0, Qt.SortOrder.AscendingOrder
85 95 )
96
86 self.__progressInfoDialog = None 97 self.__progressInfoDialog = None
87 self.__fileManager = MicroPythonFileManager(commandsInterface, self) 98 self.__fileManager = MicroPythonFileManager(commandsInterface, self)
88 99
89 self.__fileManager.longListFiles.connect(self.__handleLongListFiles) 100 self.__fileManager.longListFiles.connect(self.__handleLongListFiles)
90 self.__fileManager.currentDir.connect(self.__handleCurrentDir) 101 self.__fileManager.currentDir.connect(self.__handleCurrentDir)
91 self.__fileManager.currentDirChanged.connect(self.__handleCurrentDir) 102 self.__fileManager.currentDirChanged.connect(self.__handleCurrentDir)
92 self.__fileManager.putFileDone.connect(self.__newDeviceList) 103 self.__fileManager.putFileDone.connect(self.__newDeviceList)
93 self.__fileManager.getFileDone.connect(self.__handleGetDone) 104 self.__fileManager.getFileDone.connect(self.__handleGetDone)
94 self.__fileManager.rsyncDone.connect(self.__handleRsyncDone) 105 self.__fileManager.rsyncDone.connect(self.__handleRsyncDone)
95 self.__fileManager.rsyncProgressMessage.connect( 106 self.__fileManager.rsyncProgressMessage.connect(
96 self.__handleRsyncProgressMessage) 107 self.__handleRsyncProgressMessage
108 )
97 self.__fileManager.removeDirectoryDone.connect(self.__newDeviceList) 109 self.__fileManager.removeDirectoryDone.connect(self.__newDeviceList)
98 self.__fileManager.createDirectoryDone.connect(self.__newDeviceList) 110 self.__fileManager.createDirectoryDone.connect(self.__newDeviceList)
99 self.__fileManager.deleteFileDone.connect(self.__newDeviceList) 111 self.__fileManager.deleteFileDone.connect(self.__newDeviceList)
100 self.__fileManager.fsinfoDone.connect(self.__fsInfoResultReceived) 112 self.__fileManager.fsinfoDone.connect(self.__fsInfoResultReceived)
101 113
102 self.__fileManager.error.connect(self.__handleError) 114 self.__fileManager.error.connect(self.__handleError)
103 115
104 self.localFileTreeWidget.customContextMenuRequested.connect( 116 self.localFileTreeWidget.customContextMenuRequested.connect(
105 self.__showLocalContextMenu) 117 self.__showLocalContextMenu
118 )
106 self.deviceFileTreeWidget.customContextMenuRequested.connect( 119 self.deviceFileTreeWidget.customContextMenuRequested.connect(
107 self.__showDeviceContextMenu) 120 self.__showDeviceContextMenu
108 121 )
122
109 self.__localMenu = QMenu(self) 123 self.__localMenu = QMenu(self)
110 self.__localMenu.addAction(self.tr("Change Directory"),
111 self.__changeLocalDirectory)
112 self.__localMenu.addAction( 124 self.__localMenu.addAction(
113 self.tr("Create Directory"), self.__createLocalDirectory) 125 self.tr("Change Directory"), self.__changeLocalDirectory
126 )
127 self.__localMenu.addAction(
128 self.tr("Create Directory"), self.__createLocalDirectory
129 )
114 self.__localDelDirTreeAct = self.__localMenu.addAction( 130 self.__localDelDirTreeAct = self.__localMenu.addAction(
115 self.tr("Delete Directory Tree"), self.__deleteLocalDirectoryTree) 131 self.tr("Delete Directory Tree"), self.__deleteLocalDirectoryTree
132 )
116 self.__localMenu.addSeparator() 133 self.__localMenu.addSeparator()
117 self.__localDelFileAct = self.__localMenu.addAction( 134 self.__localDelFileAct = self.__localMenu.addAction(
118 self.tr("Delete File"), self.__deleteLocalFile) 135 self.tr("Delete File"), self.__deleteLocalFile
136 )
119 self.__localMenu.addSeparator() 137 self.__localMenu.addSeparator()
120 act = self.__localMenu.addAction(self.tr("Show Hidden Files")) 138 act = self.__localMenu.addAction(self.tr("Show Hidden Files"))
121 act.setCheckable(True) 139 act.setCheckable(True)
122 act.setChecked(Preferences.getMicroPython("ShowHiddenLocal")) 140 act.setChecked(Preferences.getMicroPython("ShowHiddenLocal"))
123 act.triggered[bool].connect(self.__localHiddenChanged) 141 act.triggered[bool].connect(self.__localHiddenChanged)
124 142
125 self.__deviceMenu = QMenu(self) 143 self.__deviceMenu = QMenu(self)
126 if not self.__repl.isMicrobit(): 144 if not self.__repl.isMicrobit():
127 self.__deviceMenu.addAction( 145 self.__deviceMenu.addAction(
128 self.tr("Change Directory"), self.__changeDeviceDirectory) 146 self.tr("Change Directory"), self.__changeDeviceDirectory
147 )
129 self.__deviceMenu.addAction( 148 self.__deviceMenu.addAction(
130 self.tr("Create Directory"), self.__createDeviceDirectory) 149 self.tr("Create Directory"), self.__createDeviceDirectory
150 )
131 if not self.__deviceWithLocalAccess: 151 if not self.__deviceWithLocalAccess:
132 self.__devDelDirAct = self.__deviceMenu.addAction( 152 self.__devDelDirAct = self.__deviceMenu.addAction(
133 self.tr("Delete Directory"), self.__deleteDeviceDirectory) 153 self.tr("Delete Directory"), self.__deleteDeviceDirectory
154 )
134 self.__devDelDirTreeAct = self.__deviceMenu.addAction( 155 self.__devDelDirTreeAct = self.__deviceMenu.addAction(
135 self.tr("Delete Directory Tree"), 156 self.tr("Delete Directory Tree"), self.__deleteDeviceDirectoryTree
136 self.__deleteDeviceDirectoryTree) 157 )
137 self.__deviceMenu.addSeparator() 158 self.__deviceMenu.addSeparator()
138 self.__devDelFileAct = self.__deviceMenu.addAction( 159 self.__devDelFileAct = self.__deviceMenu.addAction(
139 self.tr("Delete File"), self.__deleteDeviceFile) 160 self.tr("Delete File"), self.__deleteDeviceFile
161 )
140 self.__deviceMenu.addSeparator() 162 self.__deviceMenu.addSeparator()
141 act = self.__deviceMenu.addAction(self.tr("Show Hidden Files")) 163 act = self.__deviceMenu.addAction(self.tr("Show Hidden Files"))
142 act.setCheckable(True) 164 act.setCheckable(True)
143 act.setChecked(Preferences.getMicroPython("ShowHiddenDevice")) 165 act.setChecked(Preferences.getMicroPython("ShowHiddenDevice"))
144 act.triggered[bool].connect(self.__deviceHiddenChanged) 166 act.triggered[bool].connect(self.__deviceHiddenChanged)
145 if not parent.isMicrobit(): 167 if not parent.isMicrobit():
146 self.__deviceMenu.addSeparator() 168 self.__deviceMenu.addSeparator()
147 self.__deviceMenu.addAction( 169 self.__deviceMenu.addAction(
148 self.tr("Show Filesystem Info"), self.__showFileSystemInfo) 170 self.tr("Show Filesystem Info"), self.__showFileSystemInfo
149 171 )
172
150 def start(self): 173 def start(self):
151 """ 174 """
152 Public method to start the widget. 175 Public method to start the widget.
153 """ 176 """
154 dirname = "" 177 dirname = ""
156 aw = vm.activeWindow() 179 aw = vm.activeWindow()
157 if aw: 180 if aw:
158 dirname = os.path.dirname(aw.getFileName()) 181 dirname = os.path.dirname(aw.getFileName())
159 if not dirname: 182 if not dirname:
160 dirname = ( 183 dirname = (
161 Preferences.getMicroPython("MpyWorkspace") or 184 Preferences.getMicroPython("MpyWorkspace")
162 Preferences.getMultiProject("Workspace") or 185 or Preferences.getMultiProject("Workspace")
163 os.path.expanduser("~") 186 or os.path.expanduser("~")
164 ) 187 )
165 self.__listLocalFiles(dirname) 188 self.__listLocalFiles(dirname)
166 189
167 if self.__deviceWithLocalAccess: 190 if self.__deviceWithLocalAccess:
168 dirname = self.__repl.getDeviceWorkspace() 191 dirname = self.__repl.getDeviceWorkspace()
169 if dirname: 192 if dirname:
170 self.__listLocalFiles(dirname, True) 193 self.__listLocalFiles(dirname, True)
171 return 194 return
172 195
173 # list files via device script 196 # list files via device script
174 self.__fileManager.pwd() 197 self.__fileManager.pwd()
175 198
176 def stop(self): 199 def stop(self):
177 """ 200 """
178 Public method to stop the widget. 201 Public method to stop the widget.
179 """ 202 """
180 pass 203 pass
181 204
182 @pyqtSlot(str, str) 205 @pyqtSlot(str, str)
183 def __handleError(self, method, error): 206 def __handleError(self, method, error):
184 """ 207 """
185 Private slot to handle errors. 208 Private slot to handle errors.
186 209
187 @param method name of the method the error occured in 210 @param method name of the method the error occured in
188 @type str 211 @type str
189 @param error error message 212 @param error error message
190 @type str 213 @type str
191 """ 214 """
192 EricMessageBox.warning( 215 EricMessageBox.warning(
193 self, 216 self,
194 self.tr("Error handling device"), 217 self.tr("Error handling device"),
195 self.tr("<p>There was an error communicating with the connected" 218 self.tr(
196 " device.</p><p>Method: {0}</p><p>Message: {1}</p>") 219 "<p>There was an error communicating with the connected"
197 .format(method, error)) 220 " device.</p><p>Method: {0}</p><p>Message: {1}</p>"
198 221 ).format(method, error),
222 )
223
199 @pyqtSlot(str) 224 @pyqtSlot(str)
200 def __handleCurrentDir(self, dirname): 225 def __handleCurrentDir(self, dirname):
201 """ 226 """
202 Private slot to handle a change of the current directory of the device. 227 Private slot to handle a change of the current directory of the device.
203 228
204 @param dirname name of the current directory 229 @param dirname name of the current directory
205 @type str 230 @type str
206 """ 231 """
207 self.deviceCwd.setText(dirname) 232 self.deviceCwd.setText(dirname)
208 self.__newDeviceList() 233 self.__newDeviceList()
209 234
210 @pyqtSlot(tuple) 235 @pyqtSlot(tuple)
211 def __handleLongListFiles(self, filesList): 236 def __handleLongListFiles(self, filesList):
212 """ 237 """
213 Private slot to receive a long directory listing. 238 Private slot to receive a long directory listing.
214 239
215 @param filesList tuple containing tuples with name, mode, size and time 240 @param filesList tuple containing tuples with name, mode, size and time
216 for each directory entry 241 for each directory entry
217 @type tuple of (str, str, str, str) 242 @type tuple of (str, str, str, str)
218 """ 243 """
219 self.deviceFileTreeWidget.clear() 244 self.deviceFileTreeWidget.clear()
220 for name, mode, size, dateTime in filesList: 245 for name, mode, size, dateTime in filesList:
221 itm = QTreeWidgetItem(self.deviceFileTreeWidget, 246 itm = QTreeWidgetItem(
222 [name, mode, size, dateTime]) 247 self.deviceFileTreeWidget, [name, mode, size, dateTime]
248 )
223 itm.setTextAlignment(1, Qt.AlignmentFlag.AlignHCenter) 249 itm.setTextAlignment(1, Qt.AlignmentFlag.AlignHCenter)
224 itm.setTextAlignment(2, Qt.AlignmentFlag.AlignRight) 250 itm.setTextAlignment(2, Qt.AlignmentFlag.AlignRight)
225 self.deviceFileTreeWidget.header().resizeSections( 251 self.deviceFileTreeWidget.header().resizeSections(
226 QHeaderView.ResizeMode.ResizeToContents) 252 QHeaderView.ResizeMode.ResizeToContents
227 253 )
254
228 def __listLocalFiles(self, dirname="", localDevice=False): 255 def __listLocalFiles(self, dirname="", localDevice=False):
229 """ 256 """
230 Private method to populate the local files list. 257 Private method to populate the local files list.
231 258
232 @param dirname name of the local directory to be listed 259 @param dirname name of the local directory to be listed
233 @type str 260 @type str
234 @param localDevice flag indicating device access via local file system 261 @param localDevice flag indicating device access via local file system
235 @type bool 262 @type bool
236 """ 263 """
242 self.deviceCwd.setText(dirname) 269 self.deviceCwd.setText(dirname)
243 showHidden = Preferences.getMicroPython("ShowHiddenDevice") 270 showHidden = Preferences.getMicroPython("ShowHiddenDevice")
244 else: 271 else:
245 self.localCwd.setText(dirname) 272 self.localCwd.setText(dirname)
246 showHidden = Preferences.getMicroPython("ShowHiddenLocal") 273 showHidden = Preferences.getMicroPython("ShowHiddenLocal")
247 274
248 filesStatList = listdirStat(dirname, showHidden=showHidden) 275 filesStatList = listdirStat(dirname, showHidden=showHidden)
249 filesList = [( 276 filesList = [
250 decoratedName(f, s[0], os.path.isdir(os.path.join(dirname, f))), 277 (
251 mode2string(s[0]), 278 decoratedName(f, s[0], os.path.isdir(os.path.join(dirname, f))),
252 str(s[6]), 279 mode2string(s[0]),
253 mtime2string(s[8])) for f, s in filesStatList] 280 str(s[6]),
281 mtime2string(s[8]),
282 )
283 for f, s in filesStatList
284 ]
254 fileTreeWidget = ( 285 fileTreeWidget = (
255 self.deviceFileTreeWidget 286 self.deviceFileTreeWidget if localDevice else self.localFileTreeWidget
256 if localDevice else
257 self.localFileTreeWidget
258 ) 287 )
259 fileTreeWidget.clear() 288 fileTreeWidget.clear()
260 for item in filesList: 289 for item in filesList:
261 itm = QTreeWidgetItem(fileTreeWidget, item) 290 itm = QTreeWidgetItem(fileTreeWidget, item)
262 itm.setTextAlignment(1, Qt.AlignmentFlag.AlignHCenter) 291 itm.setTextAlignment(1, Qt.AlignmentFlag.AlignHCenter)
263 itm.setTextAlignment(2, Qt.AlignmentFlag.AlignRight) 292 itm.setTextAlignment(2, Qt.AlignmentFlag.AlignRight)
264 fileTreeWidget.header().resizeSections( 293 fileTreeWidget.header().resizeSections(QHeaderView.ResizeMode.ResizeToContents)
265 QHeaderView.ResizeMode.ResizeToContents) 294
266
267 @pyqtSlot(QTreeWidgetItem, int) 295 @pyqtSlot(QTreeWidgetItem, int)
268 def on_localFileTreeWidget_itemActivated(self, item, column): 296 def on_localFileTreeWidget_itemActivated(self, item, column):
269 """ 297 """
270 Private slot to handle the activation of a local item. 298 Private slot to handle the activation of a local item.
271 299
272 If the item is a directory, the list will be re-populated for this 300 If the item is a directory, the list will be re-populated for this
273 directory. 301 directory.
274 302
275 @param item reference to the activated item 303 @param item reference to the activated item
276 @type QTreeWidgetItem 304 @type QTreeWidgetItem
277 @param column column of the activation 305 @param column column of the activation
278 @type int 306 @type int
279 """ 307 """
281 if name.endswith("/"): 309 if name.endswith("/"):
282 # directory names end with a '/' 310 # directory names end with a '/'
283 self.__listLocalFiles(name[:-1]) 311 self.__listLocalFiles(name[:-1])
284 elif Utilities.MimeTypes.isTextFile(name): 312 elif Utilities.MimeTypes.isTextFile(name):
285 ericApp().getObject("ViewManager").getEditor(name) 313 ericApp().getObject("ViewManager").getEditor(name)
286 314
287 @pyqtSlot() 315 @pyqtSlot()
288 def on_localFileTreeWidget_itemSelectionChanged(self): 316 def on_localFileTreeWidget_itemSelectionChanged(self):
289 """ 317 """
290 Private slot handling a change of selection in the local pane. 318 Private slot handling a change of selection in the local pane.
291 """ 319 """
292 enable = bool(len(self.localFileTreeWidget.selectedItems())) 320 enable = bool(len(self.localFileTreeWidget.selectedItems()))
293 if enable: 321 if enable:
294 enable &= not ( 322 enable &= not (
295 self.localFileTreeWidget.selectedItems()[0].text(0) 323 self.localFileTreeWidget.selectedItems()[0].text(0).endswith("/")
296 .endswith("/")) 324 )
297 self.putButton.setEnabled(enable) 325 self.putButton.setEnabled(enable)
298 self.putAsButton.setEnabled(enable) 326 self.putAsButton.setEnabled(enable)
299 327
300 @pyqtSlot() 328 @pyqtSlot()
301 def on_localUpButton_clicked(self): 329 def on_localUpButton_clicked(self):
302 """ 330 """
303 Private slot to go up one directory level. 331 Private slot to go up one directory level.
304 """ 332 """
305 cwd = self.localCwd.text() 333 cwd = self.localCwd.text()
306 dirname = os.path.dirname(cwd) 334 dirname = os.path.dirname(cwd)
307 self.__listLocalFiles(dirname) 335 self.__listLocalFiles(dirname)
308 336
309 @pyqtSlot() 337 @pyqtSlot()
310 def on_localHomeButton_clicked(self): 338 def on_localHomeButton_clicked(self):
311 """ 339 """
312 Private slot to change directory to the configured workspace. 340 Private slot to change directory to the configured workspace.
313 """ 341 """
314 dirname = ( 342 dirname = (
315 Preferences.getMicroPython("MpyWorkspace") or 343 Preferences.getMicroPython("MpyWorkspace")
316 Preferences.getMultiProject("Workspace") or 344 or Preferences.getMultiProject("Workspace")
317 os.path.expanduser("~") 345 or os.path.expanduser("~")
318 ) 346 )
319 self.__listLocalFiles(dirname) 347 self.__listLocalFiles(dirname)
320 348
321 @pyqtSlot() 349 @pyqtSlot()
322 def on_localReloadButton_clicked(self): 350 def on_localReloadButton_clicked(self):
323 """ 351 """
324 Private slot to reload the local list. 352 Private slot to reload the local list.
325 """ 353 """
326 dirname = self.localCwd.text() 354 dirname = self.localCwd.text()
327 self.__listLocalFiles(dirname) 355 self.__listLocalFiles(dirname)
328 356
329 @pyqtSlot(QTreeWidgetItem, int) 357 @pyqtSlot(QTreeWidgetItem, int)
330 def on_deviceFileTreeWidget_itemActivated(self, item, column): 358 def on_deviceFileTreeWidget_itemActivated(self, item, column):
331 """ 359 """
332 Private slot to handle the activation of a device item. 360 Private slot to handle the activation of a device item.
333 361
334 If the item is a directory, the current working directory is changed 362 If the item is a directory, the current working directory is changed
335 and the list will be re-populated for this directory. 363 and the list will be re-populated for this directory.
336 364
337 @param item reference to the activated item 365 @param item reference to the activated item
338 @type QTreeWidgetItem 366 @type QTreeWidgetItem
339 @param column column of the activation 367 @param column column of the activation
340 @type int 368 @type int
341 """ 369 """
353 else: 381 else:
354 name = "{0}/{1}".format(cwd, item.text(0)) 382 name = "{0}/{1}".format(cwd, item.text(0))
355 if name.endswith("/"): 383 if name.endswith("/"):
356 # directory names end with a '/' 384 # directory names end with a '/'
357 self.__fileManager.cd(name[:-1]) 385 self.__fileManager.cd(name[:-1])
358 386
359 @pyqtSlot() 387 @pyqtSlot()
360 def on_deviceFileTreeWidget_itemSelectionChanged(self): 388 def on_deviceFileTreeWidget_itemSelectionChanged(self):
361 """ 389 """
362 Private slot handling a change of selection in the local pane. 390 Private slot handling a change of selection in the local pane.
363 """ 391 """
364 enable = bool(len(self.deviceFileTreeWidget.selectedItems())) 392 enable = bool(len(self.deviceFileTreeWidget.selectedItems()))
365 if enable: 393 if enable:
366 enable &= not ( 394 enable &= not (
367 self.deviceFileTreeWidget.selectedItems()[0].text(0) 395 self.deviceFileTreeWidget.selectedItems()[0].text(0).endswith("/")
368 .endswith("/")) 396 )
369 self.getButton.setEnabled(enable) 397 self.getButton.setEnabled(enable)
370 self.getAsButton.setEnabled(enable) 398 self.getAsButton.setEnabled(enable)
371 399
372 @pyqtSlot() 400 @pyqtSlot()
373 def on_deviceUpButton_clicked(self): 401 def on_deviceUpButton_clicked(self):
374 """ 402 """
375 Private slot to go up one directory level on the device. 403 Private slot to go up one directory level on the device.
376 """ 404 """
378 dirname = os.path.dirname(cwd) 406 dirname = os.path.dirname(cwd)
379 if self.__deviceWithLocalAccess: 407 if self.__deviceWithLocalAccess:
380 self.__listLocalFiles(dirname, True) 408 self.__listLocalFiles(dirname, True)
381 else: 409 else:
382 self.__fileManager.cd(dirname) 410 self.__fileManager.cd(dirname)
383 411
384 @pyqtSlot() 412 @pyqtSlot()
385 def on_deviceHomeButton_clicked(self): 413 def on_deviceHomeButton_clicked(self):
386 """ 414 """
387 Private slot to move to the device home directory. 415 Private slot to move to the device home directory.
388 """ 416 """
389 if self.__deviceWithLocalAccess: 417 if self.__deviceWithLocalAccess:
390 dirname = self.__repl.getDeviceWorkspace() 418 dirname = self.__repl.getDeviceWorkspace()
391 if dirname: 419 if dirname:
392 self.__listLocalFiles(dirname, True) 420 self.__listLocalFiles(dirname, True)
393 return 421 return
394 422
395 # list files via device script 423 # list files via device script
396 self.__fileManager.cd("/") 424 self.__fileManager.cd("/")
397 425
398 @pyqtSlot() 426 @pyqtSlot()
399 def on_deviceReloadButton_clicked(self): 427 def on_deviceReloadButton_clicked(self):
400 """ 428 """
401 Private slot to reload the device list. 429 Private slot to reload the device list.
402 """ 430 """
406 else: 434 else:
407 if dirname: 435 if dirname:
408 self.__newDeviceList() 436 self.__newDeviceList()
409 else: 437 else:
410 self.__fileManager.pwd() 438 self.__fileManager.pwd()
411 439
412 def __isFileInList(self, filename, treeWidget): 440 def __isFileInList(self, filename, treeWidget):
413 """ 441 """
414 Private method to check, if a file name is contained in a tree widget. 442 Private method to check, if a file name is contained in a tree widget.
415 443
416 @param filename name of the file to check 444 @param filename name of the file to check
417 @type str 445 @type str
418 @param treeWidget reference to the tree widget to be checked against 446 @param treeWidget reference to the tree widget to be checked against
419 @return flag indicating that the file name is present 447 @return flag indicating that the file name is present
420 @rtype bool 448 @rtype bool
421 """ 449 """
422 itemCount = treeWidget.topLevelItemCount() 450 itemCount = treeWidget.topLevelItemCount()
423 return ( 451 return itemCount > 0 and any(
424 itemCount > 0 and 452 treeWidget.topLevelItem(row).text(0) == filename for row in range(itemCount)
425 any(treeWidget.topLevelItem(row).text(0) == filename 453 )
426 for row in range(itemCount)) 454
427 )
428
429 @pyqtSlot() 455 @pyqtSlot()
430 def on_putButton_clicked(self, putAs=False): 456 def on_putButton_clicked(self, putAs=False):
431 """ 457 """
432 Private slot to copy the selected file to the connected device. 458 Private slot to copy the selected file to the connected device.
433 459
434 @param putAs flag indicating to give it a new name 460 @param putAs flag indicating to give it a new name
435 @type bool 461 @type bool
436 """ 462 """
437 selectedItems = self.localFileTreeWidget.selectedItems() 463 selectedItems = self.localFileTreeWidget.selectedItems()
438 if selectedItems: 464 if selectedItems:
443 deviceFilename, ok = QInputDialog.getText( 469 deviceFilename, ok = QInputDialog.getText(
444 self, 470 self,
445 self.tr("Put File As"), 471 self.tr("Put File As"),
446 self.tr("Enter a new name for the file"), 472 self.tr("Enter a new name for the file"),
447 QLineEdit.EchoMode.Normal, 473 QLineEdit.EchoMode.Normal,
448 filename) 474 filename,
475 )
449 if not ok or not filename: 476 if not ok or not filename:
450 return 477 return
451 else: 478 else:
452 deviceFilename = filename 479 deviceFilename = filename
453 480
454 if self.__isFileInList(deviceFilename, 481 if self.__isFileInList(deviceFilename, self.deviceFileTreeWidget):
455 self.deviceFileTreeWidget):
456 # ask for overwrite permission 482 # ask for overwrite permission
457 action, resultFilename = confirmOverwrite( 483 action, resultFilename = confirmOverwrite(
458 deviceFilename, self.tr("Copy File to Device"), 484 deviceFilename,
459 self.tr("The given file exists already" 485 self.tr("Copy File to Device"),
460 " (Enter file name only)."), 486 self.tr(
461 False, self) 487 "The given file exists already" " (Enter file name only)."
488 ),
489 False,
490 self,
491 )
462 if action == "cancel": 492 if action == "cancel":
463 return 493 return
464 elif action == "rename": 494 elif action == "rename":
465 deviceFilename = os.path.basename(resultFilename) 495 deviceFilename = os.path.basename(resultFilename)
466 496
467 if self.__deviceWithLocalAccess: 497 if self.__deviceWithLocalAccess:
468 shutil.copy2( 498 shutil.copy2(
469 os.path.join(self.localCwd.text(), filename), 499 os.path.join(self.localCwd.text(), filename),
470 os.path.join(self.deviceCwd.text(), deviceFilename) 500 os.path.join(self.deviceCwd.text(), deviceFilename),
471 ) 501 )
472 self.__listLocalFiles(self.deviceCwd.text(), 502 self.__listLocalFiles(self.deviceCwd.text(), localDevice=True)
473 localDevice=True)
474 else: 503 else:
475 deviceCwd = self.deviceCwd.text() 504 deviceCwd = self.deviceCwd.text()
476 if deviceCwd: 505 if deviceCwd:
477 if deviceCwd != "/": 506 if deviceCwd != "/":
478 deviceFilename = deviceCwd + "/" + deviceFilename 507 deviceFilename = deviceCwd + "/" + deviceFilename
479 else: 508 else:
480 deviceFilename = "/" + deviceFilename 509 deviceFilename = "/" + deviceFilename
481 self.__fileManager.put( 510 self.__fileManager.put(
482 os.path.join(self.localCwd.text(), filename), 511 os.path.join(self.localCwd.text(), filename), deviceFilename
483 deviceFilename
484 ) 512 )
485 513
486 @pyqtSlot() 514 @pyqtSlot()
487 def on_putAsButton_clicked(self): 515 def on_putAsButton_clicked(self):
488 """ 516 """
489 Private slot to copy the selected file to the connected device 517 Private slot to copy the selected file to the connected device
490 with a different name. 518 with a different name.
491 """ 519 """
492 self.on_putButton_clicked(putAs=True) 520 self.on_putButton_clicked(putAs=True)
493 521
494 @pyqtSlot() 522 @pyqtSlot()
495 def on_getButton_clicked(self, getAs=False): 523 def on_getButton_clicked(self, getAs=False):
496 """ 524 """
497 Private slot to copy the selected file from the connected device. 525 Private slot to copy the selected file from the connected device.
498 526
499 @param getAs flag indicating to give it a new name 527 @param getAs flag indicating to give it a new name
500 @type bool 528 @type bool
501 """ 529 """
502 selectedItems = self.deviceFileTreeWidget.selectedItems() 530 selectedItems = self.deviceFileTreeWidget.selectedItems()
503 if selectedItems: 531 if selectedItems:
508 localFilename, ok = QInputDialog.getText( 536 localFilename, ok = QInputDialog.getText(
509 self, 537 self,
510 self.tr("Get File As"), 538 self.tr("Get File As"),
511 self.tr("Enter a new name for the file"), 539 self.tr("Enter a new name for the file"),
512 QLineEdit.EchoMode.Normal, 540 QLineEdit.EchoMode.Normal,
513 filename) 541 filename,
542 )
514 if not ok or not filename: 543 if not ok or not filename:
515 return 544 return
516 else: 545 else:
517 localFilename = filename 546 localFilename = filename
518 547
519 if self.__isFileInList(localFilename, 548 if self.__isFileInList(localFilename, self.localFileTreeWidget):
520 self.localFileTreeWidget):
521 # ask for overwrite permission 549 # ask for overwrite permission
522 action, resultFilename = confirmOverwrite( 550 action, resultFilename = confirmOverwrite(
523 localFilename, self.tr("Copy File from Device"), 551 localFilename,
552 self.tr("Copy File from Device"),
524 self.tr("The given file exists already."), 553 self.tr("The given file exists already."),
525 True, self) 554 True,
555 self,
556 )
526 if action == "cancel": 557 if action == "cancel":
527 return 558 return
528 elif action == "rename": 559 elif action == "rename":
529 localFilename = resultFilename 560 localFilename = resultFilename
530 561
531 if self.__deviceWithLocalAccess: 562 if self.__deviceWithLocalAccess:
532 shutil.copy2( 563 shutil.copy2(
533 os.path.join(self.deviceCwd.text(), filename), 564 os.path.join(self.deviceCwd.text(), filename),
534 os.path.join(self.localCwd.text(), localFilename) 565 os.path.join(self.localCwd.text(), localFilename),
535 ) 566 )
536 self.__listLocalFiles(self.localCwd.text()) 567 self.__listLocalFiles(self.localCwd.text())
537 else: 568 else:
538 deviceCwd = self.deviceCwd.text() 569 deviceCwd = self.deviceCwd.text()
539 if deviceCwd: 570 if deviceCwd:
540 filename = deviceCwd + "/" + filename 571 filename = deviceCwd + "/" + filename
541 self.__fileManager.get( 572 self.__fileManager.get(
542 filename, 573 filename, os.path.join(self.localCwd.text(), localFilename)
543 os.path.join(self.localCwd.text(), localFilename)
544 ) 574 )
545 575
546 @pyqtSlot() 576 @pyqtSlot()
547 def on_getAsButton_clicked(self): 577 def on_getAsButton_clicked(self):
548 """ 578 """
549 Private slot to copy the selected file from the connected device 579 Private slot to copy the selected file from the connected device
550 with a different name. 580 with a different name.
551 """ 581 """
552 self.on_getButton_clicked(getAs=True) 582 self.on_getButton_clicked(getAs=True)
553 583
554 @pyqtSlot(str, str) 584 @pyqtSlot(str, str)
555 def __handleGetDone(self, deviceFile, localFile): 585 def __handleGetDone(self, deviceFile, localFile):
556 """ 586 """
557 Private slot handling a successful copy of a file from the device. 587 Private slot handling a successful copy of a file from the device.
558 588
559 @param deviceFile name of the file on the device 589 @param deviceFile name of the file on the device
560 @type str 590 @type str
561 @param localFile name of the local file 591 @param localFile name of the local file
562 @type str 592 @type str
563 """ 593 """
564 self.__listLocalFiles(self.localCwd.text()) 594 self.__listLocalFiles(self.localCwd.text())
565 595
566 @pyqtSlot() 596 @pyqtSlot()
567 def on_syncButton_clicked(self): 597 def on_syncButton_clicked(self):
568 """ 598 """
569 Private slot to synchronize the local directory to the device. 599 Private slot to synchronize the local directory to the device.
570 """ 600 """
572 self.localCwd.text(), 602 self.localCwd.text(),
573 self.deviceCwd.text(), 603 self.deviceCwd.text(),
574 mirror=True, 604 mirror=True,
575 localDevice=self.__deviceWithLocalAccess, 605 localDevice=self.__deviceWithLocalAccess,
576 ) 606 )
577 607
578 @pyqtSlot(str, str) 608 @pyqtSlot(str, str)
579 def __handleRsyncDone(self, localDir, deviceDir): 609 def __handleRsyncDone(self, localDir, deviceDir):
580 """ 610 """
581 Private method to handle the completion of the rsync operation. 611 Private method to handle the completion of the rsync operation.
582 612
583 @param localDir name of the local directory 613 @param localDir name of the local directory
584 @type str 614 @type str
585 @param deviceDir name of the device directory 615 @param deviceDir name of the device directory
586 @type str 616 @type str
587 """ 617 """
588 # simulate button presses to reload the two lists 618 # simulate button presses to reload the two lists
589 self.on_localReloadButton_clicked() 619 self.on_localReloadButton_clicked()
590 self.on_deviceReloadButton_clicked() 620 self.on_deviceReloadButton_clicked()
591 621
592 @pyqtSlot(str) 622 @pyqtSlot(str)
593 def __handleRsyncProgressMessage(self, message): 623 def __handleRsyncProgressMessage(self, message):
594 """ 624 """
595 Private slot handling progress messages sent by the file manager. 625 Private slot handling progress messages sent by the file manager.
596 626
597 @param message message to be shown 627 @param message message to be shown
598 @type str 628 @type str
599 """ 629 """
600 if self.__progressInfoDialog is None: 630 if self.__progressInfoDialog is None:
601 from .MicroPythonProgressInfoDialog import ( 631 from .MicroPythonProgressInfoDialog import MicroPythonProgressInfoDialog
602 MicroPythonProgressInfoDialog 632
603 )
604 self.__progressInfoDialog = MicroPythonProgressInfoDialog(self) 633 self.__progressInfoDialog = MicroPythonProgressInfoDialog(self)
605 self.__progressInfoDialog.finished.connect( 634 self.__progressInfoDialog.finished.connect(
606 self.__progressInfoDialogFinished) 635 self.__progressInfoDialogFinished
636 )
607 self.__progressInfoDialog.show() 637 self.__progressInfoDialog.show()
608 self.__progressInfoDialog.addMessage(message) 638 self.__progressInfoDialog.addMessage(message)
609 639
610 @pyqtSlot() 640 @pyqtSlot()
611 def __progressInfoDialogFinished(self): 641 def __progressInfoDialogFinished(self):
612 """ 642 """
613 Private slot handling the closing of the progress info dialog. 643 Private slot handling the closing of the progress info dialog.
614 """ 644 """
615 self.__progressInfoDialog.deleteLater() 645 self.__progressInfoDialog.deleteLater()
616 self.__progressInfoDialog = None 646 self.__progressInfoDialog = None
617 647
618 @pyqtSlot() 648 @pyqtSlot()
619 def __newDeviceList(self): 649 def __newDeviceList(self):
620 """ 650 """
621 Private slot to initiate a new long list of the device directory. 651 Private slot to initiate a new long list of the device directory.
622 """ 652 """
623 self.__fileManager.lls( 653 self.__fileManager.lls(
624 self.deviceCwd.text(), 654 self.deviceCwd.text(),
625 showHidden=Preferences.getMicroPython("ShowHiddenDevice") 655 showHidden=Preferences.getMicroPython("ShowHiddenDevice"),
626 ) 656 )
627 657
628 ################################################################## 658 ##################################################################
629 ## Context menu methods for the local files below 659 ## Context menu methods for the local files below
630 ################################################################## 660 ##################################################################
631 661
632 @pyqtSlot(QPoint) 662 @pyqtSlot(QPoint)
633 def __showLocalContextMenu(self, pos): 663 def __showLocalContextMenu(self, pos):
634 """ 664 """
635 Private slot to show the REPL context menu. 665 Private slot to show the REPL context menu.
636 666
637 @param pos position to show the menu at 667 @param pos position to show the menu at
638 @type QPoint 668 @type QPoint
639 """ 669 """
640 hasSelection = bool(len(self.localFileTreeWidget.selectedItems())) 670 hasSelection = bool(len(self.localFileTreeWidget.selectedItems()))
641 if hasSelection: 671 if hasSelection:
645 else: 675 else:
646 isDir = False 676 isDir = False
647 isFile = False 677 isFile = False
648 self.__localDelDirTreeAct.setEnabled(isDir) 678 self.__localDelDirTreeAct.setEnabled(isDir)
649 self.__localDelFileAct.setEnabled(isFile) 679 self.__localDelFileAct.setEnabled(isFile)
650 680
651 self.__localMenu.exec(self.localFileTreeWidget.mapToGlobal(pos)) 681 self.__localMenu.exec(self.localFileTreeWidget.mapToGlobal(pos))
652 682
653 @pyqtSlot() 683 @pyqtSlot()
654 def __changeLocalDirectory(self, localDevice=False): 684 def __changeLocalDirectory(self, localDevice=False):
655 """ 685 """
656 Private slot to change the local directory. 686 Private slot to change the local directory.
657 687
658 @param localDevice flag indicating device access via local file system 688 @param localDevice flag indicating device access via local file system
659 @type bool 689 @type bool
660 """ 690 """
661 cwdWidget = self.deviceCwd if localDevice else self.localCwd 691 cwdWidget = self.deviceCwd if localDevice else self.localCwd
662 692
663 dirPath, ok = EricPathPickerDialog.getPath( 693 dirPath, ok = EricPathPickerDialog.getPath(
664 self, 694 self,
665 self.tr("Change Directory"), 695 self.tr("Change Directory"),
666 self.tr("Select Directory"), 696 self.tr("Select Directory"),
667 EricPathPickerModes.DIRECTORY_SHOW_FILES_MODE, 697 EricPathPickerModes.DIRECTORY_SHOW_FILES_MODE,
671 if ok and dirPath: 701 if ok and dirPath:
672 if not os.path.isabs(dirPath): 702 if not os.path.isabs(dirPath):
673 dirPath = os.path.join(cwdWidget.text(), dirPath) 703 dirPath = os.path.join(cwdWidget.text(), dirPath)
674 cwdWidget.setText(dirPath) 704 cwdWidget.setText(dirPath)
675 self.__listLocalFiles(dirPath, localDevice=localDevice) 705 self.__listLocalFiles(dirPath, localDevice=localDevice)
676 706
677 @pyqtSlot() 707 @pyqtSlot()
678 def __createLocalDirectory(self, localDevice=False): 708 def __createLocalDirectory(self, localDevice=False):
679 """ 709 """
680 Private slot to create a local directory. 710 Private slot to create a local directory.
681 711
682 @param localDevice flag indicating device access via local file system 712 @param localDevice flag indicating device access via local file system
683 @type bool 713 @type bool
684 """ 714 """
685 cwdWidget = self.deviceCwd if localDevice else self.localCwd 715 cwdWidget = self.deviceCwd if localDevice else self.localCwd
686 716
687 dirPath, ok = QInputDialog.getText( 717 dirPath, ok = QInputDialog.getText(
688 self, 718 self,
689 self.tr("Create Directory"), 719 self.tr("Create Directory"),
690 self.tr("Enter directory name:"), 720 self.tr("Enter directory name:"),
691 QLineEdit.EchoMode.Normal) 721 QLineEdit.EchoMode.Normal,
722 )
692 if ok and dirPath: 723 if ok and dirPath:
693 dirPath = os.path.join(cwdWidget.text(), dirPath) 724 dirPath = os.path.join(cwdWidget.text(), dirPath)
694 try: 725 try:
695 os.mkdir(dirPath) 726 os.mkdir(dirPath)
696 self.__listLocalFiles(cwdWidget.text(), 727 self.__listLocalFiles(cwdWidget.text(), localDevice=localDevice)
697 localDevice=localDevice)
698 except OSError as exc: 728 except OSError as exc:
699 EricMessageBox.critical( 729 EricMessageBox.critical(
700 self, 730 self,
701 self.tr("Create Directory"), 731 self.tr("Create Directory"),
702 self.tr("""<p>The directory <b>{0}</b> could not be""" 732 self.tr(
703 """ created.</p><p>Reason: {1}</p>""").format( 733 """<p>The directory <b>{0}</b> could not be"""
704 dirPath, str(exc)) 734 """ created.</p><p>Reason: {1}</p>"""
735 ).format(dirPath, str(exc)),
705 ) 736 )
706 737
707 @pyqtSlot() 738 @pyqtSlot()
708 def __deleteLocalDirectoryTree(self, localDevice=False): 739 def __deleteLocalDirectoryTree(self, localDevice=False):
709 """ 740 """
710 Private slot to delete a local directory tree. 741 Private slot to delete a local directory tree.
711 742
712 @param localDevice flag indicating device access via local file system 743 @param localDevice flag indicating device access via local file system
713 @type bool 744 @type bool
714 """ 745 """
715 if localDevice: 746 if localDevice:
716 cwdWidget = self.deviceCwd 747 cwdWidget = self.deviceCwd
717 fileTreeWidget = self.deviceFileTreeWidget 748 fileTreeWidget = self.deviceFileTreeWidget
718 else: 749 else:
719 cwdWidget = self.localCwd 750 cwdWidget = self.localCwd
720 fileTreeWidget = self.localFileTreeWidget 751 fileTreeWidget = self.localFileTreeWidget
721 752
722 if bool(len(fileTreeWidget.selectedItems())): 753 if bool(len(fileTreeWidget.selectedItems())):
723 name = fileTreeWidget.selectedItems()[0].text(0) 754 name = fileTreeWidget.selectedItems()[0].text(0)
724 dirname = os.path.join(cwdWidget.text(), name[:-1]) 755 dirname = os.path.join(cwdWidget.text(), name[:-1])
725 dlg = DeleteFilesConfirmationDialog( 756 dlg = DeleteFilesConfirmationDialog(
726 self, 757 self,
727 self.tr("Delete Directory Tree"), 758 self.tr("Delete Directory Tree"),
728 self.tr( 759 self.tr("Do you really want to delete this directory tree?"),
729 "Do you really want to delete this directory tree?"), 760 [dirname],
730 [dirname]) 761 )
731 if dlg.exec() == QDialog.DialogCode.Accepted: 762 if dlg.exec() == QDialog.DialogCode.Accepted:
732 try: 763 try:
733 shutil.rmtree(dirname) 764 shutil.rmtree(dirname)
734 self.__listLocalFiles(cwdWidget.text(), 765 self.__listLocalFiles(cwdWidget.text(), localDevice=localDevice)
735 localDevice=localDevice)
736 except Exception as exc: 766 except Exception as exc:
737 EricMessageBox.critical( 767 EricMessageBox.critical(
738 self, 768 self,
739 self.tr("Delete Directory Tree"), 769 self.tr("Delete Directory Tree"),
740 self.tr("""<p>The directory <b>{0}</b> could not be""" 770 self.tr(
741 """ deleted.</p><p>Reason: {1}</p>""").format( 771 """<p>The directory <b>{0}</b> could not be"""
742 dirname, str(exc)) 772 """ deleted.</p><p>Reason: {1}</p>"""
773 ).format(dirname, str(exc)),
743 ) 774 )
744 775
745 @pyqtSlot() 776 @pyqtSlot()
746 def __deleteLocalFile(self, localDevice=False): 777 def __deleteLocalFile(self, localDevice=False):
747 """ 778 """
748 Private slot to delete a local file. 779 Private slot to delete a local file.
749 780
750 @param localDevice flag indicating device access via local file system 781 @param localDevice flag indicating device access via local file system
751 @type bool 782 @type bool
752 """ 783 """
753 if localDevice: 784 if localDevice:
754 cwdWidget = self.deviceCwd 785 cwdWidget = self.deviceCwd
755 fileTreeWidget = self.deviceFileTreeWidget 786 fileTreeWidget = self.deviceFileTreeWidget
756 else: 787 else:
757 cwdWidget = self.localCwd 788 cwdWidget = self.localCwd
758 fileTreeWidget = self.localFileTreeWidget 789 fileTreeWidget = self.localFileTreeWidget
759 790
760 if bool(len(fileTreeWidget.selectedItems())): 791 if bool(len(fileTreeWidget.selectedItems())):
761 name = fileTreeWidget.selectedItems()[0].text(0) 792 name = fileTreeWidget.selectedItems()[0].text(0)
762 filename = os.path.join(cwdWidget.text(), name) 793 filename = os.path.join(cwdWidget.text(), name)
763 dlg = DeleteFilesConfirmationDialog( 794 dlg = DeleteFilesConfirmationDialog(
764 self, 795 self,
765 self.tr("Delete File"), 796 self.tr("Delete File"),
766 self.tr( 797 self.tr("Do you really want to delete this file?"),
767 "Do you really want to delete this file?"), 798 [filename],
768 [filename]) 799 )
769 if dlg.exec() == QDialog.DialogCode.Accepted: 800 if dlg.exec() == QDialog.DialogCode.Accepted:
770 try: 801 try:
771 os.remove(filename) 802 os.remove(filename)
772 self.__listLocalFiles(cwdWidget.text(), 803 self.__listLocalFiles(cwdWidget.text(), localDevice=localDevice)
773 localDevice=localDevice)
774 except OSError as exc: 804 except OSError as exc:
775 EricMessageBox.critical( 805 EricMessageBox.critical(
776 self, 806 self,
777 self.tr("Delete File"), 807 self.tr("Delete File"),
778 self.tr("""<p>The file <b>{0}</b> could not be""" 808 self.tr(
779 """ deleted.</p><p>Reason: {1}</p>""").format( 809 """<p>The file <b>{0}</b> could not be"""
780 filename, str(exc)) 810 """ deleted.</p><p>Reason: {1}</p>"""
811 ).format(filename, str(exc)),
781 ) 812 )
782 813
783 @pyqtSlot(bool) 814 @pyqtSlot(bool)
784 def __localHiddenChanged(self, checked): 815 def __localHiddenChanged(self, checked):
785 """ 816 """
786 Private slot handling a change of the local show hidden menu entry. 817 Private slot handling a change of the local show hidden menu entry.
787 818
788 @param checked new check state of the action 819 @param checked new check state of the action
789 @type bool 820 @type bool
790 """ 821 """
791 Preferences.setMicroPython("ShowHiddenLocal", checked) 822 Preferences.setMicroPython("ShowHiddenLocal", checked)
792 self.on_localReloadButton_clicked() 823 self.on_localReloadButton_clicked()
793 824
794 ################################################################## 825 ##################################################################
795 ## Context menu methods for the device files below 826 ## Context menu methods for the device files below
796 ################################################################## 827 ##################################################################
797 828
798 @pyqtSlot(QPoint) 829 @pyqtSlot(QPoint)
799 def __showDeviceContextMenu(self, pos): 830 def __showDeviceContextMenu(self, pos):
800 """ 831 """
801 Private slot to show the REPL context menu. 832 Private slot to show the REPL context menu.
802 833
803 @param pos position to show the menu at 834 @param pos position to show the menu at
804 @type QPoint 835 @type QPoint
805 """ 836 """
806 hasSelection = bool(len(self.deviceFileTreeWidget.selectedItems())) 837 hasSelection = bool(len(self.deviceFileTreeWidget.selectedItems()))
807 if hasSelection: 838 if hasSelection:
814 if not self.__repl.isMicrobit(): 845 if not self.__repl.isMicrobit():
815 if not self.__deviceWithLocalAccess: 846 if not self.__deviceWithLocalAccess:
816 self.__devDelDirAct.setEnabled(isDir) 847 self.__devDelDirAct.setEnabled(isDir)
817 self.__devDelDirTreeAct.setEnabled(isDir) 848 self.__devDelDirTreeAct.setEnabled(isDir)
818 self.__devDelFileAct.setEnabled(isFile) 849 self.__devDelFileAct.setEnabled(isFile)
819 850
820 self.__deviceMenu.exec(self.deviceFileTreeWidget.mapToGlobal(pos)) 851 self.__deviceMenu.exec(self.deviceFileTreeWidget.mapToGlobal(pos))
821 852
822 @pyqtSlot() 853 @pyqtSlot()
823 def __changeDeviceDirectory(self): 854 def __changeDeviceDirectory(self):
824 """ 855 """
825 Private slot to change the current directory of the device. 856 Private slot to change the current directory of the device.
826 857
827 Note: This triggers a re-population of the device list for the new 858 Note: This triggers a re-population of the device list for the new
828 current directory. 859 current directory.
829 """ 860 """
830 if self.__deviceWithLocalAccess: 861 if self.__deviceWithLocalAccess:
831 self.__changeLocalDirectory(True) 862 self.__changeLocalDirectory(True)
833 dirPath, ok = QInputDialog.getText( 864 dirPath, ok = QInputDialog.getText(
834 self, 865 self,
835 self.tr("Change Directory"), 866 self.tr("Change Directory"),
836 self.tr("Enter the directory path on the device:"), 867 self.tr("Enter the directory path on the device:"),
837 QLineEdit.EchoMode.Normal, 868 QLineEdit.EchoMode.Normal,
838 self.deviceCwd.text()) 869 self.deviceCwd.text(),
870 )
839 if ok and dirPath: 871 if ok and dirPath:
840 if not dirPath.startswith("/"): 872 if not dirPath.startswith("/"):
841 dirPath = self.deviceCwd.text() + "/" + dirPath 873 dirPath = self.deviceCwd.text() + "/" + dirPath
842 self.__fileManager.cd(dirPath) 874 self.__fileManager.cd(dirPath)
843 875
844 @pyqtSlot() 876 @pyqtSlot()
845 def __createDeviceDirectory(self): 877 def __createDeviceDirectory(self):
846 """ 878 """
847 Private slot to create a directory on the device. 879 Private slot to create a directory on the device.
848 """ 880 """
851 else: 883 else:
852 dirPath, ok = QInputDialog.getText( 884 dirPath, ok = QInputDialog.getText(
853 self, 885 self,
854 self.tr("Create Directory"), 886 self.tr("Create Directory"),
855 self.tr("Enter directory name:"), 887 self.tr("Enter directory name:"),
856 QLineEdit.EchoMode.Normal) 888 QLineEdit.EchoMode.Normal,
889 )
857 if ok and dirPath: 890 if ok and dirPath:
858 self.__fileManager.mkdir(dirPath) 891 self.__fileManager.mkdir(dirPath)
859 892
860 @pyqtSlot() 893 @pyqtSlot()
861 def __deleteDeviceDirectory(self): 894 def __deleteDeviceDirectory(self):
862 """ 895 """
863 Private slot to delete an empty directory on the device. 896 Private slot to delete an empty directory on the device.
864 """ 897 """
876 else: 909 else:
877 dirname = name[:-1] 910 dirname = name[:-1]
878 dlg = DeleteFilesConfirmationDialog( 911 dlg = DeleteFilesConfirmationDialog(
879 self, 912 self,
880 self.tr("Delete Directory"), 913 self.tr("Delete Directory"),
881 self.tr( 914 self.tr("Do you really want to delete this directory?"),
882 "Do you really want to delete this directory?"), 915 [dirname],
883 [dirname]) 916 )
884 if dlg.exec() == QDialog.DialogCode.Accepted: 917 if dlg.exec() == QDialog.DialogCode.Accepted:
885 self.__fileManager.rmdir(dirname) 918 self.__fileManager.rmdir(dirname)
886 919
887 @pyqtSlot() 920 @pyqtSlot()
888 def __deleteDeviceDirectoryTree(self): 921 def __deleteDeviceDirectoryTree(self):
889 """ 922 """
890 Private slot to delete a directory and all its subdirectories 923 Private slot to delete a directory and all its subdirectories
891 recursively. 924 recursively.
904 else: 937 else:
905 dirname = name[:-1] 938 dirname = name[:-1]
906 dlg = DeleteFilesConfirmationDialog( 939 dlg = DeleteFilesConfirmationDialog(
907 self, 940 self,
908 self.tr("Delete Directory Tree"), 941 self.tr("Delete Directory Tree"),
909 self.tr( 942 self.tr("Do you really want to delete this directory tree?"),
910 "Do you really want to delete this directory tree?"), 943 [dirname],
911 [dirname]) 944 )
912 if dlg.exec() == QDialog.DialogCode.Accepted: 945 if dlg.exec() == QDialog.DialogCode.Accepted:
913 self.__fileManager.rmdir(dirname, recursive=True) 946 self.__fileManager.rmdir(dirname, recursive=True)
914 947
915 @pyqtSlot() 948 @pyqtSlot()
916 def __deleteDeviceFile(self): 949 def __deleteDeviceFile(self):
917 """ 950 """
918 Private slot to delete a file. 951 Private slot to delete a file.
919 """ 952 """
931 else: 964 else:
932 filename = name 965 filename = name
933 dlg = DeleteFilesConfirmationDialog( 966 dlg = DeleteFilesConfirmationDialog(
934 self, 967 self,
935 self.tr("Delete File"), 968 self.tr("Delete File"),
936 self.tr( 969 self.tr("Do you really want to delete this file?"),
937 "Do you really want to delete this file?"), 970 [filename],
938 [filename]) 971 )
939 if dlg.exec() == QDialog.DialogCode.Accepted: 972 if dlg.exec() == QDialog.DialogCode.Accepted:
940 self.__fileManager.delete(filename) 973 self.__fileManager.delete(filename)
941 974
942 @pyqtSlot(bool) 975 @pyqtSlot(bool)
943 def __deviceHiddenChanged(self, checked): 976 def __deviceHiddenChanged(self, checked):
944 """ 977 """
945 Private slot handling a change of the device show hidden menu entry. 978 Private slot handling a change of the device show hidden menu entry.
946 979
947 @param checked new check state of the action 980 @param checked new check state of the action
948 @type bool 981 @type bool
949 """ 982 """
950 Preferences.setMicroPython("ShowHiddenDevice", checked) 983 Preferences.setMicroPython("ShowHiddenDevice", checked)
951 self.on_deviceReloadButton_clicked() 984 self.on_deviceReloadButton_clicked()
952 985
953 @pyqtSlot() 986 @pyqtSlot()
954 def __showFileSystemInfo(self): 987 def __showFileSystemInfo(self):
955 """ 988 """
956 Private slot to show some file system information. 989 Private slot to show some file system information.
957 """ 990 """
958 self.__fileManager.fileSystemInfo() 991 self.__fileManager.fileSystemInfo()
959 992
960 @pyqtSlot(tuple) 993 @pyqtSlot(tuple)
961 def __fsInfoResultReceived(self, fsinfo): 994 def __fsInfoResultReceived(self, fsinfo):
962 """ 995 """
963 Private slot to show the file system information of the device. 996 Private slot to show the file system information of the device.
964 997
965 @param fsinfo tuple of tuples containing the file system name, the 998 @param fsinfo tuple of tuples containing the file system name, the
966 total size, the used size and the free size 999 total size, the used size and the free size
967 @type tuple of tuples of (str, int, int, int) 1000 @type tuple of tuples of (str, int, int, int)
968 """ 1001 """
969 msg = self.tr("<h3>Filesystem Information</h3>") 1002 msg = self.tr("<h3>Filesystem Information</h3>")
973 "<table>" 1006 "<table>"
974 "<tr><td>Total Size: </td><td align='right'>{1}</td></tr>" 1007 "<tr><td>Total Size: </td><td align='right'>{1}</td></tr>"
975 "<tr><td>Used Size: </td><td align='right'>{2}</td></tr>" 1008 "<tr><td>Used Size: </td><td align='right'>{2}</td></tr>"
976 "<tr><td>Free Size: </td><td align='right'>{3}</td></tr>" 1009 "<tr><td>Free Size: </td><td align='right'>{3}</td></tr>"
977 "</table>" 1010 "</table>"
978 ).format(name, 1011 ).format(
979 Globals.dataString(totalSize), 1012 name,
980 Globals.dataString(usedSize), 1013 Globals.dataString(totalSize),
981 Globals.dataString(freeSize), 1014 Globals.dataString(usedSize),
982 ) 1015 Globals.dataString(freeSize),
983 EricMessageBox.information( 1016 )
984 self, 1017 EricMessageBox.information(self, self.tr("Filesystem Information"), msg)
985 self.tr("Filesystem Information"),
986 msg)

eric ide

mercurial