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

Deletion of a modal parent changes the window position of grandparent.

    XMLWordPrintable

Details

    • Bug
    • Resolution: Unresolved
    • P2: Important
    • None
    • 6.5.3
    • None
    • Windows

    Description

      When deleting the modal parent of a modal dialog, the grandparent window position is pushed backwards.

      In the below example I have created a single QDialog called mainwindow, which is the parent of another QDialog called ABParent. The dialog ABParent is the modal parent of two more modal dialogs called A and B.

      When calling `deleteLater` in the following order,

      1. `B`
      2. `ABParent`
      3. `A`

      The grandparent of B (mainwindow) will be pushed behind the last focused application on the OS. Because I am launching my code using Visual Studio, this will be the console window. However, when the order is changed so that all children are called with `deleteLater` and then the modal parent `ABParent`,  the grandparent window position is unchanged and in front of the console window.

      This was discovered in our PyQt6 environment with our use case being multiple alert dialogs appearing from the parent modal dialog, with the option of these alert dialogs deleting the parent. This causes the main application to change the window positioning, giving the user the appearance of the application minimizing.

      The minimal reproducible code is below,

      — CMake —

      cmake_minimum_required(VERSION 3.30)
      
      project(QtBug)
      
      set(CMAKE_AUTOMOC ON)
      
      find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
      
      qt_add_executable(QtBug main.cpp)
      
      target_include_directories(QtBug PRIVATE ${CMAKE_CURRENT_LIST_DIR}/include)
      
      target_link_libraries(QtBug PRIVATE Qt6::Core Qt6::Gui Qt6::Widgets)

      — C++ (main.cpp)---

      #include <QApplication>
      #include <QDialog>
      #include <QLabel>
      #include <QPushButton>
      #include <QVBoxLayout>
      #include <iostream>
      #include "main.h"
      #include "moc_main.cpp"
      
      DialogB::DialogB(QWidget *parent) : QDialog(parent)
      {
          setWindowTitle("Dialog B");
          setLayout(new QVBoxLayout());
          QPushButton *closeButton = new QPushButton("Close", this);
          layout()->addWidget(closeButton);
          setWindowModality(Qt::ApplicationModal);
          connect(closeButton, &QPushButton::clicked, this, &DialogB::close_dialog);
      }
      
      void DialogB::close_dialog()
      {
          std::cout << "Deleting B" << std::endl;
          deleteLater();                                         // Delete B
          ABParent *parentDialog = qobject_cast<ABParent *>(parent());
          if (parentDialog) {
              std::cout << "Deleting parent " << parentDialog->objectName().toStdString() << std::endl;
              parentDialog->deleteLater();                      // Delete the Modal parent
              std::cout << "Deleting A" << std::endl;
              parentDialog->dialogA->deleteLater();             // Delete dialog A
          }
      }
      
      ABParent::ABParent(QWidget *parent) : QDialog(parent)
      {
          setWindowTitle("AB Parent");
          setObjectName("AB Parent");
          setWindowModality(Qt::ApplicationModal);
          dialogA = new QDialog(this);
          dialogB = new DialogB(this);
          dialogA->setWindowTitle("Dialog A");
          dialogA->setWindowModality(Qt::ApplicationModal);
          dialogA->show();
          dialogB->show();
      }
      
      int main(int argc, char *argv[])
      {
          QApplication app(argc, argv);
          QDialog *mainwindow = new QDialog();
          mainwindow->setWindowTitle("Main Window");
          mainwindow->show();
          ABParent *abparent = new ABParent(mainwindow);
          abparent->show();
          int result = app.exec();
          delete mainwindow;
          delete abparent;
          return result;
      }
      

      — Header File (main.h) —

      #pragma once
      
      #include <QDialog>
      
      class DialogB;
      
      class ABParent : public QDialog {
          Q_OBJECT
         public:
          QDialog *dialogA;
          DialogB *dialogB;
          ABParent(QWidget *parent = nullptr);
      };
      
      class DialogB : public QDialog {
          Q_OBJECT
         public:
             DialogB(QWidget *parent = nullptr);
         public slots:
             void close_dialog();
      };
      

       

      Attachments

        Issue Links

          No reviews matched the request. Check your Options in the drop-down menu of this sections header.

          Activity

            People

              qt.team.quick.subscriptions Qt Quick and Widgets Team
              seequentmichael Michael Cowie
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

                Created:
                Updated:

                Gerrit Reviews

                  There are no open Gerrit changes