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

Drag/drop of "text/plain" does not work, QMimeData::text() returns an empty string

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed
    • Priority: P2: Important
    • Resolution: Done
    • Affects Version/s: 5.15.0, 5.15
    • Fix Version/s: 5.15.1
    • Component/s: GUI: Drag and Drop
    • Labels:
      None
    • Environment:
      Qt 5.15.0, openSUSE Leap 15.1
    • Platform/s:
      Linux/X11
    • Commits:
      5826a7ad921930393c84b790123f493e26d0685c (qt/qtbase/5.15)

      Description

      Drag/drop of "text/plain" does not work, QMimeData::text() returns an empty string. The bug came in with the fix for QTBUG-54786, Qt 5.13.0 (despite the fix itself seems correct). Reason: QMimeDataPrivate::retrieveTypedData does not reliably return QVariant::isNull(), if the MIME type does not match, e.g. in the following case:

      #if QT_CONFIG(textcodec)
              case QMetaType::QString: {
                  const QByteArray ba = data.toByteArray();
                  QTextCodec *codec = QTextCodec::codecForName("utf-8");
                  if (format == QLatin1String("text/html"))
                      codec = QTextCodec::codecForHtml(ba, codec);
                  return codec->toUnicode(ba);
              }
      #endif // textcodec
      

      Suggested (but unreviewed) fix QMimeDataPrivate::retrieveTypedData(take the branch #if FIXED):

          #if FIXED
      
          // Text data requested: fallback to URL data if available
          if (data.isNull() && format == QLatin1String("text/plain")) {
              data = retrieveTypedData(textUriListLiteral(), QMetaType::QVariantList);
              if (data.isNull())
                  return data;
              if (data.userType() == QMetaType::QUrl) {
                  data = QVariant(data.toUrl().toDisplayString());
              } else if (data.userType() == QMetaType::QVariantList) {
                  QString text;
                  int numUrls = 0;
                  const QList<QVariant> list = data.toList();
                  for (int i = 0; i < list.size(); ++i) {
                      if (list.at(i).userType() == QMetaType::QUrl) {
                          text += list.at(i).toUrl().toDisplayString() + QLatin1Char('\n');
                          ++numUrls;
                      }
                  }
                  if (numUrls == 1)
                      text.chop(1); // no final '\n' if there's only one URL
                  data = QVariant(text);
              }
          }
      
          if (data.userType() == type || data.isNull())
              return data;
      
          #else
      
          // Text data requested: fallback to URL data if available
          if (format == QLatin1String("text/plain") && !data.isValid()) {
              data = retrieveTypedData(textUriListLiteral(), QMetaType::QVariantList);
              if (data.userType() == QMetaType::QUrl) {
                  data = QVariant(data.toUrl().toDisplayString());
              } else if (data.userType() == QMetaType::QVariantList) {
                  QString text;
                  int numUrls = 0;
                  const QList<QVariant> list = data.toList();
                  for (int i = 0; i < list.size(); ++i) {
                      if (list.at(i).userType() == QMetaType::QUrl) {
                          text += list.at(i).toUrl().toDisplayString() + QLatin1Char('\n');
                          ++numUrls;
                      }
                  }
                  if (numUrls == 1)
                      text.chop(1); // no final '\n' if there's only one URL
                  data = QVariant(text);
              }
          }
      
          if (data.userType() == type || !data.isValid())
              return data;
      
          #endif
      

      The bug can be reproduced with the attached application "app". This app shows a QLineEdit at the top and a QTextEdit at the bottom. Start two instances of that app, type an arbitrary text into the QLineEdit of the first instance and try to drag the text to the edits of the second instance. On drop the target QLineEdit receives an empty string. The target QTextEdit does not accept the drop at all, because QTextEdit refuses empty strings.

       

        Attachments

        1. qtbug_mimedata.zip
          2 kB
          Winfried Schenke

          Issue Links

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

            Activity

              People

              Assignee:
              liaqi Liang Qi
              Reporter:
              wschenke Winfried Schenke
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved:

                  Gerrit Reviews

                  There are no open Gerrit changes