Search code examples
qtdynamicsignals-slots

Creating a dynamic slot in Qt


I am trying to create slots dynamically and connect them. I am able to dynamically create pushButtons and connect them with existing slots. But what if I have a class with some member functions and I want to use these functions as slots.

From a general perspective, I want to create a template for generating slots given a function pointer. This allows us to create slots without changing the existing code and don't have to recompile using MOC. If this doesn't make sense let me know. Thank you.

-CV


Solution

  • It does make a lot of sense. I assume QSignalMapper is not what you want. If your functions don't have arguments, maybe something like this is enough:

    class SlotForwarder : public QObject
    {
        Q_OBJECT
    
    public:
    
        typedef void (*Function)(); // or whatever. I never get this syntax right...
    
        SlotForwarder(Function function, QObject* parent = 0) 
            : QObject(parent)
            , m_fptr(function)
        {}
    
    public slots:
    
        void forward()
        {
            m_fptr();
        }
    
    private:
    
        Function m_fptr;
    };
    

    Create one for each function you want to encapsulate and connect to the forward as usual.


    Now, if they do have arguments, maybe this Qt Quarterly article might be of assistance.

    Dynamic Signals and Slots by Eskil A. Blomfeldt

    The technique involves reimplementing the qt_metacall method yourself. The method has this signature:

    int QObject::qt_metacall(QMetaObject::Call call, int id, void **arguments)
    

    Call is the kind of metacall: slot, signal, property read or write, etc. Every slot has an id. The parameters are packed (by value or as pointers) inside the arguments array. Reading the code that the moc generates is a good way to understand how it all works.

    Data about raw function signatures is available only during compile time, but slots are resolved at runtime. Because of that mismatch, you will need to wrap the functions into a template adapter type that presents a constant interface to your implementation of qt_metacall and converts the arguments array into something the function can understand (cf. Python unpack operator). Boost.Signals does that kind of template hackery.