From c47f173ba9374849e68ff9adc12a8e2223261dda Mon Sep 17 00:00:00 2001 From: Mahmoud Badri Date: Thu, 3 Jun 2021 16:10:40 +0300 Subject: [PATCH] QmlDesigner: Fix asset drag issue Workaround QDrag issue that causes drag to stay active after pressing and releasing at the same point. Fixes: QDS-4446 Change-Id: Ieb25656a1e9f42c724a254820c1d290a522835d5 Reviewed-by: Miikka Heikkinen --- .../itemLibraryQmlSources/Assets.qml | 2 +- .../itemlibrary/itemlibrarywidget.cpp | 35 ++++++++++++------- .../itemlibrary/itemlibrarywidget.h | 4 ++- 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml b/share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml index 58f42cdb5d1..ef8307831eb 100644 --- a/share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml +++ b/share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml @@ -154,7 +154,7 @@ Item { onPressed: { forceActiveFocus() if (mouse.button === Qt.LeftButton) - rootView.startDragAsset(filePath) + rootView.startDragAsset(filePath, mapToGlobal(mouse.x, mouse.y)) else print("TODO: impl context menu") } diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp index 27e9fa3d511..ddfec570d56 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp @@ -115,9 +115,24 @@ bool ItemLibraryWidget::eventFilter(QObject *obj, QEvent *event) m_itemToDrag = {}; } + } else if (!m_assetToDrag.isEmpty()) { + QMouseEvent *me = static_cast(event); + if ((me->globalPos() - m_dragStartPoint).manhattanLength() > 10) { + auto drag = new QDrag(this); + drag->setPixmap(m_assetsIconProvider->requestPixmap(m_assetToDrag, nullptr, {128, 128})); + QMimeData *mimeData = new QMimeData; + mimeData->setData("application/vnd.bauhaus.libraryresource", m_assetToDrag.toUtf8()); + mimeData->setData(m_assetToDragTypeAndData.first, m_assetToDragTypeAndData.second); + drag->setMimeData(mimeData); + drag->exec(); + drag->deleteLater(); + + m_assetToDrag.clear(); + } } } else if (event->type() == QMouseEvent::MouseButtonRelease) { m_itemToDrag = {}; + m_assetToDrag.clear(); } return QObject::eventFilter(obj, event); @@ -186,6 +201,7 @@ ItemLibraryWidget::ItemLibraryWidget(AsynchronousImageCache &imageCache, new Internal::ItemLibraryImageProvider); Theme::setupTheme(m_itemViewQuickWidget->engine()); m_itemViewQuickWidget->installEventFilter(this); + m_assetsWidget->installEventFilter(this); m_fontPreviewTooltipBackend = std::make_unique(asynchronousFontImageCache); // Note: Though the text specified here appears in UI, it shouldn't be translated, as it's @@ -449,27 +465,22 @@ void ItemLibraryWidget::startDragAndDrop(const QVariant &itemLibEntry, const QPo { // Actual drag is created after mouse has moved to avoid a QDrag bug that causes drag to stay // active (and blocks mouse release) if mouse is released at the same spot of the drag start. - // This doesn't completely eliminate the bug but makes it significantly harder to produce. m_itemToDrag = itemLibEntry; m_dragStartPoint = mousePos.toPoint(); } -void ItemLibraryWidget::startDragAsset(const QString &assetPath) +void ItemLibraryWidget::startDragAsset(const QString &assetPath, const QPointF &mousePos) { QFileInfo fileInfo(assetPath); - QPair typeAndData = getAssetTypeAndData(fileInfo); + m_assetToDragTypeAndData = getAssetTypeAndData(fileInfo); - if (typeAndData.first.isEmpty()) + if (m_assetToDragTypeAndData.first.isEmpty()) return; - auto drag = new QDrag(this); - drag->setPixmap(m_assetsIconProvider->requestPixmap(assetPath, nullptr, {128, 128})); - QMimeData *mimeData = new QMimeData; - mimeData->setData(QLatin1String("application/vnd.bauhaus.libraryresource"), - fileInfo.absoluteFilePath().toUtf8()); - mimeData->setData(typeAndData.first, typeAndData.second); - drag->setMimeData(mimeData); - drag->exec(); + // Actual drag is created after mouse has moved to avoid a QDrag bug that causes drag to stay + // active (and blocks mouse release) if mouse is released at the same spot of the drag start. + m_assetToDrag = fileInfo.absoluteFilePath(); + m_dragStartPoint = mousePos.toPoint(); } QPair ItemLibraryWidget::getAssetTypeAndData(const QFileInfo &fi) const diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h index 122e67eacd3..a908649d63b 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h @@ -93,7 +93,7 @@ public: QPair getAssetTypeAndData(const QFileInfo &fi) const; Q_INVOKABLE void startDragAndDrop(const QVariant &itemLibEntry, const QPointF &mousePos); - Q_INVOKABLE void startDragAsset(const QString &assetPath); + Q_INVOKABLE void startDragAsset(const QString &assetPath, const QPointF &mousePos); Q_INVOKABLE void removeImport(const QString &importUrl); Q_INVOKABLE void addImportForItem(const QString &importUrl); Q_INVOKABLE void handleTabChanged(int index); @@ -143,6 +143,8 @@ private: AsynchronousImageCache &m_imageCache; QPointer m_model; QVariant m_itemToDrag; + QString m_assetToDrag; + QPair m_assetToDragTypeAndData; bool m_updateRetry = false; QString m_filterText; QPoint m_dragStartPoint;