How to modify the data in the model and update the view when new data is received from external?
-
This post is deleted!
-
-
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.
-
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.
-
@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? -
@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?
-
@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.
-
-
@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.
-
-
@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
-
@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.@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(); }
-
@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 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
@VRonin: With the test i got an error:
// Common error test #2, make sure that a second level index has a parent // that is the first level index.
What does above mean and how does it fit in my code?
-
@VRonin: With the test i got an error:
// Common error test #2, make sure that a second level index has a parent // that is the first level index.
What does above mean and how does it fit in my code?
@VInay123 said in How to modify the data in the model and update the view when new data is received from external?:
What does above mean and how does it fit in my code?
It means that if
model->hasChildren(parent)
is true thenindex(0,0,parent).isValid()
must be true andindex(0,0,parent).parent()==parent
.
One of these 2 conditions is violated in your model.Again I strongly suggest you use
QStandardItemModel
rather than wasting time reimplementing your own -
@VInay123 said in How to modify the data in the model and update the view when new data is received from external?:
What does above mean and how does it fit in my code?
It means that if
model->hasChildren(parent)
is true thenindex(0,0,parent).isValid()
must be true andindex(0,0,parent).parent()==parent
.
One of these 2 conditions is violated in your model.Again I strongly suggest you use
QStandardItemModel
rather than wasting time reimplementing your own@VRonin: My class looks good:
QModelIndex Model::parent(const QModelIndex& index) const { if (!index.isValid()) { return QModelIndex(); } if (isCategory(index)) { return QModelIndex(); } const auto currentItem = static_cast<ScenarioPropertyItem*>(index.internalPointer()); CategoryItem& parentItem = currentItem->parentItem(); return createIndex(currentItem->row(), 0, &parentItem); // Here the row is always 1.. is it right?? }
int Model::rowCount(const QModelIndex& parent /*= QModelIndex()*/) const { if (parent.column() > 0) { return 0; } if (!parent.isValid()) { return static_cast<int>(categories_.size()); } if (isCategory(parent)) { const auto currentCategory = static_cast<CategoryItem*>(parent.internalPointer()); return currentCategory->entryCount(); } return 0; }
int Model::columnCount(const QModelIndex& parent /*= QModelIndex()*/) const { return 2; }
Coordinates are my categories and S, T are scenariopropertiesitem. Items has category as parents. Categories dont have parents.
-
@VRonin: My class looks good:
QModelIndex Model::parent(const QModelIndex& index) const { if (!index.isValid()) { return QModelIndex(); } if (isCategory(index)) { return QModelIndex(); } const auto currentItem = static_cast<ScenarioPropertyItem*>(index.internalPointer()); CategoryItem& parentItem = currentItem->parentItem(); return createIndex(currentItem->row(), 0, &parentItem); // Here the row is always 1.. is it right?? }
int Model::rowCount(const QModelIndex& parent /*= QModelIndex()*/) const { if (parent.column() > 0) { return 0; } if (!parent.isValid()) { return static_cast<int>(categories_.size()); } if (isCategory(parent)) { const auto currentCategory = static_cast<CategoryItem*>(parent.internalPointer()); return currentCategory->entryCount(); } return 0; }
int Model::columnCount(const QModelIndex& parent /*= QModelIndex()*/) const { return 2; }
Coordinates are my categories and S, T are scenariopropertiesitem. Items has category as parents. Categories dont have parents.
@VInay123 said in How to modify the data in the model and update the view when new data is received from external?:
My class looks good:
It doesn't. as I mentioned above
@VRonin 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.
-
@VInay123 said in How to modify the data in the model and update the view when new data is received from external?:
My class looks good:
It doesn't. as I mentioned above
@VRonin 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.
@VRonin: Oh.. How could this be fixed? I have to stick to QAbstractItemModel.
This is from Qt:
-
My row method was wrong and after updating i have a new failure in the test:
// Check that we can get back our real parent. //qDebug() << "TTT 1: " << model->parent(index); //qDebug() << "TTT 2: " << parent; //qDebug() << "TTT 3: " << index; tmp = model->parent(index); Q_ASSERT(tmp == parent);
At the above point i.e. line 375 its failing.
My old row function in item used to always give 1 which was wrong. Now i made it to look at the parent and find the position.int ScenarioPropertyItem::row() const { int count = parentItem_.entryCount(); for (int i = 0; i < count; i++) { if (this->displayName_ == parentItem_.entryAt(i)->displayName_) { return i; } } }
-
My row method was wrong and after updating i have a new failure in the test:
// Check that we can get back our real parent. //qDebug() << "TTT 1: " << model->parent(index); //qDebug() << "TTT 2: " << parent; //qDebug() << "TTT 3: " << index; tmp = model->parent(index); Q_ASSERT(tmp == parent);
At the above point i.e. line 375 its failing.
My old row function in item used to always give 1 which was wrong. Now i made it to look at the parent and find the position.int ScenarioPropertyItem::row() const { int count = parentItem_.entryCount(); for (int i = 0; i < count; i++) { if (this->displayName_ == parentItem_.entryAt(i)->displayName_) { return i; } } }