I'm running a QML app on desktop Linux (KDE). When a file is dropped onto the main window of the QML app, I need to get the file path and filename as text (with or without prefix "file:///").
If I drag a file from Dolphin file manager to Firefox's address bar, the text URI (e.g., "file:///home/user/Downloads/file.txt") is dropped into the address bar and the file opens in Firefox. This shows that the drag information for a file is available from the OS.
Another test I can do using the QML app I built (code provided below) is select some text (say on a webpage) and drag that selection onto my app's main window. This works and the app obtains and stores whatever the text selection contained.
However, I am not able to drag and drop files onto my QML application. I don't understand why I can drag a text selection but not a file. I'm providing a working example of my code.
Testing on KDE, when I drop a file onto the QML app window, the onDropped
method is called. In there I do a console.log and drop.text
is empty (and drag.source is null).
How is dragging and dropping of files (e.g., from a file manager) to the QML application supposed to be implemented?
and the QML:
import QtQuick.Window 2.2
import QtQuick 2.2
import QtQuick.Controls 1.3
import QtQuick.Layouts 1.3
import QtQuick.Dialogs 1.0
ApplicationWindow {
id: rootId
visible: true
title: "Drag Drop MRE"
property int margin: 16
minimumWidth: 600
minimumHeight: 480
FileDialog {
id: fileDialog
title: "Choose File Attachment"
folder: shortcuts.home
onAccepted: {
attachments.text += fileDialog.fileUrls + '\n'
console.log("added attachment: " + fileDialog.fileUrls)
}
}
DropArea{
id: drop
enabled: true
anchors.fill: parent
anchors.margins: margin
Rectangle {
anchors.fill: parent
color: "green"
visible: parent.containsDrag
}
onEntered: console.log("entered DropArea")
onDropped:{
attachments.text += drop.text + '\n'
console.log("added attachment: " + drop.text)
console.log("drag.source: " + drag.source)
}
Drag.dragType: Drag.Automatic
GridLayout {
id: mainLayout
anchors.fill: parent
anchors.margins: margin
Label {
text: "Drag Drop MRE"
font.pixelSize: 16
Layout.row: 1
Layout.column: 1
}
GroupBox {
Layout.row: 2
Layout.column: 1
id: gridBox
Layout.fillWidth: true
GridLayout {
id: gridLayout
rows: 1
flow: GridLayout.TopToBottom
anchors.fill: parent
Label { text: "Attached files"
}
TextArea {
id: attachments
Layout.fillWidth: true
implicitHeight: 300
}
}
}
GroupBox {
Layout.row: 3
Layout.column: 1
id: rowBox
Layout.fillWidth: true
Row {
anchors.right: parent.right
id: rowLayout
Button {
id: attach_button
text: "Attach"
onClicked: fileDialog.open();
}
Button {
id: save_button
text: "Save"
onClicked: console.log(attachments.text)
}
Button {
id: exit_button
text: "Exit"
onClicked: Qt.quit()
}
}
}
}} // Grid Layout & Drop Area
}
I found a related question, but it is the other way around: Drag file from application to explorer. Can my application do the copying?
I have also built and run the Qt examples. Unfortunately, the examples suffer from the same issue, so they aren't helpful in resolving the problem. However, I have read that what I'm trying to do can be done. I just haven't found a working solution.
This should work (tested on Windows):
Window {
id: root
visible: true
width: 640
height: 480
title: qsTr("Drop Area")
DropArea {
id: dropArea;
anchors.fill: parent
onEntered: {
root.color = "gray";
drag.accept (Qt.LinkAction);
}
onDropped: {
console.log(drop.urls)
root.color = "white"
}
onExited: {
root.color = "white";
}
}
}