Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. TreeView not updating after a dataChanged signal
Forum Updated to NodeBB v4.3 + New Features

TreeView not updating after a dataChanged signal

Scheduled Pinned Locked Moved Solved General and Desktop
11 Posts 4 Posters 1.9k Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • C Offline
    C Offline
    Coubz
    wrote on last edited by
    #1

    Everything is in the title, i have a treeview displaying a custom model.
    I'm trying to edit some data in it but the dataChanged signal doesn't seems to work.

    I've tried with the begin/endResetModel which is working fine.
    I also noticed that the edited field is updating if I hide it thew reshow it by dragging the treeview out of the layer (as the content of the treeview draggable).

    I've also tried to send the signal on the root or on the parents.
    Things like that :

                QModelIndex rootIndex = createIndex(0, 0, m_root);
                QModelIndex rootIndex2 = createIndex(m_root->childCount(), m_root->columnCount(), m_root);
                emit dataChanged(rootIndex, rootIndex2);
    

    but with no results.

    I'm pretty sure there is some subtilty i didn't get but i can't find out so i need your help =)

    Here's a simplified version of what i'm doing :
    -In my tree model :

    bool MapMarkerTreeModel::setData(const QModelIndex& _index, const QVariant& _value, int _role/* = Qt::EditRole*/)
    {
        if (!_index.isValid())
        {
            return false;
        }
    
        if(MapMarkerTreeItem* item = getItem(_index))
        {
            if(item->setData(_value, _role))
            {
    //            beginResetModel(); <----- This is working
    //            endResetModel();
                emit dataChanged(_index, _index); // <----- This isn't
    
                return true;
            }
        }
    
        return false;
    }
    

    -Also in my tree model, index and parent methods :

    QModelIndex MapMarkerTreeModel::index(const MapMarkerTreeItem* _item) const
    {
        QModelIndex index{};
        if(_item != nullptr)
        {
            index = createIndex(_item->childNumber(), 0, _item);
        }
    
        return index;
    }
    
    QModelIndex MapMarkerTreeModel::parent(const QModelIndex& _index) const
    {
        if (!_index.isValid() || m_root == nullptr)
        {
            return QModelIndex();
        }
    
        MapMarkerTreeItem* childItem = getItem(_index);
        MapMarkerTreeItem* parentItem = childItem ? childItem->parent() : nullptr;
    
        if (!parentItem)
        {
            return QModelIndex();
        }
    
        return createIndex(parentItem->childNumber(), 0, parentItem);
    }
    

    I'm not sure what else I can provide for context, if anything can help please tell me.
    And thanks in advance !

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

      One thing you can do is use the QAbstractItemModelTester class to check that your implementation works as expected.

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      C 1 Reply Last reply
      2
      • SGaistS SGaist

        Hi,

        One thing you can do is use the QAbstractItemModelTester class to check that your implementation works as expected.

        C Offline
        C Offline
        Coubz
        wrote on last edited by Coubz
        #3

        @SGaist Yep I've tryed that already.
        It shown me some issues that i've corrected but the datachanged(...) still doesn't do anything.
        One noticeable fix was to return an invalid QModelIndex with the parent method when the parent is the root node of the tree.
        Is there a way to be able to break in the TreeView code to follow the signal reception an see what's wrong?

        1 Reply Last reply
        0
        • C Offline
          C Offline
          Coubz
          wrote on last edited by
          #4

          Is it possible that i miss something to set the TreeView as "dirty" ?
          The TreeView or an other Qml element that contains it, or the items inside the view maybe.
          It's weird because as i said if i drag the view to move the text of the items outside of the windows thay will update.

          Currently the hierarchy is something like that :

          ApplicationWindow
              Rectangle
                  GridLayout
                      Item
                          ColumnLayout
                              Item
                                  Rectangle
                                      TreeView
                                          TreeViewDelegate
                                              Row
                                                  CheckBox
                                                  Text
          
          Christian EhrlicherC JonBJ 2 Replies Last reply
          0
          • C Coubz

            Is it possible that i miss something to set the TreeView as "dirty" ?
            The TreeView or an other Qml element that contains it, or the items inside the view maybe.
            It's weird because as i said if i drag the view to move the text of the items outside of the windows thay will update.

            Currently the hierarchy is something like that :

            ApplicationWindow
                Rectangle
                    GridLayout
                        Item
                            ColumnLayout
                                Item
                                    Rectangle
                                        TreeView
                                            TreeViewDelegate
                                                Row
                                                    CheckBox
                                                    Text
            
            Christian EhrlicherC Online
            Christian EhrlicherC Online
            Christian Ehrlicher
            Lifetime Qt Champion
            wrote on last edited by
            #5

            Your dataChanged() is wrong somehow. Minimize your code, remove qml and use a simple QTreeView until you can either reproduce it in a minimal compilable example or find your bug. The models work correct and don't need a special update except dataChanged() when some data changes inside the model.

            Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
            Visit the Qt Academy at https://academy.qt.io/catalog

            1 Reply Last reply
            1
            • C Coubz

              Is it possible that i miss something to set the TreeView as "dirty" ?
              The TreeView or an other Qml element that contains it, or the items inside the view maybe.
              It's weird because as i said if i drag the view to move the text of the items outside of the windows thay will update.

              Currently the hierarchy is something like that :

              ApplicationWindow
                  Rectangle
                      GridLayout
                          Item
                              ColumnLayout
                                  Item
                                      Rectangle
                                          TreeView
                                              TreeViewDelegate
                                                  Row
                                                      CheckBox
                                                      Text
              
              JonBJ Offline
              JonBJ Offline
              JonB
              wrote on last edited by
              #6

              @Coubz
              I agree with @Christian-Ehrlicher. I would suspect the dataChanged() signal itself is fine and being acted on, but somehow the indexes are not what you think they are so it does not redraw the right thing?

              1 Reply Last reply
              0
              • C Offline
                C Offline
                Coubz
                wrote on last edited by Coubz
                #7

                I've managed to make it work, i'm not exactly sure to understand why tho.
                I had to change the way the setData reacts :

                bool MapMarkerTreeModel::setData(const QModelIndex& _index, const QVariant& _value, int _role/* = Qt::EditRole*/)
                {
                    if (!_index.isValid())
                    {
                        return false;
                    }
                
                    if(MapMarkerTreeItem* item = getItem(_index))
                    {
                        if(item->setData(_value, _role))
                        {
                            //emit dataChanged(_index, _index); // <-----  Previous version
                
                            QList<int> roles{Qt::DisplayRole, Qt::EditRole, _role};
                            QModelIndex id = createIndex(_index.row(), item->getColumnIdFromRole(_role), item);
                            emit dataChanged(id, id, roles);
                            return true;
                        }
                    }
                
                    return false;
                }
                

                So it seems that the dataChanged signals have to build the role into the column of the ID else it won't refresh properly.
                I thought the role param of the signal would be able to do the trick but i think there is something i didn't understood here.

                JonBJ SGaistS 2 Replies Last reply
                0
                • C Coubz

                  I've managed to make it work, i'm not exactly sure to understand why tho.
                  I had to change the way the setData reacts :

                  bool MapMarkerTreeModel::setData(const QModelIndex& _index, const QVariant& _value, int _role/* = Qt::EditRole*/)
                  {
                      if (!_index.isValid())
                      {
                          return false;
                      }
                  
                      if(MapMarkerTreeItem* item = getItem(_index))
                      {
                          if(item->setData(_value, _role))
                          {
                              //emit dataChanged(_index, _index); // <-----  Previous version
                  
                              QList<int> roles{Qt::DisplayRole, Qt::EditRole, _role};
                              QModelIndex id = createIndex(_index.row(), item->getColumnIdFromRole(_role), item);
                              emit dataChanged(id, id, roles);
                              return true;
                          }
                      }
                  
                      return false;
                  }
                  

                  So it seems that the dataChanged signals have to build the role into the column of the ID else it won't refresh properly.
                  I thought the role param of the signal would be able to do the trick but i think there is something i didn't understood here.

                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by JonB
                  #8

                  @Coubz
                  You posted this topic in General and Desktop rather than https://forum.qt.io/category/12/qml-and-qt-quick. I assumed you were talking about a Qt widgets QTreeView. Are you in fact using QML and its TreeView? You never mentioned QML....

                  1 Reply Last reply
                  0
                  • C Coubz

                    I've managed to make it work, i'm not exactly sure to understand why tho.
                    I had to change the way the setData reacts :

                    bool MapMarkerTreeModel::setData(const QModelIndex& _index, const QVariant& _value, int _role/* = Qt::EditRole*/)
                    {
                        if (!_index.isValid())
                        {
                            return false;
                        }
                    
                        if(MapMarkerTreeItem* item = getItem(_index))
                        {
                            if(item->setData(_value, _role))
                            {
                                //emit dataChanged(_index, _index); // <-----  Previous version
                    
                                QList<int> roles{Qt::DisplayRole, Qt::EditRole, _role};
                                QModelIndex id = createIndex(_index.row(), item->getColumnIdFromRole(_role), item);
                                emit dataChanged(id, id, roles);
                                return true;
                            }
                        }
                    
                        return false;
                    }
                    

                    So it seems that the dataChanged signals have to build the role into the column of the ID else it won't refresh properly.
                    I thought the role param of the signal would be able to do the trick but i think there is something i didn't understood here.

                    SGaistS Offline
                    SGaistS Offline
                    SGaist
                    Lifetime Qt Champion
                    wrote on last edited by
                    #9

                    @Coubz well, once you mention using QML it starts to make sense.

                    QML uses custom roles to access data hence if you don't tell dataChanged that the data corresponding to these roles has changed, then there's no reason for the view to update.

                    Interested in AI ? www.idiap.ch
                    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                    1 Reply Last reply
                    1
                    • C Offline
                      C Offline
                      Coubz
                      wrote on last edited by
                      #10

                      Yes i do use QML sorry.
                      So what you're saying is that if you use QML the roles handled on the code side are irrelevant ?
                      It seems a bit weird as if a edit a values at runtime i do get the proper role in the setData callback.
                      It just that i've neglected the column of the index because i was thinking that the view won't be needing it as it had the role. And because the setData callback have an index without the column setup when trigged by edition.

                      SGaistS 1 Reply Last reply
                      0
                      • C Coubz

                        Yes i do use QML sorry.
                        So what you're saying is that if you use QML the roles handled on the code side are irrelevant ?
                        It seems a bit weird as if a edit a values at runtime i do get the proper role in the setData callback.
                        It just that i've neglected the column of the index because i was thinking that the view won't be needing it as it had the role. And because the setData callback have an index without the column setup when trigged by edition.

                        SGaistS Offline
                        SGaistS Offline
                        SGaist
                        Lifetime Qt Champion
                        wrote on last edited by
                        #11

                        Quite the contrary, proper role handling is paramount to have a correctly working model view implementation.

                        Interested in AI ? www.idiap.ch
                        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                        1 Reply Last reply
                        0
                        • C Coubz has marked this topic as solved on

                        • Login

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • Users
                        • Groups
                        • Search
                        • Get Qt Extensions
                        • Unsolved