Solved How to modify the data in the model and update the view when new data is received from external?
-
Re-implement
setData
-
@SGaist: How would i provide the index values? I am really sorry, because somehow i am not able to understand this trick of updating my data (categories_) in model, i.e. how do i get index from my data and call setData? I would really appreciate if you could show in my code? This would then later emit dataChanged which will achieve my goal.
-
How exactly are you getting new data ?
What are these new data ?
One object update ?
Several objects update ?
How do they fit in your model internal representation ? -
@SGaist : I am getting this data when user clicks left mouse button. I have slot, so when user clicks button some magic is done and later i save in model member variable Info_.
The NewStructInfo looks like this:
struct NewStructInfo{
double x;
double y;
} Info_;
So now my model data categories_ looks something like this:
```
Property ----------------------------------------- Value
-->Coordinates(categoryitem pointer)
------X (scenariopropertyitem1 pointer type) ------ "Empty"
------Y (scenariopropertyitem pointer type) -------- "Empty"The above structure you can see in parsejsonobject member function. Now in the above categories_ model data i have iterate along category->secnariopropertyitem and look for the name i,e,
if(scenariopropertyitem->name == x)
// scenariopropertyitem pointer has name as class member
scenariopropertyitem->setValue(QVariant(Info_.X));
Now somehow dataChanged(??,??,Qt::displayrole) has to be called. -
Since you have to go through your model to find the correct item to update, you should already have the index matching the
scenariopropertyitem
you found, no ? -
@SGaist : How would i access it or get the index of the item? Meanwhile would you suggest me to use third option from this answer: https://stackoverflow.com/questions/29921041/getting-the-index-for-a-given-item-in-a-qtreeview-model-application.
Could you provide an example? -
This post is deleted! -
This post is deleted! -
What I always suggest is that if you are not 100% confident in your model design (and, believe me, it's a hard) just use
QAbstractItemModel* model = new QStandardItemModel(parent)
. Then use insertRows, insertColumns, and setData to setup your model -
In my Model.cpp i did the following:
emit beginResetModel(); for (auto& category : categories_) { category->entryAt(0)->setValue(1); // for testing i just set randomly my data value to 1 } emit endResetModel();
But after above changes the view is not displaying the new values.
-
@VInay123
I don't see anyentryAt()
function in Qt. So what type iscategory
, what doescategory->entryAt(0)->setValue(1)
do in the way of setting anything in the model?? -
@JonB: If you see my code Category is a class which has entryAt() function which returns back the propertyitem. So here i am setting the model data i.e. my categories_ member variable in the model class.
-
@VInay123
OK forentryAt()
. But where in your code doesentryAt(0)->setValue(1)
callQAbstractModel::setData()
(http://doc.qt.io/qt-5/qabstractitemmodel.html#setData)? Where is the http://doc.qt.io/qt-5/qabstractitemmodel.html#dataChanged signal being emitted? -
@JonB: That is the problem i am facing. I do not know how to call setData which in turn emits the signal dataChanged. I do not know how to get the indexes. Here the data is only coming from the "Info_" variable. If the it was via delegates or adapters i could easily get the indexes and call setData. But in my case i get in a structure and go through each item and update its value. Could you please show me how can i achieve this in my code i.e. change the value via setData?
-
@VInay123
Your code is way too big for me to wade through.-
If you are using
QAbstractModel
, you are using a model which holds data in rows & columns, right? -
When you put some data (received from JSON parsing or whatever), you have to decide where in the model's row/column you want to put this data, right?
-
Given that
row
&column
, you can construct aQModelIndex()
(http://doc.qt.io/qt-5/qabstractitemmodel.html#createIndex) for the data. -
Then you can pass that to your
Model::setData()
to set the value, andemit dataChanged(index, index)
to notify your view to update.
-
-
@JonB : Thank you. I implemented as following in my model:
QModelIndex index = createIndex(1, 1, categories_[0]->entryAt(0)); this->setData(index, 11, Qt::EditRole);
It is changing the value clearly. But in the view its not being displayed.
-
@VInay123
Well at least we're getting somewhere! Check the return result of yoursetData()
, maybe it's failing? Does (row, column) of (1, 1) exist in your model (else you need toinsertRows()
etc.)? Is thatsetData()
call indeed going into yourModel::setData()
and doing theemit dataChanged()
there (use a debugger or debug/print statements)? There's no point using bothbeginResetModel()
&dataChanged()
, and certainly notdataChanged()
while still inside thebeginResetModel()
before thenedRestModel()
. Change your code accordingly. -
@VInay123 said in How to modify the data in the model and update the view when new data is received from external?:
CategoryItem& parentItem = currentItem->parentItem();
return createIndex(currentItem->row(), 0, &parentItem);This is using the address of a temp item, it will not work.
QString data = file.readAll();
does not handle win/lunix line endings and encodings, use QString data = QTextStream(&file).readAll();
Use the model test to make sure your subclass works correctly
-
@JonB: Yes, I just call the setData ane here i have printed the changed:
if (role == Qt::EditRole && index.column() == 1 && index.isValid()) { auto currentItem = static_cast<ScenarioPropertyItem*>(index.internalPointer()); if (currentItem) { currentItem->setValue(value); qDebug() << currentItem->data(index.column()); emit dataChanged(index, index); return true; } }
The value is being changed here. The output looks like
QVariant(int, 11)
I have included a debug output in Data() but this is printing the default values that is empty("").
QVariantModel::data(const QModelIndex& index, int role /*= Qt::DisplayRole*/) const { if (!index.isValid()) { return QVariant(); } if (role == Qt::DisplayRole && isCategory(index)) { const auto currentCategory = static_cast<CategoryItem*>(index.internalPointer()); if (index.column() == 0) { return currentCategory->displayName(); } else { return QVariant(); } } const auto currentItem = static_cast<ScenarioPropertyItem*>(index.internalPointer()); if (role == Qt::DisplayRole && !isCategory(index)) { qDebug() << currentItem->data(index.column()); // Here its empty return currentItem->data(index.column()); } return QVariant(); }
-
@VInay123
At this point I don't know any more. Maybe someone else does. We have described how things work. You might like to set up a tiny much simplified example to test how it all works, or look on the web for other examples and start from there.