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. QMessageBox::question returning NoButton?
Forum Updated to NodeBB v4.3 + New Features

QMessageBox::question returning NoButton?

Scheduled Pinned Locked Moved Solved General and Desktop
4 Posts 2 Posters 296 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.
  • P Offline
    P Offline
    patrickkidd
    wrote on last edited by
    #1

    I am running pytest and PyQt-5 with QT_QPA_PLATFORM=offscreen and QMessageBox::question is returning NoButton, but only when many other unit tests are running first. The test runs fine alone. I have debugged the qt code from QMessageBox::question on down and for some reason QMessageBoxPrivate::_q_buttonClicked is never called.

    I can't include an example here because this is a complicated integration test. But it is clear that the QEventLoop in QDialog::exec is not executing anything.

    Under what conditions would this occur? The documentation doesn't help. Thanks!

    https://alaskafamilysystems.com/

    P 1 Reply Last reply
    0
    • P patrickkidd

      I am running pytest and PyQt-5 with QT_QPA_PLATFORM=offscreen and QMessageBox::question is returning NoButton, but only when many other unit tests are running first. The test runs fine alone. I have debugged the qt code from QMessageBox::question on down and for some reason QMessageBoxPrivate::_q_buttonClicked is never called.

      I can't include an example here because this is a complicated integration test. But it is clear that the QEventLoop in QDialog::exec is not executing anything.

      Under what conditions would this occur? The documentation doesn't help. Thanks!

      P Offline
      P Offline
      patrickkidd
      wrote on last edited by
      #2

      @patrickkidd Turns out my code was calling QApplication::quit at some point in one of the prior unit tests. So the answer is that QMessageBox::question (and the other static methods, and probably also QDialog) quietly returns the default - NoButton - when the application has quit.

      https://alaskafamilysystems.com/

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

        Hi,

        Out of curiosity, are you monkeypatching your QMessageBox for the tests ?

        Otherwise how are you making the that part work while testing ?

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

        P 1 Reply Last reply
        0
        • SGaistS SGaist

          Hi,

          Out of curiosity, are you monkeypatching your QMessageBox for the tests ?

          Otherwise how are you making the that part work while testing ?

          P Offline
          P Offline
          patrickkidd
          wrote on last edited by
          #4

          @SGaist said in QMessageBox::question returning NoButton?:

          Hi,

          Out of curiosity, are you monkeypatching your QMessageBox for the tests ?

          Otherwise how are you making the that part work while testing ?

          qtbot.clickYesAfter(lambda: model.removeTag(1))
          
          from pytestqt.qtbot import QtBot
          
          class PKQtBot(QtBot):
          
              def qWaitForMessageBox(self, action, contains=None, handleClick=None):
                  from PyQt5.QtWidgets import QAbstractButton
                  msgBoxAccepted = util.Condition()
                  def acceptMessageBox():
                      box = QApplication.activeModalWidget()
                      if box:
                          if contains:
                              assert contains in box.text()
                          if handleClick:
                              handleClick()
                              msgBoxAccepted()
                              msgBoxAccepted.timer.stop()
                          else:
                              okButton = box.button(QMessageBox.Ok)
                              box.buttonClicked[QAbstractButton].connect(msgBoxAccepted)
                              msgBoxAccepted()
                              self.mouseClick(okButton, Qt.LeftButton)
                              msgBoxAccepted.timer.stop()
                  msgBoxAccepted.timer = QTimer(QApplication.instance())
                  msgBoxAccepted.timer.timeout.connect(acceptMessageBox)
                  msgBoxAccepted.timer.start(100)
                  action()
                  msgBoxAccepted.wait()
              
              def clickYesAfter(self, action):
                  def doClickYes():
                      self.mouseClick(QApplication.activeModalWidget().button(QMessageBox.Yes),
                                      Qt.LeftButton)
                  self.qWaitForMessageBox(action, handleClick=doClickYes)
                  
              def clickNoAfter(self, action):
                  def doClickNo():
                      self.mouseClick(QApplication.activeModalWidget().button(QMessageBox.No),
                                      Qt.LeftButton)
                  self.qWaitForMessageBox(action, handleClick=doClickNo)
          
          
          @pytest.yield_fixture
          def qtbot(qApp, request):
              """ Overridden to use our qApp, because the old one was calling abort(). """
              result = PKQtBot(request)
              util.qtbot = result
              yield result
          

          I also have another one that uses my custom Condition class, which can be used to wait for a lambda or keep track of signal calls:

              def waitUntil(self, condition, timeout=2000):
                  util.Condition(condition=condition).wait(maxMS=timeout)
          
          class Condition(Debug):
              """ Allows you to wait for a signal to be called. """
              def __init__(self, only=None, condition=None):
                  self.callCount = 0
                  self.callArgs = []
                  self.senders = []
                  self.lastCallArgs  = None
                  self.only = only
                  self.condition = condition
          
              def reset(self):
                  self.callCount = 0
                  self.callArgs = []
                  self.senders = []
                  self.lastCallArgs = None
          
              def test(self):
                  """ Return true if the condition is true. """
                  if self.condition:
                      return self.condition()
                  else:
                      self.callCount > 0
          
              def set(self, *args):
                  """ Set the condition to true. Alias for condition(). """
                  self.callCount += 1
                  self.senders.append(QObject().sender())
                  self.lastCallArgs = args
                  self.callArgs.append(args)
          
              def __call__(self, *args):
                  """ Called by whatever signal that triggers the condition. """
                  if self.only:
                      only = self.only
                      if not only(*args):
                          return
                  self.set(*args)
          
              def wait(self, maxMS=2000, onError=None):
                  """ Wait for the condition to be true. onError is a callback. """
                  startTime = time.time()
                  success = True
                  app = QApplication.instance()
                  while app and not self.test():
                      try:
                          app.processEvents(QEventLoop.WaitForMoreEvents, 100)
                      except KeyboardInterrupt as e:
                          if onError:
                              onError()
                          break
                      elapsed = ((time.time() - startTime) * 1000)
                      if elapsed >= maxMS:
                          break
          

          https://alaskafamilysystems.com/

          1 Reply Last reply
          1

          • Login

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