From 850e926841eec94da03f8cadffd59d365f70954a Mon Sep 17 00:00:00 2001 From: Axel Spoerl Date: Mon, 19 Jun 2023 10:02:21 +0200 Subject: [PATCH] QDockWidget: Don't insert gap item if QDockWidgetGroupWindow has one When a dock widget is hovered over a QDockWidgetGroupWindow, a gap item is inserted at its potential docking position. Since only one item at a time can be moved with the mouse, only one such gap item can exist. QDockAreaLayoutInfo::insertGap() therefore contains an assertion, that kicks in if a second gap item is inserted. QDockWidgetGroupWindow::hover() checks if the dock widget is hovered over a gap item. If that is the case, no additional gap item is inserted. The check fails if a gap item exists in the group window, but the dock widget is hovered over another part of that group window. This can be the case if the group window already contains more than one dock widget: By inserting the gap, the group window's size changes, one of the existing dock widgets receives another hover event and a second gap insertion is attempted. This patch adds QDockAreaLayoutInfo::hasGapItem() to check if a gap already exists. The method is queried in addition to prevent a second gap insertion. An autotest has not been added, because gap items appear and disappear during hovering. The improved functionality can be tested manually with the mainwindow example. Fixes: QTBUG-112491 Fixes: QTBUG-114542 Change-Id: I9ea64e729873a86eb98ea950fbb066817fc25a07 Reviewed-by: Volker Hilsheimer (cherry picked from commit b26cdbd8777bf1348c7967138e59836990233121) Reviewed-by: Qt Cherry-pick Bot --- src/widgets/widgets/qdockarealayout.cpp | 15 +++++++++++++++ src/widgets/widgets/qdockarealayout_p.h | 1 + src/widgets/widgets/qmainwindowlayout.cpp | 8 ++++++-- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/widgets/widgets/qdockarealayout.cpp b/src/widgets/widgets/qdockarealayout.cpp index 0f8a4850041..33162bad3bf 100644 --- a/src/widgets/widgets/qdockarealayout.cpp +++ b/src/widgets/widgets/qdockarealayout.cpp @@ -1107,6 +1107,21 @@ static QRect dockedGeometry(QWidget *widget) return result; } +bool QDockAreaLayoutInfo::hasGapItem(const QList &path) const +{ + // empty path has no gap item + if (path.isEmpty()) + return false; + + // Index -1 isn't a gap + // Index out of range points at a position to be created. That isn't a gap either. + const int index = path.constFirst(); + if (index < 0 || index >= item_list.count()) + return false; + + return item_list[index].flags & QDockAreaLayoutItem::GapItem; +} + bool QDockAreaLayoutInfo::insertGap(const QList &path, QLayoutItem *dockWidgetItem) { Q_ASSERT(!path.isEmpty()); diff --git a/src/widgets/widgets/qdockarealayout_p.h b/src/widgets/widgets/qdockarealayout_p.h index 03e84d31446..4a5e8901504 100644 --- a/src/widgets/widgets/qdockarealayout_p.h +++ b/src/widgets/widgets/qdockarealayout_p.h @@ -135,6 +135,7 @@ public: void clear(); bool isEmpty() const; + bool hasGapItem(const QList &path) const; bool onlyHasPlaceholders() const; bool hasFixedSize() const; QList findSeparator(const QPoint &pos) const; diff --git a/src/widgets/widgets/qmainwindowlayout.cpp b/src/widgets/widgets/qmainwindowlayout.cpp index 0971ac5d581..e9cfd05007a 100644 --- a/src/widgets/widgets/qmainwindowlayout.cpp +++ b/src/widgets/widgets/qmainwindowlayout.cpp @@ -541,8 +541,12 @@ bool QDockWidgetGroupWindow::hover(QLayoutItem *widgetItem, const QPoint &mouseP auto newGapPos = newState.gapIndex(mousePos, nestingEnabled, tabMode); Q_ASSERT(!newGapPos.isEmpty()); - if (newGapPos == currentGapPos) - return false; // gap is already there + + // Do not insert a new gap item, if the current position already is a gap, + // or if the group window contains one + if (newGapPos == currentGapPos || newState.hasGapItem(newGapPos)) + return false; + currentGapPos = newGapPos; newState.insertGap(currentGapPos, widgetItem); newState.fitItems();