Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-72924

Enums and QFlags are not properly marshalled in QWebChannel

    XMLWordPrintable

Details

    • All
    • 38f097ba76fe5b26ccc15a5599e312336200e564 (qt/qtwebchannel/5.12)

    Description

      When exporting an object over QWebChannel, Q_ENUMs and Q_FLAGs are not properly marshalled. For example, consider the hypothetical class

      class Foo : public QObject {
          Q_OBJECT
          Q_PROPERTY(MyEnum myEnum /* ... */)
      public:
          enum MyEnum {
              MY_Foo = 0x0,
              MY_Bar = 0x1,
              MY_Last = 0x2
          };
          Q_ENUM(MyEnum)
      };
      

      On the client side, "foo.myEnum" would actually contain the string "MY_Foo" (or one of the other enumeration keys). On the other hand, assigning a number on the client side correctly sets the value on the server side.

      However, none of this works when using QFlags. This just prints warnings that the type is not supported and/or could not be converted.

      Looking into the source code of qmetaobjectpublisher.cpp, the problems are in QMetaObjectPublisher::toVariant() and QMetaObjectPublisher::wrapResult().

      In wrapResult(), the JSON Value is obtained with QJsonValue::fromVariant(), but that, in turn, switch()'es through the meta type id and if no id matches, simply returns the stringified value. Here's the point were QWebChannel sends the enum's key as a string instead of the actual value.

      In toVariant(), QVariant::convert is used to convert the JSON number to the target type, which succeeds for enums, but fails for QFlags.

      At the moment, I can work around the problem by defining custom converter functions for enum -> QJSValue and QFlags -> QJSValue (since QJSValue is special-cased in wrapResult()) as well as double -> QFlags (because the json number is converted to a QVariant(double)). I think this isn't quite how it's supposed to work.

      Part of a possible solution would be to check for QMetaType::IsEnumeration in wrapResult() and then convert the value to "int".
      That would solve the enum issue, but not the QFlags one.
      Maybe check for canConvert<int>() for every value and possibly to that conversion if it works? That would allow us to just define "custom" int <-> QFlags converters and be done with it. On the other hand, it might break a whole lot of stuff that's convertible to "int".

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            milianw Milian Wolff
            msarehn Arno Rehn
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes