I'm trying to write a method, with two parameters : the Q_PROPERTY name (char *) and the QObject * associated with, that permit to connect the notifySignal (if exists) of the Q_PROPERTY, to a void slot(QVariant), or to a slot dynamically builded which will call a void method(QVariant). The signature of the signal can vary according to the type of the parameter.

How can I achieve that in Qt 5? Maybe it's impossible, but I will not stop searching while I'm not sure of that.

So I think I have 3 solutions:

  • building dynamically a slot of the exact signature of the signal, from the signal name, and call a method(QVariant) in it, using the old Qt connect way:

    connect(sender, SIGNAL (valueChanged(QString,QString)),
        receiver, SLOT (updateValue(QString)) );
    
  • using the new Qt 5 connect system:

    connect(sender, &Sender::valueChanged,receiver, &Receiver::updateValue );
    
  • building all slots signatures that can be used with QVariant.

Althougt, I don't know how to build a slot dynamically that call a specified method for the first solution ; I don't know how to retrieve the function pointer from the QMetaMethod of the notifySignal, for the second solution ; maybe the last solution is the best way, and easy to achieve, but it seams a bit extreme.

What do you think about it?

1

There are 1 answers

0
peppe On

For "building a slot dynamically" there are private APIs in Qt (look for QMetaObjectBuilder or similar classes). However that doesn't solve the problem of the connection.

Note that QObject::connect is overloaded to take QMetaMethods as signals and slots. So you can easily build a "receiver" class object (for the only purpose of remembering which property it's acting upon):

class Receiver : public QObject {
    Q_OBJECT
public:
    explicit Receiver(const char *property, QObject *parent = 0)
        : QObject(parent),
        m_property(property)
    {}

signals:
    void propertyChangedForObject(const char *property, QObject *object);
public slots:
    void onPropertyChanged() {
        emit propertyChangedForObject(m_property, sender());
    }
private:
   const char * const m_property;
};

And hook it up in your method.