Need to modify a QList item, can List::operator[](int i) do it or is there something better?



  • Hello,
    I need to find and then modify an item in a list. I understand that "at" doesn't allow this, it uses the copy-write method instead of allowing modification. So I cam across the operator[] function which seems to describe what I want, but I am not getting the results insofar as allowing modification of the original item. Here's my function:
    void cap::logUpdate(QString step, int sessionItemIndex)
    {
    QList<workItemListEntry> *workItemListPtr = sessionItems[sessionItemIndex].select->workItemListPtr();
    workItemListEntry wi;
    for (int i=0; i < workItemListPtr->size(); i++) {
    if (workItemListPtr->at(i).survey == sessionItems[sessionItemIndex].survey) {
    wi = workItemListPtr->operator;
    break;
    }
    }
    wi.logWorkItemListEntryUpdate(step, sessionItems[sessionItemIndex].select);
    }

    (Note, that use of the "Ptr" for the list wasn't where I started and may not be helping, in debugging I added this in the event that the list itself was blocking the modification.)

    Here's my class (shortened from my real one so that it isn't to hard to review. It is the "updates" element that I'm trying to effect:
    class workItemListEntry
    {

    public:
    QList<workItemUpdate> updates;
    seriesSurvey *survey;
    int sessionItemIndex;

    workItemListEntry() {};

    void setSessionItemIndex(int index) { sessionItemIndex = index; }

    void setAge(QString str) { age = str; };
    const QString getAge() const { return age; };

    const QList<workItemUpdate> &getWorkItemUpdates() const;
    void setUpdates(const QList<workItemUpdate> &workItemUpdates) { updates = workItemUpdates; };

    void logWorkItemListEntryUpdate(QString step, QWidget *parent);

    private:
    QString age;
    };

    Last but not least, here is the member function being called:
    void workItemListEntry::logWorkItemListEntryUpdate(QString step, QWidget *parent) {
    QString name = getUserName();
    QString str = getISODateTime();
    this->updates.append(workItemUpdate(step, name, str));
    this->unsavedChanges = true;
    ((workItem *)parent)->logListProvenanceUpdate();
    }

    Anyone see my problem?
    Thank you,
    Andy


  • Qt Champions 2016

    hi
    code a bit hard to read when not formatted.

    you need to use &, i think

    struct workItemUpdate {
      int val;
    };
      workItemUpdate a;
      a.val = 100;
      QList<workItemUpdate> updates;
      updates.append(a);
       workItemUpdate& out = updates[0];
      out.val = 200;
      qDebug() << updates.at(0).val;
    `
    outputs 200


  • @mrjj Thank you; but in fact the actual update routine works when called from within the class, by another class member function. The problem occurs, when calling it from a function which is not a member of the class. Specifically, the logging function is a member of class "workItemListEntry", but in this case the function is called from a function in the class "cap". This might help expose the error - since it suggests something across class boundaries being the cause, rather than the function itself, which works as long as called within the class?


  • Qt Champions 2016

    @buckler
    well it should not matter if used across classes, (in same app)
    but depends on how you transfer the list or give access to the list ?

    You might make copy of list, if not careful.

    Try to transfer as * to list to be sure. & should also be good but * makes it hard
    to make copy as then normally "= " would just copy pointer, not whole list.
    So for test, use pointer to see if thats the case.



  • I am using pointer explicitly at the higher level workItemListPtr, and the point of using "operator[]" is to do this for an indiivdual QList item? (QList documentation reads "Returns the item at index position i as a modifiable reference. i must be a valid index position in the list (i.e., 0 <= i < size())."

    The problematic function is (with more care to the formatting, as I agree with you that it is impossible to read otherwise):

    void cap::logUpdate(QString step, int sessionItemIndex)
    {
         QList<workItemListEntry> *workItemListPtr = sessionItems[sessionItemIndex].select->workItemListPtr();
        workItemListEntry wi;
        for (int i=0; i < workItemListPtr->size(); i++) {
            if (workItemListPtr->at(i).survey == sessionItems[sessionItemIndex].survey) {
                wi = workItemListPtr->operator;
                break;
            } // end-if
        } // end-for
        wi.logWorkItemListEntryUpdate(step, sessionItems[sessionItemIndex].select);
    }
    

    [edit: added missing coding tags ``` SGaist]


  • Qt Champions 2016

    @buckler
    Ok so workItemListPtr(); does return pointer to list.
    Next question.
    is
    workItemListEntry wi;
    the item you change?
    Should it not be workItemListEntry &wi;
    as not to get copy ?

    also syntax for pointer to list to avoid the operator syntax is
    (*workItemListPtr)[i];
    You might have reason for operator so just a note.



  • I have tried a number of variations - including what you suggested as well as a form from another post, presently I have (with no improvement):

    void cap::logUpdate(QString step, int sessionItemIndex) 
    {
      QList<workItemListEntry> *workItemListPtr = sessionItems[sessionItemIndex].select->workItemListPtr();
      auto& wi = workItemListPtr->operator[](0);
      for (int i=0; i < workItemListPtr->size(); i++) {
        if (workItemListPtr->at(i).survey == sessionItems[sessionItemIndex].survey) {
          wi = workItemListPtr->operator[](i);
          break;
        }
      }
      wi.logWorkItemListEntryUpdate(step, sessionItems[sessionItemIndex].select);
    }
    

    I did add in a qDebug inside my logging function itself. I print out the actual address when it logs an update. In fact the pointer values are different when it works (i.e., the case of calling it from another function of the same class) vs. when it doesn't work (when calling it from the different class). Clearly, my attempt at pointing to the same memory isn't working.

    [edit: Added missing coding tags ``` SGaist]


  • Qt Champions 2016

    ok that does sound a bit strange
    If it possible you make copy of any other object along the way so you indirectly get new list that way?

    Like insert into other list that makes copy. ?
    QList<workItemUpdate> updates; this will be copies.

    Unless across process boundaries and dlls I have never had such issues.
    It must be something simple or very hard to detect.


  • Moderators

    @buckler Use a pointer:

    void cap::logUpdate(QString step, int sessionItemIndex) 
    {
      QList<workItemListEntry> *workItemListPtr = sessionItems[sessionItemIndex].select->workItemListPtr();
      workItemListEntry* wi = Q_NULLPTR;
      for (int i=0; i < workItemListPtr->size(); i++) {
        if (workItemListPtr->at(i).survey == sessionItems[sessionItemIndex].survey) {
          wi = &((*workItemListPtr)[i]);
          break;
        }
      }
      if (wi != Q_NULLPTR)
          wi->logWorkItemListEntryUpdate(step, sessionItems[sessionItemIndex].select);
    }
    

    And there is no need to call operator[](...) like you do, just use []



  • @jsulm Thank you! That did it! It is updating nicely now.


  • Moderators

    @buckler Glad to hear it works now :-)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.