PyQt and a SSH upload droplet

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:

  1. import sys
  2. import paramiko # for ssh
  3. import os  
  4. from PyQt4 import QtGui, QtCore
  5. from mainwindow import Ui_MainWindow

I pretty much guess that's self-explaining now. That's the standard header to initiate the form:

  1. class gui_does(QtGui.QMainWindow):
  2.    def __init__(self):
  3.       QtGui.QMainWindow.__init__(self)
  4.       self.ui = Ui_MainWindow()
  5.       self.ui.setupUi(self)
  6.  
  7.   self.setWindowTitle('To-SSH Droplet')
  8.   # to accept drops
  9.         self.setAcceptDrops(True)
  10.         self.ui.lineEdit.setText("/home/wishi/")
  11.         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.

  1.         def dragEnterEvent(self, event):
  2.                 if event.mimeData().hasUrls():
  3.                 event.acceptProposedAction()
  4.    
  5.     """ the initial drop action is scp """
  6. def dropEvent(self, event):
  7.         filelist = ('\r\n'.join([str(url.toString()) for url in event.mimeData().urls()]))
  8.         self.ui.textEdit.setText(filelist)
  9.         splitted_filelist = filelist.split("\r\n")
  10.         destination_path = self.ui.lineEdit.text()

- That's it to define the event-actions. If a user drops a file, handle it:

  1.         #privatekeyfile = os.path.expanduser('~/.ssh/id_rsa')
  2.         #mykey = paramiko.RSAKey.from_private_key_file(privatekeyfile)
  3.         username = 'wishi'
  4.         password = 'bmljZSB0cnkgaWRpb3Q='
  5.         host = 'crazylazy.info'
  6.         port = 22
  7.         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.

  1.         try:
  2.                 self.statusBar().showMessage("Uploading")
  3.                 ssh = paramiko.SSHClient()
  4.                 ssh.load_system_host_keys()
  5.                 ssh.connect(host, username = username, password = password)
  6.                 sftp = ssh.open_sftp()
  7.                
  8.                 for file in splitted_filelist:
  9.                         file = file[7:]
  10.                         patharray = file.split("/")
  11.                         destination_path = destination_path + patharray[len(patharray)-1]
  12.                         sftp.put(file, str(destination_path))
  13.            
  14.                 sftp.close()
  15.                 ssh.close()
  16.            
  17.         except:
  18.                 error = True
  19.        
  20.         if (error):    
  21.                 self.statusBar().showMessage("Error")
  22.         else:
  23.                 self.statusBar().showMessage("Ready")
  24.    
  25. if __name__=="__main__":
  26.         app = QtGui.QApplication(sys.argv)
  27.         window = gui_does()
  28.         window.show()
  29.         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

The content of this field is kept private and will not be shown publicly.

Ihr Browser versucht gerade eine Seite aus dem sogenannten Internet auszudrucken. Das Internet ist ein weltweites Netzwerk von Computern, das den Menschen ganz neue Möglichkeiten der Kommunikation bietet.

Da Politiker im Regelfall von neuen Dingen nichts verstehen, halten wir es für notwendig, sie davor zu schützen. Dies ist im beidseitigen Interesse, da unnötige Angstzustände bei Ihnen verhindert werden, ebenso wie es uns vor profilierungs- und machtsüchtigen Politikern schützt.

Sollten Sie der Meinung sein, dass Sie diese Internetseite dennoch sehen sollten, so können Sie jederzeit durch normalen Gebrauch eines Internetbrowsers darauf zugreifen. Dazu sind aber minimale Computerkenntnisse erforderlich. Sollten Sie diese nicht haben, vergessen Sie einfach dieses Internet und lassen uns in Ruhe.

Die Umgehung dieser Ausdrucksperre ist nach §95a UrhG verboten.

Mehr Informationen unter www.politiker-stopp.de.