Changing data in a Table Model
-
My data is now tucked away in a subclass of QAbstractTableModel.
The data is held within the model as a vector<MyStruct>, part of which looks like:
struct MyStruct{ bool m_bRemoved; uint16_t m_groupId; bool m_bUseAsStarting; CString m_strType; CString m_strPath; CString m_strFile; bool m_bRegistered;Some of these variables are not used for the TableView, so there is no entry for them in the data() member function (e.g. the first displayed column is derived from the CString m_strPath).
Now I want to change the model data from outside that model, but I don't believe that I have access to the QModelIndex for the displayed rows and columns, and for the non-display members of the structure, I don't think a model index could be used.
If I were to make the vector a public member of the model, I could then "break encapsulation" and update the MyStruct members in the vector. If I were to commit that heinous crime, is there a way to notify the views that the model data has been changed without having used setData()?
Is there a clean way to update arbitrary fields of that structure without breaking encapsulation?
-
Add a function to your custom model to set the data.
-
Add a function to your custom model to set the data.
Please could I ask you to elaborate some on that?
I have not (so far) made the vector public, but have provided iterators to allow me to access that data:
const_iterator cbegin()const { return mydata.begin(); } const_iterator cend()const { return mydata.end(); } iterator begin() { return mydata.begin(); } iterator end() { return mydata.end(); }where mydata is the vector<MyStruct>
So I can actually update the data - e.g.:
for (auto it = imageGroups[group].model.begin(); it != imageGroups[group].model.end(); ++it) { if (it.m_bChecked && it.IsLightFrame()) { CLightFrameInfo bmpInfo; bmpInfo.SetBitmap(it.m_strFileName, false, false); // Update list info if (bmpInfo.m_bInfoOk) { it.m_bRegistered = true; it.m_fOverallQuality = bmpInfo.m_fOverallQuality; it.m_fFWHM = bmpInfo.m_fFWHM; it.m_lNrStars = (LONG)bmpInfo.m_vStars.size(); it.m_bComet = bmpInfo.m_bComet; it.m_SkyBackground = bmpInfo.m_SkyBackground; } else { it.m_bRegistered = false; }; }; };but if I do that, there's still the issue of how to notify whoever needs to know that the model data has changed.
If that's not the approach you had in mind what sort of function were you thinking of?
Thank you
David -
@Perdrix said in Changing data in a Table Model:
I have not (so far) made the vector public, but have provided iterators to allow me to access that data:
use a custom function in your model.
there's still the issue of how to notify whoever need to know that the model data has changed.
It's properly documented: "When the data has been set, the model must let the views know that some data has changed. This is done by emitting the dataChanged() signal."
-
Please could I ask you to elaborate some on that?
I have not (so far) made the vector public, but have provided iterators to allow me to access that data:
const_iterator cbegin()const { return mydata.begin(); } const_iterator cend()const { return mydata.end(); } iterator begin() { return mydata.begin(); } iterator end() { return mydata.end(); }where mydata is the vector<MyStruct>
So I can actually update the data - e.g.:
for (auto it = imageGroups[group].model.begin(); it != imageGroups[group].model.end(); ++it) { if (it.m_bChecked && it.IsLightFrame()) { CLightFrameInfo bmpInfo; bmpInfo.SetBitmap(it.m_strFileName, false, false); // Update list info if (bmpInfo.m_bInfoOk) { it.m_bRegistered = true; it.m_fOverallQuality = bmpInfo.m_fOverallQuality; it.m_fFWHM = bmpInfo.m_fFWHM; it.m_lNrStars = (LONG)bmpInfo.m_vStars.size(); it.m_bComet = bmpInfo.m_bComet; it.m_SkyBackground = bmpInfo.m_SkyBackground; } else { it.m_bRegistered = false; }; }; };but if I do that, there's still the issue of how to notify whoever needs to know that the model data has changed.
If that's not the approach you had in mind what sort of function were you thinking of?
Thank you
David -
@Perdrix said in Changing data in a Table Model:
So is this just as simple as adding a slot in the model:
Yes but again: don't modify your data from outside the model. Add a proper function.
And don't emit a dataChanged for every cell when you only modify a row or less. -
Which brings me back to how that "proper function" should be written?
How would you implement that to achieve the changes I showed in my code snippet (which does break encapsulation and you quite rightly didn't like).
Apologies if I'm not seeing something that's obvious to you ...
D.
-
It depends on how you receive your data. I would simply pass the new MyStruct