I am writing a tree model for an app I'm making that takes it's data from an SQLite database. Each item in the db contains the values "id" (unique identifier), "parent" (id of parent, or 0 for toplevel item), and "name" (the user-visible name of the item).

It compiles fine, but the view comes out empty! I have no idea where to begin troubleshooting.

The code to fill in the db, create the model, and attach it to a QTreeView:

Qt Code:
  1. db = QSqlDatabase::addDatabase("QSQLITE");
  2. db.setDatabaseName(":memory:");
  3. db.open();
  4. QSqlQuery *query = new QSqlQuery(db);
  5.  
  6. query->exec("CREATE TABLE tags (id INTEGER, parent INTEGER, name TEXT)");
  7. query->exec("INSERT INTO tags VALUES (1, 0, 'item 1')");
  8. query->exec("INSERT INTO tags VALUES (2, 1, 'sub 1')");
  9. query->exec("INSERT INTO tags VALUES (3, 2, 'sub sub 1')");
  10. query->exec("INSERT INTO tags VALUES (4, 2, 'sub sub 2')");
  11. query->exec("INSERT INTO tags VALUES (5, 0, 'item 2')");
  12. query->exec("INSERT INTO tags VALUES (6, 5, 'sub 1')");
  13.  
  14. tagModel = new TagTreeModel(query);
  15. ui->tagTree->setModel(tagModel);
To copy to clipboard, switch view to plain text mode 

The header for the model class:

Qt Code:
  1. class TagTreeModel : public QAbstractItemModel
  2. {
  3. Q_OBJECT
  4.  
  5. public:
  6. TagTreeModel(QSqlQuery *tagDbQuery);
  7.  
  8. QModelIndex index(int row, int column, const QModelIndex &parent) const;
  9. QModelIndex parent(const QModelIndex &child) const;
  10. int rowCount(const QModelIndex &parent) const;
  11. int columnCount(const QModelIndex &parent) const;
  12. Qt::ItemFlags flags(const QModelIndex &index) const;
  13. QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
  14. QVariant headerData(int seaction, Qt::Orientation orientation, int role) const;
  15.  
  16. private:
  17.  
  18. QSqlQuery *query;
  19. };
To copy to clipboard, switch view to plain text mode 

The implementation of the model:

Qt Code:
  1. TagTreeModel::TagTreeModel(QSqlQuery *tagDbQuery) :
  2. {
  3. query = tagDbQuery;
  4. }
  5.  
  6. QModelIndex TagTreeModel::index(int row, int column, const QModelIndex &parent) const
  7. {
  8. qint32 parentId;
  9. if (parent.isValid())
  10. parentId = parent.internalId();
  11. else
  12. parentId = 0;
  13.  
  14. query->prepare("SELECT id FROM tags WHERE parent=?");
  15. query->addBindValue(parentId);
  16. query->exec();
  17.  
  18. if (query->seek(row))
  19. return createIndex(row, column, query->value(0).toInt());
  20. return QModelIndex();
  21. }
  22.  
  23. QModelIndex TagTreeModel::parent(const QModelIndex &child) const
  24. {
  25. if (!child.isValid())
  26. return QModelIndex();
  27.  
  28. query->prepare("SELECT parent FROM tags WHERE id=?");
  29. query->addBindValue(child.internalId());
  30. query->exec();
  31. query->next();
  32. qint32 parent = query->value(0).toInt();
  33.  
  34. if (parent == 0)
  35. return QModelIndex();
  36.  
  37. query->prepare("SELECT parent FROM tags WHERE id=?");
  38. query->addBindValue(parent);
  39. query->exec();
  40. query->next();
  41. qint32 parentOfParent = query->value(0).toInt();
  42.  
  43. int row = 0;
  44. query->prepare("SELECT id FROM tags WHERE parent=?");
  45. query->addBindValue(parentOfParent);
  46. query->exec();
  47. for (int i=0; query->next(); i++)
  48. {
  49. if (query->value(0).toInt() == parent)
  50. {
  51. row = i;
  52. break;
  53. }
  54. }
  55.  
  56. return createIndex(row, 0, parent);
  57. }
  58.  
  59. int TagTreeModel::rowCount(const QModelIndex &parent) const
  60. {
  61. qint32 parentId;
  62. if (parent.isValid())
  63. parentId = parent.internalId();
  64. else
  65. parentId = 0;
  66.  
  67. query->prepare("SELECT id FROM tags WHERE parent=?");
  68. query->addBindValue(parentId);
  69. query->exec();
  70. return query->size();
  71. }
  72.  
  73. int TagTreeModel::columnCount(const QModelIndex &parent) const
  74. {
  75. Q_UNUSED(parent);
  76.  
  77. return 1;
  78. }
  79.  
  80. QVariant TagTreeModel::data(const QModelIndex &index, int role) const
  81. {
  82. if (!index.isValid() || role != Qt::DisplayRole)
  83. return QVariant();
  84.  
  85. query->prepare("SELECT name FROM tags WHERE id=?");
  86. query->addBindValue(index.internalId());
  87. query->exec();
  88. query->next();
  89. return query->value(0);
  90. }
  91.  
  92. Qt::ItemFlags TagTreeModel::flags(const QModelIndex &index) const
  93. {
  94. if (!index.isValid())
  95. return Qt::ItemIsEnabled;
  96. return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
  97. }
  98.  
  99. QVariant TagTreeModel::headerData(int section, Qt::Orientation orientation, int role) const
  100. {
  101. Q_UNUSED(section);
  102.  
  103. if (orientation != Qt::Horizontal || role != Qt::DisplayRole)
  104. return QVariant();
  105. return QVariant(QString("Tag"));
  106. }
To copy to clipboard, switch view to plain text mode