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. GUI event blocking
Forum Updated to NodeBB v4.3 + New Features

GUI event blocking

Scheduled Pinned Locked Moved Solved General and Desktop
40 Posts 5 Posters 13.6k Views 5 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.
  • JonBJ JonB

    @kshegunov
    I did think about that "dirty" way of handling things.

    However (apart from the debugging issue, I use Python + PyCharm debugger, not gdb, and I wouldn't hold your breath that it will have a -nograb functionality!), the problem will be which "event() override" you have in mind.

    Because, as I said, the QWebEngineView, which produces the HTML/PDF asynchronously and has the synchronousRenderHtml() call, is not displayed to the user in this case, the UI events are being received to the original dialog where a button is pressed to produce the output. This in itself has no connection to the ("invisible") QWebEngineView --- it doesn't even know one is being used, the implementation is invisible to it. I would have to modify its event handling. And since that would break encapsulation, I really don't feel it would be a good idea to implement!

    So I will soldier on with the "blocking flag" I currently have to prevent "re-entrancy", which at least works reasonably well in practice. At least I now understand why this whole behaviour is caused.

    kshegunovK Offline
    kshegunovK Offline
    kshegunov
    Moderators
    wrote on last edited by
    #20

    @JonB said in GUI event blocking:

    the problem will be which "event() override" you have in mind.

    That would be the event() override of the class (widget) in which you grab the input. When you grab the input events all of them are redirected to the widget that called the mentioned functions, so you'd need to filter them in that same class. Basically, you grab the input in the widget/dialog/w/e and filter the input there. Whenever the operation's done (i.e. you connect the finished signal to a slot in that same dialog you release the mouse/keyboard.

    Read and abide by the Qt Code of Conduct

    JonBJ 1 Reply Last reply
    1
    • kshegunovK kshegunov

      @JonB said in GUI event blocking:

      the problem will be which "event() override" you have in mind.

      That would be the event() override of the class (widget) in which you grab the input. When you grab the input events all of them are redirected to the widget that called the mentioned functions, so you'd need to filter them in that same class. Basically, you grab the input in the widget/dialog/w/e and filter the input there. Whenever the operation's done (i.e. you connect the finished signal to a slot in that same dialog you release the mouse/keyboard.

      JonBJ Online
      JonBJ Online
      JonB
      wrote on last edited by JonB
      #21

      @kshegunov
      Sorry, my friend, but as per the explanation I wrote above, I still don't understand which widget's events you mean.

      Here is the architecture of how the code works:

      • The user starts from a dialog, which has buttons on it, like Run long-running report.
      • That button on that dialog makes call produceReportAndWaitForFinish().
      • Behind the scenes, produceReportAndWaitForFinish() goes: create invisible QWebEnginePage and await final HTML/PDF returned, invisible QWebEnginePage calls synchronousRenderHtml(), which in turn has the self.renderLoop.exec() & self.renderLoop.quit() inside itself (the QWebEnginePage), in order to produce the HTML/PDF.
      • You want me to place the "event filter" there (inside the QWebEnginePage), when I call self.renderLoop.exec().
      • However, I don't think that (the QWebEnginePage) receives any inputs. The inputs (which would cause re-entrancy) are directed to buttons on the original top-level dialog where the user originally clicked the Run long-running report button, which I don't want him to click again.

      If that is correct(?), that is why I don't want to fiddle inside QWebEnginePage with the events directed to the top-level dialog, because of encapsulation/separation of code. The QWebEnginePage does not know if it was invoked from a dialog in the first place, and the dialog has no idea that a QWebEnginePage (which will do threads/events) is involved in the production of the HTML/PDF.

      kshegunovK 1 Reply Last reply
      0
      • JonBJ JonB

        @kshegunov
        Sorry, my friend, but as per the explanation I wrote above, I still don't understand which widget's events you mean.

        Here is the architecture of how the code works:

        • The user starts from a dialog, which has buttons on it, like Run long-running report.
        • That button on that dialog makes call produceReportAndWaitForFinish().
        • Behind the scenes, produceReportAndWaitForFinish() goes: create invisible QWebEnginePage and await final HTML/PDF returned, invisible QWebEnginePage calls synchronousRenderHtml(), which in turn has the self.renderLoop.exec() & self.renderLoop.quit() inside itself (the QWebEnginePage), in order to produce the HTML/PDF.
        • You want me to place the "event filter" there (inside the QWebEnginePage), when I call self.renderLoop.exec().
        • However, I don't think that (the QWebEnginePage) receives any inputs. The inputs (which would cause re-entrancy) are directed to buttons on the original top-level dialog where the user originally clicked the Run long-running report button, which I don't want him to click again.

        If that is correct(?), that is why I don't want to fiddle inside QWebEnginePage with the events directed to the top-level dialog, because of encapsulation/separation of code. The QWebEnginePage does not know if it was invoked from a dialog in the first place, and the dialog has no idea that a QWebEnginePage (which will do threads/events) is involved in the production of the HTML/PDF.

        kshegunovK Offline
        kshegunovK Offline
        kshegunov
        Moderators
        wrote on last edited by
        #22

        @JonB said in GUI event blocking:

        If that is correct

        Nope. I mean exactly the dialog with the buttons. See (untested) code below, which I hope will clear this up:

        class DialogWithButtons : public QDialog
        {
        public:
            DialogWithButtons(QWidget * parent);
        
        public slots:
            void produceReportAndWaitForFinish();
            void reportProduced();
        
        protected:
            bool event(QEvent *) override;
        private:
            QPushButton startLongRunningOpButton;
            bool inputBlocked;
        }
        
        DialogWithButtons::DialogWithButtons(QWidget * parent)
            : QWidget(parent), startLongRunningOpButton(this), inputBlocked(false)
        {
            // Just connect the button
            QObject::connect(&startLongRunningOpButton, &QPushButton::clicked, this, &DialogWithButtons::produceReportAndWaitForFinish);
        }
        
        void DialogWithButtons::produceReportAndWaitForFinish()
        {
            inputBlocked = true;
            grabMouse();
            grabKeyboard();
        
            // Create/Init the webengine and so on, put to render and all that goodness. 
            QWebEngineView webEngine;
        
            // Connect the handlers & QEventLoop blocking
            QObject::connect(&webEngine, &QWebEngineView::loadFinished, this, &DialogWithButtons::reportProduced);
        
            QEventLoop loop;
            QObject::connect(&webEngine, &QWebEngineView::loadFinished, &loop, &QEventLoop::quit);
            loop.exec();   // Wait for processing to finish
        }
        
        void DialogWithButtons::reportProduced()
        {
             releaseMouse();
             releaseKeyboard();
             inputBlocked = false;
        }
        
        bool DialogWithButtons::event(QEvent * e)
        {
            if (inputBlocked && dynamic_cast<QInputEvent *>(e))
                return true;   // Filter out input events - we receive all of them if `inputBlocked` is true
         
            return QDialog::event(e);  // Input was not blocked or event was not UI input - delegate to the default implementation
        }
        

        Read and abide by the Qt Code of Conduct

        JonBJ 1 Reply Last reply
        3
        • kshegunovK kshegunov

          @JonB said in GUI event blocking:

          If that is correct

          Nope. I mean exactly the dialog with the buttons. See (untested) code below, which I hope will clear this up:

          class DialogWithButtons : public QDialog
          {
          public:
              DialogWithButtons(QWidget * parent);
          
          public slots:
              void produceReportAndWaitForFinish();
              void reportProduced();
          
          protected:
              bool event(QEvent *) override;
          private:
              QPushButton startLongRunningOpButton;
              bool inputBlocked;
          }
          
          DialogWithButtons::DialogWithButtons(QWidget * parent)
              : QWidget(parent), startLongRunningOpButton(this), inputBlocked(false)
          {
              // Just connect the button
              QObject::connect(&startLongRunningOpButton, &QPushButton::clicked, this, &DialogWithButtons::produceReportAndWaitForFinish);
          }
          
          void DialogWithButtons::produceReportAndWaitForFinish()
          {
              inputBlocked = true;
              grabMouse();
              grabKeyboard();
          
              // Create/Init the webengine and so on, put to render and all that goodness. 
              QWebEngineView webEngine;
          
              // Connect the handlers & QEventLoop blocking
              QObject::connect(&webEngine, &QWebEngineView::loadFinished, this, &DialogWithButtons::reportProduced);
          
              QEventLoop loop;
              QObject::connect(&webEngine, &QWebEngineView::loadFinished, &loop, &QEventLoop::quit);
              loop.exec();   // Wait for processing to finish
          }
          
          void DialogWithButtons::reportProduced()
          {
               releaseMouse();
               releaseKeyboard();
               inputBlocked = false;
          }
          
          bool DialogWithButtons::event(QEvent * e)
          {
              if (inputBlocked && dynamic_cast<QInputEvent *>(e))
                  return true;   // Filter out input events - we receive all of them if `inputBlocked` is true
           
              return QDialog::event(e);  // Input was not blocked or event was not UI input - delegate to the default implementation
          }
          
          JonBJ Online
          JonBJ Online
          JonB
          wrote on last edited by JonB
          #23

          @kshegunov
          Yes, OK, I thought so.

          The problem is, my produceReportAndWaitForFinish() in the top-level dialog does not have any kind of

              // Create/Init the webengine and so on, put to render and all that goodness. 
              QWebEngineView webEngine;
          

          inside it (and I don't want it to). It has more like:

              //  Call *completely opaque* ReportProducer to generate HTML/PDF
              //  Here we have *no knowledge* of how ReportProducer functions
              //  and to maintain code separation/encapsulation we do not want to know here
              //  We might completely change how ReportProducer works at any time
              //  without affecting any code/behaviour here in this dialog.
              ReportProducer rp;
              rp.doWhateverToProduceHtmlAndPdf()
          

          So I do understand what your approach requires, but I hope you can see why I do not wish to go down that route. But thanks for your suggestion anyway!

          kshegunovK 1 Reply Last reply
          0
          • JonBJ JonB

            @kshegunov
            Yes, OK, I thought so.

            The problem is, my produceReportAndWaitForFinish() in the top-level dialog does not have any kind of

                // Create/Init the webengine and so on, put to render and all that goodness. 
                QWebEngineView webEngine;
            

            inside it (and I don't want it to). It has more like:

                //  Call *completely opaque* ReportProducer to generate HTML/PDF
                //  Here we have *no knowledge* of how ReportProducer functions
                //  and to maintain code separation/encapsulation we do not want to know here
                //  We might completely change how ReportProducer works at any time
                //  without affecting any code/behaviour here in this dialog.
                ReportProducer rp;
                rp.doWhateverToProduceHtmlAndPdf()
            

            So I do understand what your approach requires, but I hope you can see why I do not wish to go down that route. But thanks for your suggestion anyway!

            kshegunovK Offline
            kshegunovK Offline
            kshegunov
            Moderators
            wrote on last edited by
            #24

            @JonB said in GUI event blocking:

            The problem is, my produceReportAndWaitForFinish() in the top-level dialog does not have any kind of
            [snip]
            inside it (and I don't want it to). It has more like:

            This is of no consequence, I've put the event loop/QWebEngineView here only for completeness. You can connect the grab/release slots directly from the button/custom class that generates the pdf respectively. Basically, the same as what you have now, but including 1 event override and putting in the grabMouse and releaseMouse at the appropriate places.

            Read and abide by the Qt Code of Conduct

            JonBJ 1 Reply Last reply
            1
            • kshegunovK kshegunov

              @JonB said in GUI event blocking:

              The problem is, my produceReportAndWaitForFinish() in the top-level dialog does not have any kind of
              [snip]
              inside it (and I don't want it to). It has more like:

              This is of no consequence, I've put the event loop/QWebEngineView here only for completeness. You can connect the grab/release slots directly from the button/custom class that generates the pdf respectively. Basically, the same as what you have now, but including 1 event override and putting in the grabMouse and releaseMouse at the appropriate places.

              JonBJ Online
              JonBJ Online
              JonB
              wrote on last edited by
              #25

              @kshegunov
              Hmm, so you mean in my dialog button:

              blockInputs()
              ReportProducer rp;
              rp.doWhateverToProduceHtmlAndPdf()
              releaseInputs()
              

              Right?

              kshegunovK 1 Reply Last reply
              0
              • JonBJ JonB

                @kshegunov
                Hmm, so you mean in my dialog button:

                blockInputs()
                ReportProducer rp;
                rp.doWhateverToProduceHtmlAndPdf()
                releaseInputs()
                

                Right?

                kshegunovK Offline
                kshegunovK Offline
                kshegunov
                Moderators
                wrote on last edited by
                #26

                Yep, that should work.

                Read and abide by the Qt Code of Conduct

                JonBJ 1 Reply Last reply
                1
                • kshegunovK kshegunov

                  Yep, that should work.

                  JonBJ Online
                  JonBJ Online
                  JonB
                  wrote on last edited by JonB
                  #27

                  @kshegunov
                  So, to be pedantic, and hoping I'm not annoying you, I want precisely that code/behaviour wrapped around every single button handler I have anywhere in my code, just in case the code the button invokes happens to create a thread or process events which could cause re-entrance. Which was the reason I posted this thread in the very first place.

                  There is supposed to be nothing special about my doWhateverToProduceHtmlAndPdf(), it's a complete accident/coincidence that it happens to use something (a QWebEngineView) which itself has to spin an event loop to achieve its work. I might change that tomorrow. Which is why I wanted to isolate anything about its event behaviour down inside the class which creates the QWebEngineView and not up at the caller dialog level. This approach will work in this particular case, but not in other random places in code where a button's actions might happen to spin an event loop, and that bothers me....

                  Ah well, such are the dirty practicalities of coding...!

                  EDIT: Bear with me, I'm going to post a new thread to ask a particular question which would satisfy me, just to know if it's possible.... See https://forum.qt.io/topic/88481/is-it-possible-to-intercept-a-modal-dialog-s-event-loop

                  kshegunovK 1 Reply Last reply
                  0
                  • JonBJ JonB

                    @kshegunov
                    So, to be pedantic, and hoping I'm not annoying you, I want precisely that code/behaviour wrapped around every single button handler I have anywhere in my code, just in case the code the button invokes happens to create a thread or process events which could cause re-entrance. Which was the reason I posted this thread in the very first place.

                    There is supposed to be nothing special about my doWhateverToProduceHtmlAndPdf(), it's a complete accident/coincidence that it happens to use something (a QWebEngineView) which itself has to spin an event loop to achieve its work. I might change that tomorrow. Which is why I wanted to isolate anything about its event behaviour down inside the class which creates the QWebEngineView and not up at the caller dialog level. This approach will work in this particular case, but not in other random places in code where a button's actions might happen to spin an event loop, and that bothers me....

                    Ah well, such are the dirty practicalities of coding...!

                    EDIT: Bear with me, I'm going to post a new thread to ask a particular question which would satisfy me, just to know if it's possible.... See https://forum.qt.io/topic/88481/is-it-possible-to-intercept-a-modal-dialog-s-event-loop

                    kshegunovK Offline
                    kshegunovK Offline
                    kshegunov
                    Moderators
                    wrote on last edited by
                    #28

                    @JonB said in GUI event blocking:

                    This approach will work in this particular case, but not in other random places in code where a button's actions might happen to spin an event loop, and that bothers me....

                    You could in principle adapt it to the general case. Something along:

                    class UiGuard : public QObject
                    {
                    public:
                        UiGuard(QWidget * ui)
                            : widget(ui)
                        {
                            widget->grabMouse();
                            widget->grabKeyboard();
                            widget->installEventFilter(this);
                        }
                    
                        UiGuard::~UiGuard() override
                        {
                            widget->releaseKeyboard();
                            widget->releaseMouse();
                        }
                    
                        bool eventFilter(QObject *, QEvent * event) override
                        {
                            return dynamic_cast<QInputEvent *>(event);  // Eat up the input events
                        }
                    
                    private:
                        QWidget * widget;
                    };
                    

                    And then you use in the places you have threads and/or event loops spinning, by just creating an instance:

                    // ...
                    {
                        UiGuard guard(this);  // Prevent input events while in this method
                        ReportProducer rp;
                        rp.doWhateverToProduceHtmlAndPdf()
                    }

                    Read and abide by the Qt Code of Conduct

                    JonBJ 1 Reply Last reply
                    0
                    • kshegunovK kshegunov

                      @JonB said in GUI event blocking:

                      This approach will work in this particular case, but not in other random places in code where a button's actions might happen to spin an event loop, and that bothers me....

                      You could in principle adapt it to the general case. Something along:

                      class UiGuard : public QObject
                      {
                      public:
                          UiGuard(QWidget * ui)
                              : widget(ui)
                          {
                              widget->grabMouse();
                              widget->grabKeyboard();
                              widget->installEventFilter(this);
                          }
                      
                          UiGuard::~UiGuard() override
                          {
                              widget->releaseKeyboard();
                              widget->releaseMouse();
                          }
                      
                          bool eventFilter(QObject *, QEvent * event) override
                          {
                              return dynamic_cast<QInputEvent *>(event);  // Eat up the input events
                          }
                      
                      private:
                          QWidget * widget;
                      };
                      

                      And then you use in the places you have threads and/or event loops spinning, by just creating an instance:

                      // ...
                      {
                          UiGuard guard(this);  // Prevent input events while in this method
                          ReportProducer rp;
                          rp.doWhateverToProduceHtmlAndPdf()
                      }
                      JonBJ Online
                      JonBJ Online
                      JonB
                      wrote on last edited by JonB
                      #29

                      @kshegunov
                      Yes indeed, but as we said:

                      And then you use in the places you have threads and/or event loops spinning, by just creating an instance:

                      In principle I have no idea where code might have "threads and/or event loops". (Seriously, it took me days & debugging to even discover this particular button invoked code which did that, I had no idea it did! Which is my point.) So in effect I'd like this around every single UI slot handler (or probably 99% of them but not 1%), and I'm not prepared to edit thousands of places to do that! :)

                      kshegunovK 1 Reply Last reply
                      0
                      • JonBJ JonB

                        @kshegunov
                        Yes indeed, but as we said:

                        And then you use in the places you have threads and/or event loops spinning, by just creating an instance:

                        In principle I have no idea where code might have "threads and/or event loops". (Seriously, it took me days & debugging to even discover this particular button invoked code which did that, I had no idea it did! Which is my point.) So in effect I'd like this around every single UI slot handler (or probably 99% of them but not 1%), and I'm not prepared to edit thousands of places to do that! :)

                        kshegunovK Offline
                        kshegunovK Offline
                        kshegunov
                        Moderators
                        wrote on last edited by
                        #30

                        @JonB said in GUI event blocking:

                        So in effect I'd like this around every single UI slot handler, and I'm not prepared to edit thousands of places to do that!

                        That might be rather bad idea, as event filters do hurt performance, even though in this case it's only a single dynamic_cast. You're trying to fight against the way UIs work - i.e. event driven. You could install that kind of class directly on the QCoreApplication object (with the proper modification), where you'd filter the events globally, but seems rather dubious decision.

                        Read and abide by the Qt Code of Conduct

                        JonBJ 1 Reply Last reply
                        1
                        • kshegunovK kshegunov

                          @JonB said in GUI event blocking:

                          So in effect I'd like this around every single UI slot handler, and I'm not prepared to edit thousands of places to do that!

                          That might be rather bad idea, as event filters do hurt performance, even though in this case it's only a single dynamic_cast. You're trying to fight against the way UIs work - i.e. event driven. You could install that kind of class directly on the QCoreApplication object (with the proper modification), where you'd filter the events globally, but seems rather dubious decision.

                          JonBJ Online
                          JonBJ Online
                          JonB
                          wrote on last edited by JonB
                          #31

                          @kshegunov

                          You could install that kind of class directly on the QCoreApplication object (with the proper modification), where you'd filter the events globally, but seems rather dubious decision.

                          That indeed sounds more like it, because I could do that in my own object which tests a flag to cause this behaviour, and where the flag would be set by the called code which knows it needs it and not the calling code which does not know that. This could be precisely what I am looking for....

                          You might look to look at my new https://forum.qt.io/topic/88481/is-it-possible-to-intercept-a-modal-dialog-s-event-loop now, where I'm asking just that about application versus dialog event loops....

                          kshegunovK A 2 Replies Last reply
                          0
                          • JonBJ JonB

                            @kshegunov

                            You could install that kind of class directly on the QCoreApplication object (with the proper modification), where you'd filter the events globally, but seems rather dubious decision.

                            That indeed sounds more like it, because I could do that in my own object which tests a flag to cause this behaviour, and where the flag would be set by the called code which knows it needs it and not the calling code which does not know that. This could be precisely what I am looking for....

                            You might look to look at my new https://forum.qt.io/topic/88481/is-it-possible-to-intercept-a-modal-dialog-s-event-loop now, where I'm asking just that about application versus dialog event loops....

                            kshegunovK Offline
                            kshegunovK Offline
                            kshegunov
                            Moderators
                            wrote on last edited by
                            #32

                            @JonB said in GUI event blocking:

                            You might look to look at my new

                            Will do, but later, as I have some work to do now. :)

                            Read and abide by the Qt Code of Conduct

                            JonBJ 1 Reply Last reply
                            1
                            • kshegunovK kshegunov

                              @JonB said in GUI event blocking:

                              You might look to look at my new

                              Will do, but later, as I have some work to do now. :)

                              JonBJ Online
                              JonBJ Online
                              JonB
                              wrote on last edited by JonB
                              #33

                              @kshegunov
                              Of course you must, and get back to fixing those nuclear reactors/missiles you work on :) Thanks so much for your comments!

                              1 Reply Last reply
                              2
                              • JonBJ JonB

                                @kshegunov

                                You could install that kind of class directly on the QCoreApplication object (with the proper modification), where you'd filter the events globally, but seems rather dubious decision.

                                That indeed sounds more like it, because I could do that in my own object which tests a flag to cause this behaviour, and where the flag would be set by the called code which knows it needs it and not the calling code which does not know that. This could be precisely what I am looking for....

                                You might look to look at my new https://forum.qt.io/topic/88481/is-it-possible-to-intercept-a-modal-dialog-s-event-loop now, where I'm asking just that about application versus dialog event loops....

                                A Offline
                                A Offline
                                ambershark
                                wrote on last edited by
                                #34

                                @JonB Another thing you could try is to disable all the controls you don't want being activated during processing. Then enable them when processing is done.

                                This would be better handled via a modal dialog with a progress bar (even an indefinite one) and a cancel button.

                                But the other option is just setting QWidget::setEnabled(false). People using the app may be confused why things were disabled all of a sudden though so I still think the modal progress dialog would be the best way.

                                But you could keep a list of QActions and/or QWidgets you want disabled during that call and just iterate through the list and setEnabled(false) until complete then iterate through again and enable them.

                                Just another suggestion that may work for you. You have lots of choices on how to handle this and I don't have any great advice on the "best" way so just throwing things out as I think of them. :)

                                My L-GPL'd C++ Logger github.com/ambershark-mike/sharklog

                                JonBJ 1 Reply Last reply
                                3
                                • A ambershark

                                  @JonB Another thing you could try is to disable all the controls you don't want being activated during processing. Then enable them when processing is done.

                                  This would be better handled via a modal dialog with a progress bar (even an indefinite one) and a cancel button.

                                  But the other option is just setting QWidget::setEnabled(false). People using the app may be confused why things were disabled all of a sudden though so I still think the modal progress dialog would be the best way.

                                  But you could keep a list of QActions and/or QWidgets you want disabled during that call and just iterate through the list and setEnabled(false) until complete then iterate through again and enable them.

                                  Just another suggestion that may work for you. You have lots of choices on how to handle this and I don't have any great advice on the "best" way so just throwing things out as I think of them. :)

                                  JonBJ Online
                                  JonBJ Online
                                  JonB
                                  wrote on last edited by JonB
                                  #35

                                  @ambershark
                                  Hi amber,

                                  The application has 100 "top-level" dialogs, with an average of 3 buttons each (without even including other input controls which cause code to run). That's 300 potential "callers", which might lead to "re-entrancy".

                                  Meanwhile, it has 3 "bottom-level" functions which cause a thread/event loop to be spun, which, if hit, will allow fatal "re-entrancy" in the ultimate, top-level dialog (i.e. allow another a button to be pressed while still servicing the original button press).

                                  To use setEnabled(false), or keep a stack of callers, or any solution aimed at the caller, requires me to put code in 100, or 300, places. And furthermore to maintain that as further dialogs/buttons are added in future. To deal with it by causing a block, somehow, in the offending callee requires code in 3 places.

                                  Which would you rather do?

                                  That's why I started new thread https://forum.qt.io/topic/88481/is-it-possible-to-intercept-a-modal-dialog-s-event-loop ...

                                  A 1 Reply Last reply
                                  0
                                  • JonBJ JonB

                                    @ambershark
                                    Hi amber,

                                    The application has 100 "top-level" dialogs, with an average of 3 buttons each (without even including other input controls which cause code to run). That's 300 potential "callers", which might lead to "re-entrancy".

                                    Meanwhile, it has 3 "bottom-level" functions which cause a thread/event loop to be spun, which, if hit, will allow fatal "re-entrancy" in the ultimate, top-level dialog (i.e. allow another a button to be pressed while still servicing the original button press).

                                    To use setEnabled(false), or keep a stack of callers, or any solution aimed at the caller, requires me to put code in 100, or 300, places. And furthermore to maintain that as further dialogs/buttons are added in future. To deal with it by causing a block, somehow, in the offending callee requires code in 3 places.

                                    Which would you rather do?

                                    That's why I started new thread https://forum.qt.io/topic/88481/is-it-possible-to-intercept-a-modal-dialog-s-event-loop ...

                                    A Offline
                                    A Offline
                                    ambershark
                                    wrote on last edited by
                                    #36

                                    @JonB Lol yea that sounds nasty... It sounds like it needs a massive rewrite of it's GUI. These things are not normal issues for normal guis.

                                    Having 100s of dialogs is already pretty suspicious by itself. I've written some very large GUIs (million+ lines of code) and those never even came close to 100s of anything, much less of the rarely used (in modern guis) dialogs.

                                    It sucks you got stuck supporting that. It will not be a fun job, lol.

                                    My L-GPL'd C++ Logger github.com/ambershark-mike/sharklog

                                    JonBJ 1 Reply Last reply
                                    0
                                    • A ambershark

                                      @JonB Lol yea that sounds nasty... It sounds like it needs a massive rewrite of it's GUI. These things are not normal issues for normal guis.

                                      Having 100s of dialogs is already pretty suspicious by itself. I've written some very large GUIs (million+ lines of code) and those never even came close to 100s of anything, much less of the rarely used (in modern guis) dialogs.

                                      It sucks you got stuck supporting that. It will not be a fun job, lol.

                                      JonBJ Online
                                      JonBJ Online
                                      JonB
                                      wrote on last edited by JonB
                                      #37

                                      @ambershark
                                      Well, the principle is exactly the same regardless of whether one has dialogs, windows, widgets or whatever. It's that I don't want re-entrancy when a button/other input element is clicked, till whatever code it executes has completed. And putting the onus for writing the code on the caller, of which there are potentially many, instead of in the callee, of which there are a handful if any, just seems absolutely crazy to me. Even though I seem to be a lone voice in this....

                                      A 1 Reply Last reply
                                      0
                                      • JonBJ JonB

                                        @ambershark
                                        Well, the principle is exactly the same regardless of whether one has dialogs, windows, widgets or whatever. It's that I don't want re-entrancy when a button/other input element is clicked, till whatever code it executes has completed. And putting the onus for writing the code on the caller, of which there are potentially many, instead of in the callee, of which there are a handful if any, just seems absolutely crazy to me. Even though I seem to be a lone voice in this....

                                        A Offline
                                        A Offline
                                        ambershark
                                        wrote on last edited by
                                        #38

                                        @JonB said in GUI event blocking:

                                        @ambershark
                                        Well, the principle is exactly the same regardless of whether one has dialogs, windows, widgets or whatever. It's that I don't want re-entrancy when a button/other input element is clicked, till whatever code it executes has completed. And putting the onus for writing the code on the caller, of which there are potentially many, instead of in the callee, of which there are a handful if any, just seems absolutely crazy to me. Even though I seem to be a lone voice in this....

                                        That is exactly how it works. You just happen to be invoking asynchronous code so it is telling the caller that it is "done" before it actually is. I still feel the easiest way to deal with this is to show progress and shut down reentrance to the GUI functions that should be locked during processing.

                                        I actually have an "ActionManager" class I use for this purpose in async areas of my guis. It basically just manages the whole gui so I can say something like myActionManager->disableSet(mySetofActions).. And that will disable everything in that set while my gui processes.

                                        Along those lines I still feel just a popped up modal "progress dialog" would completely protect you and stop all GUI processing until you told the progress dialog you were done and to close.

                                        I mean you could even go with the awful idea of a global variable that tells when to allow entrance to a gui function and when to not.

                                        My L-GPL'd C++ Logger github.com/ambershark-mike/sharklog

                                        JonBJ 1 Reply Last reply
                                        0
                                        • A ambershark

                                          @JonB said in GUI event blocking:

                                          @ambershark
                                          Well, the principle is exactly the same regardless of whether one has dialogs, windows, widgets or whatever. It's that I don't want re-entrancy when a button/other input element is clicked, till whatever code it executes has completed. And putting the onus for writing the code on the caller, of which there are potentially many, instead of in the callee, of which there are a handful if any, just seems absolutely crazy to me. Even though I seem to be a lone voice in this....

                                          That is exactly how it works. You just happen to be invoking asynchronous code so it is telling the caller that it is "done" before it actually is. I still feel the easiest way to deal with this is to show progress and shut down reentrance to the GUI functions that should be locked during processing.

                                          I actually have an "ActionManager" class I use for this purpose in async areas of my guis. It basically just manages the whole gui so I can say something like myActionManager->disableSet(mySetofActions).. And that will disable everything in that set while my gui processes.

                                          Along those lines I still feel just a popped up modal "progress dialog" would completely protect you and stop all GUI processing until you told the progress dialog you were done and to close.

                                          I mean you could even go with the awful idea of a global variable that tells when to allow entrance to a gui function and when to not.

                                          JonBJ Online
                                          JonBJ Online
                                          JonB
                                          wrote on last edited by JonB
                                          #39

                                          @ambershark
                                          Thanks. But in a word, this approach relies on knowing which buttons will end up invoking something which creates a thread or processes the event loop. For the hundreds of buttons I have, I want a solution where it works for all of them, given that they have no idea what the code they invoke might, might, might do. For example, this whole business of producing PDF worked fine with QWebKit without any asynchronicity/re-entrancy, and broke once it moved to QWebEngine, which is invoked way down in the code far away from the button. I had no way of knowing I ought to be looking at various buttons' code in this light, and I do not want to have to change code relating to every single button in the interface.

                                          A 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