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

QML PropertyChanges can only change one signal handler for multiple properties notified by same signal

    XMLWordPrintable

Details

    Description

      If multiple properties are declared in a C++ component using the same notification signal, a `PropertyChanges` element can only add/replace the handler for one of properties. When multiple signal handlers are added via a `PropertyChanges` element, always the first declared signal handler is the only one that works.

      I expect that I can use a `PropertyChanges` element to add a "changed" signal handler for each of the properties, but this fails when the properties share the same signal. If each property has its own notification signal, there is no problem.

      Below is an example of what I mean by "shared notification signals":

      // code placeholder
      class Monitor: public QObject
      {
          Q_OBJECT
          Q_PROPERTY(int value1 READ value1 NOTIFY readCompleted)
          Q_PROPERTY(int value2 READ value2 NOTIFY readCompleted)
          Q_PROPERTY(int value3 READ value3 NOTIFY readCompleted)
      
      public:
          explicit Monitor(QObject *parent = nullptr) : QObject(parent) {}
      
      signals:
          void readCompleted();
      
      public slots:
          void readSensor() {
              for (auto& v : mValues)
                  v += 3;
               emit readCompleted();
          }
      
      private:
          int value1() const { return mValues[0]; }
          int value2() const { return mValues[1]; }
          int value3() const { return mValues[2]; }
      
          int mValues[3] { 1, 2, 3 };
      };
      

      Below is an example of a QML declaration where I expect to be able to replace all signal handlers:

      Item {
          Monitor {
              id: monitor
              onValue1Changed: window.log("red", "onValue1Changed", value1)
              onValue2Changed: window.log("red", "onValue2Changed", value2)
              onValue3Changed: window.log("red", "onValue3Changed", value3)
          }
          states: State {
              name: "modifiedBehavior"
              when: true
              PropertyChanges {
                  target: monitor
                  onValue1Changed: window.log("blue", "PropertyChanges value1", value1)
                  onValue2Changed: window.log("blue", "PropertyChanges value2", value2)
                  onValue3Changed: window.log("blue", "PropertyChanges value3", value3)
              }
          }
      }
      

      Below is the output when the properties change. The red output is from property change handlers declared within the component in QML. They are unnecessary for demonstrating the issue. My goal in showing them is to demonstrate that the change signals are all received in QML:

      Also, if I declare a `Connections` element (not demonstrated), I can log all property changes. It is only via the PropertyChanges element that change signal notification is deficient.

      If each property has its own notification signal instead of sharing the signals, I can replace all the signal handlers. This is the behavior I expected but did not see with shared notification signals for the properties:

      I attached a project that demonstrates the behavior and has a `#if` preprocessor directive in the `Monitor.h` file that can declare notification signals for each property.

      Attachments

        1. image-2022-12-20-16-02-50-792.png
          17 kB
          Stanley Morris
        2. image-2022-12-20-16-16-23-122.png
          20 kB
          Stanley Morris
        3. SharedSignals.zip
          3 kB
          Stanley Morris

        Activity

          People

            qtqmlteam Qt Qml Team User
            stan.m Stanley Morris
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated: