diff options
author | Axel Spoerl <axel.spoerl@qt.io> | 2024-04-12 17:53:19 +0200 |
---|---|---|
committer | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2024-05-02 20:11:44 +0000 |
commit | f97e60a4f0602e1478c888ff1043276966c93387 (patch) | |
tree | fac03299df99a45288ddc22244f18fc4ae1880af /src/widgets/widgets/qmainwindowlayout.cpp | |
parent | 922ec9093d87ac8f21b0eefebb9c42d03e9dc820 (diff) |
Fix crash in QMainWindow:.tabifiedDockWidgets()
QMainWindow:.tabifiedDockWidgets() was refactored in Qt 6.6.3, because
it returned wrong values. It now loops from 0 to
QMainWindowTabBar::count() and uses QMainWindowTabBar::dockAt(), to
get the dock widget pointer for an index.
When a dock widget is removed from a floating tab, event processing is
necessary for the item_list and QMainWindowTabBar::count() to get in
sync. This case was overlooked in the refactoring. It can lead to
dockAt() being called with an out-of-bounds index, which it asserted.
The assertion triggered, when QMainWindow::removeDockWidget() and
QMainWindow::tabifiedDockWidgets() were called right after each other,
without processing events inbetween.
QMainWindowTabBar::dockWidgets() doesn't add nullptr to the list, it
returns.
Therefore, return nullptr, when dockAt() is called out-of-bounds.
Add test functionality in
tst_QDockWidget::updateTabBarOnVisibilityChanged().
Fixes: QTBUG-124262
Pick-to: 6.7 6.5
Change-Id: If66084b9f00b4e39f7a620da68df67c735029cf1
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'src/widgets/widgets/qmainwindowlayout.cpp')
-rw-r--r-- | src/widgets/widgets/qmainwindowlayout.cpp | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/src/widgets/widgets/qmainwindowlayout.cpp b/src/widgets/widgets/qmainwindowlayout.cpp index db17e50d5c..85c58fd70f 100644 --- a/src/widgets/widgets/qmainwindowlayout.cpp +++ b/src/widgets/widgets/qmainwindowlayout.cpp @@ -1931,6 +1931,11 @@ bool QMainWindowTabBar::contains(const QDockWidget *dockWidget) const return false; } +// When a dock widget is removed from a floating tab, +// Events need to be processed for the tab bar to realize that the dock widget is gone. +// In this case count() counts the dock widget in transition and accesses dockAt +// with an out-of-bounds index. +// => return nullptr in contrast to other xxxxxAt() functions QDockWidget *QMainWindowTabBar::dockAt(int index) const { QMainWindowTabBar *that = const_cast<QMainWindowTabBar *>(this); @@ -1938,10 +1943,15 @@ QDockWidget *QMainWindowTabBar::dockAt(int index) const QDockAreaLayoutInfo *info = mlayout->dockInfo(that); if (!info) return nullptr; + const int itemIndex = info->tabIndexToListIndex(index); - Q_ASSERT(itemIndex >= 0 && itemIndex < info->item_list.count()); - const QDockAreaLayoutItem &item = info->item_list.at(itemIndex); - return item.widgetItem ? qobject_cast<QDockWidget *>(item.widgetItem->widget()) : nullptr; + if (itemIndex >= 0) { + Q_ASSERT(itemIndex < info->item_list.count()); + const QDockAreaLayoutItem &item = info->item_list.at(itemIndex); + return item.widgetItem ? qobject_cast<QDockWidget *>(item.widgetItem->widget()) : nullptr; + } + + return nullptr; } void QMainWindowTabBar::mouseMoveEvent(QMouseEvent *e) |