I have a simple file handling widget which can copy/cut/paste selected files from/to clipboard. I would like to be able to exchange files using these commands between this widget and Windows Explorer (potentially other file managers such as Total Commander or Free Commander). I already found that I can store the file names to the clipboard as QList<QUrl>
using QMimeData::setUrls()
and restore them similarly. This way I am able to copy and paste between my widget and the above mentioned file managers because they seem to use the same format for storing file names. But I do not know how to cut items to clipboard (i.e. delete after the file is pasted). I assume that the receiver (the application which pastes the data) is responsible for deleting the cut files. In that case it must be somehow encoded in the clipboard data, that the files have been cut rather than copied, this information can be retrieved by the receiving application. How is this done? Or is there any other way? I know this is possible because this works perfectly between Windows Explorer and Free Commander. I.e. when you cut files in Window Explorer and paste them to Free Commander, the original file is deleted and vice versa.
UPDATE:
I found there is also another part of MIME data "Preferred DropEffect"
which can have value of 5
(copy) or 2
(cut). When I set the QByteArray
to 4 bytes which correspond to an integer of value 5
or 2
, I can distinguish whether Windows Explorer initiated cut or copy. If it is cut, then I can move the file rather than copy. It works well. Unfortunately this still works one way only from Windows Explorer to Qt application. I still have not found why the opposite direction does not work. There are also some other MIME data which are however hard to decode for me. Maybe there is the key.
UPDATE 2: Mimimal code to reproduce the behvaiour is here. Make sure the file hardcoded in the program exists. Try to run the program and after closing the window open open Windows Explorer go to arbitrary folder where you can write and press Ctrl+V... Then the copy of the file should appear in that directory but it is not deleted from the source directory. The program below uses constant 2 which means cut rather than copy which means the original file should disappear.
#include <QApplication>
#include <QClipboard>
#include <QDataStream>
#include <QMimeData>
#include <QUrl>
#include <QWidget>
int main(int argc, char *argv[])
{
QApplication application(argc, argv);
auto mimeData = new QMimeData;
// store the URL to files which I want to cut
QList<QUrl> urls;
urls.append(QUrl::fromLocalFile("C:/mypath/myfile.txt")); // use your path or make sure this file exist
mimeData->setUrls(urls);
// store drop effect indicating whether I want to cut or copy
int dropEffect = 2; // 2 for cut and 5 for copy
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
stream << dropEffect;
mimeData->setData("Preferred DropEffect", data);
QApplication::clipboard()->setMimeData(mimeData);
QWidget window;
window.show();
return application.exec();
}
See also How to programmatically cut/copy/get files to/from the Windows clipboard in a system standard compliant form? and https://msdn.microsoft.com/en-us/library/windows/desktop/bb776904(v=vs.85).aspx#delete_on_paste