Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 230
Chenna V Avatar asked Apr 19 '11 16:04

Chenna V


2 Answers

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.

like image 198
andref Avatar answered Oct 05 '22 01:10

andref


A continuation of andref's code so as to use any member function as a slot

    class SlotForwarder : public QObject
    {
        Q_OBJECT

    public:

        typedef void (*Function)();

        SlotForwarder(Function function, QObject* parent = 0) 
            : QObject(parent)
            , m_fptr(function)
        {}

    public slots:

        void forward()
        {
            m_fptr();
        }

    private:

        Function m_fptr;
    };

    int main(){
      QApplication a(argc, argv);
      MyClass myClassObject; //contains a function called MemberFunc
      //create a slotforwarder object so 
      SlotForwarder *memberFuncSlot = new SlotForwarder (std::tr1::bind(&MyClass::MemberFunc, &myClassObject));
      QObject::connect(ui.button,SIGNAL(clicked()),memberFuncSlot,SLOT(forward());
    }
like image 29
Chenna V Avatar answered Oct 04 '22 23:10

Chenna V