Details
-
Bug
-
Resolution: Fixed
-
P1: Critical
-
6.6.3
-
None
-
f97e60a4f (dev), 4e396bcdc (6.7), 70a9c2689 (tqtc/lts-6.5)
Description
There seems to be a regression between 6.6.2 and 6.6.3 that can cause a crash upon calling QMainWindow:.tabifiedDockWidgets.
Accessing the tabified dock widgets after removing a dock widget crashes in QMainWindowTabBar::dockAt. Instead of asserting, the function could return nullptr:
QDockWidget *QMainWindowTabBar::dockAt(int index) const { QMainWindowTabBar *that = const_cast<QMainWindowTabBar *>(this); QMainWindowLayout* mlayout = qt_mainwindow_layout(mainWindow); 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; }
A small application that demonstrates the issue is attached. Here's the code:
#include <QApplication> #include <QDockWidget> #include <QHBoxLayout> #include <QMainWindow> #include <QPushButton> int main(int argc, char* argv[]) { QApplication application(argc, argv); QMainWindow mainWindow; // set up the dock widgets QDockWidget* dockWidgetA = new QDockWidget(&mainWindow); QDockWidget* dockWidgetB = new QDockWidget(&mainWindow); { dockWidgetA->setWindowTitle("A"); dockWidgetB->setWindowTitle("B"); mainWindow.addDockWidget(Qt::RightDockWidgetArea, dockWidgetA, Qt::Vertical); mainWindow.addDockWidget(Qt::RightDockWidgetArea, dockWidgetB, Qt::Vertical); mainWindow.tabifyDockWidget(dockWidgetB, dockWidgetA); } // set up the test { QWidget* centralWidget = new QWidget(&mainWindow); QHBoxLayout* centralWidgetLayout = new QHBoxLayout(centralWidget); mainWindow.setCentralWidget(centralWidget); QPushButton* testButton = new QPushButton("Crash", centralWidget); centralWidgetLayout->addWidget(testButton); QObject::connect(testButton, &QPushButton::clicked, testButton, [&mainWindow, dockWidgetA, dockWidgetB] { // remove one of the dock widgets mainWindow.removeDockWidget(dockWidgetA); #if 1 // crash! mainWindow.tabifiedDockWidgets(dockWidgetB); #else // activating the layout first ensures that the main window layout is properly updated mainWindow.layout()->activate(); mainWindow.tabifiedDockWidgets(dockWidgetB); #endif }); } mainWindow.show(); return application.exec(); }