LINUX.ORG.RU

Qt4/5: как узнать есть ли слот с именем у объекта?


0

1

Есть объект, наследованный от QObject, у него могут быть два слота с разными именами и разными параметрами. Я хочу вызывать первый слот если такой есть, и если нет - то второй.

У меня всё работает, но при попытке invokeMethod если слота нет - возвращает false (ну окей) и, увы, какает в консоль словами «QMetaObject::invokeMethod: No such method».

А вот как бы мне выяснить есть вообще там такой слот, прежде чем пытаться чего-то вызывать?

P.S. Мне бы просто выяснить наличие метода с именем, не важно какие у него параметры, т.к. я знаю что у слотов с данным конкретными именем в моей задаче - жестко определенный набор аргументов.

QMetaObject::method, QMetaObject::methodCount

anonymous ()
Ответ на: комментарий от anonymous

Слишком опасно, есть вероятность опечаток, которые не обнаружишь в compile-time.

Я бы завёл булевые флаги в объекте (по возможности) или набор enum (в зависимости от количества слотов).

Chaser_Andrey ★★★★★ ()
Ответ на: комментарий от Chaser_Andrey

QMetaObject::method

В моем случае опечатки исключены, т.к. сразу работают оба сценария и если что - я сразу эту увижу.

Как узнать наличие слота при помощи QMetaObject::method? Я глядел, но так и не понял...

I-Love-Microsoft ★★★★★ ()
Ответ на: комментарий от Chaser_Andrey

Нашел только это:

 const QMetaObject* metaObject = obj->metaObject();
 QStringList methods;
 for(int i = metaObject->methodOffset(); i < metaObject->methodCount(); ++i)
     methods << QString::fromLatin1(metaObject->method(i).signature());
Тупо перебор, и возможно медленный.

Может действительно булевые...

I-Love-Microsoft ★★★★★ ()
Ответ на: комментарий от Chaser_Andrey

есть вероятность опечаток, которые не обнаружишь в compile-time

Ну и что?

buddhist ★★★★★ ()
Ответ на: комментарий от Chaser_Andrey

Слишком опасно, есть вероятность опечаток, которые не обнаружишь в compile-time.

Да ладно, питонисты же живут как-то.

anonymous ()

я вот так делаю, правда тут вызов слота, а установка соединения сигнал-слот, но для проверки можно использовать метод ptrTarget->metaObject()->indexOfSlot(QMetaObject::normalizedSignature(qPrintable(slotName))) и если результат не -1, то можно его вызывать через invokeMethod

if (ptrSource && ptrTarget) {
        //find signal ID of the source QObject
        int sig = ptrSource->metaObject()->indexOfSignal(QMetaObject::normalizedSignature(qPrintable(signalName)));

        //find slot ID of the target QObject
        int slt = ptrTarget->metaObject()->indexOfSlot(QMetaObject::normalizedSignature(qPrintable(slotName)));
        if (sig != -1) {
            if (slt != -1) {
                //connect source's signal to target's slot
                QMetaObject::connect(ptrSource, sig, ptrTarget, slt, Qt::QueuedConnection);
                (log << "Qt connection established:" << sourceObjName << "+" << targetObjName).debug();
                return true;
            } else {
                (log << "connectClients: object" << targetObjName << "has no Qt-Slot '" << slotName <<"'").warn();
            }
        } else {
            (log << "connectClients: object" << sourceObjName << "has no Qt-Signal '" << signalName <<"'").warn();
        }
    } else {
        (log << "failed to get " << sourceObjName << "pointer " << ptrSource <<
                "or " << targetObjName << "pointer "<< ptrTarget).error();
    }

HighwayStar ★★★★★ ()
Ответ на: комментарий от HighwayStar

ptrTarget->metaObject()->indexOfSlot(QMetaObject::normalizedSignature(qPrintable(slotName)))

То что надо! Я предполагал что такое можно (ибо в доках есть это есть), но разве в qPrintable(slotName) я могу просто написать имя слота, безо всяких там «сигнатур аргументов»?

Спасибо :)

I-Love-Microsoft ★★★★★ ()
Ответ на: комментарий от buddhist

Адепт интерпретируемых языков с динамической типизацией?

Chaser_Andrey ★★★★★ ()
Ответ на: комментарий от I-Love-Microsoft

если слот с аргументами, то его нужно туда писать так как он пишется при вызове connect(obj, SIGNAL(), obj SLOT())

например «changeData(int, int, QString)»

HighwayStar ★★★★★ ()
Ответ на: комментарий от HighwayStar

Чёто нихт арбайтен:

bool is_slot_exists(QObject *obj, const char *slot_sign)
{
	if(obj == NULL) return false;
	if(obj->metaObject()->indexOfSlot(QMetaObject::normalizedSignature(slot_sign)) == -1) return false;
	return true;
}
А проверяю так:
qDebug() << "SLOT(quake())=" << is_slot_exists(this, SLOT(quake()));
Но слот quake 100% есть без аргументов. Пробовал и с ними и без, и проверять существующие слоты и несуществующие... Чето не пашет, всегда false.

I-Love-Microsoft ★★★★★ ()
Ответ на: комментарий от I-Love-Microsoft

в твоем примере нужно писать так

qDebug() << "SLOT(quake())=" << is_slot_exists(this, "quake()");

может быть еще нужно добавить qPrintable() так где он в моем примере

HighwayStar ★★★★★ ()
Ответ на: комментарий от HighwayStar

Сделал is_slot_exists(this, «quake()») - вернуло true, т.е. работает как надо. А вот у слотов с параметрами пока не работает...

Добавил if(obj->metaObject()->indexOfSlot(QMetaObject::normalizedSignature(qPrintable(slot_sign))) == -1) return false; но не принимает...

Есть ли примеры? Не гуглятся и в доках глухо.

I-Love-Microsoft ★★★★★ ()
Ответ на: комментарий от I-Love-Microsoft

The function returns a QMetaObject::Connection that represents a handle to a connection if it successfully connects the signal to the slot. The connection handle will be invalid if it cannot create the connection, for example, if QObject is unable to verify the existence of either signal or method, or if their signatures aren't compatible. You can check if the handle is valid by casting it to a bool.

Я так полагаю, это не сгодится, connect - check - disconnect?

anonymous ()
Ответ на: комментарий от I-Love-Microsoft
QMetaMethod	method(int index) const
int	methodCount() const

Разве нельзя так получить список всех методов и линейно найти нужный тебе вручную?

anonymous ()
Ответ на: комментарий от HighwayStar

Вру! Опечатался... Всё работает!!!

qDebug() << "111=" << is_slot_exists(this, "slot_with_params(QByteArray,quint32,bool)");
qDebug() << "333=" << is_slot_exists(this, "quake()");

Сама функция:

bool is_slot_exists(QObject *obj, const char *slot_sign)
{
	if(obj == NULL) return false;
	if(obj->metaObject()->indexOfSlot(QMetaObject::normalizedSignature(qPrintable(slot_sign))) == -1) return false;
	return true;
}

Выкладываю, чтобы осталось рабочее решение, когда надо просто проверить есть ли слот.

I-Love-Microsoft ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.