Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. How to prevent a modal QDialog from being hidden or close after calling exec.
Qt 6.11 is out! See what's new in the release blog

How to prevent a modal QDialog from being hidden or close after calling exec.

Scheduled Pinned Locked Moved Unsolved General and Desktop
7 Posts 4 Posters 316 Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    Didier Donner
    wrote on last edited by Didier Donner
    #1

    Hello everyone,

    I am having a problem I cannot find a proper solution for.

    I am writing code which requires a control and if it fails, I want to display a blocking QDialog which asks the end-user of he wants to retry or cancel the operation.
    The dialog is customized because it has to display a lot of information but it has the behavior of a QMessageBox with Accept and Reject
    So I call QDialog::exec and whether the QDialog is rejected or accepted, I cancel or retry the operation.

    My problem is that I would like to prevent the QDialog from disappearing when I retry the operation and avoid a sequence of 'kill the pop-up' dialog if the retry fails.
    I would like to manage the QDialog myself with reject.

    The calling code is

    class MyErrorDialog : public QDialog {
    };
    
    MyErrorDialog* error_dialog = nullptr;
    bool retry = false;
    do {
           if( control() ) {
               // Success 
               if( error_dialog != nullptr ) {
                   // Dismiss the error dialog if it has been displayed previously
                   error_dialog->reject();
                   return true;
               }
               retry = error_dialog->exec() == QDialog::Accepted;    
           } while( retry == true );
          // User cancelled the operation so we can dismiss the dialog
          error_dialog->reject(); 
          return false;
    }
    

    The MyErrorDialog has 2 QCommandLink button, the retry one connected to accept, the cancel one connected to reject and they trigger the proper results.
    I tried overriding QDialog::hideEvent or QDialog::closeEvent but after exec, MyErrorDialog always disappear

    Is my idea possible or am I making a mistake by trying to call multiple time exec on the same dialog? Once exec is finished, the local event loop is dead so I cannot keep my error dialog alive.
    I cannot easily move the logic of control in a QDialog::accept. That would simplify things: I would just have to override QDialog::accept and test the control there

    Thank you in advance.

    Didier

    JonBJ 1 Reply Last reply
    0
    • D Didier Donner

      Hello everyone,

      I am having a problem I cannot find a proper solution for.

      I am writing code which requires a control and if it fails, I want to display a blocking QDialog which asks the end-user of he wants to retry or cancel the operation.
      The dialog is customized because it has to display a lot of information but it has the behavior of a QMessageBox with Accept and Reject
      So I call QDialog::exec and whether the QDialog is rejected or accepted, I cancel or retry the operation.

      My problem is that I would like to prevent the QDialog from disappearing when I retry the operation and avoid a sequence of 'kill the pop-up' dialog if the retry fails.
      I would like to manage the QDialog myself with reject.

      The calling code is

      class MyErrorDialog : public QDialog {
      };
      
      MyErrorDialog* error_dialog = nullptr;
      bool retry = false;
      do {
             if( control() ) {
                 // Success 
                 if( error_dialog != nullptr ) {
                     // Dismiss the error dialog if it has been displayed previously
                     error_dialog->reject();
                     return true;
                 }
                 retry = error_dialog->exec() == QDialog::Accepted;    
             } while( retry == true );
            // User cancelled the operation so we can dismiss the dialog
            error_dialog->reject(); 
            return false;
      }
      

      The MyErrorDialog has 2 QCommandLink button, the retry one connected to accept, the cancel one connected to reject and they trigger the proper results.
      I tried overriding QDialog::hideEvent or QDialog::closeEvent but after exec, MyErrorDialog always disappear

      Is my idea possible or am I making a mistake by trying to call multiple time exec on the same dialog? Once exec is finished, the local event loop is dead so I cannot keep my error dialog alive.
      I cannot easily move the logic of control in a QDialog::accept. That would simplify things: I would just have to override QDialog::accept and test the control there

      Thank you in advance.

      Didier

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by
      #2

      @Didier-Donner
      I'm sorry I haven't followed the detail of what you are asking for. But QDialog::exec() is intended to destroy and exit, and read what it says there. If you want to keep the dialog around and manage it yourself use QDialog::open().

      1 Reply Last reply
      0
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #3

        Hi,

        @JonB nothing wrong with calling exec multiple time, it's just blocking slot with the caveat of the internal loop. However I do agree that open is likely the better tool here.

        @Didier-Donner As for keeping the dialog alive, you should then use your own signal as you neither want to accept nor reject. Both are "closing" actions. So they don't fit your architecture.

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        JonBJ 1 Reply Last reply
        0
        • SGaistS SGaist

          Hi,

          @JonB nothing wrong with calling exec multiple time, it's just blocking slot with the caveat of the internal loop. However I do agree that open is likely the better tool here.

          @Didier-Donner As for keeping the dialog alive, you should then use your own signal as you neither want to accept nor reject. Both are "closing" actions. So they don't fit your architecture.

          JonBJ Offline
          JonBJ Offline
          JonB
          wrote on last edited by
          #4

          @SGaist said in How to prevent a modal QDialog from being hidden or close after calling exec.:

          @JonB nothing wrong with calling exec multiple time, it's just blocking slot with the caveat of the internal loop. However I do agree that open is likely the better tool here.

          I thought OP was calling exec() once but wanted control the dialog so it did not exit or it retried or something, he keeps saying he wants to keep it alive. But maybe not :)

          As for pattern, I thought putting up another modal dialog when you have one on the go was "frowned upon" for end users. But again maybe not :)

          1 Reply Last reply
          0
          • Kent-DorfmanK Offline
            Kent-DorfmanK Offline
            Kent-Dorfman
            wrote on last edited by Kent-Dorfman
            #5

            Without dissecting the above...don't create it as a modal dialog. Make it modeless and manually manage display/hide state for the best control of what's going on.

            The dystopian literature that served as a warning in my youth has become an instruction manual in my elder years.

            1 Reply Last reply
            1
            • D Offline
              D Offline
              Didier Donner
              wrote on last edited by
              #6

              Hello everyone,

              I realized that my idea could not work with my current architecture. I need to shift the validation to the dialog by override QDialog::accept. This way, I can keep my dialog visible, provide the end-user some feedback in case the retry fails.
              I would have preferred to keep the UI and the backend separated but that cannot be the case so be it

              Thank you all for your answers. Take care

              Didier

              JonBJ 1 Reply Last reply
              0
              • D Didier Donner

                Hello everyone,

                I realized that my idea could not work with my current architecture. I need to shift the validation to the dialog by override QDialog::accept. This way, I can keep my dialog visible, provide the end-user some feedback in case the retry fails.
                I would have preferred to keep the UI and the backend separated but that cannot be the case so be it

                Thank you all for your answers. Take care

                Didier

                JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by
                #7

                @Didier-Donner said in How to prevent a modal QDialog from being hidden or close after calling exec.:

                I need to shift the validation to the dialog by override QDialog::accept. This way, I can keep my dialog visible, provide the end-user some feedback in case the retry fails.
                I would have preferred to keep the UI and the backend separated but that cannot be the case so be it

                Now I understand. You could still probably do it per my suggestion of using QDialog::open() instead of exec(), since you then control when to close the dialog and can not do so on validation failure.

                However, if you wish to do the validation inside the dialog prior to accept() from within exec() you can do that. You can still keep the UI and the backend separate by, for example, providing a small contract class which is virtual/abstract. That would provide one (pure) virtual method like virtual bool isValid(...) const = 0;. The dialog exports this abstract class and calls isValid(...) to decide what to do. The caller provides a concrete implementation of the abstract class with isValid(...) taking some parameter for the backend implementation to examine. This is a common paradigm and more or less keeps UI and backend separated.

                1 Reply Last reply
                0

                • Login

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Search
                • Get Qt Extensions
                • Unsolved