--- /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