View not updating after appendRow
-
I attached the model directly to the view without a proxy (so only the DisplayRole is displayed, not my UserData). But the same problem happens even then. I can append a row to the model, but the view is still not updated to show the new row.
So the problem here is not the proxy, or connecting signals to the proxy model.
-
@Rizzer
Hmm.
Strange.
Did you browse the
http://doc.qt.io/qt-5/qtwidgets-itemviews-editabletreemodel-example.html
sample.
It seems to usebeginInsertRows(parent, position, position + rows - 1); endInsertRows();
(like you) and it updates. ?!
(no dataChanged )Can it be some sort of index problem ? You say it does actually update the model but
the view is clueless. So wonder if it can be something like that. -
In my case I'm only adding 1 row, so "rows-1" would cancel, "beginInsertRows(parent, position, position)". For me, "position=rowCount()", intended to indicate I'm appending at the end of the model.
Could there be a problem with parent? I'm not feeding any parent into my addEntry() function, I'm inferring a parent from firstIndex.parent(). I don't have a tree structure so I don't mean to have anything fancy with index parents.
-
You seem to be on the wrong track here. This
beginInsertRows(firstIndex.parent(),rowCount(),rowCount()); this->appendRow (newItem); endInsertRows();
is very wrong.
appendRow
already calls begin/end so calling it around the call to appendRows will most definitely screw up the view. Also you shouldn't emit adataChanged
signal. It's for when data of existing items changes, not when new data is added.layoutChanged()
is also for other purposes. This should be enough:void MyModel::addEntry(MyItem *newItem) { newItem->setFlags(Qt::ItemIsEditable|newItem->flags()); appendRow (newItem); }
If it's not then there's either something wrong with the connection or the view. Are you calling any disconnects on the model/view or
blockSignals()
at any point? Are you reimplementing any methods of the view? Is the item properly created when you add it (e.g. not on the stack and without parent)? Does it work with vanilla QTableView and QStandardItemModel? -
Thanks Chris. I've been trying to put together a complete minimal test project. But my test project is awkwardly failing to reproduce the problem (i.e. the test view does successfully show the new row). You're right, in the test model I only need to use appendRow(newItem) alone, without the extra signals.
I'm not using blockSignals. In my proxy in MyProxy::setSourceModel(newModel), if there's an existing sourceModel then I disconnect from the dataChanged signal from that sourceModel before calling QIdentityProxyModel::setSourceModel(newModel). Then I connect to dataChanged from newModel.
Apart from that, the only use of disconnect in my code is disconnecting the timeout of a QTimer (not related to adding rows).
In the view I'm reimplementing MyView::currentChanged(const QModelIndex ¤t, const QModelIndex &previous). I do that to set a data value before calling QTableView::currentChanged(current, previous).
I create the item in another function of MyModel using MyItem *newItem = new MyItem(), and then pass it to addEntry(newItem). I'm not certain if the stack and parent is correct. Certainly I didn't create it using, say, "new MyItem(this)". Should I be doing that? But I didn't do it in my minimal test project either, where the view is working.
-
@Rizzer said:
Should I be doing that?
On the contrary. The item is taken over by the model so you shouldn't give it a parent.
If it works with a simple example there's gotta be some glitch in your derived classes. Try to strip it down one by one until it works - first replace your item class with a QStandardItem, then the model and then the view. This should let you locate the faulty component.As for the proxy class - you said that it fails with or without it so it should not matter, but generally you don't need to manually connect/disconnect the dataChanged signal. It's done automatically by the classes provided in Qt. Unless of course you're connecting some customized methods of yours.
-
With the proxy, I'm converting a "1-column" model into a "2-column" model. I make proxy::data(index, role) with index.column=1 and role=Qt::DisplayRole return a user field drawn from the sourceModel (where column=0). When data in the sourceModel is updated, it emits dataChanged with column=0, so the view doesn't know about the update for column=1. So I connect to the dataChanged signal from the sourceModel and re-emit it for the proxy, altering proxyBottomRight to include column=1.
For the rest of it, you're right, it looks like I'll just have to trawl through each class step by step.
-
@Rizzer said:
I have a model subclassed from QStandardItemModel
Have you tried append rows using itemFromIndex ? something like this ?
QStandardItem *itemToAdd = new QStandardItem(itemName); model->itemFromIndex(modelIndex)->appendRow(itemToAdd);
-
-
It could be something in the Qt Designer ui form I was using. I've found that if I start afresh with a new form rebuilding the ui from scratch, then the view in the new ui does get updated straight away as expected.
I still don't know precisely what was driving the problem, but this "workaround" will do as a solution.