Esempio n. 1
0
class FtpClient(QWidget):
    def __init__(self, parent=None):
        super(FtpClient, self).__init__(parent)
        self.ftp = FTP()
        self.setupGui()
        self.downloads = []
        self.remote.homeButton.clicked.connect(self.cdToRemoteHomeDirectory)
        self.remote.fileList.itemDoubleClicked.connect(
            self.cdToRemoteDirectory)
        self.remote.fileList.itemClicked.connect(
            lambda: self.remote.downloadButton.setEnabled(True))
        self.remote.backButton.clicked.connect(self.cdToRemoteBackDirectory)
        self.remote.nextButton.clicked.connect(self.cdToRemoteNextDirectory)
        self.remote.downloadButton.clicked.connect(
            lambda: Thread(target=self.download).start())
        self.remote.refreshButton.clicked.connect(self.updateRemoteFileList)

        self.local.homeButton.clicked.connect(self.cdToLocalHomeDirectory)
        self.local.fileList.itemDoubleClicked.connect(self.cdToLocalDirectory)
        self.local.fileList.itemClicked.connect(
            lambda: self.local.uploadButton.setEnabled(True))
        self.local.backButton.clicked.connect(self.cdToLocalBackDirectory)
        self.local.nextButton.clicked.connect(self.cdToLocalNextDirectory)
        self.local.uploadButton.clicked.connect(
            lambda: Thread(target=self.upload).start())
        self.local.connectButton.clicked.connect(self.connect)
        self.local.refreshButton.clicked.connect(self.updateLocalFileList)

        self.progressDialog = ProgressDialog(self)

    def setupGui(self):
        self.resize(1200, 650)
        self.local = LocalGuiWidget(self)
        self.remote = RemoteGuiWidget(self)
        main_layout = QHBoxLayout()
        main_layout.addWidget(self.remote)
        main_layout.addWidget(self.local)
        main_layout.setSpacing(0)

        self.setLayout(main_layout)

    def initialize(self):
        self.localBrowseRec = []
        self.remoteBrowseRec = []
        self.pwd = self.ftp.pwd()
        self.local_pwd = os.getenv('HOME')
        self.remoteOriginPath = self.pwd
        self.localOriginPath = self.local_pwd
        self.localBrowseRec.append(self.local_pwd)
        self.remoteBrowseRec.append(self.pwd)
        self.downloadToRemoteFileList()
        self.loadToLocaFileList()

    def disconnect(self):
        pass

    def connect(self):
        try:
            from urlparse import urlparse
        except ImportError:
            from urllib.parse import urlparse

        result = QInputDialog.getText(self, 'Connect To Host', 'Host Address',
                                      QLineEdit.Normal)
        if not result[1]:
            return
        try:
            host = str(result[0].toUtf8())
        except AttributeError:
            host = str(result[0])

        try:
            if urlparse(host).hostname:
                self.ftp.connect(host=urlparse(host).hostname,
                                 port=21,
                                 timeout=10)
            else:
                self.ftp.connect(host=host, port=21, timeout=10)
            self.login()
        except Exception as error:
            raise error

    def login(self):
        ask = loginDialog(self)
        if not ask:
            return
        else:
            user, passwd = ask[:2]
        self.ftp.user = user
        self.ftp.passwd = passwd
        self.ftp.set_pasv(False)
        self.ftp.login(user=user, passwd=passwd)
        self.initialize()

    def downloadToRemoteFileList(self):
        self.remote.refreshButton.setEnabled(True)
        self.remoteWordList = []
        self.remoteDir = {}
        self.ftp.dir('.', self.addItemToRemoteFileList)
        self.remote.completerModel.setStringList(self.remoteWordList)

    def loadToLocaFileList(self):
        self.local.refreshButton.setEnabled(True)
        self.localWordList = []
        self.localDir = {}
        for f in os.listdir(self.local_pwd):
            pathname = os.path.join(self.local_pwd, f)
            self.addItemToLocalFileList(fileProperty(pathname))
        self.local.completerModel.setStringList(self.localWordList)

    def addItemToRemoteFileList(self, content):
        mode, num, owner, group, size, date, filename = self.parseFileInfo(
            content)
        if content.startswith('d'):
            icon = qIcon('folder.png')
            pathname = os.path.join(self.pwd, filename)
            self.remoteDir[pathname] = True
            self.remoteWordList.append(filename)
        else:
            icon = qIcon('file.png')

        item = QTreeWidgetItem()
        item.setIcon(0, icon)
        for n, i in enumerate((filename, size, owner, group, date, mode)):
            item.setText(n, i)

        self.remote.fileList.addTopLevelItem(item)
        if not self.remote.fileList.currentItem():
            self.remote.fileList.setCurrentItem(
                self.remote.fileList.topLevelItem(0))
            self.remote.fileList.setEnabled(True)

    def addItemToLocalFileList(self, content):
        mode, num, owner, group, size, date, filename = self.parseFileInfo(
            content)
        if content.startswith('d'):
            icon = qIcon('folder.png')
            pathname = os.path.join(self.local_pwd, filename)
            self.localDir[pathname] = True
            self.localWordList.append(filename)

        else:
            icon = qIcon('file.png')

        item = QTreeWidgetItem()
        item.setIcon(0, icon)
        for n, i in enumerate((filename, size, owner, group, date, mode)):
            item.setText(n, i)
        self.local.fileList.addTopLevelItem(item)
        if not self.local.fileList.currentItem():
            self.local.fileList.setCurrentItem(
                self.local.fileList.topLevelItem(0))
            self.local.fileList.setEnabled(True)

    def parseFileInfo(self, file):
        """
        parse files information "drwxr-xr-x 2 root wheel 1024 Nov 17 1993 lib" result like follower
                                "drwxr-xr-x", "2", "root", "wheel", "1024 Nov 17 1993", "lib"
        """
        item = [f for f in file.split(' ') if f != '']
        mode, num, owner, group, size, date, filename = (item[0], item[1],
                                                         item[2], item[3],
                                                         item[4],
                                                         ' '.join(item[5:8]),
                                                         ' '.join(item[8:]))
        return mode, num, owner, group, size, date, filename

    def cdToRemotePath(self):
        try:
            pathname = str(self.remote.pathEdit.text().toUtf8())
        except AttributeError:
            pathname = str(self.remote.pathEdit.text())
        try:
            self.ftp.cwd(pathname)
        except:
            return
        self.cwd = pathname.startswith(
            os.path.sep) and pathname or os.path.join(self.pwd, pathname)
        self.updateRemoteFileList()
        self.remote.backButton.setEnabled(True)
        if os.path.abspath(pathname) != self.remoteOriginPath:
            self.remote.homeButton.setEnabled(True)
        else:
            self.remote.homeButton.setEnabled(False)

    def cdToRemoteDirectory(self, item):
        pathname = os.path.join(self.pwd, str(item.text(0)))
        if not self.isRemoteDir(pathname):
            return
        self.remoteBrowseRec.append(pathname)
        self.ftp.cwd(pathname)
        self.pwd = self.ftp.pwd()
        self.updateRemoteFileList()
        self.remote.backButton.setEnabled(True)
        if pathname != self.remoteOriginPath:
            self.remote.homeButton.setEnabled(True)

    def cdToRemoteBackDirectory(self):
        pathname = self.remoteBrowseRec[self.remoteBrowseRec.index(self.pwd) -
                                        1]
        if pathname != self.remoteBrowseRec[0]:
            self.remote.backButton.setEnabled(True)
        else:
            self.remote.backButton.setEnabled(False)

        if pathname != self.remoteOriginPath:
            self.remote.homeButton.setEnabled(True)
        else:
            self.remote.homeButton.setEnabled(False)
        self.remote.nextButton.setEnabled(True)
        self.pwd = pathname
        self.ftp.cwd(pathname)
        self.updateRemoteFileList()

    def cdToRemoteNextDirectory(self):
        pathname = self.remoteBrowseRec[self.remoteBrowseRec.index(self.pwd) +
                                        1]
        if pathname != self.remoteBrowseRec[-1]:
            self.remote.nextButton.setEnabled(True)
        else:
            self.remote.nextButton.setEnabled(False)
        self.remote.backButton.setEnabled(True)
        if pathname != self.remoteOriginPath:
            self.remote.homeButton.setEnabled(True)
        else:
            self.remote.homeButton.setEnabled(False)
        self.remote.backButton.setEnabled(True)
        self.pwd = pathname
        self.ftp.cwd(pathname)
        self.updateRemoteFileList()

    def cdToRemoteHomeDirectory(self):
        self.ftp.cwd(self.remoteOriginPath)
        self.pwd = self.remoteOriginPath
        self.updateRemoteFileList()
        self.remote.homeButton.setEnabled(False)

    def cdToLocalPath(self):
        try:
            pathname = str(self.local.pathEdit.text().toUtf8())
        except AttributeError:
            pathname = str(self.local.pathEdit.text())
        pathname = pathname.endswith(os.path.sep) and pathname or os.path.join(
            self.local_pwd, pathname)
        if not os.path.exists(pathname) and not os.path.isdir(pathname):
            return

        else:
            self.localBrowseRec.append(pathname)
            self.local_pwd = pathname
            self.updateLocalFileList()
            self.local.backButton.setEnabled(True)
            print(pathname, self.localOriginPath)
            if os.path.abspath(pathname) != self.localOriginPath:
                self.local.homeButton.setEnabled(True)
            else:
                self.local.homeButton.setEnabled(False)

    def cdToLocalDirectory(self, item):
        pathname = os.path.join(self.local_pwd, str(item.text(0)))
        if not self.isLocalDir(pathname):
            return
        self.localBrowseRec.append(pathname)
        self.local_pwd = pathname
        self.updateLocalFileList()
        self.local.backButton.setEnabled(True)
        if pathname != self.localOriginPath:
            self.local.homeButton.setEnabled(True)

    def cdToLocalBackDirectory(self):
        pathname = self.localBrowseRec[
            self.localBrowseRec.index(self.local_pwd) - 1]
        if pathname != self.localBrowseRec[0]:
            self.local.backButton.setEnabled(True)
        else:
            self.local.backButton.setEnabled(False)
        if pathname != self.localOriginPath:
            self.local.homeButton.setEnabled(True)
        else:
            self.local.homeButton.setEnabled(False)
        self.local.nextButton.setEnabled(True)
        self.local_pwd = pathname
        self.updateLocalFileList()

    def cdToLocalNextDirectory(self):
        pathname = self.localBrowseRec[
            self.localBrowseRec.index(self.local_pwd) + 1]
        if pathname != self.localBrowseRec[-1]:
            self.local.nextButton.setEnabled(True)
        else:
            self.local.nextButton.setEnabled(False)
        if pathname != self.localOriginPath:
            self.local.homeButton.setEnabled(True)
        else:
            self.local.homeButton.setEnabled(False)
        self.local.backButton.setEnabled(True)
        self.local_pwd = pathname
        self.updateLocalFileList()

    def cdToLocalHomeDirectory(self):
        self.local_pwd = self.localOriginPath
        self.updateLocalFileList()
        self.local.homeButton.setEnabled(False)

    def updateLocalFileList(self):
        self.local.fileList.clear()
        self.loadToLocaFileList()

    def updateRemoteFileList(self):
        self.remote.fileList.clear()
        self.downloadToRemoteFileList()

    def isLocalDir(self, dirname):
        return self.localDir.get(dirname, None)

    def isRemoteDir(self, dirname):
        return self.remoteDir.get(dirname, None)

    def download(self):
        item = self.remote.fileList.currentItem()
        filesize = int(item.text(1))

        try:
            srcfile = os.path.join(self.pwd, str(item.text(0).toUtf8()))
            dstfile = os.path.join(self.local_pwd, str(item.text(0).toUtf8()))
        except AttributeError:
            srcfile = os.path.join(self.pwd, str(item.text(0)))
            dstfile = os.path.join(self.local_pwd, str(item.text(0)))

        pb = self.progressDialog.addProgress(
            type='download',
            title=srcfile,
            size=filesize,
        )
        pb.show()

        def callback(data):
            pb.set_value(data)
            file.write(data)

        file = open(dstfile, 'wb')
        fp = FTP()
        fp.set_pasv(False)
        fp.connect(host=self.ftp.host,
                   port=self.ftp.port,
                   timeout=self.ftp.timeout)
        fp.login(user=self.ftp.user, passwd=self.ftp.passwd)
        try:
            fp.retrbinary(cmd='RETR ' + srcfile, callback=callback)
        except:
            pb.destroy()

    def upload(self):
        item = self.local.fileList.currentItem()
        filesize = int(item.text(1))

        try:
            srcfile = os.path.join(self.local_pwd, str(item.text(0).toUtf8()))
            dstfile = os.path.join(self.pwd, str(item.text(0).toUtf8()))
        except AttributeError:
            srcfile = os.path.join(self.local_pwd, str(item.text(0)))
            dstfile = os.path.join(self.pwd, str(item.text(0)))

        pb = self.progressDialog.addProgress(
            type='upload',
            title=srcfile,
            size=filesize,
        )
        pb.show()

        file = open(srcfile, 'rb')
        fp = FTP()
        fp.connect(host=self.ftp.host,
                   port=self.ftp.port,
                   timeout=self.ftp.timeout)
        fp.login(user=self.ftp.user, passwd=self.ftp.passwd)
        fp.set_pasv(False)
        try:
            fp.storbinary(cmd='STOR ' + dstfile,
                          fp=file,
                          callback=pb.set_value)
        except:
            pb.destroy()
Esempio n. 2
0
class FtpClient(QWidget):
    def __init__(self, parent=None):
        super(FtpClient, self).__init__(parent)
        self.ftp = FTP()
        self.setup_gui()
        self.downloads = []
        self.localBrowseRec = []
        self.remoteBrowseRec = []
        self.local_pwd = os.getenv('HOME')
        self.ftp_hostname = ''
        self.ftp_username = ''
        self.ftp_password = ''
        # self.ftp_hostname = os.getenv('ftp_hostname')
        # self.ftp_username = os.getenv('ftp_username')
        # self.ftp_password = os.getenv('ftp_password')

        self.local.pathEdit.setText(self.local_pwd)
        self.localOriginPath = self.local_pwd
        self.localBrowseRec.append(self.local_pwd)
        self.load_to_local_filelist()

        # Signals
        self.remote.homeButton.clicked.connect(self.cd_to_remote_home_directory)
        self.remote.fileList.itemDoubleClicked.connect(self.cd_to_remote_directory)
        self.remote.fileList.itemClicked.connect(lambda: self.remote.downloadButton.setEnabled(True))
        self.remote.backButton.clicked.connect(self.cd_to_remote_back_directory)
        self.remote.nextButton.clicked.connect(self.cd_to_remote_next_directory)
        self.remote.downloadButton.clicked.connect(lambda: Thread(target=self.download).start())
        self.remote.connectButton.clicked.connect(self.connect)
        # QObject.connect(self.remote.pathEdit, pyqtSignal('returnPressed( )'), self.cd_to_remote_path)
        self.remote.pathEdit.returnPressed.connect(self.cd_to_remote_path)

        self.local.homeButton.clicked.connect(self.cd_to_local_home_directory)
        self.local.fileList.itemDoubleClicked.connect(self.cd_to_local_directory)
        self.local.fileList.itemClicked.connect(lambda: self.local.uploadButton.setEnabled(True))
        self.local.backButton.clicked.connect(self.cd_to_local_back_directory)
        self.local.nextButton.clicked.connect(self.cd_to_local_next_directory)
        self.local.uploadButton.clicked.connect(lambda: Thread(target=self.upload).start())
        self.local.connectButton.clicked.connect(self.connect)
        # QObject.connect(self.local.pathEdit, pyqtSignal('returnPressed( )'), self.cd_to_local_path)
        self.local.pathEdit.returnPressed.connect(self.cd_to_local_path)

        self.progressDialog = ProgressDialog(self)

    def setup_gui(self):
        self.resize(1200, 650)
        self.local = LocalGuiWidget(self)
        self.remote = RemoteGuiWidget(self)
        mainLayout = QHBoxLayout()
        mainLayout.addWidget(self.local)
        mainLayout.addWidget(self.remote)
        mainLayout.setSpacing(0)
        # mainLayout.setMargin(5)
        self.setLayout(mainLayout)

    def initialize(self):
        # self.localBrowseRec = []
        # self.remoteBrowseRec = []
        self.pwd = self.ftp.pwd()

        # self.local_pwd = os.getenv('HOME')
        self.remoteOriginPath = self.pwd
        # self.localOriginPath = self.local_pwd
        # self.localBrowseRec.append(self.local_pwd)
        self.remoteBrowseRec.append(self.pwd)
        self.download_to_remote_filelist()
        # self.loadToLocaFileList()

    def disconnect(self):
        pass

    def connect(self):
        if not bool(self.ftp_hostname):
            try:
                from urlparse import urlparse
            except ImportError:
                from urllib.parse import urlparse

            result = QInputDialog.getText(self, 'Connect To Host', 'Host Address', QLineEdit.Normal)
            if not result[1]:
                return
            try:
                self.ftp_hostname = str(result[0])
            except AttributeError:
                self.ftp_hostname = str(result[0])

        try:
            if self.ftp_hostname:
                self.ftp.connect(host=self.ftp_hostname, port=21, timeout=10)
            else:
                self.ftp.connect(host=self.ftp_hostname, port=21, timeout=10)
            self.login()
        except Exception as error:
            raise error

    def login(self):
        # if not bool(self.ftp_username) or bool(self.ftp_password):
        ask = loginDialog(self)
        if not ask:
            return
        else:
            self.ftp_username, self.ftp_password = ask[:2]

        # self.ftp.user = self.ftp_username
        # self.ftp.passwd = self.ftp_password
        self.ftp.login(user=self.ftp_username, passwd=self.ftp_password)
        self.initialize()
        self.remote.pathEdit.setText(self.pwd)

    '''
    def connect(self, address, port=21, timeout=10):
        from urlparse import urlparse
        if urlparse(address).hostname:
            self.ftp.connect(urlparse(address).hostname, port, timeout)
        else:
            self.ftp.connect(address, port, timeout)

    def login(self, name=None, passwd=None):
        if not name:
            self.ftp.login( )
        else:
            self.ftp.login(name, passwd)
            self.ftp.user, self.ftp.passwd = (user, passwd)
        self.initialize( )
    '''

    # ---------------------------------------------------------------------------------#
    ## the download_to_remote_filelist with load_to_local_filelist is doing the same thing ##
    # ---------------------------------------------------------------------------------#
    def download_to_remote_filelist(self):
        """
        download file and directory list from FTP Server
        """
        self.remoteWordList = []
        self.remoteDir = {}
        self.ftp.dir('.', self.add_item_to_remote_filelist)
        self.remote.completerModel.setStringList(self.remoteWordList)
        self.remote.fileList.sortByColumn(0, Qt.SortOrder.AscendingOrder)

    def load_to_local_filelist(self):
        """
        load file and directory list from local computer
        """
        self.localWordList = []
        self.localDir = {}
        for f in os.listdir(self.local_pwd):
            pathname = os.path.join(self.local_pwd, f)
            self.add_item_to_local_filelist(fileProperty(pathname))
        self.local.completerModel.setStringList(self.localWordList)
        self.local.fileList.sortByColumn(0, Qt.SortOrder.AscendingOrder)

    def add_item_to_remote_filelist(self, content):
        mode, num, owner, group, filesize_human, date, filename, size = self.parse_file_info(content)
        if content.startswith('d'):
            icon = qIcon('folder.png')
            pathname = os.path.join(self.pwd, filename)
            self.remoteDir[pathname] = True
            self.remoteWordList.append(filename)

        else:
            icon = qIcon('file.png')

        item = QTreeWidgetItem()
        item.setIcon(0, icon)
        for n, i in enumerate((filename, filesize_human, owner, group, date, mode, size)):
            item.setText(n, i)

        self.remote.fileList.addTopLevelItem(item)
        if not self.remote.fileList.currentItem():
            self.remote.fileList.setCurrentItem(self.remote.fileList.topLevelItem(0))
            self.remote.fileList.setEnabled(True)

    def add_item_to_local_filelist(self, content):
        mode, num, owner, group, filesize_human, date, filename, size = self.parse_file_info(content)
        if content.startswith('d'):
            icon = qIcon('folder.png')
            pathname = os.path.join(self.local_pwd, filename)
            self.localDir[pathname] = True
            self.localWordList.append(filename)

        else:
            icon = qIcon('file.png')

        item = QTreeWidgetItem()
        item.setIcon(0, icon)
        for n, i in enumerate((filename, filesize_human, owner, group, date, mode, size)):
            # print((filename, size, owner, group, date, mode))
            item.setText(n, i)
        self.local.fileList.addTopLevelItem(item)
        if not self.local.fileList.currentItem():
            self.local.fileList.setCurrentItem(self.local.fileList.topLevelItem(0))
            self.local.fileList.setEnabled(True)

    def parse_file_info(self, file):
        """
        parse files information "drwxr-xr-x 2 root wheel 1024 Nov 17 1993 lib" result like follower
                                "drwxr-xr-x", "2", "root", "wheel", "1024 Nov 17 1993", "lib"
        """
        item = [f for f in file.split(' ') if f != '']
        mode, num, owner, group, size, date, filename = (
            item[0], item[1], item[2], item[3], item[4], ' '.join(item[5:8]), ' '.join(item[8:]))
        filesize_human = HumanBytes.format(int(size), precision=2)
        return mode, num, owner, group, filesize_human, date, filename, size

    # --------------------------#
    ## for remote file system ##
    # --------------------------#
    def cd_to_remote_path(self):
        try:
            pathname = str(self.remote.pathEdit.text())
        except AttributeError:
            pathname = str(self.remote.pathEdit.text())
        try:
            self.ftp.cwd(pathname)
        except:
            return
        self.cwd = pathname.startswith(os.path.sep) and pathname or os.path.join(self.pwd, pathname)
        self.update_remote_filelist()
        self.remote.pathEdit.setText(self.cwd)
        self.remote.backButton.setEnabled(True)
        if os.path.abspath(pathname) != self.remoteOriginPath:
            self.remote.homeButton.setEnabled(True)
        else:
            self.remote.homeButton.setEnabled(False)

    def cd_to_remote_directory(self, item, column):
        pathname = os.path.join(self.pwd, str(item.text(0)))
        if not self.is_remote_dir(pathname):
            return
        self.remoteBrowseRec.append(pathname)
        self.ftp.cwd(pathname)
        self.pwd = self.ftp.pwd()
        self.remote.pathEdit.setText(self.pwd)
        self.update_remote_filelist()
        self.remote.backButton.setEnabled(True)
        if pathname != self.remoteOriginPath:
            self.remote.homeButton.setEnabled(True)

    def cd_to_remote_back_directory(self):
        pathname = self.remoteBrowseRec[self.remoteBrowseRec.index(self.pwd) - 1]
        if pathname != self.remoteBrowseRec[0]:
            self.remote.backButton.setEnabled(True)
        else:
            self.remote.backButton.setEnabled(False)

        if pathname != self.remoteOriginPath:
            self.remote.homeButton.setEnabled(True)
        else:
            self.remote.homeButton.setEnabled(False)
        self.remote.nextButton.setEnabled(True)
        self.pwd = pathname
        self.ftp.cwd(pathname)
        self.update_remote_filelist()
        self.remote.pathEdit.setText(self.pwd)

    def cd_to_remote_next_directory(self):
        pathname = self.remoteBrowseRec[self.remoteBrowseRec.index(self.pwd) + 1]
        if pathname != self.remoteBrowseRec[-1]:
            self.remote.nextButton.setEnabled(True)
        else:
            self.remote.nextButton.setEnabled(False)
        self.remote.backButton.setEnabled(True)
        if pathname != self.remoteOriginPath:
            self.remote.homeButton.setEnabled(True)
        else:
            self.remote.homeButton.setEnabled(False)
        self.remote.backButton.setEnabled(True)
        self.pwd = pathname
        self.ftp.cwd(pathname)
        self.update_remote_filelist()
        self.remote.pathEdit.setText(self.pwd)

    def cd_to_remote_home_directory(self):
        self.ftp.cwd(self.remoteOriginPath)
        self.pwd = self.remoteOriginPath
        self.update_remote_filelist()
        self.remote.pathEdit.setText(self.pwd)
        self.remote.homeButton.setEnabled(False)

    # -------------------------#
    ## for local file system ##
    # -------------------------#
    def cd_to_local_path(self):
        try:
            pathname = str(self.local.pathEdit.text())
        except AttributeError:
            pathname = str(self.local.pathEdit.text())
        pathname = pathname.endswith(os.path.sep) and pathname or os.path.join(self.local_pwd, pathname)
        if not os.path.exists(pathname) and not os.path.isdir(pathname):
            return

        else:
            self.localBrowseRec.append(pathname)
            self.local_pwd = pathname
            self.update_local_filelist()
            self.local.pathEdit.setText(self.local_pwd)
            self.local.backButton.setEnabled(True)
            print(pathname, self.localOriginPath)
            if os.path.abspath(pathname) != self.localOriginPath:
                self.local.homeButton.setEnabled(True)
            else:
                self.local.homeButton.setEnabled(False)

    def cd_to_local_directory(self, item, column):
        pathname = os.path.join(self.local_pwd, str(item.text(0)))
        if not self.is_local_dir(pathname):
            return
        self.localBrowseRec.append(pathname)
        self.local_pwd = pathname
        self.update_local_filelist()
        self.local.pathEdit.setText(self.local_pwd)
        self.local.backButton.setEnabled(True)
        if pathname != self.localOriginPath:
            self.local.homeButton.setEnabled(True)

    def cd_to_local_back_directory(self):
        pathname = self.localBrowseRec[self.localBrowseRec.index(self.local_pwd) - 1]
        if pathname != self.localBrowseRec[0]:
            self.local.backButton.setEnabled(True)
        else:
            self.local.backButton.setEnabled(False)
        if pathname != self.localOriginPath:
            self.local.homeButton.setEnabled(True)
        else:
            self.local.homeButton.setEnabled(False)
        self.local.nextButton.setEnabled(True)
        self.local_pwd = pathname
        self.update_local_filelist()
        self.local.pathEdit.setText(self.local_pwd)

    def cd_to_local_next_directory(self):
        pathname = self.localBrowseRec[self.localBrowseRec.index(self.local_pwd) + 1]
        if pathname != self.localBrowseRec[-1]:
            self.local.nextButton.setEnabled(True)
        else:
            self.local.nextButton.setEnabled(False)
        if pathname != self.localOriginPath:
            self.local.homeButton.setEnabled(True)
        else:
            self.local.homeButton.setEnabled(False)
        self.local.backButton.setEnabled(True)
        self.local_pwd = pathname
        self.update_local_filelist()
        self.local.pathEdit.setText(self.local_pwd)

    def cd_to_local_home_directory(self):
        self.local_pwd = self.localOriginPath
        self.update_local_filelist()
        self.local.pathEdit.setText(self.local_pwd)
        self.local.homeButton.setEnabled(False)

    def update_local_filelist(self):
        self.local.fileList.clear()
        self.load_to_local_filelist()

    def update_remote_filelist(self):
        self.remote.fileList.clear()
        self.download_to_remote_filelist()

    def is_local_dir(self, dirname):
        return self.localDir.get(dirname, None)

    def is_remote_dir(self, dirname):
        return self.remoteDir.get(dirname, None)

    def download(self):
        item = self.remote.fileList.currentItem()
        filesize = int(item.text(6))

        try:
            srcfile = os.path.join(self.pwd, str(item.text(0)))
            dstfile = os.path.join(self.local_pwd, str(item.text(0)))
        except AttributeError:
            srcfile = os.path.join(self.pwd, str(item.text(0)))
            dstfile = os.path.join(self.local_pwd, str(item.text(0)))

        pb = self.progressDialog.addProgress(
            type='download',
            title=srcfile,
            size=filesize,
        )

        def callback(data):
            pb.set_value(data)
            file.write(data)

        file = open(dstfile, 'wb')
        fp = FTP()
        fp.connect(host=self.ftp_hostname, port=self.ftp.port, timeout=self.ftp.timeout)
        fp.login(user=self.ftp_username, passwd=self.ftp_password)
        fp.retrbinary(cmd='RETR ' + srcfile, callback=callback)

    def upload(self):
        item = self.local.fileList.currentItem()
        print(item)
        # filesize = int(item.text(1))
        filesize = int(item.text(6))

        try:
            srcfile = os.path.join(self.local_pwd, str(item.text(0)))
            dstfile = os.path.join(self.pwd, str(item.text(0)))
        except AttributeError:
            srcfile = os.path.join(self.local_pwd, str(item.text(0)))
            dstfile = os.path.join(self.pwd, str(item.text(0)))

        pb = self.progressDialog.addProgress(
            type='upload',
            title=srcfile,
            size=filesize,
        )

        file = open(srcfile, 'rb')
        fp = FTP()
        fp.connect(host=self.ftp_hostname, port=self.ftp.port, timeout=self.ftp.timeout)
        fp.login(user=self.ftp_username, passwd=self.ftp_password)
        fp.storbinary(cmd='STOR ' + dstfile, fp=file, callback=pb.set_value)
Esempio n. 3
0
class FtpClient(QtGui.QWidget):
    def __init__(self, parent=None):
        super(FtpClient, self).__init__(parent)
        self.ftp = FTP( )
        self.setupGui( )
        self.downloads=[ ]
        self.remote.homeButton.clicked.connect(self.cdToRemoteHomeDirectory)
        self.remote.fileList.itemDoubleClicked.connect(self.cdToRemoteDirectory)
        self.remote.fileList.itemClicked.connect(lambda: self.remote.downloadButton.setEnabled(True))
        self.remote.backButton.clicked.connect(self.cdToRemoteBackDirectory)
        self.remote.nextButton.clicked.connect(self.cdToRemoteNextDirectory)
        self.remote.downloadButton.clicked.connect(lambda: Thread(target=self.download).start())
        QObject.connect(self.remote.pathEdit, SIGNAL('returnPressed( )'), self.cdToRemotePath)

        self.local.homeButton.clicked.connect(self.cdToLocalHomeDirectory)
        self.local.fileList.itemDoubleClicked.connect(self.cdToLocalDirectory)
        self.local.fileList.itemClicked.connect(lambda: self.local.uploadButton.setEnabled(True))
        self.local.backButton.clicked.connect(self.cdToLocalBackDirectory)
        self.local.nextButton.clicked.connect(self.cdToLocalNextDirectory)
        self.local.uploadButton.clicked.connect(lambda: Thread(target=self.upload).start())
        self.local.connectButton.clicked.connect(self.connect)
        QObject.connect(self.local.pathEdit, SIGNAL('returnPressed( )'), self.cdToLocalPath)

        self.progressDialog = ProgressDialog(self)

    def setupGui(self):
        self.resize(1200, 650)
        self.local  = LocalGuiWidget(self)
        self.remote = RemoteGuiWidget(self)
        mainLayout = QtGui.QHBoxLayout( )
        mainLayout.addWidget(self.remote)
        mainLayout.addWidget(self.local)
        mainLayout.setSpacing(0)
        mainLayout.setMargin(5)
        self.setLayout(mainLayout)

    def initialize(self):
        self.localBrowseRec    = [ ]
        self.remoteBrowseRec   = [ ]
        self.pwd               = self.ftp.pwd( )
        self.local_pwd         = os.getenv('HOME')
        self.remoteOriginPath  = self.pwd
        self.localOriginPath   = self.local_pwd
        self.localBrowseRec.append(self.local_pwd)
        self.remoteBrowseRec.append(self.pwd)
        self.downloadToRemoteFileList( )
        self.loadToLocaFileList( )

    def disconnect(self):
        pass

    def connect(self):
        try:
            from urlparse import urlparse
        except ImportError:
            from urllib.parse import urlparse


        result = QtGui.QInputDialog.getText(self, 'Connect To Host', 'Host Address', QtGui.QLineEdit.Normal)
        if not result[1]:
            return
        try:
            host = str(result[0].toUtf8())
        except AttributeError:
            host = str(result[0])

        try:
            if urlparse(host).hostname:
                self.ftp.connect(host=urlparse(host).hostname, port=21, timeout=10)
            else:
                self.ftp.connect(host=host, port=21, timeout=10)
            self.login()
        except Exception as error:
            raise error

    def login(self):
        ask = loginDialog(self)
        if not ask:
            return
        else:
            user, passwd = ask[:2]
        self.ftp.user   = user
        self.ftp.passwd = passwd
        self.ftp.login(user=user, passwd=passwd)
        self.initialize( )

    '''
    def connect(self, address, port=21, timeout=10):
        from urlparse import urlparse
        if urlparse(address).hostname:
            self.ftp.connect(urlparse(address).hostname, port, timeout)
        else:
            self.ftp.connect(address, port, timeout)

    def login(self, name=None, passwd=None):
        if not name:
            self.ftp.login( )
        else:
            self.ftp.login(name, passwd)
            self.ftp.user, self.ftp.passwd = (user, passwd)
        self.initialize( )
    '''
    #---------------------------------------------------------------------------------#
    ## the downloadToRemoteFileList with loadToLocalFileList is doing the same thing ##
    #---------------------------------------------------------------------------------#
    def downloadToRemoteFileList(self):
        """
        download file and directory list from FTP Server
        """
        self.remoteWordList = [ ]
        self.remoteDir      = { }
        self.ftp.dir('.', self.addItemToRemoteFileList)
        self.remote.completerModel.setStringList(self.remoteWordList)

    def loadToLocaFileList(self):
        """
        load file and directory list from local computer
        """
        self.localWordList = [ ]
        self.localDir      = { }
        for f in os.listdir(self.local_pwd):
            pathname = os.path.join(self.local_pwd, f)
            self.addItemToLocalFileList(fileProperty(pathname))
        self.local.completerModel.setStringList(self.localWordList)

    def addItemToRemoteFileList(self, content):
        mode, num, owner, group, size, date, filename = self.parseFileInfo(content)
        if content.startswith('d'):
            icon     = qIcon('folder.png')
            pathname = os.path.join(self.pwd, filename)
            self.remoteDir[ pathname] = True
            self.remoteWordList.append(filename)

        else:
            icon = qIcon('file.png')

        item = QtGui.QTreeWidgetItem( )
        item.setIcon(0, icon)
        for n, i in enumerate((filename, size, owner, group, date, mode)):
            item.setText(n, i)

        self.remote.fileList.addTopLevelItem(item)
        if not self.remote.fileList.currentItem():
            self.remote.fileList.setCurrentItem(self.remote.fileList.topLevelItem(0))
            self.remote.fileList.setEnabled(True)

    def addItemToLocalFileList(self, content):
        mode, num, owner, group, size, date, filename = self.parseFileInfo(content)
        if content.startswith('d'):
            icon     = qIcon('folder.png')
            pathname = os.path.join(self.local_pwd, filename)
            self.localDir[ pathname ] = True
            self.localWordList.append(filename)

        else:
            icon = qIcon('file.png')

        item  = QtGui.QTreeWidgetItem( )
        item.setIcon(0, icon)
        for n, i in enumerate((filename, size, owner, group, date, mode)):
            #print((filename, size, owner, group, date, mode))
            item.setText(n, i)
        self.local.fileList.addTopLevelItem(item)
        if not self.local.fileList.currentItem():
            self.local.fileList.setCurrentItem(self.local.fileList.topLevelItem(0))
            self.local.fileList.setEnabled(True)

    def parseFileInfo(self, file):
        """
        parse files information "drwxr-xr-x 2 root wheel 1024 Nov 17 1993 lib" result like follower
                                "drwxr-xr-x", "2", "root", "wheel", "1024 Nov 17 1993", "lib"
        """
        item = [f for f in file.split(' ') if f != '']
        mode, num, owner, group, size, date, filename = (
            item[0], item[1], item[2], item[3], item[4], ' '.join(item[5:8]), ' '.join(item[8:]))
        return (mode, num, owner, group, size, date, filename)

    #--------------------------#
    ## for remote file system ##
    #--------------------------#
    def cdToRemotePath(self):
        try:
            pathname = str(self.remote.pathEdit.text().toUtf8())
        except AttributeError:
            pathname = str(self.remote.pathEdit.text())
        try:
            self.ftp.cwd(pathname)
        except:
            return
        self.cwd = pathname.startswith(os.path.sep) and pathname or os.path.join(self.pwd, pathname)
        self.updateRemoteFileList( )
        self.remote.backButton.setEnabled(True)
        if os.path.abspath(pathname) != self.remoteOriginPath:
            self.remote.homeButton.setEnabled(True)
        else:
            self.remote.homeButton.setEnabled(False)

    def cdToRemoteDirectory(self, item, column):
        pathname = os.path.join(self.pwd, str(item.text(0)))
        if not self.isRemoteDir(pathname):
            return
        self.remoteBrowseRec.append(pathname)
        self.ftp.cwd(pathname)
        self.pwd = self.ftp.pwd( )
        self.updateRemoteFileList( )
        self.remote.backButton.setEnabled(True)
        if pathname != self.remoteOriginPath:
            self.remote.homeButton.setEnabled(True)

    def cdToRemoteBackDirectory(self):
        pathname = self.remoteBrowseRec[ self.remoteBrowseRec.index(self.pwd)-1 ]
        if pathname != self.remoteBrowseRec[0]:
            self.remote.backButton.setEnabled(True)
        else:
            self.remote.backButton.setEnabled(False)

        if pathname != self.remoteOriginPath:
            self.remote.homeButton.setEnabled(True)
        else:
            self.remote.homeButton.setEnabled(False)
        self.remote.nextButton.setEnabled(True)
        self.pwd = pathname
        self.ftp.cwd(pathname)
        self.updateRemoteFileList( )

    def cdToRemoteNextDirectory(self):
        pathname = self.remoteBrowseRec[self.remoteBrowseRec.index(self.pwd)+1]
        if pathname != self.remoteBrowseRec[-1]:
            self.remote.nextButton.setEnabled(True)
        else:
            self.remote.nextButton.setEnabled(False)
        self.remote.backButton.setEnabled(True)
        if pathname != self.remoteOriginPath:
            self.remote.homeButton.setEnabled(True)
        else:
            self.remote.homeButton.setEnabled(False)
        self.remote.backButton.setEnabled(True)
        self.pwd = pathname
        self.ftp.cwd(pathname)
        self.updateRemoteFileList( )

    def cdToRemoteHomeDirectory(self):
        self.ftp.cwd(self.remoteOriginPath)
        self.pwd = self.remoteOriginPath
        self.updateRemoteFileList( )
        self.remote.homeButton.setEnabled(False)

    #-------------------------#
    ## for local file system ##
    #-------------------------#
    def cdToLocalPath(self):
        try:
            pathname = str(self.local.pathEdit.text( ).toUtf8())
        except AttributeError:
            pathname = str(self.local.pathEdit.text())
        pathname = pathname.endswith(os.path.sep) and pathname or os.path.join(self.local_pwd, pathname)
        if not os.path.exists(pathname) and not os.path.isdir(pathname):
            return

        else:
            self.localBrowseRec.append(pathname)
            self.local_pwd = pathname
            self.updateLocalFileList( )
            self.local.backButton.setEnabled(True)
            print(pathname, self.localOriginPath)
            if os.path.abspath(pathname) != self.localOriginPath:
                self.local.homeButton.setEnabled(True)
            else:
                self.local.homeButton.setEnabled(False)

    def cdToLocalDirectory(self, item, column):
        pathname = os.path.join(self.local_pwd, str(item.text(0)))
        if not self.isLocalDir(pathname):
            return
        self.localBrowseRec.append(pathname)
        self.local_pwd = pathname
        self.updateLocalFileList( )
        self.local.backButton.setEnabled(True)
        if pathname != self.localOriginPath:
            self.local.homeButton.setEnabled(True)

    def cdToLocalBackDirectory(self):
        pathname = self.localBrowseRec[ self.localBrowseRec.index(self.local_pwd)-1 ]
        if pathname != self.localBrowseRec[0]:
            self.local.backButton.setEnabled(True)
        else:
            self.local.backButton.setEnabled(False)
        if pathname != self.localOriginPath:
            self.local.homeButton.setEnabled(True)
        else:
            self.local.homeButton.setEnabled(False)
        self.local.nextButton.setEnabled(True)
        self.local_pwd = pathname
        self.updateLocalFileList( )

    def cdToLocalNextDirectory(self):
        pathname = self.localBrowseRec[self.localBrowseRec.index(self.local_pwd)+1]
        if pathname != self.localBrowseRec[-1]:
            self.local.nextButton.setEnabled(True)
        else:
            self.local.nextButton.setEnabled(False)
        if pathname != self.localOriginPath:
            self.local.homeButton.setEnabled(True)
        else:
            self.local.homeButton.setEnabled(False)
        self.local.backButton.setEnabled(True)
        self.local_pwd = pathname
        self.updateLocalFileList( )

    def cdToLocalHomeDirectory(self):
        self.local_pwd = self.localOriginPath
        self.updateLocalFileList( )
        self.local.homeButton.setEnabled(False)

    def updateLocalFileList(self):
        self.local.fileList.clear( )
        self.loadToLocaFileList( )

    def updateRemoteFileList(self):
        self.remote.fileList.clear( )
        self.downloadToRemoteFileList( )

    def isLocalDir(self, dirname):
        return self.localDir.get(dirname, None)

    def isRemoteDir(self, dirname):
        return self.remoteDir.get(dirname, None)

    def download(self):
        item     = self.remote.fileList.currentItem( )
        filesize = int(item.text(1))

        try:
            srcfile  = os.path.join(self.pwd, str(item.text(0).toUtf8()))
            dstfile  = os.path.join(self.local_pwd, str(item.text(0).toUtf8()))
        except AttributeError:
            srcfile  = os.path.join(self.pwd, str(item.text(0)))
            dstfile  = os.path.join(self.local_pwd, str(item.text(0)))

        pb = self.progressDialog.addProgress(
            type='download',
            title=srcfile,
            size=filesize,
        )

        def callback(data):
            pb.set_value(data)
            file.write(data)

        file = open(dstfile, 'wb')
        fp = FTP( )
        fp.connect(host=self.ftp.host, port=self.ftp.port, timeout=self.ftp.timeout)
        fp.login(user=self.ftp.user, passwd=self.ftp.passwd)
        fp.retrbinary(cmd='RETR '+srcfile, callback=callback)

    def upload(self):
        item     = self.local.fileList.currentItem( )
        filesize = int(item.text(1))

        try:
            srcfile  = os.path.join(self.local_pwd, str(item.text(0).toUtf8()))
            dstfile  = os.path.join(self.pwd, str(selected_item.text(0).toUtf8()))
        except AttributeError:
            srcfile  = os.path.join(self.local_pwd, str(item.text(0)))
            dstfile  = os.path.join(self.pwd, str(selected_item.text(0)))

        pb = self.progressDialog.addProgress(
            type='upload',
            title=srcfile,
            size=filesize,
        )

        file = open(srcfile, 'rb')
        fp = FTP( )
        fp.connect(host=self.ftp.host, port=self.ftp.port, timeout=self.ftp.timeout)
        fp.login(user=self.ftp.user, passwd=self.ftp.passwd)
        fp.storbinary(cmd='STOR '+dstfile, fp=file, callback=pb.set_value)