QStandardItemModel appendRow doesn't update QML TreeView
-
wrote on 23 Apr 2016, 17:10 last edited by
Hey, adding an item into my subclassed QStandardItemModel works perfectly fine when using appendRow in the constructor of the model, however it works nowhere else. The items are to the model when added to the invisibleRootItem, but they are not shown in the tree. Do I need to update the TreeView manually somehow?
-
wrote on 23 Apr 2016, 21:07 last edited by
No idea?
-
Hi,
Please practice some patience, allow 24 hours before bumping your own thread. Not all people on this forum live in the same timezone as you.
Did you follow the example about [Inserting and removing rows](http://doc.qt.io/qt-5/model-view-programming.html ?
-
wrote on 23 Apr 2016, 22:40 last edited by
I guess? Do I need to reimplement insertRows? If so, how does that work for my QStandardItems?
-
What did you change in you subclass regarding QStandardItemModel ?
-
wrote on 23 Apr 2016, 22:49 last edited by
Nothing apart from custom roles I use in childEntry->setData.
class ProjectTreeModel : public QStandardItemModel { Q_OBJECT public: explicit ProjectTreeModel(QObject *parent = 0); virtual ~ProjectTreeModel() = default; Q_INVOKABLE QString initializeModel(QString dirLoation); enum ProjectTreeModel_Roles { ProjectTreeModel_Role_Name = Qt::DisplayRole, ProjectTreeModel_Role_Type = Qt::WhatsThisRole, ProjectTreeModel_Role_Icon = Qt::DecorationRole }; QHash<int, QByteArray> roleNames() const override; private: void addChildEntry( const QString& name, const QString& type, const QString& icon, QStandardItem parent); void addRootEntry( const QString& name, const QString& type, const QString& icon); QHash<int, QByteArray> m_roleNameMapping; };
This is my class, so as you can see there is nothing really done with it.
-
How/where are you appending rows outside the constructor ?
-
wrote on 23 Apr 2016, 22:57 last edited by
In the addRootEntry (and later in the addChildEntry where it should add a child to a given QStandardItem) in reaction to a button press.
auto rootEntry = new QStandardItem( name ); rootEntry->setData( icon, ProjectTreeModel_Role_Icon ); rootEntry->setData( type, ProjectTreeModel_Role_Type ); rootEntry->setData( name, ProjectTreeModel_Role_Name ); invisibleRootItem()->appendRow(rootEntry);
This is what it does.
-
wrote on 24 Apr 2016, 16:19 last edited by
Do I need to tell my view somehow that the model got updated?
-
I'd emit dataChanged with the new index passing your custom roles.
-
wrote on 24 Apr 2016, 20:26 last edited by
I added emit dataChanged(QModelIndex(), QModelIndex(), roles); after my appendRow, which should update the whole view(?), but it still doesn't work.
-
wrote on 24 Apr 2016, 20:31 last edited by
This is my whole class right now, in case that helps:
ProjectTreeModel::ProjectTreeModel(QObject *parent) : QStandardItemModel(parent) { m_roleNameMapping[ProjectTreeModel_Role_Name] = "name_role"; m_roleNameMapping[ProjectTreeModel_Role_Type] = "type_role"; m_roleNameMapping[ProjectTreeModel_Role_Icon] = "icon_role"; } void ProjectTreeModel::addRootEntry( const QString& name, const QString& type, const QString& icon) { auto rootEntry = new QStandardItem( name ); rootEntry->setData( icon, ProjectTreeModel_Role_Icon ); rootEntry->setData( type, ProjectTreeModel_Role_Type ); rootEntry->setData( name, ProjectTreeModel_Role_Name ); invisibleRootItem()->appendRow(rootEntry); qDebug() << rootEntry; qDebug() << this->rowCount(); QVector<int> vector(0); vector.append(ProjectTreeModel_Role_Icon); vector.append(ProjectTreeModel_Role_Type); vector.append(ProjectTreeModel_Role_Name); emit dataChanged(QModelIndex(), QModelIndex(), vector); } QHash<int, QByteArray> ProjectTreeModel::roleNames() const { return m_roleNameMapping; }
-
AFAIK, no. You are passing two invalid indexes. If you want to trigger a refresh, give the top left and bottom right indexes of the part of the model that should get refreshed on the view.
-
wrote on 25 Apr 2016, 06:56 last edited by
Okay, tried it with emit dataChanged(invisibleRootItem()->index(), rootEntry->index(), vector); which should work, but it doesn't.
-
wrote on 25 Apr 2016, 17:37 last edited by
Or at least I think that should update everything from the root item to the newly created entry.
-
How are you adding that new row outside the constructor ?
-
wrote on 25 Apr 2016, 21:20 last edited by
With the appendRow() method (on the invisible root item) as mentioned earlier.
-
I meant, where are you calling appendRow ?
-
wrote on 26 Apr 2016, 04:52 last edited by
In a function that is called in response to a button click. (that function calls addRootItem multiple times)
-
wrote on 26 Apr 2016, 07:50 last edited by Orkblutt
What about using beginInsertRows() / endInsertRow() ?
8/24