Event Filters

An event filter is installed on a widget and gives us a chance to manipulate events before they reach that widget.
Every QObject class can be installed as an Event Filter, and all it needs to do is implement the eventFilter(QObject *obj, QEvent *evt) method. The method should return "true" if we want to block the event (so it won't reach the target widget), or false if it can pass through the filter.

For a more in depth explanation, please see my article Using Event Filters To Save Subclasses on QtCollege.

Best thing about Event Filtering is that in many cases it saves us from subclassing a native widget.
Here's a simple use case of counting the backspace clicks on a TextEdit.

#include <QApplication>
#include <QtGui>
#include <QDebug>

class MainWindow : public QMainWindow
{
  public:
    MainWindow();

  protected:
    bool eventFilter(QObject *obj, QEvent *ev);

  private:
    QTextEdit *textEdit;
    QLabel    *bpCounter;
    int        count;
};

MainWindow::MainWindow()
{
  count = 0;
  bpCounter = new QLabel(QString("Backspace Count: %1").arg(count));
  textEdit = new QTextEdit;
  setCentralWidget(textEdit);

  statusBar()->addWidget(bpCounter);
  textEdit->installEventFilter(this);
}

bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
  if (obj == textEdit) {
    if (event->type() == QEvent::KeyPress) {
      QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
      if ( keyEvent->key() == Qt::Key_Backspace ) {
        bpCounter->setText(QString("Backspace Count: %1").arg(count++));
      }
    }

    // pass the event to the widget
    return false;
  }
  else {
    // pass the event on to the parent class
    return QMainWindow::eventFilter(obj, event);
  }
};

int main(int argc, char **argv)
{
  QApplication app(argc, argv);

  MainWindow mw;
  mw.show();

  app.exec();
}

A second example uses the same mechanism to replace tabs with spaces. The idea is capture every tab press event, and insert four spaces instead.
This is a nice filter than can be installed or uninstalled on a text edit based on user's preferences.

#define TAB_COUNT 4

bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
  if (obj == textEdit)
  {
    if (event->type() == QEvent::KeyPress)
    {
      QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
      if ( keyEvent->key() == Qt::Key_Tab )
      {
        // 4 spaces
        textEdit->insertPlainText(QString().fill(' ', 4));
        return true;
      }
    }

    // pass the event to the widget
    return false;
  }
  else {
    // pass the event on to the parent class
    return QMainWindow::eventFilter(obj, event);
  }
}