Results 1 to 10 of 10

Thread: SQL Tree Model Help

  1. #1
    Join Date
    Jun 2010
    Posts
    142
    Thanks
    11
    Thanked 4 Times in 3 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Unhappy SQL Tree Model Help

    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 

  2. #2
    Join Date
    May 2009
    Location
    USA
    Posts
    300
    Thanks
    82
    Thanked 11 Times in 11 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: SQL Tree Model Help

    First off, I don't think QtSql is going to recognize a Sqlite database named :memory - where is this defined? It needs to be like myDB.sqlite Have you checked to see if the database is actually being created? With another tool maybe. How about a qDebug to see if the database is open? Also, I don't see where you have populated your model with a model->select();

  3. #3
    Join Date
    Jan 2006
    Location
    Germany
    Posts
    4,380
    Thanks
    19
    Thanked 1,005 Times in 913 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows Symbian S60
    Wiki edits
    5

    Default Re: SQL Tree Model Help

    The :memory: is fine. It creates a temporal database in the memory with no file representation. But sharing a query with the model is a bad idea it will come to problems. Better just tell the model the database name and let the model do all the rest. Debug if any of your model methods is called.

  4. #4
    Join Date
    Jun 2010
    Posts
    142
    Thanks
    11
    Thanked 4 Times in 3 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: SQL Tree Model Help

    Quote Originally Posted by waynew View Post
    Also, I don't see where you have populated your model with a model->select();
    What select() method? It doesn't exist in QAbstractItemModel!

    Quote Originally Posted by Lykurg View Post
    But sharing a query with the model is a bad idea it will come to problems. Better just tell the model the database name and let the model do all the rest.
    Why?

    And I need different parts of the program to access different parts of the database, so isn't it necessary to share it?

  5. #5
    Join Date
    Jan 2006
    Location
    Germany
    Posts
    4,380
    Thanks
    19
    Thanked 1,005 Times in 913 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows Symbian S60
    Wiki edits
    5

    Default Re: SQL Tree Model Help

    It definitly work, but it is a better design if your model is independent. It simply can save you from a lot of possible errors. And there is no need. If you give the connection name and database name you can "duplicate" the connection without any loose.

    But is any of your model method called?

  6. #6
    Join Date
    Jun 2010
    Posts
    142
    Thanks
    11
    Thanked 4 Times in 3 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: SQL Tree Model Help

    Quote Originally Posted by Lykurg View Post
    But is any of your model method called?
    Yes. headerData() seems to be called a huge amount of times, but data() is never called!

  7. #7
    Join Date
    Jun 2010
    Posts
    142
    Thanks
    11
    Thanked 4 Times in 3 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: SQL Tree Model Help

    Help? Anyone?

  8. #8
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: SQL Tree Model Help

    How are you determining that data() is never called? Is it the absence of displayed values in your view, a debug output statement in the method, single-stepping/breakpoints? Are you checking that your queries succeed? Are you checking that internalId() returns what you are expecting?

  9. #9
    Join Date
    Jun 2010
    Posts
    142
    Thanks
    11
    Thanked 4 Times in 3 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: SQL Tree Model Help

    I gave up on it for a few days and revisited it recently, and found out that the problem was that SQLite does not support the QSqlQuery::size() method.

  10. #10
    Join Date
    Jun 2015
    Posts
    1
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: SQL Tree Model Help

    I found subclassing QSqlQuery solves this issue. Thanks to your orginal code!
    Qt Code:
    1. class TMySqlQuery : public QSqlQuery
    2. {
    3. public:
    4. TMySqlQuery(QSqlDatabase db);
    5. int size();
    6.  
    7. };
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. TMySqlQuery::TMySqlQuery(QSqlDatabase db)
    2. : QSqlQuery (db)
    3. {
    4. }
    5.  
    6.  
    7. int TMySqlQuery::size()
    8. {
    9. if (QSqlQuery::size() == -1) {
    10. int c = at();
    11. last();
    12. int s = at();
    13. seek(c, false);
    14. return s+1;
    15. } else {
    16. return QSqlQuery::size();
    17. }
    18. }
    To copy to clipboard, switch view to plain text mode 

Similar Threads

  1. Tree model examples
    By elcuco in forum Qt Programming
    Replies: 5
    Last Post: 18th October 2009, 23:44
  2. A simple example of a tree model
    By YaK in forum Qt Programming
    Replies: 2
    Last Post: 4th March 2009, 17:15
  3. Writing a Tree model.
    By kaushal_gaurav in forum Qt Programming
    Replies: 6
    Last Post: 16th January 2009, 11:22
  4. Editable Tree Model
    By kloffy in forum Qt Programming
    Replies: 5
    Last Post: 10th October 2007, 15:49
  5. using the example of simple tree model
    By krishna.bv in forum Qt Programming
    Replies: 1
    Last Post: 22nd December 2006, 12:28

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.