Results 1 to 6 of 6

Thread: How to update items in a QTreeView

  1. #1
    Join Date
    Aug 2009
    Posts
    23
    Thanks
    3

    Default How to update items in a QTreeView

    Hi all,

    I am a newbie using Qt and I am stuck with this problem. Let me resume ...

    I am trying to display a tree containing nodes representing resource items.
    Those items have several attributes (image id, ...) and booleans such as resourceVisible [true|false].

    I am able to display the tree with icons representing my booleans (using a delegate). I also use a QSortFilterProxyModel to filter the rows.

    Now I would like to update the model when the user click on the icon representing the boolean resourceVisible. But I can't have it work :-\

    Here is my program

    Structure defining a resource:

    Qt Code:
    1. struct ResourceTreeItem {
    2.  
    3. ResourceTreeItem(std::string resourceID=""):m_resourceID(resourceID), m_resourceVisible(true), m_contentVisible(true),
    4. m_boundaryBoxVisible(true), m_mosaicked(true), m_IDVisible(true) {}
    5.  
    6. ResourceTreeItem(const ResourceTreeItem& copy): m_resourceID(copy.m_resourceID), m_resourceVisible(copy.m_resourceVisible), m_contentVisible(copy.m_contentVisible),
    7. m_boundaryBoxVisible(copy.m_boundaryBoxVisible), m_mosaicked(copy.m_mosaicked), m_IDVisible(copy.m_IDVisible) {}
    8.  
    9. std::string m_resourceID;
    10. bool m_resourceVisible;
    11. bool m_contentVisible;
    12. bool m_boundaryBoxVisible;
    13. bool m_mosaicked;
    14. bool m_IDVisible;
    15. };
    To copy to clipboard, switch view to plain text mode 

    A node (based on Editable Tree Model Example):

    Qt Code:
    1. class ResourceTreeNode {
    2. public:
    3. ResourceTreeNode(const ResourceTreeItem& data, ResourceTreeNode* parent = 0);
    4. ~ResourceTreeNode();
    5.  
    6. QVariant data(int column) const;
    7. bool setData(int column, const QVariant& value);
    8. ResourceTreeNode* child(int number);
    9. ResourceTreeNode* parent();
    10.  
    11. int childCount() const;
    12. int childNumber() const;
    13. bool insertChildren(int position, int count, ResourceTreeItem resourceTreeItem);
    14. bool removeChildren(int position, int count);
    15.  
    16. private:
    17. ResourceTreeNode* m_parent;
    18. ResourceTreeItem m_resourceTreeItem;
    19. QList<ResourceTreeNode*> m_childrens;
    20.  
    21. };
    To copy to clipboard, switch view to plain text mode 

    A custom model (also based on Editable Tree Model Example):

    Qt Code:
    1. class QResourceTreeModel : public QAbstractItemModel
    2. {
    3. Q_OBJECT
    4.  
    5. public slots:
    6. void itemClicked(const QModelIndex &index);
    7.  
    8. public:
    9. static const int NB_COLUMN = 6;
    10.  
    11. QResourceTreeModel(QObject *parent = 0) : QAbstractItemModel(parent), m_root(0) {}
    12. QResourceTreeModel(ResourceTreeNode* root, QObject *parent = 0) : QAbstractItemModel(parent), m_root(root) {}
    13.  
    14. void setRootNode(ResourceTreeNode* node);
    15.  
    16. QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const;
    17. QModelIndex parent(const QModelIndex& index) const;
    18.  
    19.  
    20. int rowCount(const QModelIndex &parent = QModelIndex()) const;
    21. int columnCount(const QModelIndex &parent = QModelIndex()) const;
    22.  
    23. QVariant data(const QModelIndex &index, int role) const;
    24. QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
    25.  
    26. private:
    27. ResourceTreeNode* getNode(const QModelIndex& index) const;
    28. ResourceTreeNode* m_root;
    29. };
    To copy to clipboard, switch view to plain text mode 

    Basically I connect the signal clicked(const QModelIndex &) to my slot itemClicked(const QModelIndex &index) so I can update the corresponding cell in the tree.

    Here is some key methods ...

    Qt Code:
    1. QVariant ResourceTreeNode::data(int column) const
    2. {
    3. switch (column) {
    4. case 0:
    5. return QVariant(m_resourceTreeItem.m_resourceVisible);
    6. case 1:
    7. return QVariant(m_resourceTreeItem.m_resourceID.c_str());
    8. case 2:
    9. return QVariant(m_resourceTreeItem.m_contentVisible);
    10. case 3:
    11. return QVariant(m_resourceTreeItem.m_boundaryBoxVisible);
    12. case 4:
    13. return QVariant(m_resourceTreeItem.m_mosaicked);
    14. case 5:
    15. return QVariant(m_resourceTreeItem.m_IDVisible);
    16. default:
    17. return QVariant();
    18. }
    19.  
    20. return QVariant();
    21. }
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. bool ResourceTreeNode::setData(int column, const QVariant& value) {
    2.  
    3. if (column < 0 || column >= 5) {
    4. return false;
    5. }
    6.  
    7. switch (column) {
    8. case 0:
    9. m_resourceTreeItem.m_resourceVisible = value.toBool();
    10. case 1:
    11. m_resourceTreeItem.m_resourceID = value.toString().toStdString();
    12. case 2:
    13. m_resourceTreeItem.m_contentVisible = value.toBool();
    14. case 3:
    15. m_resourceTreeItem.m_boundaryBoxVisible = value.toBool();
    16. case 4:
    17. m_resourceTreeItem.m_mosaicked = value.toBool();
    18. case 5:
    19. m_resourceTreeItem.m_IDVisible = value.toBool();
    20. default:
    21. break;
    22. }
    23.  
    24. return true;
    25. }
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. void QResourceTreeModel::itemClicked(const QModelIndex &index) {
    2. if ((index.isValid()) && (index.column() != 1)) {
    3.  
    4. /* The idea is to store false if it was true or true if it was false */
    5.  
    6. ResourceTreeNode* node = getNode(index);
    7. bool result = node->setData(index.column(), QVariant(!node->data(index.column()).toBool()));
    8.  
    9. if (result) {
    10. emit dataChanged(index, index);
    11. }
    12. }
    13. }
    To copy to clipboard, switch view to plain text mode 


    My problem comes from the method ResourceTreeNode::getNode(index) in QResourceTreeModel::itemClicked(index). The returned node does not contain any ResourceTreeItem? I used a log in getNode() and the problem only happen when I call getNode() from my slot. Somebody have any hints?

  2. #2
    Join Date
    Dec 2006
    Posts
    849
    Thanks
    6
    Thanked 163 Times in 151 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: How to update items in a QTreeView

    i) the error is probably: you gave your model an index of the proxy model instead of its own (you need to call QAbstractProxyModel::mapToSource(); also it is a good idea to pace assert() in one's model to ensure the indexes passed are from the right model

    ii) you should call dataChanged() in setData(); setData() can be called directly

    iii) to feature checkboxes, have a look at QAbstractItemModel::data() and Qt::CheckStateRole, you do not need a custom delegate for that (although you can, of course, go that way, too.)

    HTH

  3. #3
    Join Date
    Aug 2009
    Posts
    23
    Thanks
    3

    Default Re: How to update items in a QTreeView

    Thank you for helping me ...

    i) I will investigate on QAbstractProxyModel::mapToSource() as I didn't use it before.

    ii) I'll move the signal dataChanged() but what do you mean by setData() should be called directly?

    iii) I don't want checkboxes else I would have used the role as described in the model/view programming page. I need an icon to be shown when a resource is visible and another icon when the resource is hidden (a la Photoshop).

  4. #4
    Join Date
    Aug 2009
    Posts
    23
    Thanks
    3

    Default Re: How to update items in a QTreeView

    With your inputs, I was able to fix my code.
    As you said, it comes from the proxy model. I should connect the clicked() signal to the proxy model and not directly to the real model behind. Then use the mapToSource() method to retrieve the data using the right index.

    Thanks, Lionel

  5. #5
    Join Date
    Dec 2006
    Posts
    849
    Thanks
    6
    Thanked 163 Times in 151 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: How to update items in a QTreeView

    I didn't say setData() should be called directly, but only that it could be called directly (by someone), since it is a public part of your model's api. And if someone should do that, you need to emit dataChanged() there - otherwise the view's won't reflect the change if made (only) via setData().

    HTH

  6. The following user says thank you to caduel for this useful post:

    laugusti (12th August 2009)

  7. #6
    Join Date
    Aug 2009
    Posts
    23
    Thanks
    3

    Default Re: How to update items in a QTreeView

    My bad ... I didn't read correctly!
    Now all updates go through setData() with the signal dataChanged() there.

    Regards, Lionel

Similar Threads

  1. QcomboBox update QTreeView
    By josiah47 in forum Newbie
    Replies: 2
    Last Post: 5th March 2009, 23:32
  2. QTreeView and expandable items
    By SiLiZiUMM in forum Qt Programming
    Replies: 6
    Last Post: 29th April 2008, 13:21
  3. Edit items on QTreeView + QDirModel
    By junior0007 in forum Qt Programming
    Replies: 4
    Last Post: 23rd November 2007, 07:16
  4. How to update scene after removing items
    By nileshsince1980 in forum Qt Programming
    Replies: 4
    Last Post: 20th September 2007, 09:56
  5. Drag & drop items on the same QTreeView
    By wind in forum Qt Programming
    Replies: 2
    Last Post: 11th October 2006, 14:29

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.