diff options
author | Henning Gruendl <henning.gruendl@qt.io> | 2020-03-13 10:44:37 +0100 |
---|---|---|
committer | Henning Gründl <henning.gruendl@qt.io> | 2020-03-13 12:29:51 +0000 |
commit | 0b7970feb4c4098f41ba537c99b4d278935e38e7 (patch) | |
tree | 64af9ef0fe37028b26c3a2ad6a32ef362ddedebf /src/libs | |
parent | 206e7d3e7011ad2a75604e3cccb7bc1a5a136065 (diff) |
ADS: Fix repeatedly dropping in same area crash
6c687d28def5c24f3eeb67c9e13d5cfab40cebd0
1c2383f8eb94bc8570e554efa5f842a8ab1461ea
Task-number: QDS-1751
Change-Id: I933b1f53da8ce423cd5d38ff2863f58606006596
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
Diffstat (limited to 'src/libs')
-rw-r--r-- | src/libs/advanceddockingsystem/dockcontainerwidget.cpp | 47 | ||||
-rw-r--r-- | src/libs/advanceddockingsystem/dockcontainerwidget.h | 8 | ||||
-rw-r--r-- | src/libs/advanceddockingsystem/dockoverlay.cpp | 8 | ||||
-rw-r--r-- | src/libs/advanceddockingsystem/dockoverlay.h | 7 | ||||
-rw-r--r-- | src/libs/advanceddockingsystem/docksplitter.cpp | 10 | ||||
-rw-r--r-- | src/libs/advanceddockingsystem/docksplitter.h | 10 | ||||
-rw-r--r-- | src/libs/advanceddockingsystem/floatingdragpreview.cpp | 14 |
7 files changed, 67 insertions, 37 deletions
diff --git a/src/libs/advanceddockingsystem/dockcontainerwidget.cpp b/src/libs/advanceddockingsystem/dockcontainerwidget.cpp index 10fdc8cde2..b308879a9f 100644 --- a/src/libs/advanceddockingsystem/dockcontainerwidget.cpp +++ b/src/libs/advanceddockingsystem/dockcontainerwidget.cpp @@ -595,7 +595,7 @@ namespace ADS { DockWidget *droppedDockWidget = qobject_cast<DockWidget *>(widget); DockAreaWidget *droppedDockArea = qobject_cast<DockAreaWidget *>(widget); - DockAreaWidget *newDockArea; + DockAreaWidget *newDockArea = nullptr; if (droppedDockWidget) { newDockArea = new DockAreaWidget(m_dockManager, q); @@ -605,6 +605,18 @@ namespace ADS } newDockArea->addDockWidget(droppedDockWidget); } else { + // We check, if we insert the dropped widget into the same place that + // it already has and do nothing, if it is the same place. It would + // also work without this check, but it looks nicer with the check + // because there will be no layout updates + auto splitter = internal::findParent<DockSplitter*>(droppedDockArea); + auto insertParam = internal::dockAreaInsertParameters(area); + if (splitter == m_rootSplitter && insertParam.orientation() == splitter->orientation()) { + if (insertParam.append() && splitter->lastWidget() == droppedDockArea) + return; + else if (!insertParam.append() && splitter->firstWidget() == droppedDockArea) + return; + } droppedDockArea->dockContainer()->removeDockArea(droppedDockArea); newDockArea = droppedDockArea; } @@ -1217,36 +1229,13 @@ namespace ADS } } - void DockContainerWidget::dropWidget(QWidget *widget, const QPoint &targetPosition) + void DockContainerWidget::dropWidget(QWidget *widget, DockWidgetArea dropArea, DockAreaWidget *targetAreaWidget) { - qCInfo(adsLog) << Q_FUNC_INFO; DockWidget *singleDockWidget = topLevelDockWidget(); - DockAreaWidget *dockArea = dockAreaAt(targetPosition); - auto dropArea = InvalidDockWidgetArea; - auto containerDropArea = d->m_dockManager->containerOverlay()->dropAreaUnderCursor(); - - if (dockArea) { - auto dropOverlay = d->m_dockManager->dockAreaOverlay(); - dropOverlay->setAllowedAreas(dockArea->allowedAreas()); - dropArea = dropOverlay->showOverlay(dockArea); - if (containerDropArea != InvalidDockWidgetArea && containerDropArea != dropArea) { - dropArea = InvalidDockWidgetArea; - } - - if (dropArea != InvalidDockWidgetArea) { - qCInfo(adsLog) << "Dock Area Drop Content: " << dropArea; - d->moveToNewSection(widget, dockArea, dropArea); - } - } - - // mouse is over container - if (InvalidDockWidgetArea == dropArea) { - dropArea = containerDropArea; - qCInfo(adsLog) << "Container Drop Content: " << dropArea; - if (dropArea != InvalidDockWidgetArea) { - d->moveToContainer(widget, dropArea); - } - } + if (targetAreaWidget) + d->moveToNewSection(widget, targetAreaWidget, dropArea); + else + d->moveToContainer(widget, dropArea); // If there was a top level widget before the drop, then it is not top // level widget anymore diff --git a/src/libs/advanceddockingsystem/dockcontainerwidget.h b/src/libs/advanceddockingsystem/dockcontainerwidget.h index 41d1d2f0ba..0d3b930f5d 100644 --- a/src/libs/advanceddockingsystem/dockcontainerwidget.h +++ b/src/libs/advanceddockingsystem/dockcontainerwidget.h @@ -104,9 +104,13 @@ protected: void dropFloatingWidget(FloatingDockContainer *floatingWidget, const QPoint &targetPos); /** - * Drop a dock area or a dock widget given in widget parameter + * Drop a dock area or a dock widget given in widget parameter. + * If the TargetAreaWidget is a nullptr, then the DropArea indicates + * the drop area for the container. If the given TargetAreaWidget is not + * a nullptr, then the DropArea indicates the drop area in the given + * TargetAreaWidget */ - void dropWidget(QWidget *widget, const QPoint &targetPos); + void dropWidget(QWidget *widget, DockWidgetArea dropArea, DockAreaWidget *targetAreaWidget); /** * Adds the given dock area to this container widget diff --git a/src/libs/advanceddockingsystem/dockoverlay.cpp b/src/libs/advanceddockingsystem/dockoverlay.cpp index e80fcbba8b..64558e0d48 100644 --- a/src/libs/advanceddockingsystem/dockoverlay.cpp +++ b/src/libs/advanceddockingsystem/dockoverlay.cpp @@ -399,6 +399,14 @@ namespace ADS { return result; } + DockWidgetArea DockOverlay::visibleDropAreaUnderCursor() const + { + if (isHidden() || !d->m_dropPreviewEnabled) + return InvalidDockWidgetArea; + else + return dropAreaUnderCursor(); + } + DockWidgetArea DockOverlay::showOverlay(QWidget *target) { if (d->m_targetWidget == target) { diff --git a/src/libs/advanceddockingsystem/dockoverlay.h b/src/libs/advanceddockingsystem/dockoverlay.h index 6d1a192512..e5ee00024e 100644 --- a/src/libs/advanceddockingsystem/dockoverlay.h +++ b/src/libs/advanceddockingsystem/dockoverlay.h @@ -94,6 +94,13 @@ public: DockWidgetArea dropAreaUnderCursor() const; /** + * This function returns the same like dropAreaUnderCursor() if this + * overlay is not hidden and if drop preview is enabled and returns + * InvalidDockWidgetArea if it is hidden or drop preview is disabled. + */ + DockWidgetArea visibleDropAreaUnderCursor() const; + + /** * Show the drop overly for the given target widget */ DockWidgetArea showOverlay(QWidget *target); diff --git a/src/libs/advanceddockingsystem/docksplitter.cpp b/src/libs/advanceddockingsystem/docksplitter.cpp index ec6d8915df..dfc976298c 100644 --- a/src/libs/advanceddockingsystem/docksplitter.cpp +++ b/src/libs/advanceddockingsystem/docksplitter.cpp @@ -89,4 +89,14 @@ namespace ADS return false; } + QWidget *DockSplitter::firstWidget() const + { + return (count() > 0) ? widget(0) : nullptr; + } + + QWidget *DockSplitter::lastWidget() const + { + return (count() > 0) ? widget(count() - 1) : nullptr; + } + } // namespace ADS diff --git a/src/libs/advanceddockingsystem/docksplitter.h b/src/libs/advanceddockingsystem/docksplitter.h index 45351a34e2..872f2f04d9 100644 --- a/src/libs/advanceddockingsystem/docksplitter.h +++ b/src/libs/advanceddockingsystem/docksplitter.h @@ -67,6 +67,16 @@ public: * Returns true, if any of the internal widgets is visible */ bool hasVisibleContent() const; + + /** + * Returns first widget or nullptr if splitter is empty + */ + QWidget *firstWidget() const; + + /** + * Returns last widget of nullptr is splitter is empty + */ + QWidget *lastWidget() const; }; // class DockSplitter } // namespace ADS diff --git a/src/libs/advanceddockingsystem/floatingdragpreview.cpp b/src/libs/advanceddockingsystem/floatingdragpreview.cpp index 5732ae408e..539ef4a11c 100644 --- a/src/libs/advanceddockingsystem/floatingdragpreview.cpp +++ b/src/libs/advanceddockingsystem/floatingdragpreview.cpp @@ -262,12 +262,14 @@ namespace ADS void FloatingDragPreview::finishDragging() { qCInfo(adsLog) << Q_FUNC_INFO; - auto dockDropArea = d->m_dockManager->dockAreaOverlay()->dropAreaUnderCursor(); - auto containerDropArea = d->m_dockManager->containerOverlay()->dropAreaUnderCursor(); - bool dropPossible = (dockDropArea != InvalidDockWidgetArea) - || (containerDropArea != InvalidDockWidgetArea); - if (d->m_dropContainer && dropPossible) { - d->m_dropContainer->dropWidget(d->m_content, QCursor::pos()); + auto dockDropArea = d->m_dockManager->dockAreaOverlay()->visibleDropAreaUnderCursor(); + auto containerDropArea = d->m_dockManager->containerOverlay()->visibleDropAreaUnderCursor(); + if (d->m_dropContainer && (dockDropArea != InvalidDockWidgetArea)) { + d->m_dropContainer->dropWidget(d->m_content, + dockDropArea, + d->m_dropContainer->dockAreaAt(QCursor::pos())); + } else if (d->m_dropContainer && (containerDropArea != InvalidDockWidgetArea)) { + d->m_dropContainer->dropWidget(d->m_content, containerDropArea, nullptr); } else { DockWidget *dockWidget = qobject_cast<DockWidget *>(d->m_content); FloatingDockContainer *floatingWidget = nullptr; |