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

        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