diff --git a/src/libs/advanceddockingsystem/dockcontainerwidget.cpp b/src/libs/advanceddockingsystem/dockcontainerwidget.cpp index 10fdc8cde25..b308879a9f6 100644 --- a/src/libs/advanceddockingsystem/dockcontainerwidget.cpp +++ b/src/libs/advanceddockingsystem/dockcontainerwidget.cpp @@ -595,7 +595,7 @@ namespace ADS { DockWidget *droppedDockWidget = qobject_cast(widget); DockAreaWidget *droppedDockArea = qobject_cast(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(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 41d1d2f0ba2..0d3b930f5da 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 e80fcbba8b0..64558e0d483 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 6d1a1925127..e5ee00024e3 100644 --- a/src/libs/advanceddockingsystem/dockoverlay.h +++ b/src/libs/advanceddockingsystem/dockoverlay.h @@ -93,6 +93,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 */ diff --git a/src/libs/advanceddockingsystem/docksplitter.cpp b/src/libs/advanceddockingsystem/docksplitter.cpp index ec6d8915df5..dfc976298c9 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 45351a34e22..872f2f04d94 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 5732ae408e3..539ef4a11c7 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(d->m_content); FloatingDockContainer *floatingWidget = nullptr;