eric6/MicroPython/MicroPythonFileManagerWidget.py

branch
micropython
changeset 7081
ed510767c096
parent 7080
9a3adf033f90
child 7082
ec199ef0cfc6
diff -r 9a3adf033f90 -r ed510767c096 eric6/MicroPython/MicroPythonFileManagerWidget.py
--- a/eric6/MicroPython/MicroPythonFileManagerWidget.py	Mon Jul 22 20:17:33 2019 +0200
+++ b/eric6/MicroPython/MicroPythonFileManagerWidget.py	Tue Jul 23 19:43:14 2019 +0200
@@ -19,8 +19,9 @@
 
 from .Ui_MicroPythonFileManagerWidget import Ui_MicroPythonFileManagerWidget
 
-from .MicroPythonFileSystem import (
-    MicroPythonFileManager, decoratedName, mode2string, mtime2string
+from .MicroPythonFileSystem import MicroPythonFileManager
+from .MicroPythonFileSystemUtilities import (
+    mtime2string, mode2string, decoratedName, listdirStat
 )
 
 import UI.PixmapCache
@@ -44,6 +45,7 @@
         super(MicroPythonFileManagerWidget, self).__init__(parent)
         self.setupUi(self)
         
+        self.syncButton.setIcon(UI.PixmapCache.getIcon("2rightarrow"))
         self.putButton.setIcon(UI.PixmapCache.getIcon("1rightarrow"))
         self.getButton.setIcon(UI.PixmapCache.getIcon("1leftarrow"))
         self.localUpButton.setIcon(UI.PixmapCache.getIcon("1uparrow"))
@@ -61,9 +63,35 @@
         
         self.__fileManager.longListFiles.connect(self.__handleLongListFiles)
         self.__fileManager.currentDir.connect(self.__handleCurrentDir)
+        self.__fileManager.currentDirChanged.connect(self.__handleCurrentDir)
+        self.__fileManager.putFileDone.connect(self.__handlePutDone)
+        self.__fileManager.getFileDone.connect(self.__handleGetDone)
+        self.__fileManager.rsyncDone.connect(self.__handleRsyncDone)
+        self.__fileManager.rsyncMessages.connect(self.__handleRsyncMessages)
         
         self.__fileManager.longListFilesFailed.connect(self.__handleError)
         self.__fileManager.currentDirFailed.connect(self.__handleError)
+        self.__fileManager.currentDirChangeFailed.connect(self.__handleError)
+        self.__fileManager.putFileFailed.connect(self.__handleError)
+        self.__fileManager.getFileFailed.connect(self.__handleError)
+        self.__fileManager.rsyncFailed.connect(self.__handleError)
+        
+        # TODO: add context menus for panes (separate menus)
+        # local pane:
+        #  Change Directory
+        #
+        # device pane:
+        #  Change Directory
+        #  Create Directory
+        #  Delete Directory
+        #  Delete Directory Tree (= recursive delete)
+        #  ----------------------------
+        #  Delete File
+        #  ----------------------------
+        #  Synchronize Time
+        #  Show Time
+        #  ----------------------------
+        #  Show Version
     
     def start(self):
         """
@@ -139,28 +167,6 @@
         @param dirname name of the local directory to be listed
         @type str
         """     # __IGNORE_WARNING_D234__
-        def isvisible(name):
-            return not name.startswith(".") and not name.endswith("~")
-        
-        def stat(filename):
-            try:
-                rstat = os.lstat(filename)
-            except Exception:
-                rstat = os.stat(filename)
-            return tuple(rstat)
-        
-        def listdir_stat(dirname):
-            try:
-                if dirname:
-                    files = os.listdir(dirname)
-                else:
-                    files = os.listdir()
-            except OSError:
-                return []
-            if dirname in ('', '/'):
-                return [(f, stat(f)) for f in files if isvisible(f)]
-            return [(f, stat(os.path.join(dirname, f))) for f in files
-                    if isvisible(f)]
         
         if not dirname:
             dirname = os.getcwd()
@@ -168,7 +174,7 @@
             dirname = dirname[:-1]
         self.localCwd.setText(dirname)
         
-        filesStatList = listdir_stat(dirname)
+        filesStatList = listdirStat(dirname)
         filesList = [(
             decoratedName(f, s[0], os.path.isdir(os.path.join(dirname, f))),
             mode2string(s[0]),
@@ -198,7 +204,7 @@
         name = os.path.join(self.localCwd.text(), item.text(0))
         if name.endswith("/"):
             # directory names end with a '/'
-            self.__listLocalFiles(name)
+            self.__listLocalFiles(name[:-1])
         elif Utilities.MimeTypes.isTextFile(name):
             e5App().getObject("ViewManager").getEditor(name)
     
@@ -226,41 +232,177 @@
     @pyqtSlot(QTreeWidgetItem, int)
     def on_deviceFileTreeWidget_itemActivated(self, item, column):
         """
-        Slot documentation goes here.
+        Private slot to handle the activation of a device item.
         
-        @param item DESCRIPTION
+        If the item is a directory, the current working directory is changed
+        and the list will be re-populated for this directory.
+        
+        @param item reference to the activated item
         @type QTreeWidgetItem
-        @param column DESCRIPTION
+        @param column column of the activation
         @type int
         """
-        # TODO: not implemented yet
-        # chdir to activated directory triggering a pwd triggering a lls
+        name = os.path.join(self.deviceCwd.text(), item.text(0))
+        if name.endswith("/"):
+            # directory names end with a '/'
+            self.__fileManager.cd(name[:-1])
     
     @pyqtSlot()
     def on_deviceFileTreeWidget_itemSelectionChanged(self):
         """
-        Slot documentation goes here.
+        Private slot handling a change of selection in the local pane.
         """
-        # TODO: not implemented yet
+        enable = bool(len(self.deviceFileTreeWidget.selectedItems()))
+        if enable:
+            enable &= not (
+                self.deviceFileTreeWidget.selectedItems()[0].text(0)
+                .endswith("/"))
+        self.getButton.setEnabled(enable)
     
     @pyqtSlot()
     def on_deviceUpButton_clicked(self):
         """
-        Slot documentation goes here.
+        Private slot to go up one directory level on the device.
+        """
+        cwd = self.deviceCwd.text()
+        dirname = os.path.dirname(cwd)
+        self.__fileManager.cd(dirname)
+    
+    def __isFileInList(self, filename, treeWidget):
         """
-        # TODO: not implemented yet
-        raise NotImplementedError
+        Private method to check, if a file name is contained in a tree widget.
+        
+        @param filename name of the file to check
+        @type str
+        @param treeWidget reference to the tree widget to be checked against
+        @return flag indicating that the file name is present
+        @rtype bool
+        """
+        itemCount = treeWidget.topLevelItemCount()
+        if itemCount:
+            for row in range(itemCount):
+                if treeWidget.topLevelItem(row).text(0) == filename:
+                    return True
+        
+        return False
     
     @pyqtSlot()
     def on_putButton_clicked(self):
         """
-        Slot documentation goes here.
+        Private slot to copy the selected file to the connected device.
         """
-        # TODO: not implemented yet
+        selectedItems = self.localFileTreeWidget.selectedItems()
+        if selectedItems:
+            filename = selectedItems[0].text(0).strip()
+            if not filename.endswith("/"):
+                # it is really a file
+                if self.__isFileInList(filename, self.deviceFileTreeWidget):
+                    # ask for overwrite permission
+                    ok = E5MessageBox.yesNo(
+                        self,
+                        self.tr("Copy File to Device"),
+                        self.tr("<p>The file <b>{0}</b> exists on the"
+                                " connected device. Overwrite it?</p>")
+                        .format(filename)
+                    )
+                    if not ok:
+                        return
+                    # TODO: allow to rename the new file
+                
+                self.__fileManager.put(
+                    os.path.join(self.localCwd.text(), filename),
+                    os.path.join(self.deviceCwd.text(), filename)
+                )
     
     @pyqtSlot()
     def on_getButton_clicked(self):
         """
-        Slot documentation goes here.
+        Private slot to copy the selected file from the connected device.
+        """
+        selectedItems = self.deviceFileTreeWidget.selectedItems()
+        if selectedItems:
+            filename = selectedItems[0].text(0).strip()
+            if not filename.endswith("/"):
+                # it is really a file
+                if self.__isFileInList(filename, self.localFileTreeWidget):
+                    # ask for overwrite permission
+                    ok = E5MessageBox.yesNo(
+                        self,
+                        self.tr("Copy File from Device"),
+                        self.tr("<p>The file <b>{0}</b> exists locally."
+                                " Overwrite it?</p>")
+                        .format(filename)
+                    )
+                    if not ok:
+                        return
+                    # TODO: allow to rename the new file
+                
+                self.__fileManager.get(
+                    os.path.join(self.deviceCwd.text(), filename),
+                    os.path.join(self.localCwd.text(), filename)
+                )
+    
+    @pyqtSlot(str, str)
+    def __handlePutDone(self, localFile, deviceFile):
+        """
+        Private slot handling a successful copy of a file to the device.
+        
+        @param localFile name of the local file
+        @type str
+        @param deviceFile name of the file on the device
+        @type str
+        """
+        self.__fileManager.lls(self.deviceCwd.text())
+    
+    @pyqtSlot(str, str)
+    def __handleGetDone(self, deviceFile, localFile):
         """
-        # TODO: not implemented yet
+        Private slot handling a successful copy of a file from the device.
+        
+        @param deviceFile name of the file on the device
+        @type str
+        @param localFile name of the local file
+        @type str
+        """
+        self.__listLocalFiles(self.localCwd.text())
+    
+    @pyqtSlot()
+    def on_syncButton_clicked(self):
+        """
+        Private slot to synchronize the local directory to the device.
+        """
+        self.__fileManager.rsync(
+            self.localCwd.text(),
+            self.deviceCwd.text(),
+            mirror=True
+        )
+    
+    @pyqtSlot(str, str)
+    def __handleRsyncDone(self, localDir, deviceDir):
+        """
+        Private method to handle the completion of the rsync operation.
+        
+        @param localDir name of the local directory
+        @type str
+        @param deviceDir name of the device directory
+        @type str
+        """
+        self.__listLocalFiles(self.localCwd.text())
+        self.__fileManager.lls(self.deviceCwd.text())
+    
+    @pyqtSlot(list)
+    def __handleRsyncMessages(self, messages):
+        """
+        Private slot to handle messages from the rsync operation.
+        
+        @param messages list of message generated by the rsync operation
+        @type list
+        """
+        E5MessageBox.information(
+            self,
+            self.tr("rsync Messages"),
+            self.tr("""<p>rsync gave the following messages</p>"""
+                    """<ul><li>{0}</li></ul>""").format(
+                "</li><li>".join(messages)
+            )
+        )

eric ide

mercurial