Details
-
Suggestion
-
Resolution: Unresolved
-
P3: Somewhat important
-
4.4.0
-
None
Description
The code below tries to implement a QMimeData class that generates files on the fly, based on application data. However, the retrieveData function is called immediately during the drag, which also generates the temporary files even though that is not necessary yet. The stack trace for the premature calls is:
DynamicFileSource::retrieveData(const QString &
{length=13 str="text/uri-list"}, QVariant::Type List) line 40QMimeDataPrivate::retrieveTypedData(const QString & {length=13 str="text/uri-list"}
, QVariant::Type List) line 71 + 23 bytes
QMimeData::urls() line 299 + 47 bytes
QWindowsMimeURI::canConvertFromMime(const tagFORMATETC &
QWindowsMimeURI::formatsForMime(const QString & {length=13 str="text/uri-list"}, const QMimeData * 0x00be8f48) line 662 + 51 bytes
QWindowsMime::allFormatsForMime(const QMimeData * 0x00be8f48) line 350 + 49 bytes
QOleDataObject::EnumFormatEtc(QOleDataObject * const 0x00bea118, unsigned long 1, IEnumFORMATETC * * 0x0012bdf0) line 486 + 21 bytes
OLE32! 775334f5()
OLE32! 775d08dd()
OLE32! 775cff2e()
OLE32! 775d0468()
QDragManager::drag(QDrag * 0x00be8630) line 847 + 22 bytes
QDrag::exec(QFlags<enum Qt::DropAction> {...}
, Qt::DropAction IgnoreAction) line 254 + 12 bytes
class DynamicFileSource : public QMimeData { Q_OBJECT public: DynamicFileSource(const QStringList &relativeFilePaths) { QDir temp(QDir::tempPath()); QList<QUrl> urls; foreach(QString fileName, relativeFilePaths) { QString localFile = temp.path() + "/" + fileName; QFileInfo fileInfo(localFile); qDebug() << "making path" << fileInfo.absolutePath(); QFile::remove(localFile); temp.mkpath(fileInfo.absolutePath()); qDebug() << "storing url" << localFile; urls << QUrl::fromLocalFile(localFile); } setUrls(urls); } ~DynamicFileSource() { qDebug() << "destroying file source"; foreach(QUrl url, urls()) { QFile::remove(url.toLocalFile()); } } signals: void fileRequested(QFile *file); protected: bool hasFormat(const QString &mimeType) const { return mimeType == QLatin1String("text/uri-list"); } QVariant retrieveData(const QString & mimeType, QVariant::Type type ) const { QVariant data = QMimeData::retrieveData(mimeType, type); if (hasFormat(mimeType) && type == QVariant::List) { QList<QVariant> urls = data.toList(); foreach(QVariant url, urls) { Q_ASSERT(url.type() == QVariant::Url); QFile file(url.toUrl().toLocalFile()); if (file.open(QIODevice::WriteOnly)) { emit const_cast<DynamicFileSource*>(this)->fileRequested(&file); file.close(); } } } return data; } }; class Widget : public QWidget { Q_OBJECT public: Widget() { } protected: void mouseMoveEvent(QMouseEvent *e) { QDrag *drag = new QDrag(this); QStringList files; files << "test.txt" << "test2.txt"; DynamicFileSource *data = new DynamicFileSource(files); connect(data, SIGNAL(fileRequested(QFile*)), this, SLOT(writeData(QFile*))); drag->setMimeData(data); drag->exec(Qt::CopyAction); } private slots: void writeData(QFile *file) { QTextStream out(file); out << "hello world!"; } };