Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Qt 4.x: how to implement drag-and-drop onto the desktop or into a folder?

I've written a little file-transfer application written in C++ using Qt 4.x ... it logs into a server, shows the user a list of files available on the server, and lets the user upload or download files.

This all works fine; you can even drag a file in from the desktop (or from an open folder), and when you drop the file icon into the server-files-list-view, the dropped file gets uploaded to the server.

Now I have a request for the opposite action as well... my users would like to be able to drag a file out of the server-files-list-view and onto the desktop, or into an open folder window, and have that file get downloaded into that location.

That seems like a reasonable request, but I don't know how to implement it. Is there a way for a Qt application to find out the directory corresponding to where "drop event" occurred, when the icon was dropped onto the desktop or into an open folder window? Ideally this would be a Qt-based platform-neutral mechanism, but if that doesn't exist, then platform-specific mechanisms for MacOS/X and Windows (XP or higher) would suffice.

Any ideas?

like image 947
Jeremy Friesner Avatar asked Apr 27 '10 19:04

Jeremy Friesner


People also ask

How to drag in Qt?

To start a drag, create a QDrag object, and call its exec() function. In most applications, it is a good idea to begin a drag and drop operation only after a mouse button has been pressed and the cursor has been moved a certain distance.


2 Answers

Look at QMimeData and its documentation, it has a virtual function

virtual QVariant retrieveData  ( const QString & mimetype, QVariant::Type type ) const

this means to do you drag to the outside you implement this functions accordingly

class DeferredMimeData : public QMimeData
{
  DeferredMimeData(QString downloadFilename) : m_filename(downloadFilename)

  virtual QVariant retrieveData (const QString & mimetype, QVariant::Type type) const 
  {
    if (mimetype matches expected && type matches expected)
    {
       perform download with m_filename
    }
  }
}

The delayed encoding examples shows this principle.

You will probably also have to override hasFormat and formats to provide the appropriate types, application/octet-stream probably being the one that might get you the most play, you will probably have to read up on how windows specifically handles drag and drop using mime types.

I don't know how you will supply the file name under which the file is saved, but you will probably have to get into the windows side of things. Looking at the source of QWindowsMime might also help. There might me a multiple step process where you will get requests for text/uri-list data for the filenames and then application/octet-stream for the data.

Hope this helps

like image 92
Harald Scheirich Avatar answered Sep 22 '22 07:09

Harald Scheirich


I think you are going about that in the wrong way.

You don't care where the drop goes to, you just know it was dropped. In the DropEvent, download the file to a temporary location and then set the mime data to be what was downloaded. Granted this may end up with a second copy to the hard drive, it will be cross platform from the start. You may be able to optimize it afterward with platform specific calls.

Take a look at Dropsite example to see how the mime data works from other sources...

Edit:

It looks like the double copy method is the standard if you don't write a shell extension (for windows at least). Filezilla and 7zip both do that, they return a "text/uri-list" mime type with a temp location. This way explorer copies the data from the temp location to the real one. Your application can do the same, create a temp file (or just the name) with no data. Using the delayed encoding example, create the data on the drop. This whole operation is very platform specific it appears. On Linux (running KDE) I can drag and drop just based on mime type. It appears that windows is not as flexible.

like image 33
Adam W Avatar answered Sep 23 '22 07:09

Adam W