An example of connecting a signal by name in QT

class TableColumn : public QObject
{
    Q_OBJECT

public slots:

    void onValueChanged()
    {
        emit onChanged();
    }

signals:

    void onChanged();
};
template <class T>
class PropertyColumn : public TableColumn
{
public:

    PropertyColumn(const char* name) :
        m_prop(makeProperty(name)),
        m_signalMethod(m_prop.notifySignal())
    {}

    QVariant value(const T* p_item)
    {
        QVariant val = m_prop.read(p_item);

        return val;
    }

    void connectChanged(T* p_item)
    {
        const int i = metaObject()->indexOfSignal("onChanged()");

        if (i == -1)
        {
            throw std::runtime_error("onChanged() signal does not exist.");
        }

        QMetaMethod update_slot = metaObject()->method(i);

        QObject::connect(p_item, m_signalMethod, static_cast<TableColumn*>(this), update_slot);
    }

    void connectChanged2(T* p_item)
    {
        const int i = metaObject()->indexOfSlot("onValueChanged()");

        if (i == -1)
        {
            throw std::runtime_error("onValueChanged() slot does not exist.");
        }

        QMetaMethod update_slot = metaObject()->method(i);

        QObject::connect(p_item, m_signalMethod, static_cast<TableColumn*>(this), update_slot);
    }

private:

    QMetaProperty makeProperty(const char* name)
    {
        const QMetaObject* mo = &T::staticMetaObject;

        const int i = mo->indexOfProperty(name);

        if (i == -1)
        {
            throw std::runtime_error("Property does not exist.");
        }

        return mo->property(i);
    }

    QMetaProperty m_prop;

    QMetaMethod m_signalMethod;
};
AWL_TEST(PropertyColumn)
{
    ValueTestObject vo;

    const int expected_value = 5;

    vo.setValue(expected_value);

    qtil::PropertyColumn<ValueTestObject> col("value");

    const int actual_value = col.value(&vo).value<int>();

    AWL_ASSERT_EQUAL(expected_value, actual_value);

    col.connectChanged(&vo);

    col.connectChanged2(&vo);

    QObject::connect(static_cast<qtil::TableColumn*>(&col), &qtil::TableColumn::onChanged,
        [&]()
        {
            context.logger.debug(awl::format() << "value changed.");
        });

    vo.setValue(7);
}

2 Responses to An example of connecting a signal by name in QT

  1. dmitriano says:

    QBindable Class
    https://doc.qt.io/qt-6/qbindable.html
    MyClass *myObject;
    QBindable bindableX = myObject->bindableX();
    qDebug() << bindableX.hasBinding(); // prints false
    QProperty y {42};
    bindableX.setBinding([&](){ return 2*y.value(); });
    qDebug() << bindableX.hasBinding() <x(); // prints true 84

Leave a Reply

Your email address will not be published. Required fields are marked *