Система метаобъектов Qt: испускать сигнал, используя строку с его именем

Система сигналов/слотов Qt потрясающая, но похоже, что ей не хватает какой-то действительно полезной функциональности (или, по крайней мере, я не могу найти, как ее использовать). У меня есть класс с большим количеством сигналов, и этот класс имеет switch, который должен излучать правильный сигнал в зависимости от значения переменной. Теперь я решаю это с помощью препроцессора C:

#define CASE(_NAME) \    
case MyEnum_ ## _NAME: \
{ \
    emit MySignal_ ## _NAME(); \
    do_other_stuff(); \
    break; \
}

switch(val)
{
CASE(Val_1)
CASE(Val_2)
CASE(Val_3)
}

Это просто не выглядит правильно. Я уверен, что есть более элегантный способ. QMetaObject имеет метод indexOfSignal, который может дать мне внутренний идентификатор сигнала Qt, используя строку с его именем. Если бы я мог генерировать сигнал, используя этот идентификатор, мой код стал бы намного чище.

Я взглянул на реализацию метода сигнала, сгенерированную moc, и похоже, что единственное, что отличается от одного сигнала к другому, это одна цифра:

void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
QMetaObject::activate(this, &staticMetaObject, <signal_id>, _a);

где <signal_id> — целое число, уникальное для каждого сигнала.

Итак, вопрос в том, как мне emit(int signalIdx)? Или, по крайней мере, получить возможность позвонить QMetaObject::activate, так как он выглядит скрытым в приватных заголовках?


person ScumCoder    schedule 27.02.2015    source источник


Ответы (2)


Используйте QMetaObject::invokeMethod

Я использую это в своей программе:

mCaller — это объект с определенным слотом, а mSlotName — имя слота.

QMetaObject::invokeMethod(mCaller, mSlotName.toLatin1().constData(), Qt::DirectConnection)
person fbucek    schedule 27.02.2015
comment
В вашем случае это, конечно, имя сигнала. Работает так же. - person fbucek; 27.02.2015
comment
Ладно, это неловко. Я почему-то думал, что invokeMethod используется только, ну, для вызова метаметодов и слотов, а не для генерации сигналов. - person ScumCoder; 28.02.2015

Хоть QMetaObject::invokeMethod() и лучше, но можно и подавать сигнал только по номеру: emit p->metaObject()->method(n).invoke(...);

person Matt    schedule 27.02.2015
comment
Спасибо. Мне почему-то не пришло в голову, что сигнал — это тоже метод, который можно вызывать. - person ScumCoder; 28.02.2015