views:

1770

answers:

1

I would like to call some custom copy code when the user releases Ctrl+C. When 'C' is released before Ctrl, Qt sends a key event that matches with QKeySequence::Copy. When Ctrl is released before 'C', the release event does not match.

When the key release event comes in with Ctrl, is there a way to see if 'C' is still being held down?

When I don't handle Ctrl being released first, the event gets passed along and it does a regular copy, which is exactly what I don't want to happen.

bool
MyWidget::eventFilter(QObject* object, QEvent* event)
{
   // the text edit box filters its events through here
   if (object == m_text_edit_box)
   {
      if (event->type() == QEvent::KeyPress)
      {
         QKeyEvent *key_event = static_cast<QKeyEvent*>(event);

         if (key_event->matches(QKeySequence::Copy))
         {
            // don't do anything and don't pass along event
            return true;
         }
      }
      else if (event->type() == QEvent::KeyRelease)
      {
         QKeyEvent *key_event = static_cast<QKeyEvent*>(event);

         if (key_event->matches(QKeySequence::Copy))
         {
            // we only get in here if 'c' is released before ctrl
            callCustomCopy();
            return true;
         }
      }
   }

   // pass along event
   return false;
}
+1  A: 

You could query the letter 'C' and the meta key 'Ctrl' specifically and not rely on key_even->matches(). you can of course in the object where you located the eventfilter on the keydown event store the fact wether the keydown sequence did match copy.

This (untested) might work for you, note that the static variable should be a member variable of the class that this is contained in, this just seemed clearer in the context of this example. The exact logic of what you want to accomplish might need more state information to be carried between events.

bool MyWidget::eventFilter(QObject* object, QEvent* event)
{
  // Remember state between events
  static foundCopy = false;
  // the text edit box filters its events through here
  if (object == m_text_edit_box)
  {
    if (event->type() == QEvent::KeyPress)
    {
    QKeyEvent *key_event = static_cast<QKeyEvent*>(event);
      if (key_event->matches(QKeySequence::Copy))
      {
        foundCopy = true;
        // don't do anything and don't pass along event
        return true;
      }
      else
      {
        foundCopy = false;
        // This is another sequence, ignore and pass event
        // Note that this will trigger with ctrl+c+a and others

      }
    }
    else if (event->type() == QEvent::KeyRelease)
    {
      QKeyEvent *key_event = static_cast<QKeyEvent*>(event);
      if (foundCopy)
      {
        callCustomCopy();
        foundCopy = false;
        return true;
      }
      // This should keep the system copy from triggering
      if (key_event->matches(QKeySequence::Copy))
      {
        return true;
      }
    }
  }

   // pass along event
 return false;
}

Another way would be to collect the actual state of all the keys pressed at the current time and then when one is released see which ones are still pressed.

From a UI point of view please bear in mind that all keyboard actions are performed on press, (e.g. typeing, windows paste), performing actions on release in general might confuse the user, especially when there is a visible result to the action. I can't tell from your example what you are trying to accomplish.

Harald Scheirich