Hello all,

I've been trying for hours to get this QTreeView / QAbstractItemModel code snippet to work with Qt4.4 and VC++ 2008 Express. When I expand the nested items twice, Qt fails with the assert "ASSERT: "i > -1" in file itemviews\qtreeview.cpp, line 3013". Am I doing something wrong?

Qt Code:
  1. #include <QtGui>
  2. class TestModel;
  3.  
  4. class SceneTest : public QDialog {
  5. public:
  6. SceneTest();
  7. protected:
  8. QTreeView *tree;
  9. TestModel *model;
  10. };
  11.  
  12. class InternalItem {
  13. public:
  14. InternalItem() {
  15. parent = NULL;
  16. }
  17. ~InternalItem() {qDeleteAll(children);}
  18. int row() {
  19. if (parent) {
  20. return parent->children.indexOf(this);
  21. } else {
  22. return 0;
  23. }
  24. }
  25. InternalItem *append(InternalItem *iitem) {children.append(iitem); return (iitem->parent = this);}
  26. InternalItem *parent;
  27. QList < InternalItem * > children;
  28. };
  29.  
  30. class TestModel : public QAbstractItemModel {
  31. public:
  32. TestModel();
  33. QVariant data(const QModelIndex &index, int role) const;
  34. Qt::ItemFlags flags(const QModelIndex &index) const;
  35. QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
  36. int rowCount(const QModelIndex &parent = QModelIndex()) const;
  37. int columnCount(const QModelIndex &parent) const;
  38. QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
  39. QModelIndex parent(const QModelIndex &) const;
  40. protected:
  41. InternalItem *root;
  42. };
  43.  
  44. TestModel::TestModel() {
  45. root = new InternalItem();
  46. root->append(new InternalItem());
  47. root->append(new InternalItem());
  48. root->children[1]->append(new InternalItem());
  49. root->children[1]->children[0]->append(new InternalItem());
  50. root->children[1]->children[0]->children[0]->append(new InternalItem());
  51. }
  52.  
  53. Qt::ItemFlags TestModel::flags(const QModelIndex &index) const {
  54. return index.isValid() ? (Qt::ItemIsEnabled | Qt::ItemIsSelectable) : 0;
  55. }
  56.  
  57. QVariant TestModel::data(const QModelIndex &index, int role) const {
  58. if (!index.isValid() || index.column() >= 1)
  59. return QVariant();
  60. if (role == Qt::DisplayRole) {
  61. InternalItem *iitem = static_cast < InternalItem * >(index.internalPointer());
  62. if (index.column() == 0) {
  63. return (long)iitem;
  64. }
  65. }
  66. return QVariant();
  67. }
  68.  
  69. QModelIndex TestModel::index(int row, int column, const QModelIndex &parent) const {
  70. if (!hasIndex(row, column, parent)) {
  71. return QModelIndex();
  72. }
  73. InternalItem *parentItem = NULL;
  74. if (!parent.isValid()) {
  75. parentItem = root;
  76. } else {
  77. parentItem = static_cast<InternalItem*>(parent.internalPointer());
  78. }
  79. InternalItem *child = parentItem->children[row];
  80. if (child) {
  81. return createIndex(row, column, child);
  82. } else {
  83. return QModelIndex();
  84. }
  85. }
  86.  
  87. QModelIndex TestModel::parent(const QModelIndex &index) const {
  88. if (!index.isValid()) return QModelIndex();
  89. InternalItem *iindex = static_cast < InternalItem * >(index.internalPointer());
  90. if (!iindex->parent || iindex->parent == root) {
  91. return QModelIndex();
  92. } else {
  93. return createIndex(iindex->row(), 0, iindex->parent);
  94. }
  95. }
  96.  
  97. QVariant TestModel::headerData(int section, Qt::Orientation orientation, int role) const {
  98. if (section == 0 && role == Qt::DisplayRole) {
  99. return QString("A");
  100. } else {
  101. return QVariant();
  102. }
  103. }
  104.  
  105. int TestModel::rowCount(const QModelIndex &parent) const {
  106. if (parent.column() > 0) return 0;
  107. if (parent.isValid()) {
  108. return static_cast < InternalItem * >(parent.internalPointer())->children.size();
  109. } else {
  110. return root->children.size();
  111. }
  112. }
  113.  
  114. int TestModel::columnCount(const QModelIndex &parent) const {
  115. return 1;
  116. }
  117.  
  118. SceneTest::SceneTest() : QDialog(NULL) {
  119. model = new TestModel();
  120. tree = new QTreeView(this);
  121. tree->setModel(model);
  122. QBoxLayout *layout = new QHBoxLayout(this);
  123. layout->addWidget(tree);
  124. }
To copy to clipboard, switch view to plain text mode