eric6/MicroPython/MicroPythonFileManagerWidget.py

branch
micropython
changeset 7131
f75e990caf99
parent 7130
6014d37d9683
child 7134
21d23ca51680
equal deleted inserted replaced
7130:6014d37d9683 7131:f75e990caf99
9 9
10 from __future__ import unicode_literals 10 from __future__ import unicode_literals
11 11
12 import os 12 import os
13 import shutil 13 import shutil
14 import time
15 14
16 from PyQt5.QtCore import pyqtSlot, Qt, QPoint 15 from PyQt5.QtCore import pyqtSlot, Qt, QPoint
17 from PyQt5.QtWidgets import ( 16 from PyQt5.QtWidgets import (
18 QWidget, QTreeWidgetItem, QHeaderView, QMenu, QInputDialog, QLineEdit, 17 QWidget, QTreeWidgetItem, QHeaderView, QMenu, QInputDialog, QLineEdit,
19 QDialog 18 QDialog
114 self.__localDelDirTreeAct = self.__localMenu.addAction( 113 self.__localDelDirTreeAct = self.__localMenu.addAction(
115 self.tr("Delete Directory Tree"), self.__deleteLocalDirectoryTree) 114 self.tr("Delete Directory Tree"), self.__deleteLocalDirectoryTree)
116 self.__localMenu.addSeparator() 115 self.__localMenu.addSeparator()
117 self.__localDelFileAct = self.__localMenu.addAction( 116 self.__localDelFileAct = self.__localMenu.addAction(
118 self.tr("Delete File"), self.__deleteLocalFile) 117 self.tr("Delete File"), self.__deleteLocalFile)
119 self.__localMenu.addSeparator()
120 self.__localMenu.addAction(
121 self.tr("Show Time"), self.__showLocalTime)
122 118
123 self.__deviceMenu = QMenu(self) 119 self.__deviceMenu = QMenu(self)
124 if not self.__repl.isMicrobit(): 120 if not self.__repl.isMicrobit():
125 self.__deviceMenu.addAction( 121 self.__deviceMenu.addAction(
126 self.tr("Change Directory"), self.__changeDeviceDirectory) 122 self.tr("Change Directory"), self.__changeDeviceDirectory)
127 self.__deviceMenu.addAction( 123 self.__deviceMenu.addAction(
128 self.tr("Create Directory"), self.__createDeviceDirectory) 124 self.tr("Create Directory"), self.__createDeviceDirectory)
129 self.__devDelDirAct = self.__deviceMenu.addAction( 125 if not self.__deviceWithLocalAccess:
130 self.tr("Delete Directory"), self.__deleteDeviceDirectory) 126 self.__devDelDirAct = self.__deviceMenu.addAction(
127 self.tr("Delete Directory"), self.__deleteDeviceDirectory)
131 self.__devDelDirTreeAct = self.__deviceMenu.addAction( 128 self.__devDelDirTreeAct = self.__deviceMenu.addAction(
132 self.tr("Delete Directory Tree"), 129 self.tr("Delete Directory Tree"),
133 self.__deleteDeviceDirectoryTree) 130 self.__deleteDeviceDirectoryTree)
134 self.__deviceMenu.addSeparator() 131 self.__deviceMenu.addSeparator()
135 self.__devDelFileAct = self.__deviceMenu.addAction( 132 self.__devDelFileAct = self.__deviceMenu.addAction(
296 Private slot to reload the local list. 293 Private slot to reload the local list.
297 """ 294 """
298 dirname = self.localCwd.text() 295 dirname = self.localCwd.text()
299 self.__listLocalFiles(dirname) 296 self.__listLocalFiles(dirname)
300 297
301 # TODO:
302 @pyqtSlot(QTreeWidgetItem, int) 298 @pyqtSlot(QTreeWidgetItem, int)
303 def on_deviceFileTreeWidget_itemActivated(self, item, column): 299 def on_deviceFileTreeWidget_itemActivated(self, item, column):
304 """ 300 """
305 Private slot to handle the activation of a device item. 301 Private slot to handle the activation of a device item.
306 302
311 @type QTreeWidgetItem 307 @type QTreeWidgetItem
312 @param column column of the activation 308 @param column column of the activation
313 @type int 309 @type int
314 """ 310 """
315 name = os.path.join(self.deviceCwd.text(), item.text(0)) 311 name = os.path.join(self.deviceCwd.text(), item.text(0))
316 if name.endswith("/"): 312 if self.__deviceWithLocalAccess:
317 # directory names end with a '/' 313 if name.endswith("/"):
318 self.__fileManager.cd(name[:-1]) 314 # directory names end with a '/'
315 self.__listLocalFiles(name[:-1], True)
316 elif Utilities.MimeTypes.isTextFile(name):
317 e5App().getObject("ViewManager").getEditor(name)
318 else:
319 if name.endswith("/"):
320 # directory names end with a '/'
321 self.__fileManager.cd(name[:-1])
319 322
320 @pyqtSlot() 323 @pyqtSlot()
321 def on_deviceFileTreeWidget_itemSelectionChanged(self): 324 def on_deviceFileTreeWidget_itemSelectionChanged(self):
322 """ 325 """
323 Private slot handling a change of selection in the local pane. 326 Private slot handling a change of selection in the local pane.
328 self.deviceFileTreeWidget.selectedItems()[0].text(0) 331 self.deviceFileTreeWidget.selectedItems()[0].text(0)
329 .endswith("/")) 332 .endswith("/"))
330 self.getButton.setEnabled(enable) 333 self.getButton.setEnabled(enable)
331 self.getAsButton.setEnabled(enable) 334 self.getAsButton.setEnabled(enable)
332 335
333 # TODO:
334 @pyqtSlot() 336 @pyqtSlot()
335 def on_deviceUpButton_clicked(self): 337 def on_deviceUpButton_clicked(self):
336 """ 338 """
337 Private slot to go up one directory level on the device. 339 Private slot to go up one directory level on the device.
338 """ 340 """
339 cwd = self.deviceCwd.text() 341 cwd = self.deviceCwd.text()
340 dirname = os.path.dirname(cwd) 342 dirname = os.path.dirname(cwd)
341 self.__fileManager.cd(dirname) 343 if self.__deviceWithLocalAccess:
342 344 self.__listLocalFiles(dirname, True)
343 # TODO: 345 else:
346 self.__fileManager.cd(dirname)
347
344 @pyqtSlot() 348 @pyqtSlot()
345 def on_deviceReloadButton_clicked(self): 349 def on_deviceReloadButton_clicked(self):
346 """ 350 """
347 Private slot to reload the device list. 351 Private slot to reload the device list.
348 """ 352 """
349 dirname = self.deviceCwd.text() 353 dirname = self.deviceCwd.text()
350 if dirname: 354 if self.__deviceWithLocalAccess:
351 self.__fileManager.lls(dirname) 355 self.__listLocalFiles(dirname, True)
352 else: 356 else:
353 self.__fileManager.pwd() 357 if dirname:
358 self.__fileManager.lls(dirname)
359 else:
360 self.__fileManager.pwd()
354 361
355 def __isFileInList(self, filename, treeWidget): 362 def __isFileInList(self, filename, treeWidget):
356 """ 363 """
357 Private method to check, if a file name is contained in a tree widget. 364 Private method to check, if a file name is contained in a tree widget.
358 365
368 if treeWidget.topLevelItem(row).text(0) == filename: 375 if treeWidget.topLevelItem(row).text(0) == filename:
369 return True 376 return True
370 377
371 return False 378 return False
372 379
373 # TODO:
374 @pyqtSlot() 380 @pyqtSlot()
375 def on_putButton_clicked(self, putAs=False): 381 def on_putButton_clicked(self, putAs=False):
376 """ 382 """
377 Private slot to copy the selected file to the connected device. 383 Private slot to copy the selected file to the connected device.
378 384
407 if action == "cancel": 413 if action == "cancel":
408 return 414 return
409 elif action == "rename": 415 elif action == "rename":
410 deviceFilename = os.path.basename(resultFilename) 416 deviceFilename = os.path.basename(resultFilename)
411 417
412 deviceCwd = self.deviceCwd.text() 418 if self.__deviceWithLocalAccess:
413 if deviceCwd: 419 shutil.copy2(
414 deviceFilename = deviceCwd + "/" + deviceFilename 420 os.path.join(self.localCwd.text(), filename),
415 self.__fileManager.put( 421 os.path.join(self.deviceCwd.text(), deviceFilename)
416 os.path.join(self.localCwd.text(), filename), 422 )
417 deviceFilename 423 self.__listLocalFiles(self.deviceCwd.text(),
418 ) 424 localDevice=True)
425 else:
426 deviceCwd = self.deviceCwd.text()
427 if deviceCwd and deviceCwd != "/":
428 deviceFilename = deviceCwd + "/" + deviceFilename
429 self.__fileManager.put(
430 os.path.join(self.localCwd.text(), filename),
431 deviceFilename
432 )
419 433
420 @pyqtSlot() 434 @pyqtSlot()
421 def on_putAsButton_clicked(self): 435 def on_putAsButton_clicked(self):
422 """ 436 """
423 Private slot to copy the selected file to the connected device 437 Private slot to copy the selected file to the connected device
424 with a different name. 438 with a different name.
425 """ 439 """
426 self.on_putButton_clicked(putAs=True) 440 self.on_putButton_clicked(putAs=True)
427 441
428 # TODO:
429 @pyqtSlot() 442 @pyqtSlot()
430 def on_getButton_clicked(self, getAs=False): 443 def on_getButton_clicked(self, getAs=False):
431 """ 444 """
432 Private slot to copy the selected file from the connected device. 445 Private slot to copy the selected file from the connected device.
433 446
461 if action == "cancel": 474 if action == "cancel":
462 return 475 return
463 elif action == "rename": 476 elif action == "rename":
464 localFilename = resultFilename 477 localFilename = resultFilename
465 478
466 deviceCwd = self.deviceCwd.text() 479 if self.__deviceWithLocalAccess:
467 if deviceCwd: 480 shutil.copy2(
468 filename = deviceCwd + "/" + filename 481 os.path.join(self.deviceCwd.text(), filename),
469 if not os.path.isabs(localFilename): 482 os.path.join(self.localCwd.text(), localFilename)
470 localFilename = os.path.join(self.localCwd.text(), 483 )
471 localFilename) 484 self.__listLocalFiles(self.localCwd.text())
472 self.__fileManager.get( 485 else:
473 filename, 486 deviceCwd = self.deviceCwd.text()
474 localFilename 487 if deviceCwd:
475 ) 488 filename = deviceCwd + "/" + filename
489 self.__fileManager.get(
490 filename,
491 os.path.join(self.localCwd.text(), localFilename)
492 )
476 493
477 @pyqtSlot() 494 @pyqtSlot()
478 def on_getAsButton_clicked(self): 495 def on_getAsButton_clicked(self):
479 """ 496 """
480 Private slot to copy the selected file from the connected device 497 Private slot to copy the selected file from the connected device
492 @param localFile name of the local file 509 @param localFile name of the local file
493 @type str 510 @type str
494 """ 511 """
495 self.__listLocalFiles(self.localCwd.text()) 512 self.__listLocalFiles(self.localCwd.text())
496 513
497 # TODO:
498 @pyqtSlot() 514 @pyqtSlot()
499 def on_syncButton_clicked(self): 515 def on_syncButton_clicked(self):
500 """ 516 """
501 Private slot to synchronize the local directory to the device. 517 Private slot to synchronize the local directory to the device.
502 """ 518 """
503 self.__fileManager.rsync( 519 self.__fileManager.rsync(
504 self.localCwd.text(), 520 self.localCwd.text(),
505 self.deviceCwd.text(), 521 self.deviceCwd.text(),
506 mirror=True 522 mirror=True,
523 localDevice=self.__deviceWithLocalAccess,
507 ) 524 )
508 525
509 @pyqtSlot(str, str) 526 @pyqtSlot(str, str)
510 def __handleRsyncDone(self, localDir, deviceDir): 527 def __handleRsyncDone(self, localDir, deviceDir):
511 """ 528 """
673 self.tr("""<p>The directory <b>{0}</b> could not be""" 690 self.tr("""<p>The directory <b>{0}</b> could not be"""
674 """ deleted.</p><p>Reason: {1}</p>""").format( 691 """ deleted.</p><p>Reason: {1}</p>""").format(
675 dirname, str(exc)) 692 dirname, str(exc))
676 ) 693 )
677 694
678 # TODO: 695 @pyqtSlot()
679 @pyqtSlot() 696 def __deleteLocalFile(self, localDevice=False):
680 def __deleteLocalFile(self):
681 """ 697 """
682 Private slot to delete a local file. 698 Private slot to delete a local file.
683 """ 699
684 if bool(len(self.localFileTreeWidget.selectedItems())): 700 @param localDevice flag indicating device access via local file system
685 name = self.localFileTreeWidget.selectedItems()[0].text(0) 701 @type bool
686 filename = os.path.join(self.localCwd.text(), name) 702 """
703 if localDevice:
704 cwdWidget = self.deviceCwd
705 fileTreeWidget = self.deviceFileTreeWidget
706 else:
707 cwdWidget = self.localCwd
708 fileTreeWidget = self.localFileTreeWidget
709
710 if bool(len(fileTreeWidget.selectedItems())):
711 name = fileTreeWidget.selectedItems()[0].text(0)
712 filename = os.path.join(cwdWidget.text(), name)
687 dlg = DeleteFilesConfirmationDialog( 713 dlg = DeleteFilesConfirmationDialog(
688 self, 714 self,
689 self.tr("Delete File"), 715 self.tr("Delete File"),
690 self.tr( 716 self.tr(
691 "Do you really want to delete this file?"), 717 "Do you really want to delete this file?"),
692 [filename]) 718 [filename])
693 if dlg.exec_() == QDialog.Accepted: 719 if dlg.exec_() == QDialog.Accepted:
694 try: 720 try:
695 os.remove(filename) 721 os.remove(filename)
696 self.__listLocalFiles(self.localCwd.text()) 722 self.__listLocalFiles(cwdWidget.text(),
723 localDevice=localDevice)
697 except (OSError, IOError) as exc: 724 except (OSError, IOError) as exc:
698 E5MessageBox.critical( 725 E5MessageBox.critical(
699 self, 726 self,
700 self.tr("Delete File"), 727 self.tr("Delete File"),
701 self.tr("""<p>The file <b>{0}</b> could not be""" 728 self.tr("""<p>The file <b>{0}</b> could not be"""
702 """ deleted.</p><p>Reason: {1}</p>""").format( 729 """ deleted.</p><p>Reason: {1}</p>""").format(
703 filename, str(exc)) 730 filename, str(exc))
704 ) 731 )
705 732
706 # TODO: move to repl widget super menu
707 @pyqtSlot()
708 def __showLocalTime(self):
709 """
710 Private slot to show the local date and time.
711 """
712 localdatetime = time.localtime()
713 loacldate = time.strftime('%Y-%m-%d', localdatetime)
714 localtime = time.strftime('%H:%M:%S', localdatetime)
715 E5MessageBox.information(
716 self,
717 self.tr("Local Date and Time"),
718 self.tr("<h3>Local Date and Time</h3>"
719 "<table>"
720 "<tr><td><b>Date</b></td><td>{0}</td></tr>"
721 "<tr><td><b>Time</b></td><td>{1}</td></tr>"
722 "</table>"
723 ).format(loacldate, localtime)
724 )
725
726 ################################################################## 733 ##################################################################
727 ## Context menu methods for the device files below 734 ## Context menu methods for the device files below
728 ################################################################## 735 ##################################################################
729 736
730 @pyqtSlot(QPoint) 737 @pyqtSlot(QPoint)
742 isFile = not isDir 749 isFile = not isDir
743 else: 750 else:
744 isDir = False 751 isDir = False
745 isFile = False 752 isFile = False
746 if not self.__repl.isMicrobit(): 753 if not self.__repl.isMicrobit():
747 self.__devDelDirAct.setEnabled(isDir) 754 if not self.__deviceWithLocalAccess:
755 self.__devDelDirAct.setEnabled(isDir)
748 self.__devDelDirTreeAct.setEnabled(isDir) 756 self.__devDelDirTreeAct.setEnabled(isDir)
749 self.__devDelFileAct.setEnabled(isFile) 757 self.__devDelFileAct.setEnabled(isFile)
750 758
751 self.__deviceMenu.exec_(self.deviceFileTreeWidget.mapToGlobal(pos)) 759 self.__deviceMenu.exec_(self.deviceFileTreeWidget.mapToGlobal(pos))
752 760
796 if self.__deviceWithLocalAccess: 804 if self.__deviceWithLocalAccess:
797 self.__deleteLocalDirectoryTree(True) 805 self.__deleteLocalDirectoryTree(True)
798 else: 806 else:
799 if bool(len(self.deviceFileTreeWidget.selectedItems())): 807 if bool(len(self.deviceFileTreeWidget.selectedItems())):
800 name = self.deviceFileTreeWidget.selectedItems()[0].text(0) 808 name = self.deviceFileTreeWidget.selectedItems()[0].text(0)
801 dirname = self.deviceCwd.text() + "/" + name[:-1] 809 cwd = self.deviceCwd.text()
810 if cwd and cwd != "/":
811 dirname = cwd + "/" + name[:-1]
812 else:
813 dirname = "/" + name[:-1]
802 dlg = DeleteFilesConfirmationDialog( 814 dlg = DeleteFilesConfirmationDialog(
803 self, 815 self,
804 self.tr("Delete Directory"), 816 self.tr("Delete Directory"),
805 self.tr( 817 self.tr(
806 "Do you really want to delete this directory?"), 818 "Do you really want to delete this directory?"),
817 if self.__deviceWithLocalAccess: 829 if self.__deviceWithLocalAccess:
818 self.__deleteLocalDirectoryTree(True) 830 self.__deleteLocalDirectoryTree(True)
819 else: 831 else:
820 if bool(len(self.deviceFileTreeWidget.selectedItems())): 832 if bool(len(self.deviceFileTreeWidget.selectedItems())):
821 name = self.deviceFileTreeWidget.selectedItems()[0].text(0) 833 name = self.deviceFileTreeWidget.selectedItems()[0].text(0)
822 dirname = self.deviceCwd.text() + "/" + name[:-1] 834 cwd = self.deviceCwd.text()
835 if cwd and cwd != "/":
836 dirname = cwd + "/" + name[:-1]
837 else:
838 dirname = "/" + name[:-1]
823 dlg = DeleteFilesConfirmationDialog( 839 dlg = DeleteFilesConfirmationDialog(
824 self, 840 self,
825 self.tr("Delete Directory Tree"), 841 self.tr("Delete Directory Tree"),
826 self.tr( 842 self.tr(
827 "Do you really want to delete this directory tree?"), 843 "Do you really want to delete this directory tree?"),
828 [dirname]) 844 [dirname])
829 if dlg.exec_() == QDialog.Accepted: 845 if dlg.exec_() == QDialog.Accepted:
830 self.__fileManager.rmdir(dirname, recursive=True) 846 self.__fileManager.rmdir(dirname, recursive=True)
831 847
832 # TODO:
833 @pyqtSlot() 848 @pyqtSlot()
834 def __deleteDeviceFile(self): 849 def __deleteDeviceFile(self):
835 """ 850 """
836 Private slot to delete a file. 851 Private slot to delete a file.
837 """ 852 """
838 if bool(len(self.deviceFileTreeWidget.selectedItems())): 853 if self.__deviceWithLocalAccess:
839 name = self.deviceFileTreeWidget.selectedItems()[0].text(0) 854 self.__deleteLocalFile(True)
840 dirname = self.deviceCwd.text() 855 else:
841 if dirname: 856 if bool(len(self.deviceFileTreeWidget.selectedItems())):
842 filename = dirname + "/" + name 857 name = self.deviceFileTreeWidget.selectedItems()[0].text(0)
843 else: 858 dirname = self.deviceCwd.text()
844 filename = name 859 if dirname and dirname != "/":
845 dlg = DeleteFilesConfirmationDialog( 860 filename = dirname + "/" + name
846 self, 861 else:
847 self.tr("Delete File"), 862 filename = "/" + name
848 self.tr( 863 dlg = DeleteFilesConfirmationDialog(
849 "Do you really want to delete this file?"), 864 self,
850 [filename]) 865 self.tr("Delete File"),
851 if dlg.exec_() == QDialog.Accepted: 866 self.tr(
852 self.__fileManager.delete(filename) 867 "Do you really want to delete this file?"),
868 [filename])
869 if dlg.exec_() == QDialog.Accepted:
870 self.__fileManager.delete(filename)
853 871
854 @pyqtSlot() 872 @pyqtSlot()
855 def __showFileSystemInfo(self): 873 def __showFileSystemInfo(self):
856 """ 874 """
857 Private slot to show some file system information. 875 Private slot to show some file system information.

eric ide

mercurial