eric6/MicroPython/MicroPythonFileManagerWidget.py

branch
micropython
changeset 7078
bca506f8c756
child 7080
9a3adf033f90
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric6/MicroPython/MicroPythonFileManagerWidget.py	Mon Jul 22 18:48:27 2019 +0200
@@ -0,0 +1,232 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2019 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a file manager for MicroPython devices.
+"""
+
+from __future__ import unicode_literals
+
+import os
+
+from PyQt5.QtCore import pyqtSlot, Qt
+from PyQt5.QtWidgets import QWidget, QTreeWidgetItem, QHeaderView
+
+from E5Gui import E5MessageBox
+from E5Gui.E5Application import e5App
+
+from .Ui_MicroPythonFileManagerWidget import Ui_MicroPythonFileManagerWidget
+
+from .MicroPythonFileSystem import (
+    MicroPythonFileManager, decoratedName, mode2string, mtime2string
+)
+
+import UI.PixmapCache
+import Preferences
+
+
+class MicroPythonFileManagerWidget(QWidget, Ui_MicroPythonFileManagerWidget):
+    """
+    Class implementing a file manager for MicroPython devices.
+    """
+    def __init__(self, port, parent=None):
+        """
+        Constructor
+        
+        @param port port name of the device
+        @type str
+        @param parent reference to the parent widget
+        @type QWidget
+        """
+        super(MicroPythonFileManagerWidget, self).__init__(parent)
+        self.setupUi(self)
+        
+        self.putButton.setIcon(UI.PixmapCache.getIcon("1rightarrow"))
+        self.getButton.setIcon(UI.PixmapCache.getIcon("1leftarrow"))
+        
+        self.putButton.setEnabled(False)
+        self.getButton.setEnabled(False)
+        
+        self.localFileTreeWidget.header().setSortIndicator(
+            0, Qt.AscendingOrder)
+        self.deviceFileTreeWidget.header().setSortIndicator(
+            0, Qt.AscendingOrder)
+        
+        self.__fileManager = MicroPythonFileManager(port, self)
+        
+        self.__fileManager.longListFiles.connect(self.__handleLongListFiles)
+        self.__fileManager.currentDir.connect(self.__handleCurrentDir)
+        
+        self.__fileManager.longListFilesFailed.connect(self.__handleError)
+        self.__fileManager.currentDirFailed.connect(self.__handleError)
+    
+    def start(self):
+        """
+        Public method to start the widget.
+        """
+        self.__fileManager.connect()
+        
+        dirname = ""
+        vm = e5App().getObject("ViewManager")
+        aw = vm.activeWindow()
+        if aw:
+            dirname = os.path.dirname(aw.getFileName())
+        if not dirname:
+            dirname = (Preferences.getMultiProject("Workspace") or
+                       os.path.expanduser("~"))
+        self.__listLocalFiles(dirname)
+        
+        self.__fileManager.pwd()
+    
+    def stop(self):
+        """
+        Public method to stop the widget.
+        """
+        self.__fileManager.disconnect()
+    
+    @pyqtSlot(str)
+    def __handleError(self, error):
+        """
+        Private slot to handle errors.
+        
+        @param error error message
+        @type str
+        """
+        E5MessageBox.warning(
+            self,
+            self.tr("Error handling device"),
+            self.tr("<p>There was an error communicating with the connected"
+                    " device.</p><p>Message: {0}</p>").format(error))
+    
+    @pyqtSlot(str)
+    def __handleCurrentDir(self, dirname):
+        """
+        Private slot to handle a change of the current directory of the device.
+        
+        @param dirname name of the current directory
+        @type str
+        """
+        self.deviceCwd.setText(dirname)
+        self.__fileManager.lls(dirname)
+    
+    @pyqtSlot(tuple)
+    def __handleLongListFiles(self, filesList):
+        """
+        Private slot to receive a long directory listing.
+        
+        @param filesList tuple containing tuples with name, mode, size and time
+            for each directory entry
+        @type tuple of (str, str, str, str)
+        """
+        self.deviceFileTreeWidget.clear()
+        for name, mode, size, time in filesList:
+            itm = QTreeWidgetItem(self.deviceFileTreeWidget,
+                                  [name, mode, size, time])
+            itm.setTextAlignment(1, Qt.AlignHCenter)
+            itm.setTextAlignment(2, Qt.AlignRight)
+        self.deviceFileTreeWidget.header().resizeSections(
+            QHeaderView.ResizeToContents)
+    
+    def __listLocalFiles(self, dirname=""):
+        """
+        Private method to populate the local files list.
+        
+        @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()
+        self.localCwd.setText(dirname)
+        
+        filesStatList = listdir_stat(dirname)
+        filesList = [(
+            decoratedName(f, s[0]),
+            mode2string(s[0]),
+            str(s[6]),
+            mtime2string(s[8])) for f, s in filesStatList]
+        self.localFileTreeWidget.clear()
+        for item in filesList:
+            itm = QTreeWidgetItem(self.localFileTreeWidget, item)
+            itm.setTextAlignment(1, Qt.AlignHCenter)
+            itm.setTextAlignment(2, Qt.AlignRight)
+        self.localFileTreeWidget.header().resizeSections(
+            QHeaderView.ResizeToContents)
+    
+    @pyqtSlot(QTreeWidgetItem, int)
+    def on_localFileTreeWidget_itemActivated(self, item, column):
+        """
+        Slot documentation goes here.
+        
+        @param item DESCRIPTION
+        @type QTreeWidgetItem
+        @param column DESCRIPTION
+        @type int
+        """
+        # TODO: not implemented yet
+        # show listing of activated directory
+    
+    @pyqtSlot()
+    def on_localFileTreeWidget_itemSelectionChanged(self):
+        """
+        Slot documentation goes here.
+        """
+        # TODO: not implemented yet
+    
+    @pyqtSlot(QTreeWidgetItem, int)
+    def on_deviceFileTreeWidget_itemActivated(self, item, column):
+        """
+        Slot documentation goes here.
+        
+        @param item DESCRIPTION
+        @type QTreeWidgetItem
+        @param column DESCRIPTION
+        @type int
+        """
+        # TODO: not implemented yet
+        # chdir to activated directory triggering a pwd triggering a lls
+    
+    @pyqtSlot()
+    def on_deviceFileTreeWidget_itemSelectionChanged(self):
+        """
+        Slot documentation goes here.
+        """
+        # TODO: not implemented yet
+    
+    @pyqtSlot()
+    def on_putButton_clicked(self):
+        """
+        Slot documentation goes here.
+        """
+        # TODO: not implemented yet
+    
+    @pyqtSlot()
+    def on_getButton_clicked(self):
+        """
+        Slot documentation goes here.
+        """
+        # TODO: not implemented yet

eric ide

mercurial