If you ever tried to handle drag’n’drop files in your Qt application, you would usually come up with the code like the following.
First of all you will need a Drop Area somewhere in your application, which will handle drops
DropArea {
anchors.fill: parent
onDropped: {
if (drop.hasUrls) {
var filesCount = yourCppModel.dropFiles(drop.urls)
console.log(filesCount + ' files added via drag&drop')
}
}
}
Where yourCppModel is a model exposed to Qml in main.cpp or wherever like this:
QQmlContext *rootContext = engine.rootContext();
rootContext->setContextProperty("yourCppModel", &myCppModel);
and int dropFiles(const QList<QUrl> &urls)
is just an ordinary method exposed to QML via Q_INVOKABLE
attribute.
You will sure notice everything works fine unless you’re working under OS X. In OS X instead of QUrls to local files you will get something like this: _ file:///.file/id=6571367.2773272/
_. There’s a bug in Qt for that and it even looks closed, but it still doesn’t work for me that’s why I’ve implemented my own helper using mixing of Objective-C and Qt-C++ code.
I’ve added a osxnshelper.h
and osxnshelper.mm
source file with helper method to my project:
#include <Foundation/Foundation.h>
#include <QUrl>
QUrl fromNSUrl(const QUrl &url) {
NSURL *nsUrl = url.toNSURL();
NSString *path = nsUrl.path;
QString qtString = QString::fromNSString(path);
return QUrl::fromLocalFile(qtString);
}
and added it into the .pro file with conditional define:
macx {
OBJECTIVE_SOURCES += \
osxnsurlhelper.mm
LIBS += -framework Foundation
HEADERS += osxnsurlhelper.h
}
Now I’m able to use this helper in my actual dropFiles()
method:
int MySuperCppModel::dropFiles(const QList<QString> &urls)
{
QList<QString> localUrls;
#ifdef Q_OS_MAC
foreach (const QUrl &url, urls) {
QUrl localUrl = fromNSUrl(url);
localUrls.append(localUrl);
}
#else
localUrls = urls;
#endif
// ......
}
That’s it. Now it works perfectly.