Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Access and Change QList<QObject*> dynamic property in QObject*
QtWS25 Last Chance

Access and Change QList<QObject*> dynamic property in QObject*

Scheduled Pinned Locked Moved Solved General and Desktop
qobjectdynamicpropertyqlistqobjectreference
9 Posts 3 Posters 6.8k Views
  • 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.
  • DongD Offline
    DongD Offline
    Dong
    wrote on last edited by Dong
    #1

    I got DynamicObject Class inherited from QObject

    This is Data Structure of my Data

    (Object/Property : Data Type/Class)

    • rootObj : DynamicObject
      • ItemsSource : QList<QObject*>
        • [0] : DynamicObject*
          • Name : QString
          • Status : Enum
        • [1] : DynamicObject*
        • [2] : DynamicObject*
        • [3] : DynamicObject*

    I can set the Name of item in list like this.

    rootObj->property("ItemsSource").value<QList<QObject*> >()[3]->setProperty("Name", "New Campaign Name");
    

    But I can't set an item to new object like this

    rootObj->property("ItemsSource").value<QList<QObject*> >()[3] = rootObj->property("ItemsSource").value<QList<QObject*> >()[9];
    

    I tried Pointer Referrence like this but it doesn't work.

    void setObject(QObject *& obj, QObject * obj2)
    {
        obj = obj2;
    }
    
    setObject(rootObj->property("ItemsSource").value<QList<QObject*> >()[3], 
        rootObj->property("ItemsSource").value<QList<QObject*> >()[9]);
    

    I also want to remove/insert item as well.

    Any one know why? and how to do it?

    1 Reply Last reply
    0
    • mrjjM Offline
      mrjjM Offline
      mrjj
      Lifetime Qt Champion
      wrote on last edited by
      #2

      @Dong said:
      Hi
      Do you try to copy QObject based classes ?

      you void setObject(QObject *& obj, QObject * obj2)
      seem to use the = operator
      and if u read in
      http://doc.qt.io/qt-5.5/object.html#qt-objects-identity-vs-value

      "Therefore, QObject and all subclasses of QObject (direct or indirect) have their copy constructor and assignment operator disabled."

      It seems that its not allowed. Not sure if you copy actual Objects or just mere pointers.

      1 Reply Last reply
      1
      • DongD Offline
        DongD Offline
        Dong
        wrote on last edited by
        #3

        @mrjj
        Thanks for your notice about the "Copy Constructor & Assignment Operator Disabled"
        May be I had to build my own "Set" function to copy Object's Properties one by one.

        There is an other question in my post.
        My rootObj also have "SelectedItems" Property
        So, I want to set a list of selected items from "ItemsSource"
        And Insert/Remove/Re-Assign an item into/from "SelectedItems" later.

        Can you help me with this?

        mrjjM 1 Reply Last reply
        0
        • DongD Dong

          @mrjj
          Thanks for your notice about the "Copy Constructor & Assignment Operator Disabled"
          May be I had to build my own "Set" function to copy Object's Properties one by one.

          There is an other question in my post.
          My rootObj also have "SelectedItems" Property
          So, I want to set a list of selected items from "ItemsSource"
          And Insert/Remove/Re-Assign an item into/from "SelectedItems" later.

          Can you help me with this?

          mrjjM Offline
          mrjjM Offline
          mrjj
          Lifetime Qt Champion
          wrote on last edited by mrjj
          #4

          @Dong
          Hi
          The SelectedItems is a Qlist ?
          Each Property is QVariant.
          so you could make
          QLIst<QVariant> SelectedItems;
          and just use the normal Qlist add/remove functions.

          I have not tried stuffing a list of variant into a property so not sure how to do that.
          update:
          ahh it has tolist function
          http://doc.qt.io/qt-5.5/qvariant.html#toList
          So you can take out the QList again from the variant and then
          add/remove. and then put it back into property.

          You can get list of all properties this way
          http://doc.qt.io/qt-5/qobject.html#dynamicPropertyNames

          1 Reply Last reply
          0
          • kshegunovK Offline
            kshegunovK Offline
            kshegunov
            Moderators
            wrote on last edited by
            #5

            Ouch, my head hurts, 7 operators and 4 function calls on a single line is a bit much for me personally.
            Your problem is that you take the variant's value by QVariant::value, which creates a shallow copy of your list. I'm pretty sure that variant was not intended to store properties in this way, since it doesn't provide a function to operate on the actual variable.

            If you want to change the lists you'd need to do something like this:

            // Take the list
            QObjectList properties = rootObj->property("ItemsSource").value<QObjectList>();
            // Do modify, insert, delete w/e
            ...
            // Update the property
            rootObj->setProperty("ItemsSource", QVariant::fromValue(properties));
            

            Read and abide by the Qt Code of Conduct

            1 Reply Last reply
            2
            • DongD Offline
              DongD Offline
              Dong
              wrote on last edited by
              #6

              @mrjj & @kshegunov :

              Thanks for your help.

              I already thought about kshegunov solution. completely re-assign the ItemsSource Property.
              But it seem to be "dummy" and I want to find some other way like (pointer / reference or something else)

              I'm more familiar with C# where all Object are reference type so we can modify it directly.

              Anyway, Thanks again !

              kshegunovK 1 Reply Last reply
              0
              • DongD Dong

                @mrjj & @kshegunov :

                Thanks for your help.

                I already thought about kshegunov solution. completely re-assign the ItemsSource Property.
                But it seem to be "dummy" and I want to find some other way like (pointer / reference or something else)

                I'm more familiar with C# where all Object are reference type so we can modify it directly.

                Anyway, Thanks again !

                kshegunovK Offline
                kshegunovK Offline
                kshegunov
                Moderators
                wrote on last edited by kshegunov
                #7

                @Dong said:

                But it seem to be "dummy" and I want to find some other way like (pointer / reference or something else)

                Well, you depend on what the library has provided for you, and since QVariant will not provide you with a reference you can't modify its contents directly. In all probability the variant type is correctly denying direct access (internally it a union in a struct) as the QVariant class can't be sure what exactly it's storing (it just holds a pointer to data). That's the reason you use template functions to convert from/to variant type.

                I'm more familiar with C# where all Object are reference type so we can modify it directly.

                This is true for FORTRAN as well, and is much error prone. Imagine when you pass an immutable string to a function. The function can change it at any point thus breaking the program stack. This is a classical example why FORTRAN is not type safe. C++ is a bit more evolved in that matter, providing you with copious amounts of ways to ensure that your types will not be corrupted by external means. C# of course is much cleaner than FORTRAN, and allows the variables to be passed as const, but in C++ the by value or by reference passing of arguments/objects is in the hands of the program designer and the language does not presume to know what you want to achieve.

                Read and abide by the Qt Code of Conduct

                1 Reply Last reply
                0
                • DongD Offline
                  DongD Offline
                  Dong
                  wrote on last edited by Dong
                  #8

                  @kshegunov :

                  Can you explain this?

                  //I can set the Name of item in list like this.
                  rootObj->property("ItemsSource").value<QList<QObject*> >()[3]->setProperty("Name", "New Campaign Name");
                  
                  //But I can't set an item to new object like this
                  rootObj->property("ItemsSource").value<QList<QObject*> >()[3] = rootObj->property("ItemsSource").value<QList<QObject*> >()[9];
                  
                  
                  Edit:
                  
                  I thought I found the answer:
                  As Kshegunov said: QVariant::value create a Shallow Copy of QList<QObject*> so
                     - This Shallow Copy list completely different with the original list.
                     - But the QObject* Pointer in that Copy List still point to the same addess as the Original Pointer.
                  
                  That why we can set individual Property, but cannot replace the Object.
                  kshegunovK 1 Reply Last reply
                  0
                  • DongD Dong

                    @kshegunov :

                    Can you explain this?

                    //I can set the Name of item in list like this.
                    rootObj->property("ItemsSource").value<QList<QObject*> >()[3]->setProperty("Name", "New Campaign Name");
                    
                    //But I can't set an item to new object like this
                    rootObj->property("ItemsSource").value<QList<QObject*> >()[3] = rootObj->property("ItemsSource").value<QList<QObject*> >()[9];
                    
                    
                    Edit:
                    
                    I thought I found the answer:
                    As Kshegunov said: QVariant::value create a Shallow Copy of QList<QObject*> so
                       - This Shallow Copy list completely different with the original list.
                       - But the QObject* Pointer in that Copy List still point to the same addess as the Original Pointer.
                    
                    That why we can set individual Property, but cannot replace the Object.
                    kshegunovK Offline
                    kshegunovK Offline
                    kshegunov
                    Moderators
                    wrote on last edited by kshegunov
                    #9

                    @Dong
                    Hello,
                    Sorry for the late reply. Yes, you've got the essence of it. Qt's containers (QList included) are pretty smart in respect to copying, they will not copy the actual data until you change it. They are implicitly shared. This is done so you can return and copy the container many times, but in actuality internally only a pointer is reassigned and reference counter updated. When you call a non-const function on that list, Qt checks the reference counter and if more than one object is attached to the data, then and only then the data is detached (copied). When you put your list in the QVariant it is stored by value (making a shallow copy), but QVariant will return a shallow copy as well (meaning the data will not be changed, only the internal pointer reassigned and reference counter incremented).

                    Now, for your particular case:
                    The first line of code works, because you don't modify the list, but take an element (which is a pointer) and modify the object the list is holding reference to. This doesn't cause the list data to be copied. The second line you have, doesn't work, because you're changing the list data (assigning a new value to a list's element), which causes the list data to be detached and in practice, you're operating on a completely different set of data.

                    Here is a reference if you're interested in the way QList and other containers manage their data, and what implicit sharing is.

                    Read and abide by the Qt Code of Conduct

                    1 Reply Last reply
                    0

                    • Login

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