Qt World Summit: Submit your Presentation


qdbusxml2cpp generated properties with NOTIFY signals



  • First, it seems that qdbusxml2cpp does not generate NOTIFY signals. Is there a way to get it to do that? Being able to specify a signal with an annotation of some kind seems reasonable. Is there a technical reason why this is not available? This seems like a fairly large gap in DBus and QML integration. As it is, we will likely have to hand code our QDbusAbstractInterface classes, rather than using those generated by qdbusxml2cpp.



  • @greenroom Here is an example to make my question more clear: given the following DBus interface xml

    <!--
               SpeedRpm
               The current handpiece speed in RPM.
    -->
    <property name="speedRpm" type="q" access="read"/>
    

    the following code is generated

    Q_PROPERTY(ushort speedRpm READ speedRpm)
    inline ushort speedRpm() const
    { return qvariant_cast< ushort >(property("speedRpm")); }
    

    Why can't qdbusxml2cpp generate this code

    Q_PROPERTY(ushort speedRpm READ speedRpm NOTIFY speedRpmChanged)
    inline ushort speedRpm() const
    { return qvariant_cast< ushort >(property("speedRpm")); }
    ...
    signals:
    void speedRpmChanged(ushort speed);
    

  • Lifetime Qt Champion

    Hi,

    Just an educated guess: there's no reason from your description to add a signal. You have a read only property. If you want to have an additional signal then your interface declaration should state that as well.

    Not all Qt properties have notification signal.



  • @SGaist I will add some more context to make the use case more clear. The goal is to use this interface from QML. For example,

    Text {
            id: speedText
            text:  HpA.speedRpm
    ...
    }
    

    So, in this case we need the NOTIFY signal.


  • Lifetime Qt Champion

    I understand you need. What I am saying is that you likely need to make your interface declaration more complete in order for the notify signal to be generated.



  • @SGaist said in qdbusxml2cpp generated properties with NOTIFY signals:

    make your interface declaration more complete

    I am sorry, I don't understand what you mean. What is it missing?


  • Lifetime Qt Champion

    It's missing the signal part.



  • Has anyone figured out a way to get qdbusxml2cpp to generated properties with the NOTIFY signal?

    I have an interface which I defined and it expressly says that the property has a change signal, but when I create an XML from it and use that XML to generate a proxy class for the interface it does not expose the NOTIFY signal (although the signal is defined with QT_SIGNAL)...

    Here is the original Interface Class:

    class benchInterface : public QObject {
        Q_OBJECT;
        Q_CLASSINFO("D-Bus Interface", "com.cana.bench")
    
        Q_PROPERTY(uchar gpioa READ gpioa WRITE setGpioa NOTIFY gpioaChanged)
        Q_PROPERTY(QString state READ getState WRITE setState NOTIFY stateChanged)
    
      public:
        benchInterface(QObject *parent = nullptr);
        virtual ~benchInterface();
    
      public slots:
        bool startProcess(QString data);
        void quit();
    
      signals:
        void processComplete(QString data);
        void processFailed(int errorcode);
        void gpioaChanged();
        void stateChanged();
    
      private slots:
        void onTimer();
    
      private:
        uchar gpioa();
        void setGpioa(uchar value);
    
        void setState(QString newState);
        QString getState();
    
        QString processData;
        QString state = "Idle";
    
        std::unique_ptr<cana::interface::i2c::i2c> i2c2_controller;
        std::unique_ptr<MCP23017> mcp23017;
    };
    

    So I have a property state which is a QString which has a notify signal stateChanged(). The XML produced from qdbuscpp2xml is :

    <!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
    <node>
      <interface name="com.cana.bench">
        <property name="gpioa" type="y" access="readwrite"/>
        <property name="state" type="s" access="readwrite"/>
        <signal name="processComplete">
          <arg name="data" type="s" direction="out"/>
        </signal>
        <signal name="processFailed">
          <arg name="errorcode" type="i" direction="out"/>
        </signal>
        <signal name="gpioaChanged">
        </signal>
        <signal name="stateChanged">
        </signal>
        <method name="startProcess">
          <arg type="b" direction="out"/>
          <arg name="data" type="s" direction="in"/>
        </method>
        <method name="quit">
        </method>
      </interface>
    </node>
    

    But the resulting proxy class does not expose the NOTIFY signal:

    /*
     * Proxy class for interface com.cana.bench
     */
    class ComCanaBenchInterface : public QDBusAbstractInterface {
        Q_OBJECT
      public:
        static inline const char *staticInterfaceName() { return "com.cana.bench"; }
    
      public:
        ComCanaBenchInterface(const QString &service, const QString &path,
                              const QDBusConnection &connection,
                              QObject *parent = nullptr);
    
        ~ComCanaBenchInterface();
    
        Q_PROPERTY(uchar gpioa READ gpioa WRITE setGpioa)
        inline uchar gpioa() const {
            return qvariant_cast<uchar>(property("gpioa"));
        }
        inline void setGpioa(uchar value) {
            setProperty("gpioa", QVariant::fromValue(value));
        }
    
        Q_PROPERTY(QString state READ state WRITE setState)
        inline QString state() const {
            return qvariant_cast<QString>(property("state"));
        }
        inline void setState(const QString &value) {
            setProperty("state", QVariant::fromValue(value));
        }
    
      public Q_SLOTS: // METHODS
        inline QDBusPendingReply<> quit() {
            QList<QVariant> argumentList;
            return asyncCallWithArgumentList(QStringLiteral("quit"), argumentList);
        }
    
        inline QDBusPendingReply<bool> startProcess(const QString &data) {
            QList<QVariant> argumentList;
            argumentList << QVariant::fromValue(data);
            return asyncCallWithArgumentList(QStringLiteral("startProcess"),
                                             argumentList);
        }
    
      Q_SIGNALS: // SIGNALS
        void gpioaChanged();
        void processComplete(const QString &data);
        void processFailed(int errorcode);
        void stateChanged();
    };
    

    Is there something I am missing? When I manually add the NOTIFY to the generated proxy class then the property works correctly (using from QML).

    Thank you,
    Michael Uman
    Sr Firmware Engineer
    Cana Technologies



  • Judging from the source code of qdbusxml2cpp: it cannot generate NOTIFY declarations for properties at all.

    Christian


Log in to reply