Details
-
Bug
-
Resolution: Done
-
P2: Important
-
5.15.0, 5.15
-
None
-
Qt 5.15.0, openSUSE Leap 15.1
-
-
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
Issue Links
- relates to
-
QTBUG-102438 Drag/drop of "text/plain" does not work, QMimeData::text() returns an empty string
- Closed