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. Keystroke is forwarded unintentionally
Forum Updated to NodeBB v4.3 + New Features

Keystroke is forwarded unintentionally

Scheduled Pinned Locked Moved Solved General and Desktop
13 Posts 4 Posters 478 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.
  • SGaistS Offline
    SGaistS Offline
    SGaist
    Lifetime Qt Champion
    wrote on last edited by
    #4

    In this case you can use the buttonClicked signal to know what happened.

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

    1 Reply Last reply
    0
    • D Offline
      D Offline
      django.Reinhard
      wrote on last edited by
      #5

      Hi,

      guess I have to go back to school again - nobody understands my writing :(

      @SGaist said in Keystroke is forwarded unintentionally:

      ... to know what happened.

      I already know, what happened.

      In the screenshot usecase the delete key with focus at tableview was pressed, which raises this dialog. When the user selects "No" button (cursor right) and presses Enter, then the delete operation aborts.
      ... but then the edit operation starts (which is bound to Enter key with focus at tableview). When edit starts, the standard dialog has already been removed ...

      But when enter was pressed, the dialog had the focus and not the tableview. So the event forwarding is faulty, as the action is already processed.

      So that's going wrong, and I'm looking for a way to get out of that trap.

      If it is possible to clear event-queue programmatically, best point is imho the function that calls QMessageBox::question

      1 Reply Last reply
      0
      • C Offline
        C Offline
        ChrisW67
        wrote on last edited by
        #6

        @django-Reinhard said in Keystroke is forwarded unintentionally:

        So that's going wrong, and I'm looking for a way to get out of that trap.

        If your view has QAbstractItemView::AnyKeyPressed as its edit trigger then the Delete you started with probably put the cell into edit mode before your dialog blocked the event loop of the main program. It stays in that mode when your dialog is dismissed.
        Hard to say for sure... we cannot see your code or "keyboard handler" or how the plumbing is done. Guessing is what we are left with.

        D 1 Reply Last reply
        0
        • C ChrisW67

          @django-Reinhard said in Keystroke is forwarded unintentionally:

          So that's going wrong, and I'm looking for a way to get out of that trap.

          If your view has QAbstractItemView::AnyKeyPressed as its edit trigger then the Delete you started with probably put the cell into edit mode before your dialog blocked the event loop of the main program. It stays in that mode when your dialog is dismissed.
          Hard to say for sure... we cannot see your code or "keyboard handler" or how the plumbing is done. Guessing is what we are left with.

          D Offline
          D Offline
          django.Reinhard
          wrote on last edited by
          #7

          @ChrisW67 said in Keystroke is forwarded unintentionally:

          if your view has QAbstractItemView::AnyKeyPressed as its edit trigger

          Well, not intentionally. Don't know, what default is, but I don't use intable editing. Editor is the widget at the lower right.

          @ChrisW67 said in Keystroke is forwarded unintentionally:

          Hard to say for sure... we cannot see your code or "keyboard handler" or how the plumbing is done. Guessing is what we are left with.

          Yes, you're absolutely right! My fault.

          My code is available.

          excerpts from it ...

          Keyboard handler:

          void ToolManager::keyReleaseEvent(QKeyEvent *event) {
            switch (event->key()) {
              case KeyCodes::Enter:
                   if (tools->hasFocus()) editTool();
                   break;
                   ...
              case KeyCodes::Insert: {
                   if (categories->hasFocus()) createCategory();
                   else if (tools->hasFocus()) createTool();
                   } break;
              case KeyCodes::Delete: {
                   if (categories->hasFocus()) deleteCategory();
                   else if (tools->hasFocus()) deleteTool();
                   } break;
              case KeyCodes::F6_Key: {
                   if (categories->hasFocus()) renameCategory();
                   } break;
              case KeyCodes::F10_Key:
                   if (tEdit->isEnabled()) saveToolChanges();
                   break;
              }
            event->setAccepted(true);
            }
          

          ... delete-Function:

          void ToolManager::deleteTool() {
            qDebug() << "delete tool: " << toolModel->record(tool2Edit).value("num");
            QMessageBox::StandardButton reply;
          
            reply = QMessageBox::question(this
                                        , tr("QMessageBox::question()")
                                        , tr("Should this tool be deleted?")
                                        , QMessageBox::Yes | QMessageBox::No);
            if (reply == QMessageBox::No) return;
            if (!toolModel->removeRows(tool2Edit, 1)) qDebug() << toolModel->lastError().text();
            if (!toolModel->submitAll())              qDebug() << toolModel->lastError().text();
            }
          

          ... and edit-Function:

          void ToolManager::editTool() {
            categories->hide();
            tools->hide();
            tEdit->setEnabled(true);
          
            // fill all space inside QScrollarea
            if (edSize.width() == -1 && edSize.height() == -1) edSize = tEdit->size();
            tEdit->resize(size().width() - 20, size().height() - 20);
          
            // data record is already loaded into editor,
            // so just inform about how to finish editing
            QMessageBox::information(this
                                   , tr("QMessageBox::information()")
                                   , tr("To finish tool editing press F10 "
                                        "to save changes or ESC to abort."));
            }
          
          
          1 Reply Last reply
          0
          • D Offline
            D Offline
            django.Reinhard
            wrote on last edited by
            #8

            Hi,

            I did some further tests, but situation does not look any nicer.

            I tried to patch Qt like this:

            void QPushButton::keyPressEvent(QKeyEvent *e)
            {
                Q_D(QPushButton);
                switch (e->key()) {
                case Qt::Key_Enter:
                case Qt::Key_Return:
                    if (autoDefault() || d->defaultButton) {
                        e->setAccepted(true);                     // added 4 test
                        click();
                        break;
                    }
                    Q_FALLTHROUGH();
                default:
                    QAbstractButton::keyPressEvent(e);
                }
            }
            

            which worked fine in debugging session, but failed in release code.
            So I guessed, it is a timing issue, but adding some sleep did not change anything either.

            so I tried to check timestamp of keyEvent - but against all logic keyEvent that arrives my widget class has newer timestamp, than timestamp when messagebox got closed ...

            So I tried to use EventFilter - but - cursor right arrives the filter, but Enter that triggered the button did not arrive the filter.

            I also tried to use a modified messagebox, that uses open instead of exec - but on open no dialog window appeared.

            Actually I run out of ideas.

            debug logs prints this:

            • before mb::exec
            • Messagebox finished ...
            • after mb::exec - myTS: 12197200
            • TM: enter ( 16777220 ) has ts: 12197346
            • myTS: 12197350

            "before mb::exec" is originated in delete-function, just before calling exec of the messagebox

            "Messagebox finished" is printed by the callback, connected to messagebox::finished

            "after mb::exec" is printed from delete-function, after closing the messagebox. So the Enter-keypress has happened before that timestamp (myTS).

            "TM: enter" is printed from keyboard-handler of the main widget (parent of treeview, tableview and editor).

            Last message "myTS" is the timestamp printed from keyboard-handler when release of Enter-key has been detected.

            So even if event routing might be ok, timestamp refresh is definitely NOT ok. And as QEvent does not contain the widget, that had the focus when the key was pressed, I don't know, how to solve that trap.

            Any hint is appreciated!

            1 Reply Last reply
            1
            • mrjjM Offline
              mrjjM Offline
              mrjj
              Lifetime Qt Champion
              wrote on last edited by
              #9

              Hi

              For test, could you use this function

              void MainWindow::deleteTool()
              {
                  QMessageBox *msgBox = new QMessageBox(this);
                  msgBox->setText("QMessageBox::question()");
                  msgBox->setInformativeText("Should this tool be deleted?");
                  msgBox->setStandardButtons(QMessageBox::Yes | QMessageBox::No);
                  msgBox->setDefaultButton(QMessageBox::Yes);
                  msgBox->setIcon(QMessageBox::Question);
                 // handle answer
                  connect(msgBox, &QMessageBox::buttonClicked, this, [this, msgBox](QAbstractButton * button) {
                      if ( msgBox->button(QMessageBox::StandardButton::Yes) == button )
                          qDebug() << "Yes to the dress"; // youcan use this->toolModel->xxxx
                      msgBox->deleteLater();
                  });
                
                  msgBox->open();
              }
              
              

              and see if return still bleeds through as then we know it is indeed a side effect of the exec() / local event loop.

              1 Reply Last reply
              0
              • D Offline
                D Offline
                django.Reinhard
                wrote on last edited by django.Reinhard
                #10

                Hi,

                thank you for your attention!

                I changed your code to this:

                  QMessageBox *msgBox = new QMessageBox(this);
                
                  msgBox->setText("QMessageBox::question()");
                  msgBox->setInformativeText("Should this tool be deleted?");
                  msgBox->setStandardButtons(QMessageBox::Yes | QMessageBox::No);
                  msgBox->setDefaultButton(QMessageBox::Yes);
                  msgBox->setIcon(QMessageBox::Question);
                
                  // handle answer
                  connect(msgBox, &QMessageBox::buttonClicked
                        , this, [this, msgBox](QAbstractButton * button) {
                                  if (msgBox->button(QMessageBox::StandardButton::Yes) == button)
                                     qDebug() << "Yes to the dress"; // youcan use this->toolModel->xxxx
                                  else
                                     qDebug() << "No - don't drop this";
                                  qDebug() << "from mb::callback - myTS:" << timeStamp();
                                  msgBox->deleteLater();
                                  });
                  msgBox->open();
                

                ... and the same happens.
                Debug log shows:

                No - don't drop this
                from mb::callback - myTS: 1068270
                TM: enter ( 16777220 ) has ts:  1068408
                myTS: 1068410
                

                I updated my repo, in case you want debug.

                Just to clarify things: usecase is:

                • select a tool (in tableview)
                • hit delete key (which opens the messagebox)
                • hit cursor right to change focus from "Yes" to "No"
                • hit Enter to activate the button

                then editor starts with tool detail data, started from keyboard-handler keyRelease and Enter-key.

                I thought I had similar code.
                Could someone please explain me, why in my case nothing happens, when I call msgBox->open() ?

                My code looks like:

                QMessageBox* MessageBox::showMessage(QWidget *parent
                                                  , QMessageBox::Icon icon
                                                  , const QString &title
                                                  , const QString &text
                                                  , const QString &button0Text
                                                  , const QString &button1Text
                                                  , const QString &button2Text
                                                  , int
                                                  , int ) {
                  mb = new QMessageBox(icon, title, text, QMessageBox::NoButton, parent);
                  QString myButton0Text = button0Text;
                
                  if (myButton0Text.isEmpty())
                     myButton0Text = QDialogButtonBox::tr("OK");
                
                  mb->addButton(myButton0Text, QMessageBox::ActionRole);
                  if (!button1Text.isEmpty()) mb->addButton(button1Text, QMessageBox::ActionRole);
                  if (!button2Text.isEmpty()) mb->addButton(button2Text, QMessageBox::ActionRole);
                //  const QList<QAbstractButton *> &buttonList = messageBox.d_func()->customButtonList;
                
                //  messageBox.setDefaultButton(static_cast<QPushButton *>(buttonList.value(defaultButtonNumber)));
                //  messageBox.setEscapeButton(buttonList.value(escapeButtonNumber));
                
                  connect(mb, &QMessageBox::finished, this, &MessageBox::finished);
                //  messageBox.exec();
                  return mb;
                  }
                
                
                QMessageBox* MessageBox::question(QWidget* parent, const QString& title, const QString& text) {
                  return showMessage(parent, QMessageBox::Question, title, text, tr("Yes"), tr("No"), QString());
                  }
                
                
                void MessageBox::finished() {
                  qDebug() << "Messagebox finished ...";
                  }
                

                In ToolManager::delete I had this code:

                  MessageBox   mb;
                  QMessageBox* qmb = mb.question(this
                                              , tr("QMessageBox::question()")
                                              , tr("Should this tool be deleted?"));
                
                //  qmb->installEventFilter(this);
                
                  qDebug() << "before mb::exec";
                  qmb->exec();
                  qDebug() << "after mb::exec - myTS:" << timeStamp();
                
                  return;
                

                I tried qmb->open() but nothing happened.
                Therefore I got back to qmb->exec().

                mrjjM 1 Reply Last reply
                0
                • D django.Reinhard

                  Hi,

                  thank you for your attention!

                  I changed your code to this:

                    QMessageBox *msgBox = new QMessageBox(this);
                  
                    msgBox->setText("QMessageBox::question()");
                    msgBox->setInformativeText("Should this tool be deleted?");
                    msgBox->setStandardButtons(QMessageBox::Yes | QMessageBox::No);
                    msgBox->setDefaultButton(QMessageBox::Yes);
                    msgBox->setIcon(QMessageBox::Question);
                  
                    // handle answer
                    connect(msgBox, &QMessageBox::buttonClicked
                          , this, [this, msgBox](QAbstractButton * button) {
                                    if (msgBox->button(QMessageBox::StandardButton::Yes) == button)
                                       qDebug() << "Yes to the dress"; // youcan use this->toolModel->xxxx
                                    else
                                       qDebug() << "No - don't drop this";
                                    qDebug() << "from mb::callback - myTS:" << timeStamp();
                                    msgBox->deleteLater();
                                    });
                    msgBox->open();
                  

                  ... and the same happens.
                  Debug log shows:

                  No - don't drop this
                  from mb::callback - myTS: 1068270
                  TM: enter ( 16777220 ) has ts:  1068408
                  myTS: 1068410
                  

                  I updated my repo, in case you want debug.

                  Just to clarify things: usecase is:

                  • select a tool (in tableview)
                  • hit delete key (which opens the messagebox)
                  • hit cursor right to change focus from "Yes" to "No"
                  • hit Enter to activate the button

                  then editor starts with tool detail data, started from keyboard-handler keyRelease and Enter-key.

                  I thought I had similar code.
                  Could someone please explain me, why in my case nothing happens, when I call msgBox->open() ?

                  My code looks like:

                  QMessageBox* MessageBox::showMessage(QWidget *parent
                                                    , QMessageBox::Icon icon
                                                    , const QString &title
                                                    , const QString &text
                                                    , const QString &button0Text
                                                    , const QString &button1Text
                                                    , const QString &button2Text
                                                    , int
                                                    , int ) {
                    mb = new QMessageBox(icon, title, text, QMessageBox::NoButton, parent);
                    QString myButton0Text = button0Text;
                  
                    if (myButton0Text.isEmpty())
                       myButton0Text = QDialogButtonBox::tr("OK");
                  
                    mb->addButton(myButton0Text, QMessageBox::ActionRole);
                    if (!button1Text.isEmpty()) mb->addButton(button1Text, QMessageBox::ActionRole);
                    if (!button2Text.isEmpty()) mb->addButton(button2Text, QMessageBox::ActionRole);
                  //  const QList<QAbstractButton *> &buttonList = messageBox.d_func()->customButtonList;
                  
                  //  messageBox.setDefaultButton(static_cast<QPushButton *>(buttonList.value(defaultButtonNumber)));
                  //  messageBox.setEscapeButton(buttonList.value(escapeButtonNumber));
                  
                    connect(mb, &QMessageBox::finished, this, &MessageBox::finished);
                  //  messageBox.exec();
                    return mb;
                    }
                  
                  
                  QMessageBox* MessageBox::question(QWidget* parent, const QString& title, const QString& text) {
                    return showMessage(parent, QMessageBox::Question, title, text, tr("Yes"), tr("No"), QString());
                    }
                  
                  
                  void MessageBox::finished() {
                    qDebug() << "Messagebox finished ...";
                    }
                  

                  In ToolManager::delete I had this code:

                    MessageBox   mb;
                    QMessageBox* qmb = mb.question(this
                                                , tr("QMessageBox::question()")
                                                , tr("Should this tool be deleted?"));
                  
                  //  qmb->installEventFilter(this);
                  
                    qDebug() << "before mb::exec";
                    qmb->exec();
                    qDebug() << "after mb::exec - myTS:" << timeStamp();
                  
                    return;
                  

                  I tried qmb->open() but nothing happened.
                  Therefore I got back to qmb->exec().

                  mrjjM Offline
                  mrjjM Offline
                  mrjj
                  Lifetime Qt Champion
                  wrote on last edited by
                  #11

                  @django-Reinhard

                  Hmm so it seems its not due to using exec()

                  If I want to run your code, I have to call/run setupDb first ?

                  1 Reply Last reply
                  0
                  • D Offline
                    D Offline
                    django.Reinhard
                    wrote on last edited by
                    #12

                    Yes, its a separate pro-file, which creates and populates the database.

                    1 Reply Last reply
                    0
                    • D Offline
                      D Offline
                      django.Reinhard
                      wrote on last edited by
                      #13

                      Just to close this:

                      I added a timecode check and this way I could sort out the unwanted/wrong keyevent.

                      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