Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. General talk
  3. Brainstorm
  4. division of labor between QML and C++
Forum Updated to NodeBB v4.3 + New Features

division of labor between QML and C++

Scheduled Pinned Locked Moved Solved Brainstorm
9 Posts 3 Posters 1.8k Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • mzimmersM Offline
    mzimmersM Offline
    mzimmers
    wrote on last edited by
    #1

    Hi all -

    My app displays a view of equipment items, populated from a list model. When selected, a detail screen appears, from which the user can edit properties of the selected item. It's important to note here that these edits don't go directly into the model; they are used to form an HTTP PATCH message (this is done in C++). When I get a response to this message, I then update the model (the response contains the changed properties, so I don't need to store them for subsequent retrieval).

    Complicating this is the fact that the equipment struct will be sub-classed (sub-structed?) many times.

    I'm trying to figure out the best division of labor between QML and C++. Seems to me I have a couple choices:

    1. I can create a temporary equipment item in my QML, update it with the user changes, and pass it back to my C++ which handles forming and sending the HTTP request. The signature would look like this:
     Q_INVOKABLE void sendPatchRequest(Equipment equipment);
    

    The difficulty here is the subclasses; I don't know how to make my C++ "receive" anything more specific than an equipment struct.

    1. I can form a JS array of the changes, using the roles and values, and send them to the C++. The signature would look like this:
    Q_INVOKABLE void sendPatchRequest(QUuid uuid,
        QList<EquipmentRoles> roles,
        QList<QVariant> values);
    

    As the subclass can be determined from one of the parent class properties (the "category"), I can then form the HTTP request from this array. This is viable, but it feels like I'm trying to do too much in the QML. This is also going to be a lot of coding, both in QML and C++.

    I'd prefer the first option, but I don't know how to get around the issue of preserving the subclass properties in the call. Does anyone have any other ideas on how to go about this?

    Thanks...

    S 1 Reply Last reply
    0
    • SGaistS SGaist

      @mzimmers it is good that it has no knowledge of the model. The only think that it should do is return it's internal state in a format suitable to be sent. The fact that the model will use an HTTP request or GRPC does not have any impact on your Equipment classes.

      It would be something along the lines of:

      void MyModel::sendSomething(int index) {
          Equipement *equipment = data(index, Qt::UserRole).value<Equipment *>();
          qnam->post("https://mythink.com/upload/", equipment->state());
      }
      

      Where state would return a json representation of its state. So the equipment does not care about the model nor what will be done with the value returned by the state method. So you have proper separation of concerns.

      mzimmersM Offline
      mzimmersM Offline
      mzimmers
      wrote on last edited by
      #8

      @SGaist the call from QML to my model must include the temporary object, as it doesn't exist within the model (I suppose I could change this).

      The ideal flow on this would be:

      1. QML calls the model with the changed (temporary) object
      2. the model invokes a method in the subclass to populate a QJsonObject
      3. the model forms an outgoing message from the QJsonObject

      but none of this will work if the model doesn't know what subclass it is receiving, and currently I haven't been able to find a way to do this.

      mzimmersM 1 Reply Last reply
      0
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #2

        Hi,

        Your equipment base class could have a virtual method that returns the patch data and all the subclasses would reimplement it. That way you can have everything implemented in C++.

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        mzimmersM 1 Reply Last reply
        0
        • SGaistS SGaist

          Hi,

          Your equipment base class could have a virtual method that returns the patch data and all the subclasses would reimplement it. That way you can have everything implemented in C++.

          mzimmersM Offline
          mzimmersM Offline
          mzimmers
          wrote on last edited by mzimmers
          #3

          @SGaist a couple of questions:

          1. how best to return the patch data from QML to C++? Which of my above options seems preferable?
          2. would you expect the QML --> C++ route to go through the model, or directly to the item(s) in the list? I can do it either way, but if the latter, I think I'd either need to move my message management from the model into the equipment struct, or use a signal/slot mechanism, which seems kind of stilted.
          3. the real problem is how to get the equipment model to recognize what subclass of Equipment it's being passed. As long as the model's function signature expects a type of Equipment, there doesn't seem to be any way to convert it to a subclass of equipment. I lose all of the subclass' properties.
            Thanks...
          S 1 Reply Last reply
          0
          • mzimmersM mzimmers

            Hi all -

            My app displays a view of equipment items, populated from a list model. When selected, a detail screen appears, from which the user can edit properties of the selected item. It's important to note here that these edits don't go directly into the model; they are used to form an HTTP PATCH message (this is done in C++). When I get a response to this message, I then update the model (the response contains the changed properties, so I don't need to store them for subsequent retrieval).

            Complicating this is the fact that the equipment struct will be sub-classed (sub-structed?) many times.

            I'm trying to figure out the best division of labor between QML and C++. Seems to me I have a couple choices:

            1. I can create a temporary equipment item in my QML, update it with the user changes, and pass it back to my C++ which handles forming and sending the HTTP request. The signature would look like this:
             Q_INVOKABLE void sendPatchRequest(Equipment equipment);
            

            The difficulty here is the subclasses; I don't know how to make my C++ "receive" anything more specific than an equipment struct.

            1. I can form a JS array of the changes, using the roles and values, and send them to the C++. The signature would look like this:
            Q_INVOKABLE void sendPatchRequest(QUuid uuid,
                QList<EquipmentRoles> roles,
                QList<QVariant> values);
            

            As the subclass can be determined from one of the parent class properties (the "category"), I can then form the HTTP request from this array. This is viable, but it feels like I'm trying to do too much in the QML. This is also going to be a lot of coding, both in QML and C++.

            I'd prefer the first option, but I don't know how to get around the issue of preserving the subclass properties in the call. Does anyone have any other ideas on how to go about this?

            Thanks...

            S Offline
            S Offline
            SamiV123
            wrote on last edited by SamiV123
            #4

            @mzimmers said in division of labor between QML and C++:

            Q_INVOKABLE void sendPatchRequest(Equipment equipment);

            This looks very dodgy if (like you said) you have multiple Equipment classes, since here you're slicing the object.

            Would seem that you should use a pointer/reference here if the runtime type of 'equipment' is a polymorphic type.

            1 Reply Last reply
            0
            • mzimmersM mzimmers

              @SGaist a couple of questions:

              1. how best to return the patch data from QML to C++? Which of my above options seems preferable?
              2. would you expect the QML --> C++ route to go through the model, or directly to the item(s) in the list? I can do it either way, but if the latter, I think I'd either need to move my message management from the model into the equipment struct, or use a signal/slot mechanism, which seems kind of stilted.
              3. the real problem is how to get the equipment model to recognize what subclass of Equipment it's being passed. As long as the model's function signature expects a type of Equipment, there doesn't seem to be any way to convert it to a subclass of equipment. I lose all of the subclass' properties.
                Thanks...
              S Offline
              S Offline
              SamiV123
              wrote on last edited by
              #5

              @mzimmers said in division of labor between QML and C++:

              the real problem is how to get the equipment model to recognize what subclass of Equipment it's being passed. As long as the model's function signature expects a type of Equipment, there doesn't seem to be any way to convert it to a subclass of equipment. I lose all of the subclass' properties.
              Thanks...

              That's what down casting is for generally speaking.

              But like @SGaist said perhaps you should consider adding a virtual interface method in the Equipment class that can convert the internal state of your "equipment" into some byte representation that you can send over HTTP.

              mzimmersM 1 Reply Last reply
              0
              • S SamiV123

                @mzimmers said in division of labor between QML and C++:

                the real problem is how to get the equipment model to recognize what subclass of Equipment it's being passed. As long as the model's function signature expects a type of Equipment, there doesn't seem to be any way to convert it to a subclass of equipment. I lose all of the subclass' properties.
                Thanks...

                That's what down casting is for generally speaking.

                But like @SGaist said perhaps you should consider adding a virtual interface method in the Equipment class that can convert the internal state of your "equipment" into some byte representation that you can send over HTTP.

                mzimmersM Offline
                mzimmersM Offline
                mzimmers
                wrote on last edited by
                #6

                @SamiV123 said in division of labor between QML and C++:

                But like @SGaist said perhaps you should consider adding a virtual interface method in the Equipment class that can convert the internal state of your "equipment" into some byte representation that you can send over HTTP.

                This approach definitely minimizes the work that I need to do in QML, which is good. But my equipment struct has no knowledge of the model, or any of its methods. And, since it's a Q_GADGET, I can't use signals to notify the model of the need for a change.

                So each instance of Equipment and its subclasses would have to handle the entire patch operation: building the list of properties to patch, creating the JSON, and sending the message. I'd greatly prefer this be handled in one location (the model).

                SGaistS 1 Reply Last reply
                0
                • mzimmersM mzimmers

                  @SamiV123 said in division of labor between QML and C++:

                  But like @SGaist said perhaps you should consider adding a virtual interface method in the Equipment class that can convert the internal state of your "equipment" into some byte representation that you can send over HTTP.

                  This approach definitely minimizes the work that I need to do in QML, which is good. But my equipment struct has no knowledge of the model, or any of its methods. And, since it's a Q_GADGET, I can't use signals to notify the model of the need for a change.

                  So each instance of Equipment and its subclasses would have to handle the entire patch operation: building the list of properties to patch, creating the JSON, and sending the message. I'd greatly prefer this be handled in one location (the model).

                  SGaistS Offline
                  SGaistS Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on last edited by
                  #7

                  @mzimmers it is good that it has no knowledge of the model. The only think that it should do is return it's internal state in a format suitable to be sent. The fact that the model will use an HTTP request or GRPC does not have any impact on your Equipment classes.

                  It would be something along the lines of:

                  void MyModel::sendSomething(int index) {
                      Equipement *equipment = data(index, Qt::UserRole).value<Equipment *>();
                      qnam->post("https://mythink.com/upload/", equipment->state());
                  }
                  

                  Where state would return a json representation of its state. So the equipment does not care about the model nor what will be done with the value returned by the state method. So you have proper separation of concerns.

                  Interested in AI ? www.idiap.ch
                  Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                  mzimmersM 1 Reply Last reply
                  0
                  • SGaistS SGaist

                    @mzimmers it is good that it has no knowledge of the model. The only think that it should do is return it's internal state in a format suitable to be sent. The fact that the model will use an HTTP request or GRPC does not have any impact on your Equipment classes.

                    It would be something along the lines of:

                    void MyModel::sendSomething(int index) {
                        Equipement *equipment = data(index, Qt::UserRole).value<Equipment *>();
                        qnam->post("https://mythink.com/upload/", equipment->state());
                    }
                    

                    Where state would return a json representation of its state. So the equipment does not care about the model nor what will be done with the value returned by the state method. So you have proper separation of concerns.

                    mzimmersM Offline
                    mzimmersM Offline
                    mzimmers
                    wrote on last edited by
                    #8

                    @SGaist the call from QML to my model must include the temporary object, as it doesn't exist within the model (I suppose I could change this).

                    The ideal flow on this would be:

                    1. QML calls the model with the changed (temporary) object
                    2. the model invokes a method in the subclass to populate a QJsonObject
                    3. the model forms an outgoing message from the QJsonObject

                    but none of this will work if the model doesn't know what subclass it is receiving, and currently I haven't been able to find a way to do this.

                    mzimmersM 1 Reply Last reply
                    0
                    • mzimmersM mzimmers

                      @SGaist the call from QML to my model must include the temporary object, as it doesn't exist within the model (I suppose I could change this).

                      The ideal flow on this would be:

                      1. QML calls the model with the changed (temporary) object
                      2. the model invokes a method in the subclass to populate a QJsonObject
                      3. the model forms an outgoing message from the QJsonObject

                      but none of this will work if the model doesn't know what subclass it is receiving, and currently I haven't been able to find a way to do this.

                      mzimmersM Offline
                      mzimmersM Offline
                      mzimmers
                      wrote on last edited by
                      #9

                      Just to close this topic out, here's what I ended up doing (posted elsewhere as well):

                      // will need one of these for each subclass
                      void EquipmentModel::sendPatchRequest(const Vsp &equipment) {
                          sendBaseRequest(equipment);
                      }
                      void EquipmentModel::sendBaseRequest(const Equipment &equipment)
                      {
                      	...
                      	// the line below will call the override function
                      	// for the appropriate subclass.
                      	equipment.addPatchFields(listEntry, qjo, rolesToKeys);
                      

                      Not super elegant, but it works. Thanks to all for the suggestions.

                      1 Reply Last reply
                      0
                      • mzimmersM mzimmers has marked this topic as solved on

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved