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 <volker.hilsheimer@qt.io>
(cherry picked from commit b26cdbd8777bf1348c7967138e59836990233121)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Axel Spoerl 2023-06-19 10:02:21 +02:00 committed by Qt Cherry-pick Bot
parent bede24ee04
commit 850e926841
3 changed files with 22 additions and 2 deletions

View File

@ -1107,6 +1107,21 @@ static QRect dockedGeometry(QWidget *widget)
return result;
}
bool QDockAreaLayoutInfo::hasGapItem(const QList<int> &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<int> &path, QLayoutItem *dockWidgetItem)
{
Q_ASSERT(!path.isEmpty());

View File

@ -135,6 +135,7 @@ public:
void clear();
bool isEmpty() const;
bool hasGapItem(const QList<int> &path) const;
bool onlyHasPlaceholders() const;
bool hasFixedSize() const;
QList<int> findSeparator(const QPoint &pos) const;

View File

@ -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();