Search code examples
c++qtqt5eventfilter

QWidgetWindow as QObject in event filter with Qt5


In the migration from Qt4 to Qt5 for some code I have to filter events on my application but it does not work anymore. My software has to filter all events when in "Edition Mode" so only a few widgets/buttons can be available/clickable.

I have a class InputGrabber with a QVector of Pointers to QWidget and an eventFilter function. When passing to "Edit" mode , I append the widgets' pointers to the QVector of my InputGrabber that will be available:

_inputGrabber->add (_gpView);
_inputGrabber->add (_gpView->viewport ());
_inputGrabber->add (_gpView->horizontalScrollBar ());
_inputGrabber->add (_gpView->verticalScrollBar ());
_inputGrabber->add (_view->mainWindow().toolBarMap()["editSquel"]);

and then, on the eventFilter function the code goes like:

bool InputGrabber::eventFilter (QObject* object, QEvent* anevent)
{
    if (QInputEvent* event = dynamic_cast <QInputEvent*> (anevent))
      {
        QWidget* widget = dynamic_cast <QWidget*> (object);
        if (widget)
        {
          if (_widgetList.contains (widget) || _widgetList.contains (widget->parentWidget ()))
            return QObject::eventFilter (object, event);
          else if (QDialog* dlg = dynamic_cast <QDialog*> (widget))
            return QObject::eventFilter (object, event);
          else if (QDialogButtonBox* dlg = dynamic_cast <QDialogButtonBox*> (widget->parentWidget ()))
            return QObject::eventFilter (object, event);
          else
            return true;
        }
        else
          return true;
      }
      else
        return QObject::eventFilter (object, event);
    } 
}

The issue migrating to Qt5 is that the following cast:

QWidget* widget = dynamic_cast <QWidget*> (object);

returns NULL when object inherits from QWidgetWindow.

Has anyone found same issue and got a solution that follows the same strategy? I wouldn't like to change the behavior of my software, making loops on all widgets and setting setDisabled() for each one.

Thank you very much!


Solution

  • I think your code is wrong here:

    return QObject::eventFilter (object, event);
    

    should be

    return QObject::eventFilter (object, anevent);
    

    and possibly:

    bool InputGrabber::eventFilter (QObject* object, QEvent* anevent)
    {
      if (QInputEvent* event = dynamic_cast <QInputEvent*> (anevent))
      {
        //etc
      }
      return QObject::eventFilter (object, anevent);
    }
    

    this way, if you don't explicitly return true or false, it will always propagate the event in the chain correctly.

    If your casts fail, just don't return anything and let it fall back to the last line. If somehow you stop the event propagation when you meet an object you don't know anything about (like the misterious QWidgetWindow) you are probably breaking the UI logic. If you let the propagation go on, it is very likely that the event you're waiting for will come out, soon or later.