From 10:00 CET Friday 22nd November we will adjust how the server works to deal with some recently reported problems. Therefore there may be a load problem, if you experience more problems than usual trying to access the forum then please PM AndyS or any of the moderators so they can inform me.


QStandardItemModel appendRow doesn't update QML TreeView


  • Lifetime Qt Champion

    What did you change in you subclass regarding QStandardItemModel ?



  • 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.


  • Lifetime Qt Champion

    How/where are you appending rows outside the constructor ?



  • 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.



  • Do I need to tell my view somehow that the model got updated?


  • Lifetime Qt Champion

    I'd emit dataChanged with the new index passing your custom roles.



  • I added emit dataChanged(QModelIndex(), QModelIndex(), roles); after my appendRow, which should update the whole view(?), but it still doesn't work.



  • 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;
    }
    

  • Lifetime Qt Champion

    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.



  • Okay, tried it with emit dataChanged(invisibleRootItem()->index(), rootEntry->index(), vector); which should work, but it doesn't.



  • Or at least I think that should update everything from the root item to the newly created entry.


  • Lifetime Qt Champion

    How are you adding that new row outside the constructor ?



  • With the appendRow() method (on the invisible root item) as mentioned earlier.


  • Lifetime Qt Champion

    I meant, where are you calling appendRow ?



  • In a function that is called in response to a button click. (that function calls addRootItem multiple times)



  • What about using beginInsertRows() / endInsertRow() ?



  • That doesn't seem to work either.



  • Does anyone know of some piece of sample code for a dynamic model with Qt Quick and QStandardItemModel where you can add rows and edit items after the construction?



  • Oh, Damnit. I had a ProjectTreeViewModel { id:projecttreeviewmodel } in my UI components and used that instead of my treeviewmodel added as a context property.


  • Lifetime Qt Champion

    Sneaky one !

    Glad you found out :)