Modern GUIs need Drag and Drop
The following is an example for a drag & drop action with PyQt4. It uses paramiko for SSH interactions. I'm well aware that it won't work on Windows that way. But that's a Windows problem. I'm also well aware that there's a password in this file. Give it a try.
The source is at GitHub. The indention seems to be broken there. But that's a GitHub problem. It seems to be broken here, too. But that's a Drupal problem. ;). Actually it isn't even a problem.
Just the imports. The os module is necessary if you want paramiko to use your private ssh-key. The sys module is needed due argv:
- import sys
- import paramiko # for ssh
- import os
- from PyQt4 import QtGui, QtCore
- from mainwindow import Ui_MainWindow
I pretty much guess that's self-explaining now. That's the standard header to initiate the form:
- class gui_does(QtGui.QMainWindow):
- def __init__(self):
- QtGui.QMainWindow.__init__(self)
- self.ui = Ui_MainWindow()
- self.ui.setupUi(self)
- self.setWindowTitle('To-SSH Droplet')
- # to accept drops
- self.setAcceptDrops(True)
- self.ui.lineEdit.setText("/home/wishi/")
- self.statusBar().showMessage('Ready')
To make an application accept drop-acrions simply define this in an __init__. Compared to Cocoa e. g. this is really trivial.
- def dragEnterEvent(self, event):
- if event.mimeData().hasUrls():
- event.acceptProposedAction()
- """ the initial drop action is scp """
- def dropEvent(self, event):
- filelist = ('\r\n'.join([str(url.toString()) for url in event.mimeData().urls()]))
- self.ui.textEdit.setText(filelist)
- splitted_filelist = filelist.split("\r\n")
- destination_path = self.ui.lineEdit.text()
- That's it to define the event-actions. If a user drops a file, handle it:
- #privatekeyfile = os.path.expanduser('~/.ssh/id_rsa')
- #mykey = paramiko.RSAKey.from_private_key_file(privatekeyfile)
- username = 'wishi'
- password = 'bmljZSB0cnkgaWRpb3Q='
- host = 'crazylazy.info'
- port = 22
- error = False
So... paramiko is able to use your private key, as stated in the comment. It also supports passwords. Surely you know, that Base64 isn't used in SSH ;). However in this case it makes sense.
- try:
- self.statusBar().showMessage("Uploading")
- ssh = paramiko.SSHClient()
- ssh.load_system_host_keys()
- ssh.connect(host, username = username, password = password)
- sftp = ssh.open_sftp()
- for file in splitted_filelist:
- file = file[7:]
- patharray = file.split("/")
- destination_path = destination_path + patharray[len(patharray)-1]
- sftp.put(file, str(destination_path))
- sftp.close()
- ssh.close()
- except:
- error = True
- if (error):
- self.statusBar().showMessage("Error")
- else:
- self.statusBar().showMessage("Ready")
- if __name__=="__main__":
- app = QtGui.QApplication(sys.argv)
- window = gui_does()
- window.show()
- sys.exit(app.exec_())
The interesting point here are the text conversions, which are necessary. You see that str(destionation_path) converts self.ui.lineEdit.text(). That's confusing at the beginning, but Qt handles text as unicode. Most Python installation don't.
Paramiko wants an ASCII string. So you convert this into a standard Python string-type. Furthermore you see that the string-operations introduced in nearly every Python tutorial I ever read are more than essential. Even in GUI programming they're central.
If you take a look at the for-loop: destination_path = destination_path + patharray[len(patharray)-1] -> makes sftp.put keep the filename and put it into the destination_path. You need the last element, which is len(element)-1.
The URI string normally starts with "file://". You don't want to pass these identifier-string to sftp.put. So you start at th 7th (file = file[7:]) position. That converts the URI into a general Unix path.
The rest of the app is trivial. Starting Qt Designer, clicking: the GUI just needs a lineEdit and a textEdit. The whole project including the QT Designer files are at GitHub. Surely you can enhance it with a progress bar, a menu-bar, preferences and extend it into a full featured sftp client.
This is just a general snippet on how to implement Drag and Drop actions with Qt and Python. If you want to dive into it, enhance it and:
Have fun,
wishi



Post new comment