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. How do you update QAbstructListModel item from outside a view?

How do you update QAbstructListModel item from outside a view?

Scheduled Pinned Locked Moved Solved General and Desktop
qabstractmodelnotify
6 Posts 2 Posters 531 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.
  • C Offline
    C Offline
    Curtwagner1984
    wrote on 8 Jun 2022, 08:43 last edited by
    #1

    Greetings.

    Suppose I have the following struct: (Pseudo code, please ignore syntax errors)

    struct: {
    QString: Stock Name,
    double: Stock Value
    }
    

    And I have a QAbstructListModel subclass that has a QList of those structs as the underlying model.

    Now let's say another part of my program connected to the internet and saw that "Stock A" has dropped 4 points and I want my model to reflect this, how should it be done?

    The SetData function in the QAbstructListModel subclass is expected to be used from a view and it expects a QModelIndex. And even if it didn't, There's no easy way to find Stock A inside the QAbstructListModel subclass.

    Should I search for "Stock A" struct in the model and then replace it with a new struct with new data and then call dataChanged signal?

    Or maybe I should also hold a pointer to 'Stock A' struct outside the QAbstructListModel and then modify it directly. And in make it emit a signal when it's changed. (Through properties) and connect this signal to the dataChanged signal inside the subclass of QAbstructListModel. This way I will be able to modify 'Stock A' from the pointer.

    Are those ways correct? Are there better ways?

    J 1 Reply Last reply 8 Jun 2022, 08:52
    0
    • C Curtwagner1984
      8 Jun 2022, 08:43

      Greetings.

      Suppose I have the following struct: (Pseudo code, please ignore syntax errors)

      struct: {
      QString: Stock Name,
      double: Stock Value
      }
      

      And I have a QAbstructListModel subclass that has a QList of those structs as the underlying model.

      Now let's say another part of my program connected to the internet and saw that "Stock A" has dropped 4 points and I want my model to reflect this, how should it be done?

      The SetData function in the QAbstructListModel subclass is expected to be used from a view and it expects a QModelIndex. And even if it didn't, There's no easy way to find Stock A inside the QAbstructListModel subclass.

      Should I search for "Stock A" struct in the model and then replace it with a new struct with new data and then call dataChanged signal?

      Or maybe I should also hold a pointer to 'Stock A' struct outside the QAbstructListModel and then modify it directly. And in make it emit a signal when it's changed. (Through properties) and connect this signal to the dataChanged signal inside the subclass of QAbstructListModel. This way I will be able to modify 'Stock A' from the pointer.

      Are those ways correct? Are there better ways?

      J Offline
      J Offline
      JonB
      wrote on 8 Jun 2022, 08:52 last edited by
      #2

      @Curtwagner1984 said in How do you update QAbstructListModel item from outside a view?:

      The SetData function in the QAbstructListModel subclass is expected to be used from a view

      Not particularly. QAbstractListModel::setData() is a method of the model which can be called from anywhere.

      Should I search for "Stock A" struct in the model and then replace it with a new struct with new data and then call dataChanged signal?

      Yes (you can just alter the double member without needing to create a new struct).

      and it expects a QModelIndex. And even if it didn't, There's no easy way to find Stock A inside the QAbstructListModel subclass.

      You need a QModelIndex if you want to access/update via the model's data/setData(). You can update the data directly in your backing data store without going via an index if you wish, but you will still need the QModelndex to issue the dataChanged() signal.

      One way or another you will need to know/find the QModelIndex for a given Stock Name. You might search sequentially if unordered, do a binary search if sorted alphabetically, or use a QMap for the Stock Names to map them to indexes.

      1 Reply Last reply
      0
      • C Offline
        C Offline
        Curtwagner1984
        wrote on 8 Jun 2022, 09:02 last edited by
        #3

        So to summarize:

        1. Find QModelIndex of the item in question.
        2. Call setData() with the QModelIndex and data you want to change. (Possibly only change he wanted data by specifing a role in the function)
        3. setData should emit datachanged signal with the given QModelIndex

        One question though? How do I get a QModelIndex of something?

        Let's say I have a QMap<QString,StockStruct> stocks in the submclass of QAbstructListmModel.
        How do I find the QModelIndex of stocks["Stock A"]?

        Do I need to have a list of QList<StockStruct> and then QMap<QString,int>
        And for each time I insert something into the model:

        void AddData(StockStruct stockStruct){
         this->_stockList.append(stockStruct);
        this->_stockNameMap.insert(stockStruct.name,this._stockList.indexOf(stockStruct));
        }
        

        ?

        J 1 Reply Last reply 8 Jun 2022, 10:57
        0
        • C Curtwagner1984
          8 Jun 2022, 09:02

          So to summarize:

          1. Find QModelIndex of the item in question.
          2. Call setData() with the QModelIndex and data you want to change. (Possibly only change he wanted data by specifing a role in the function)
          3. setData should emit datachanged signal with the given QModelIndex

          One question though? How do I get a QModelIndex of something?

          Let's say I have a QMap<QString,StockStruct> stocks in the submclass of QAbstructListmModel.
          How do I find the QModelIndex of stocks["Stock A"]?

          Do I need to have a list of QList<StockStruct> and then QMap<QString,int>
          And for each time I insert something into the model:

          void AddData(StockStruct stockStruct){
           this->_stockList.append(stockStruct);
          this->_stockNameMap.insert(stockStruct.name,this._stockList.indexOf(stockStruct));
          }
          

          ?

          J Offline
          J Offline
          JonB
          wrote on 8 Jun 2022, 10:57 last edited by JonB 6 Aug 2022, 10:58
          #4

          @Curtwagner1984
          Kind of, yes.

          First be clear: a QModelIndex is (from your point of view) just a row number (and column number within that row, but that's not relevant here). You need to be able to map that to/from your own backing data structure.

          Simplest is just to maintain your backing "array" in the same order as the row numbers in the Qt model, then they agree on row number.

          • Just how many stocks are you maintaining? A sequential search for name is fine if you have only a "handful" of stocks, then nothing else needs doing.

          • If you have a fair number, and you are frequently needing to look up a stock by its Stock Name, if you are prepared to sort your backing data alphabetically by Stock Name you can look that up quickly with a binary search of your array. But then you cannot just append() a new entry in AddData(), you must insert() in sorted order (or re-sort after any additions).

          • Or you can do it like you show. Maintaining one list/array indexed by/in row number order, and another structure (e.g. a QMap) for fast look up by key.

          Effectively a database with a primary key does the latter. It will not actually maintain/store the rows in PK order, as that would involve moving records around in storage on insert/delete/update PK, so it maintains an index into the data, like a QMap or a QHash, just to allow fast look up.

          1 Reply Last reply
          0
          • C Offline
            C Offline
            Curtwagner1984
            wrote on 8 Jun 2022, 12:55 last edited by
            #5

            Thank you, this helped me a lot, I've managed to successfully test this and it worked!

            I ended up doing a QList, QMap pair, not because I have a lot of rows, but because my data changes very frequently so quick lookups would be very helpful.

            I've run into another problem on the QML side though... (Maybe it warrants a separate question)

            I can manage to successfully update the UI when data changes using the dataChanged signal.

            However, on the QML side of things I've ran into a bit of a snag. Let's say I want to do several things when a stock drops below a certain threshold. And this state is a bool variable in the data struct let's say bIsStockBelowThreashold.

            So when this boolean changes I want to change the background color, set the text in different font and maybe play an animation.

            I'm a bit lost as to how I can tie those changes to the change in the data. For example if the role name for this data is 'IsStockBelowThreashold' I can write in the background area of my qml:

            Rect:{
              id:backgroundRect
             color: IsStockBelowThreashold == true ? "red":"green"
            }
            

            And then I can do the same in the Text object:

            Text:{
              id:panicText
             font.pixelSize: IsStockBelowThreashold == true ? 28:24
            }
            

            Meaning that in each area I want to react to "IsStockBelowThreashold" changing, I need to check them individually. I much rather write a single function that doing all those changes and trigger it on IsStockBelowThreashold changed. But I have no idea how to do that. Is that even possible?

            (I'm sorry if my explanation a bit all over the place).

            1 Reply Last reply
            0
            • C Offline
              C Offline
              Curtwagner1984
              wrote on 8 Jun 2022, 13:12 last edited by
              #6

              Ok, so I figured it out, you make a property and bind the role to this property:

              property var stockPanic: IsStockBelowThreashold 
              

              And then you can do:

              onStockPanicChanged:{
               functionThatChangesWhateverYouWant();
              }
              
              1 Reply Last reply
              0

              6/6

              8 Jun 2022, 13:12

              • Login

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