7

I've got issue sending a custom class as an argument of a signal through Qt's web channel.

There isn't any error in the console, not even a warning, for both compilation and run time. Even though, I've got a null as parameters in my JavaScript signal handler. It works perfectly well with QString, int and others but not with my objects.

I saw this post: How to register a class for use it in a QWebChannel signal in Qt. The problem seems to be similar at first, but their solution doesn't work me. I have a public default constructor, a public copy constructor, and a public destructor. I used both qRegisterMetaType() and Q_DECLARE_METATYPE and still nothing.

By printing messages received by qwebchannel.js, I realized that the C++ send the null value. Which means that it doesn't know how to send my class.

Does anyone have an idea of what could be happening or how to solve it? (Propose even if you don't know)

Thanks in advance!

EDIT: After Research, I realized that issue come from this line in QWebChannel (singalhandler_p.h):

template<class Receiver>
void SignalHandler<Receiver>::dispatch(const QObject *object, const int signalIdx, void **argumentData)
{
    Q_ASSERT(m_signalArgumentTypes.contains(object->metaObject()));
    const QHash<int, QVector<int> > &objectSignalArgumentTypes = m_signalArgumentTypes.value(object->metaObject());
    QHash<int, QVector<int> >::const_iterator signalIt = objectSignalArgumentTypes.constFind(signalIdx);
    if (signalIt == objectSignalArgumentTypes.constEnd()) {
        // not connected to this signal, skip
        return;
    }
    const QVector<int> &argumentTypes = *signalIt;
    QVariantList arguments;
    arguments.reserve(argumentTypes.count());
    // TODO: basic overload resolution based on number of arguments?
    for (int i = 0; i < argumentTypes.count(); ++i) {
        const QMetaType::Type type = static_cast<QMetaType::Type>(argumentTypes.at(i));
        QVariant arg;
        if (type == QMetaType::QVariant) {
            arg = *reinterpret_cast<QVariant *>(argumentData[i + 1]);
        } else {
            arg = QVariant(type, argumentData[i + 1]);
        }
        arguments.append(arg);
    }
    m_receiver->signalEmitted(object, signalIdx, arguments);
}

As you can see, when a signal is sent from C++ through the channel, the arguments are converted in QVariant. After a few tests, I realized that the QVariant::typeName() return the name of my type, but doesn't contain anything from it.

I tried a single code to understand what I'm doing wrong. MyClass myClass; QVariant variant = QVariant::fromValue(myClass);

std::cout << (int)doc.isArray() << std::endl;
std::cout << (int)doc.isEmpty() << std::endl;
std::cout << (int)doc.isNull() << std::endl;
std::cout << (int)doc.isObject() << std::endl;

std::cout << variant.typeName() << ": [" << variant.toJsonDocument().toJson().toStdString() << "]" << std::endl;

The header for MyClass is:

class MyClass : public QObject
{
    Q_OBJECT

    Q_PROPERTY(int a MEMBER a)

public:
    MyClass(QObject *parent = NULL);
    MyClass(const MyClass &);

    int a;
};

Q_DECLARE_METATYPE(MyClass)

And this give the output:

0
1
1
0
MaClass: []

I don't understand why it's always empty. I tried to create getters and setters but the result is the same.

Community
  • 1
  • 1
Axel Payan
  • 99
  • 7

0 Answers0