Code Jamming Everyday IT problems, solutions and discussions

Handling drag'n'drop of files in Qt under OS X

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 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 {

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 = urls;
    // ......

That’s it. Now it works perfectly.

Buy me a coffeeBuy me a coffee
comments powered by Disqus