Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-2225

QMimeData::retrieveData is called before the data is required

    XMLWordPrintable

Details

    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 40
      QMimeDataPrivate::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 &

      {...}, const QMimeData * 0x00be8f48) line 566 + 13 bytes
      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!";
          }
      };
      

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            pullatti Prasanth Ullattil
            vhilshei Volker Hilsheimer
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:

              Gerrit Reviews

                There are no open Gerrit changes