Question

In my QML:

DropArea {
  onDropped: {
    root.dropSignal(drop);
  }
}

With the signal defined as:

signal dropSignal(var data)

My slot function:

void MainSlot::dropSlot(const QVariant &data)
{
  qDebug() << "Called the C++ slot with data:" << data;
}

This outputs the following:

Called the C++ slot with data: QVariant(QObject*, QQuickDropEvent(0x7fff5fbfd828) ) 

I need help casting this object to what I would expect is a Drop event of some kind. I want the C++ code to handle the logic of accepting/rejecting the drop and accessing the data from the drop.

I can't find QQuickDropEvent in the class reference. I did find QDropEvent. From the documentation on DragArea, it is not clear what is the C++ equivalent to the QML DragEvent or in which header file DragEvent is defined in.

Trying a cast like this has not worked:

QDropEvent *item = qobject_cast<QDropEvent*>(v.value<QObject*>());
Was it helpful?

Solution

QML's DragEvent = QQuickDropEvent

This is stated in this updated version of the QML DragEvent documentation fresh from the sources

/*!
    \qmltype DragEvent
    \instantiates QQuickDropEvent
    \inqmlmodule QtQuick
    \ingroup qtquick-input-events
    \brief Provides information about a drag event

    The position of the drag event can be obtained from the \l x and \l y
    properties, and the \l keys property identifies the drag keys of the event
    \l source.

    The existence of specific drag types can be determined using the \l hasColor,
    \l hasHtml, \l hasText, and \l hasUrls properties.

    The list of all supplied formats can be determined using the \l formats property.

    Specific drag types can be obtained using the \l colorData, \l html, \l text,
    and \l urls properties.

    A string version of any available mimeType can be obtained using \l getDataAsString.
*/

QQuickDropEvent's header is available in src/quick/items/qquickdroparea_p.h. I guess this is a private header file again, which means you are not supposed to handle these events in C++ but in Javascript.

A QQuickDropEvent instance contains a private instance variable of type QDropEvent that you can not access directly.

Edit: You might want to copy the drop's properties in Javascript and pass an array to C++ (untested):

DropArea {
    var actionIdToString = function(id) {
        if (id ===   Qt.CopyAction) return 'Qt.CopyAction';
        if (id ===   Qt.MoveAction) return 'Qt.MoveAction';
        if (id ===   Qt.LinkAction) return 'Qt.LinkAction';
        if (id === Qt.IgnoreAction) return 'Qt.IgnoreAction';
        return 'Unexpected action';
    }

    onDropped: {
        var dropProperties = [
            drop.accepted,
            actionIdToString(drop.action),
            drop.drag.source,
            drop.keys,
            drop.supportedActions,
            drop.x,
            drop.y
        ]
        root.dropSignal(dropProperties);
    }
}

There is a blog post about passing more complex datastructures between C++ and QML. As far as I can see, you will get a QVariantList when passing a Javascript array to your slot.

You might want to consider using a Javascript object (JSON style) in order to access the drop's properties by name instead of index in C++, but I am not sure how well objects survive the step from QML to C++.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top