Results 1 to 4 of 4

Thread: Viewing QSqlTableModel in QTreeView through a proxy model

  1. #1
    Join Date
    Nov 2017
    Posts
    5
    Qt products
    Qt5
    Platforms
    Windows Android

    Default Viewing QSqlTableModel in QTreeView through a proxy model

    I'm trying to use a proxy model to take a 'parentId' column in a QSqlTableModel (using SQLITE) and view the hierarchy with a QTreeView. To make this work without needed a treeItem-type class I'm using internalId() from QModelIndex to store the 'parentId'. It works 99% of the time and I can't nail down where I'm messing up. I can view the parents/children and even expand/collapse them but I cannot select the children of a parent item. The selectionModel's selectionChanged() signal and the proxy models index() return the expected QModelIndex and so I don't know what is making the view upset. Here is the code that produces the issue. Thanks for any insight or suggestions

    mainwindow.h
    Qt Code:
    1. #ifndef MAINWINDOW_H
    2. #define MAINWINDOW_H
    3.  
    4. #include <QMainWindow>
    5. #include <QSqlError>
    6.  
    7. class QTreeView;
    8. class sqlTreeModelTest;
    9.  
    10. class MainWindow : public QMainWindow
    11. {
    12. Q_OBJECT
    13.  
    14. public:
    15. explicit MainWindow(QWidget *parent = 0);
    16. QSqlError initdb();
    17. private:
    18. QTreeView *treeView;
    19. void setupModel();
    20. };
    21.  
    22. #endif // MAINWINDOW_H
    To copy to clipboard, switch view to plain text mode 

    mainwindow.cpp
    Qt Code:
    1. #include "mainwindow.h"
    2. #include "sqltreemodeltest.h"
    3. #include "proxytreemodeltest.h"
    4.  
    5. #include <QTreeView>
    6. #include <QVBoxLayout>
    7. #include <QSqlQuery>
    8.  
    9. MainWindow::MainWindow(QWidget *parent) :
    10. QMainWindow(parent)
    11. {
    12. QWidget *centralWidget = new QWidget(this);
    13. QVBoxLayout *verticalLayout = new QVBoxLayout(centralWidget);
    14. treeView = new QTreeView(centralWidget);
    15. verticalLayout->addWidget(treeView);
    16. setCentralWidget(centralWidget);
    17.  
    18. QSqlError error = initdb();
    19. if(error.isValid())
    20. qDebug() << error.text();
    21. setupModel();
    22. }
    23.  
    24. QSqlError MainWindow::initdb() {
    25.  
    26. QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    27.  
    28. db.setDatabaseName(":memory:");
    29. if(!db.open())
    30. return db.lastError();
    31.  
    32. QStringList tables = db.tables();
    33. if(tables.contains("test", Qt::CaseInsensitive))
    34. if(!q.exec("DROP TABLE test"))
    35. return q.lastError();
    36.  
    37. if(!q.exec(QLatin1String("CREATE TABLE test(id INTEGER PRIMARY KEY, title VARCHAR, type INTEGER, parentId INTEGER DEFAULT 0)")))
    38. return q.lastError();
    39. if(!q.exec(QLatin1String("INSERT INTO test (title, type, parentId)"
    40. "VALUES ('row0', 0, 0),"
    41. "('row0a', 0, 1)")))
    42. return q.lastError();
    43. return QSqlError();
    44. }
    45.  
    46. void MainWindow::setupModel() {
    47.  
    48. sqlTreeModelTest *testModel = new sqlTreeModelTest(this);
    49. testModel->setTable("test");
    50. testModel->select();
    51.  
    52. proxyTreeModelTest *treeProxy = new proxyTreeModelTest(this);
    53. treeProxy->setSourceModel(testModel);
    54.  
    55. treeView->setModel(treeProxy);
    56. treeView->setSelectionBehavior(QAbstractItemView::SelectRows);
    57. treeView->setSelectionMode(QAbstractItemView::SingleSelection);
    58. }
    To copy to clipboard, switch view to plain text mode 

    sqltreemodeltest.h
    Qt Code:
    1. #ifndef SQLTREEMODELTEST_H
    2. #define SQLTREEMODELTEST_H
    3.  
    4. #include <QSqlTableModel>
    5.  
    6. class sqlTreeModelTest : public QSqlTableModel
    7. {
    8. Q_OBJECT
    9.  
    10. public:
    11. sqlTreeModelTest(QObject *parent=0);
    12. virtual Qt::ItemFlags flags(const QModelIndex &index) const;
    13. };
    14.  
    15. #endif // SQLTREEMODELTEST_H
    To copy to clipboard, switch view to plain text mode 

    sqltreemodeltest.cpp
    Qt Code:
    1. #include "sqltreemodeltest.h"
    2.  
    3. sqlTreeModelTest::sqlTreeModelTest(QObject *parent) : QSqlTableModel(parent) {}
    4.  
    5. Qt::ItemFlags sqlTreeModelTest::flags(const QModelIndex &index) const {
    6. //QSqlTableModel doesn't allow children so use these flags
    7. if(index.isValid())
    8. return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
    9. else
    10. return 0;
    11. }
    To copy to clipboard, switch view to plain text mode 

    proxytreemodeltest.h
    Qt Code:
    1. #ifndef PROXYTREEMODELTEST_H
    2. #define PROXYTREEMODELTEST_H
    3.  
    4. #include <QDebug>
    5. #include <QAbstractProxyModel>
    6.  
    7. class QSqlQuery;
    8.  
    9. class proxyTreeModelTest : public QAbstractProxyModel
    10. {
    11. Q_OBJECT
    12.  
    13. public:
    14. proxyTreeModelTest(QObject *parent=0);
    15. virtual QModelIndex mapFromSource(const QModelIndex &sourceIndex) const;
    16. virtual QModelIndex mapToSource(const QModelIndex &proxyIndex) const;
    17. virtual QModelIndex parent(const QModelIndex &child) const;
    18.  
    19. virtual QModelIndex index(int row, int column, const QModelIndex &parent) const;
    20. virtual int rowCount(const QModelIndex &parent) const;
    21. virtual int columnCount(const QModelIndex &parent) const { return sourceModel()->columnCount(parent); }
    22.  
    23. virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const { return sourceModel()->headerData(section,orientation,role); }
    24. virtual bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role) { return sourceModel()->setHeaderData(section,orientation,value,role); }
    25.  
    26. virtual bool hasChildren(const QModelIndex &parent) const;
    27.  
    28. private:
    29.  
    30. int getParentId(int childId) const;
    31. QSqlQuery* getChildren(int parentId) const;
    32. };
    33.  
    34. #endif // PROXYTREEMODELTEST_H
    To copy to clipboard, switch view to plain text mode 

    proxytreemodeltest.cpp
    Qt Code:
    1. #include "proxytreemodeltest.h"
    2.  
    3. #include <QSqlQuery>
    4. #include <QSqlTableModel>
    5. #include <QSqlError>
    6.  
    7. #include <QDebug>
    8.  
    9. proxyTreeModelTest::proxyTreeModelTest(QObject *parent) : QAbstractProxyModel(parent) {}
    10.  
    11. QModelIndex proxyTreeModelTest::mapFromSource(const QModelIndex &sourceIndex) const {
    12. if(!sourceIndex.isValid())
    13. return QModelIndex();
    14.  
    15. int id = (sourceIndex.column() == 0) ? sourceIndex.data().toInt() : sourceIndex.sibling(sourceIndex.row(),0).data().toInt();
    16.  
    17. int row = -1;
    18. QSqlQuery* q = getChildren(getParentId(id));
    19. while(q->next()) {
    20. row++;
    21. if(q->value(0).toInt() == id)
    22. break;
    23. }
    24. delete q;
    25. return createIndex(row, sourceIndex.column(), id);
    26. }
    27.  
    28. QModelIndex proxyTreeModelTest::mapToSource(const QModelIndex &proxyIndex) const {
    29. if(!proxyIndex.isValid())
    30. return QModelIndex();
    31.  
    32. int id = proxyIndex.internalId();
    33.  
    34. q.exec("SELECT id FROM test");
    35. int row = -1;
    36. while(q.next()) {
    37. row++;
    38. if(q.value(0).toInt() == id)
    39. break;
    40. }
    41. return sourceModel()->index(row, proxyIndex.column());
    42. }
    43.  
    44. bool proxyTreeModelTest::hasChildren(const QModelIndex &parent) const {
    45.  
    46. q.prepare("SELECT COUNT(*) FROM test WHERE parentId=?");
    47. q.addBindValue(parent.internalId());
    48. q.exec();
    49. q.first();
    50. return q.value(0).toInt() > 0;
    51. }
    52.  
    53. QModelIndex proxyTreeModelTest::parent(const QModelIndex &childIndex) const {
    54.  
    55. int childId = childIndex.internalId();
    56. int parentId = getParentId(childId);
    57. if(parentId == 0)
    58. return QModelIndex();
    59.  
    60. int parentRow = -1;
    61. QSqlQuery* q = getChildren(getParentId(parentId));
    62. while(q->next()) {
    63. parentRow++;
    64. if(q->value(0).toInt() == parentId)
    65. break;
    66. }
    67. delete q;
    68. return createIndex(parentRow, childIndex.row(), parentId);
    69. }
    70.  
    71. QModelIndex proxyTreeModelTest::index(int row, int column, const QModelIndex &parent) const {
    72.  
    73. if(row < 0 || column < 0)
    74. return QModelIndex();
    75.  
    76. QSqlQuery* q = getChildren(parent.internalId());
    77. q->seek(row);
    78. int id = q->value(0).toInt();
    79. delete q;
    80. return createIndex(row, column, id);
    81. }
    82.  
    83. int proxyTreeModelTest::rowCount(const QModelIndex &parent) const {
    84.  
    85. QSqlQuery* q = getChildren(parent.internalId());
    86.  
    87. //use last() and at() since SQLite does not support query size calls
    88. q->last();
    89. int size = q->at() + 1;
    90. delete q;
    91. return size;
    92. }
    93.  
    94. int proxyTreeModelTest::getParentId(int childId) const {
    95. q.prepare("SELECT parentId FROM test WHERE id=?");
    96. q.addBindValue(childId);
    97. q.exec();
    98. q.first();
    99. return q.value(0).toInt();
    100. }
    101.  
    102. QSqlQuery* proxyTreeModelTest::getChildren(int parentId) const {
    103. QSqlQuery* q = new QSqlQuery;
    104. q->prepare("SELECT id FROM test WHERE parentId=?");
    105. q->addBindValue(parentId);
    106. q->exec();
    107. return q;
    108. }
    To copy to clipboard, switch view to plain text mode 

    main.cpp
    Qt Code:
    1. #include "mainwindow.h"
    2. #include <QApplication>
    3.  
    4. int main(int argc, char *argv[])
    5. {
    6. QApplication a(argc, argv);
    7. MainWindow w;
    8. w.show();
    9.  
    10. return a.exec();
    11. }
    To copy to clipboard, switch view to plain text mode 

  2. #2
    Join Date
    Mar 2018
    Posts
    1
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Viewing QSqlTableModel in QTreeView through a proxy model

    In sqltreemodeltest.cpp.

    return Qt::ItemIsEnabled | Qt::ItemIsSelectable|Qt::ItemIsEditable;

    You need add a flag Qt::ItemIsEditable;


    Added after 19 minutes:


    Oh, sorry, I misunderstand the question.
    Last edited by LinJH; 14th March 2018 at 22:22.

  3. #3
    Join Date
    Aug 2018
    Posts
    1
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows Android

    Default Re: Viewing QSqlTableModel in QTreeView through a proxy model

    i want to say;
    change
    "treeView->setSelectionBehavior(QAbstractItemView::SelectRow s);"
    to
    "treeView->setSelectionBehavior(QAbstractItemView::SelectIte ms);"
    in mainwindow.cpp

    thats all

    but, i think you are not a beginner and this solution is not for you isn,t it?

    and how we add and delete nodes, any idea?
    (i am a beginner)

  4. #4
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,122
    Thanks
    291
    Thanked 847 Times in 834 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Viewing QSqlTableModel in QTreeView through a proxy model

    and how we add and delete nodes, any idea?
    The way you add or delete nodes is to change the QAbstractItemModel-based model that the QTreeView uses to build itself. The QTreeView is simply a way to display the model, and does not contain any data itself beyond what is needed to show the model on screen.

    You can find information on tree views and item models in the Qt documentation, tutorials, and examples.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

Similar Threads

  1. How to use proxy model?
    By gurmeet in forum Qt Programming
    Replies: 3
    Last Post: 18th March 2015, 08:18
  2. Replies: 24
    Last Post: 18th September 2013, 06:35
  3. Replies: 1
    Last Post: 29th August 2013, 05:41
  4. Source Model Ad Proxy Model
    By sajis997 in forum Qt Programming
    Replies: 1
    Last Post: 19th July 2011, 05:13
  5. Custom Model and Proxy Model
    By frank100 in forum Qt Programming
    Replies: 1
    Last Post: 20th December 2010, 14:30

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.