c++jsonqtcommunicationqmetatype

How to register a class for use it in a QWebChannel signal in Qt


Im using QT 5 with a WebChannel to communicate with a HTML Page. I successfully able to communicate texts and strings. however i woud like to communicate some points data.

the official documentation says

"No manual message passing and serialization of data is required," http://doc.qt.io/qt-5/qwebchannel.html

When i try to send a object or an array, instead of a string, the application throw this message:

Don't know how to handle 'data', use qRegisterMetaType to register it.

How can I emit a signal with a Point class instead of a string object? Or to serialize a class to a string.

This is the object that i would like to send to my HTML

Point class

class MyData{
public :
    int x,y,z;
};
Q_DECLARE_METATYPE(MyData)

Map class

class MyMap : public QObject{
Q_OBJECT

public:
    explicit MyMap ();

signals:
    updateText(const QString &text); // registered
    updateData(MyData &data); //   Don't know how to handle 'data', use qRegisterMetaType to register it.

public slots:
    receiveText(const QString &text);
};

and the main code

qRegisterMetaType<MyData>();

// setup the channel
QWebChannel channel;
QObject::connect(&clientWrapper, &WebSocketClientWrapper::clientConnected, &channel, &QWebChannel::connectTo);

// setup the dialog and publish it to the QWebChannel
channel.registerObject(QStringLiteral("map"), &map);

map.updateText("text");

MyData data;
data.x=10;
data.y=12;
data.z=13;
map.updateData(data);

Solution

  • Per Qt documentation:

    To use the type T in QVariant, using Q_DECLARE_METATYPE() is sufficient. To use the type T in queued signal and slot connections, qRegisterMetaType() must be called before the first connection is established.

    In my own code, I use Q_DECLARE_METATYPE for classes I want to store in a QVariant (this macro has to by put at global scope). And I qRegisterMetaType<T>() for classes I want to be passed to signals/slots (this function has to be called before the signal.slot connection is made). I never had to call both if using only one feature.

    So, for your example, this should work:

    qRegisterMetaType<MyData>( "MyData" );
    // then, form here, you can connect `updateData(MyData)` signal to any slot taking a MyData parameter
    

    For signal/slot declaration:

    Make sure MyData declaration is known when you do this (no forward declaration).

    Note also that not all classes/structs can be registered this way, they must have:

    a public default constructor, a public copy constructor, and a public destructor

    It's the case for your MyData class (default ones are OK), so it should work smoothly.