Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-124262

[Reg] Crash when calling QMainWindow:.tabifiedDockWidgets after QMainWindow::removeDockWidget

    XMLWordPrintable

Details

    • f97e60a4f (dev), 4e396bcdc (6.7)

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

       

       

       

      Attachments

        For Gerrit Dashboard: QTBUG-124262
        # Subject Branch Project Status CR V

        Activity

          People

            axelspoerl Axel Spoerl
            as Andreas Strunski
            Votes:
            2 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There is 1 open Gerrit change