using boost signals instead of qt

2019-03-11 15:10发布

问题:

This is a long shot but, having come across a constrain in a form of a qt's signals, slots being unable to be templatized, I'm just thinking of replacing them with boost signals, would that be viable option?

回答1:

You are not forced to use qt's signals and slots. From Using Qt with 3rd Party Signals and Slots:

It is possible to use Qt with a 3rd party signal/slot mechanism. You can even use both mechanisms in the same project. Just add the following line to your qmake project (.pro) file.

CONFIG += no_keywords

It tells Qt not to define the moc keywords signals, slots, and emit, because these names will be used by a 3rd party library, e.g. Boost. Then to continue using Qt signals and slots with the no_keywords flag, simply replace all uses of the Qt moc keywords in your sources with the corresponding Qt macros Q_SIGNALS (or Q_SIGNAL), Q_SLOTS (or Q_SLOT), and Q_EMIT.

There is a complete explanation of how to connect boost signals to qt signals.


I found this adapter somewhere on the net, but no idea where:

#ifndef _QT_2_FUNC_3_H_
#define _QT_2_FUNC_3_H_

#include <iostream>

#include <boost/function.hpp>
#include <boost/type_traits.hpp>

#include <QObject>

#include <libQtSignalAdapters/QtConnDefault.h>

using namespace boost;

namespace QtSignalAdapters
{

/**
* \cond
*/
template<typename SIGNATURE>
class Qt2FuncSlot3
{
public:
    typedef function<SIGNATURE> FuncType;
    typedef typename function_traits<SIGNATURE>::arg1_type ParmType1;
    typedef typename function_traits<SIGNATURE>::arg2_type ParmType2;
    typedef typename function_traits<SIGNATURE>::arg3_type ParmType3;

    Qt2FuncSlot3(const FuncType& func) :
        func_(func)
    {
    }

    void call(QObject* sender, void **arguments)
    {
        ParmType1* a1 = reinterpret_cast<ParmType1*>(arguments[1]);
        ParmType2* a2 = reinterpret_cast<ParmType2*>(arguments[2]);
        ParmType3* a3 = reinterpret_cast<ParmType3*>(arguments[3]);
        if ( func_ )
            func_(*a1,*a2, *a3);
    }

private:
    FuncType func_;
};
/**
* \endcond
*/

template<typename SIGNATURE>
class Qt2Func3 : public QObject, public QtConnDefault
{
public:
    typedef function<SIGNATURE> FuncType;
    typedef typename function_traits<SIGNATURE>::arg1_type ParmType;

    Qt2Func3(QObject* qobject, int signalIdx, const FuncType& func,
            bool initiallyConnected=true) :
        QObject(qobject),
        QtConnDefault(qobject, signalIdx),
        func_(func)
    {
        //
        // Get the next usable slot ID on this...
        //
        slotIdx_ = metaObject()->methodCount();

        //
        // Create a slot to handle invoking the boost::function object.
        //
        slot_ = new Qt2FuncSlot3<SIGNATURE>(func);

        if ( initiallyConnected )
            connect();
    }

    ~Qt2Func3()
    {
        delete slot_;
    }

    int qt_metacall(QMetaObject::Call c, int id, void **arguments)
    {
        id = QObject::qt_metacall(c, id, arguments);
        if ( id < 0 || c != QMetaObject::InvokeMetaMethod )
            return id;

        slot_->call(sender(), arguments);
        return -1;
    }

    void connect()
    {
        connect_();
    }

    void disconnect()
    {
        disconnect_();
    }

private:
    void connect_()
    {
        connected_ =
            QMetaObject::connect(qobject_, signalIdx_, this, slotIdx_);
    }

    void disconnect_()
    {
        connected_ =
            !QMetaObject::disconnect(qobject_, signalIdx_, this, slotIdx_);
    }


    FuncType func_;
    Qt2FuncSlot3<SIGNATURE>* slot_;
};

}

#endif

So, basically you have to reimplement qt_metacall function.



标签: c++ qt boost qt4