PDA

View Full Version : Dragging text/uri-list: Qt inserts garbage



drhex
15th September 2011, 21:12
I need to drag image files (in the form of URLs) to other applications. It should work for

Drag to image editor (which will open the image files)
Drag to terminal window (which will paste the URLs into the commandline)

Here is a minimal demo of the problem. It is to be started with the paths to a few local image files as arguments. These will be displayed in a QLabel and can then be dragged.


#include <QtGui>

class Foo : public QLabel
{
QPoint dragpos;
QStringList files;
public:
Foo(QStringList data) : QLabel(data.join("\n")), files(data) {setAcceptDrops(true);}
void mousePressEvent(QMouseEvent *ev) {
if (ev->button() == Qt::LeftButton) dragpos = ev->pos();
}
void mouseMoveEvent(QMouseEvent *ev)
{
if ((ev->buttons() & Qt::LeftButton) && (ev->pos() - dragpos).manhattanLength() >= QApplication::startDragDistance()) {
QDrag *drag = new QDrag(this);
QMimeData *mdata = new QMimeData();
QList<QUrl> urlist;
foreach (QString file, files) {
urlist << QUrl::fromLocalFile(file);
}
mdata->setUrls(urlist);
mdata->setText("Plain text version");
qDebug("has text/x-moz-url: %s", mdata->hasFormat("text/x-moz-url") ? "yes":"no"); // says "no"
mdata->removeFormat("text/x-moz-url"); // no effect as isn't there yet
drag->setMimeData(mdata);
drag->start(Qt::CopyAction);
}
}
void dragEnterEvent(QDragEnterEvent *ev) {
ev->acceptProposedAction();
}
void dropEvent(QDropEvent *ev) {
foreach (QString format, ev->mimeData()->formats()) {
qDebug("%s", qPrintable(format));
}
QByteArray ba = ev->mimeData()->data("text/x-moz-url");
qDebug("got x-moz-url = %s", qPrintable(QString::fromRawData((QChar *)(ba.data()), int(ba.size()/sizeof(QChar)))));
}
};

int main( int argc, char **argv )
{
QApplication app( argc, argv );
QStringList files;
QDir dir;

for (int i=1; i<argc; i++) files.append(dir.absoluteFilePath(argv));

Foo foo(files);
foo.show();

return app.exec();
}

Using the program above, I can drag a few image files to the gimp image editor and they will open fine.
I can also drag the URLs to the konsole terminal program and the filenames will be pasted in, properly quoted.
But when I drag into gnome-terminal (the default Ubuntu terminal), I only get the first filename, with an extraneous \r\n.
This is because Qt, in addition to the text/uri-list that I inserted into the QMimeData object, also adds something in text/x-moz-url format (the latter format being preferred by gnome-terminal).
Start two copies of the program above (both with filename arguments) and drag from one to the other to see what is dragged and what is received.
So, my questions are:

Why does Qt add data in text/x-moz-url format without being asked to?
Why does that data only include the first filename? (this link (https://developer.mozilla.org/en/dragdrop/recommended_drag_types) suggests [I]x-moz-url can handle multiple urls)
How can I construct a draggable object with text/uri-list but lacking text/x-moz-url?


(Using Qt-4.8.0-beta)

drhex
22nd September 2011, 21:45
It may not be possible to avoid a text/x-moz-url component in the dragged data, but it is possible to control what it contains, e.g. the following code fragment can be used to define both it and a standard text/uri-list:


QList<QUrl> urlist;
QString str;
foreach (QString file, files) {
urlist << QUrl::fromLocalFile(file);
str += QString("'%1' ").arg(file);
}
mdata->setUrls(urlist);
QByteArray ba;
ba.setRawData((char *)str.data(), str.length()*sizeof(QChar));
mdata->setData("text/x-moz-url", ba);