Question

The signal/slot mechanism in Qt, is a static mechanism. The classes have to be preprocessed by the moc compiler.
Now I want to create signals and slots dynamically at run-time.
I already have a working solution, but it feels to me like a hack, although I am using publicly available methods.
This is the code for dynamic slots:

bool DynamicQObject::connectDynamicSlot(const QString &objectName, QObject *pSourceObject, QMetaMethod signalMethod)
{
    QByteArray slotName = signalMethod.name().prepend("on").append("(");
    QStringList parameters;
    for (int i = 0, j = signalMethod.parameterCount(); i < j; ++i)
    {
        parameters << QMetaType::typeName(signalMethod.parameterType(i));
    }
    slotName.append(parameters.join(",")).append(")");
    QByteArray theSignal = QMetaObject::normalizedSignature(signalMethod.methodSignature().constData());
    QByteArray theSlot = QMetaObject::normalizedSignature(slotName);
    if (!QMetaObject::checkConnectArgs(theSignal, theSlot))
    {
        return false;
    }

    int signalId = pSourceObject->metaObject()->indexOfSignal(theSignal);
    if (signalId < 0)
    {
        return false;
    }

    int slotId = slotIndices.value(theSlot, -1);
    if (slotId < 0)
    {
        slotId = slotList.size();
        slotIndices[theSlot] = slotId;
        slotList.append(createSlot(theSlot, objectName, signalMethod));
    }

    return QMetaObject::connect(pSourceObject, signalId, this, slotId + metaObject()->methodCount());
}

As you can see, I make intensive use of the QMetaObject, and particularly the index of the slots (method count).
The code for dynamic signals is comparable.

Now my question is: how future proof is this solution, especially because I assume that the index must be at least one bigger than the methodCount()?

Was it helpful?

Solution

Now my question is: how future proof is this solution, especially because I assume that the index must be at least one bigger than the methodCount()?

It should work as of now.

As for future proof... may be. The snippet is using unsupported features which means those might break at any point in the future. It is likely though it will continue working.

OTHER TIPS

As a separate option, if all your things are very similar in nature (like in a vector or something), consider connecting to a lambda function. eg:

QObject::connect(iter->checkbox, &QCheckBox::stateChanged,
                [&, iter->startup_status](int new_val) {
                    if (new_val == Qt::CheckState::Checked) {
                        startup_status = true;
                    } else {
                        startup_status = false;
                    }
                });

where iter is a struct/class that has public fields

QCheckBox *checkbox;
bool startup_status;

by this method, it is possible to have a variable number of very similar "slots" (which aren't actually slots, but act like slots)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top