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>
{
public:
if (ev->button() == Qt::LeftButton) dragpos = ev->pos();
}
{
if ((ev
->buttons
() & Qt
::LeftButton) && (ev
->pos
() - dragpos
).
manhattanLength() >
= QApplication::startDragDistance()) { QList<QUrl> urlist;
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);
}
}
ev->acceptProposedAction();
}
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 )
{
for (int i=1; i<argc; i++) files.append(dir.absoluteFilePath(argv[i]));
Foo foo(files);
foo.show();
return app.exec();
}
#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[i]));
Foo foo(files);
foo.show();
return app.exec();
}
To copy to clipboard, switch view to plain text mode
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 suggests 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)
Bookmarks