Как получить доступный для человека тип события из QEvent?

Я хочу отладить код обработки событий и хотел бы преобразовать значение QEvent::Type enum в удобочитаемую строку. QEvent имеет макрос Q_GADGET, поэтому предположительно есть способ вытащить это?

Ответ 1

Последние версии Qt делают правильные вещи при выводе событий в поток отладки, поэтому ниже не требуется. Если вы получаете ошибку, похожую на warning C4273: 'operator <<' : inconsistent dll linkage, это означает, что ваша версия Qt уже поддерживает это без необходимости использования кода ниже.

Макрос Q_GADGET добавляет к классу член QMetaObject staticMetaObject. Определение статического метаобъекта генерируется moc, а оно - в случае QEvent - содержит информацию перечисления.

Ниже приведен пример того, как использовать это, чтобы дать более разумный вывод событий QDebug.

#include <QEvent>
#include <QMetaEnum>
#include <QDebug>   

/// Gives human-readable event type information.
QDebug operator<<(QDebug str, const QEvent * ev) {
   static int eventEnumIndex = QEvent::staticMetaObject
         .indexOfEnumerator("Type");
   str << "QEvent";
   if (ev) {
      QString name = QEvent::staticMetaObject
            .enumerator(eventEnumIndex).valueToKey(ev->type());
      if (!name.isEmpty()) str << name; else str << ev->type();
   } else {
      str << (void*)ev;
   }
   return str.maybeSpace();
}

Пример использования:

void MyObject::event(QEvent* ev) {
  qDebug() << "handling an event" << ev;
}

Ответ 2

Q_GADGET и Q_ENUM можно комбинировать, чтобы получить следующий шаблон:

template<typename EnumType>
QString ToString(const EnumType& enumValue)
{
    const char* enumName = qt_getEnumName(enumValue);
    const QMetaObject* metaObject = qt_getEnumMetaObject(enumValue);
    if (metaObject)
    {
        const int enumIndex = metaObject->indexOfEnumerator(enumName);
        return QString("%1::%2::%3").arg(metaObject->className(), enumName, metaObject->enumerator(enumIndex).valueToKey(enumValue));
    }

    return QString("%1::%2").arg(enumName).arg(static_cast<int>(enumValue));
}

Пример:

void MyObject::event(QEvent* ev) 
{
    qDebug() << ToString(ev->type());
}