Results 1 to 19 of 19

Thread: QSql*Model + QTreeView : make a tree

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Oct 2007
    Posts
    22
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QSql*Model + QTreeView : make a tree

    I'm back. I'm totally lost :/

    I understood I have to subclass QAbstractProxyModel, but I really don't know what to write in the methods.
    Could you please help me a little bit ?

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,018 Times in 4,794 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QSql*Model + QTreeView : make a tree

    The proxy is to transform a flat model into a tree. You need to return proper model indexes and parent indexes. If you don't feel comfortable enough with implementing your own proxy model (which is not very simple) I suggest you use QStandardItemModel and manually fill it with data fetched from the sql table.

  3. #3
    Join Date
    Oct 2007
    Posts
    22
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QSql*Model + QTreeView : make a tree

    Hello,

    Well, I want to learn, so I will try to make a proxy.

    Tell me if I'm wrong :
    - I create a TreeModel class (based on the Simple Tree model example from doc.trolltech.com)
    - Every time my Qsql*Model will change, I will populate my TreeModel through the Proxy.
    - The proxy will make the correspondance between the Qsl*Model and my TreeModel.

    Does it sound good ?

  4. #4
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,018 Times in 4,794 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QSql*Model + QTreeView : make a tree

    No. You need to subclass QAbstractProxyModel.

  5. #5
    Join Date
    Oct 2006
    Posts
    12
    Thanked 3 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QSql*Model + QTreeView : make a tree

    ProxyModel is deprecated... You should take a look at simple tree view example. You can make a tree model from flat sql result by choosing what columns will be the tree parent creating initiator (I'm bad with english )

    For example:

    Qt Code:
    1. Column_001 | Column_002
    2. -----------+-----------
    3. value_001 | value002
    4. value_001 | value003
    5. value_002 | value004
    6. value_002 | value005
    7. value_003 | value006
    To copy to clipboard, switch view to plain text mode 

    You should get (with the use of some code logic):

    Qt Code:
    1. value_001
    2. +-- value_002
    3. +-- value_003
    4. value_002
    5. +-- value_004
    6. +-- value_005
    7. value_003
    8. +-- value_006
    To copy to clipboard, switch view to plain text mode 

  6. #6
    Join Date
    May 2006
    Posts
    788
    Thanks
    49
    Thanked 48 Times in 46 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QSql*Model + QTreeView : make a tree

    I build mysql netset on a tree ... to infinit loop whithout proxie or so..
    The query is long but running...

    #define TREECAT "SELECT n.*, round((n.rgt-n.lft-1)/2,0) AS childs, count(*)+(n.lft>1) AS level, ((min(p.rgt)-n.rgt-(n.lft>1))/2) > 0 AS lower, (( (n.lft-max(p.lft)>1) )) AS upper FROM FAKTURA_SUB n, FAKTURA_SUB p WHERE n.lft BETWEEN p.lft AND p.rgt AND (p.root_id = n.root_id) AND (p.id != n.id OR n.lft = 1) GROUP BY n.root_id,n.id ORDER BY n.root_id,n.lft"

    You running only level 1 rows and append to QStandardItemModel(); root
    all sub level go to self on composing ....
    and you can move level up or dow append ....

    a tree online demo http://www.klempert.de/nested_sets/demo/



    Qt Code:
    1. QList<QStandardItem *> Cat_Tree::Compose( int rowposition )
    2. {
    3. QSqlRecord r = ReadModel->record(rowposition);
    4. int level;
    5. int childs;
    6. QList<QStandardItem *> Horrizzontal_Line;
    7. for (int x = 0; x < DisplayFields.size(); ++x) {
    8.  
    9. Horrizzontal_Line.append( xxxxx )
    10. }
    11. /* check on qmap unique ! */
    12. if (!OnBox(rowposition)) {
    13. RowUnique.insert(rowposition,level);
    14. }
    15. /* if moore childs append ..... loops */
    16. if (childs > 0 ) {
    17. for (int i = 0; i < childs; ++i) {
    18. const int jumpto = i + 1 + rowposition;
    19. if (!OnBox(jumpto)) {
    20. diritto.first()->appendRow(Compose(jumpto));
    21. }
    22. }
    23. }
    24. return diritto;
    25. }
    To copy to clipboard, switch view to plain text mode 
    Attached Images Attached Images

  7. #7
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,018 Times in 4,794 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QSql*Model + QTreeView : make a tree

    Quote Originally Posted by vladeck View Post
    ProxyModel is deprecated...
    Oh, really? Very interesting... since when?

  8. #8
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Thanks
    28
    Thanked 976 Times in 912 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QSql*Model + QTreeView : make a tree

    Quote Originally Posted by wysota View Post
    Oh, really? Very interesting... since when?
    4.1 or something. Just when QAbstractProxyModel and QSortFilterProxyModel came in to replace it.

  9. #9
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,018 Times in 4,794 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QSql*Model + QTreeView : make a tree

    Quote Originally Posted by jacek View Post
    4.1 or something. Just when QAbstractProxyModel and QSortFilterProxyModel came in to replace it.
    Gee... isn't that QAbstractProxyModel I was writing about? I could have sworn the "abstract" word was there... and it still is, isn't it?

  10. #10
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Thanks
    28
    Thanked 976 Times in 912 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QSql*Model + QTreeView : make a tree

    Quote Originally Posted by wysota View Post
    I could have sworn the "abstract" word was there... and it still is, isn't it?
    Not in vladeck's post.

  11. #11
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,018 Times in 4,794 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QSql*Model + QTreeView : make a tree

    I know that and you know that. Does he know that?

  12. #12
    Join Date
    Oct 2007
    Posts
    22
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QSql*Model + QTreeView : make a tree

    Hello,

    I finally gave up with the idea of subclassing a QAbstractProxyModel because I had no idea how to do that ...
    So I used a QStandardItemModel and everything works now.

    If someone has a solution with a proxy, I would be very glad to see it.



    Anyway, thanks to all the people who tried to help me.

  13. #13
    Join Date
    Oct 2006
    Posts
    12
    Thanked 3 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Lightbulb Re: QSql*Model + QTreeView : make a tree (SOLUTION)

    Here is the working code I use for making tree model out of sql query:

    TreeItem.hpp:
    Qt Code:
    1. /**
    2.  @file
    3. */
    4.  
    5. #ifndef TEST_DATA_TREEITEM_HPP
    6. #define TEST_DATA_TREEITEM_HPP
    7.  
    8. // Qt headers
    9. #include <QtCore/QList>
    10. #include <QtCore/QVariant>
    11.  
    12.  
    13. namespace test{
    14. namespace data {
    15.  
    16. class TreeItem
    17. {
    18. public:
    19. TreeItem(const QList<QVariant>& data, TreeItem* parent = 0);
    20. ~TreeItem();
    21.  
    22. void AddChild(TreeItem* child);
    23. TreeItem* GetChild(int rowIndex);
    24. int GetNumberOfChildren() const;
    25. int GetNumberOfColumns() const;
    26. QVariant GetData(int columnIndex) const;
    27. int GetRowIndex() const;
    28.  
    29.  
    30. TreeItem* GetParent();
    31.  
    32. private:
    33. QList<TreeItem*> _Children;
    34. QList<QVariant> _ItemData;
    35. TreeItem* _Parent;
    36. };
    37.  
    38. } // namespace data
    39. } // namespace test
    40.  
    41. #endif // TEST_DATA_TREEITEM_HP
    To copy to clipboard, switch view to plain text mode 

    TreeItem.cpp:
    Qt Code:
    1. /**
    2.  @file
    3. */
    4.  
    5. // Project headers
    6. #include "TreeItem.hpp"
    7.  
    8.  
    9. namespace test {
    10. namespace data {
    11.  
    12. TreeItem::TreeItem(const QList<QVariant>& data, TreeItem* parent)
    13. {
    14. _Parent = parent;
    15. _ItemData = data;
    16. }
    17.  
    18. TreeItem::~TreeItem()
    19. { qDeleteAll(_Children); }
    20.  
    21. void TreeItem::AddChild(TreeItem* child)
    22. { _Children.append(child); }
    23.  
    24. TreeItem* TreeItem::GetChild(int rowIndex)
    25. { return _Children.value(rowIndex); }
    26.  
    27. int TreeItem::GetNumberOfChildren() const
    28. { return _Children.count(); }
    29.  
    30. int TreeItem::GetNumberOfColumns() const
    31. { return _ItemData.count(); }
    32.  
    33. QVariant TreeItem::GetData(int columnIndex) const
    34. { return _ItemData.value(columnIndex); }
    35.  
    36. TreeItem* TreeItem::GetParent()
    37. { return _Parent; }
    38.  
    39. int TreeItem::GetRowIndex() const
    40. {
    41.  
    42. if (_Parent)
    43. return _Parent->_Children.indexOf(const_cast<TreeItem*>(this));
    44.  
    45. return 0;
    46. }
    47.  
    48. } // namespace data
    49. } // namespace test
    To copy to clipboard, switch view to plain text mode 

    SqlTreeModel.hpp:
    Qt Code:
    1. /**
    2.  @file
    3. */
    4.  
    5. #ifndef TEST_DATA_SQLTREEMODEL_HPP
    6. #define TEST_DATA_SQLTREEMODEL_HPP
    7.  
    8. // Qt headers
    9. #include <QtCore/QAbstractItemModel>
    10. #include <QtSql/QSqlQuery>
    11.  
    12.  
    13. namespace test {
    14. namespace data {
    15.  
    16. // Forward declarations
    17. class TreeItem;
    18.  
    19. class SqlTreeModel : public QAbstractItemModel
    20. {
    21. Q_OBJECT
    22.  
    23. public:
    24. SqlTreeModel(QObject* parent = NULL);
    25. ~SqlTreeModel();
    26.  
    27. void SetQuery(const QSqlQuery& query);
    28. bool Select();
    29.  
    30. void SetGroupByIndexes(const QList<int>& columnIndexes);
    31. void SetGroupTitleFormat(const QString& format);
    32.  
    33. QVariant GetData(const QModelIndex& index, int role) const;
    34. Qt::ItemFlags GetFlags(const QModelIndex& index) const;
    35. QVariant GetHeaderData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
    36. QModelIndex GetIndex(int rowIndex, int columnIndex, const QModelIndex& parent = QModelIndex()) const;
    37. QModelIndex GetParent(const QModelIndex& index) const;
    38. int rowCount(const QModelIndex& parent = QModelIndex()) const;
    39. int columnCount(const QModelIndex& parent = QModelIndex()) const;
    40.  
    41. private:
    42. QVariant data(const QModelIndex& index, int role) const;
    43. QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
    44. QModelIndex index(int rowIndex, int columnIndex, const QModelIndex& parent = QModelIndex()) const;
    45. QModelIndex parent(const QModelIndex& index) const;
    46.  
    47. TreeItem* _Root;
    48.  
    49. QSqlQuery _Query;
    50. QList<int> _GroupColumns;
    51. QString _GroupTitleFormat;
    52.  
    53. void Create(TreeItem* parent);
    54. };
    55.  
    56. } // namespace data
    57. } // namespace test
    58.  
    59. #endif // TEST_DATA_SQLTREEMODEL_HPP
    To copy to clipboard, switch view to plain text mode 

    SqlTreeModel.cpp:
    Qt Code:
    1. /**
    2.  @file
    3. */
    4.  
    5. // Project headers
    6. #include "TreeItem.hpp"
    7. #include "SqlTreeModel.hpp"
    8.  
    9. // Qt headers
    10. #include <QtCore/QTextStream>
    11. #include <QtSql/QSqlRecord>
    12.  
    13.  
    14. namespace test {
    15. namespace data {
    16.  
    17. SqlTreeModel::SqlTreeModel(QObject* parent /* = NULL */)
    18. : _Root(NULL),
    19. {
    20. _GroupColumns << 0;
    21. _GroupTitleFormat = "{0}";
    22. }
    23.  
    24. SqlTreeModel::~SqlTreeModel()
    25. {
    26. if (_Root != NULL)
    27. delete _Root;
    28. }
    29.  
    30. void SqlTreeModel::SetQuery(const QSqlQuery& query)
    31. { _Query = query; }
    32.  
    33. bool SqlTreeModel::Select()
    34. {
    35. if (!_Query.isActive())
    36. return false;
    37.  
    38. QSqlRecord record = _Query.record();
    39. const int record_count = record.count();
    40. QList<QVariant> root_data;
    41.  
    42. for (int i = 0; i < record_count; ++i)
    43. {
    44. if (_GroupColumns.indexOf(i) == -1)
    45. root_data << record.fieldName(i);
    46. }
    47.  
    48. _Root = new TreeItem(root_data);
    49. Create(_Root);
    50.  
    51. return true;
    52. }
    53.  
    54. void SqlTreeModel::SetGroupByIndexes(const QList<int>& columnIndexes)
    55. { _GroupColumns = columnIndexes; }
    56.  
    57. void SqlTreeModel::SetGroupTitleFormat(const QString& format)
    58. { _GroupTitleFormat = format; }
    59.  
    60. QVariant SqlTreeModel::GetData( const QModelIndex& index, int role ) const
    61. {
    62. return data(index, role);
    63. }
    64.  
    65. QVariant SqlTreeModel::data(const QModelIndex& index, int role) const
    66. {
    67. if (!index.isValid())
    68. return QVariant();
    69.  
    70. if (role != Qt::DisplayRole)
    71. return QVariant();
    72.  
    73. TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
    74. return item->GetData(index.column());
    75. }
    76.  
    77. Qt::ItemFlags SqlTreeModel::GetFlags(const QModelIndex& index) const
    78. {
    79. if (!index.isValid())
    80. return 0;
    81.  
    82. return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
    83. }
    84.  
    85. QVariant SqlTreeModel::GetHeaderData( int section, Qt::Orientation orientation, int role /*= Qt::DisplayRole*/ ) const
    86. {
    87. return headerData(section, orientation, role);
    88. }
    89. QVariant SqlTreeModel::headerData(int section, Qt::Orientation orientation, int role) const
    90. {
    91. if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
    92. return _Root->GetData(section);
    93.  
    94. return QVariant();
    95. }
    96.  
    97. QModelIndex SqlTreeModel::GetIndex( int rowIndex, int columnIndex, const QModelIndex& parent /*= QModelIndex()*/ ) const
    98. {
    99. return index(rowIndex, columnIndex, parent);
    100. }
    101.  
    102. QModelIndex SqlTreeModel::index(int rowIndex, int columnIndex, const QModelIndex& parent) const
    103. {
    104. if (!hasIndex(rowIndex, columnIndex, parent))
    105. return QModelIndex();
    106.  
    107. TreeItem *parent_item;
    108.  
    109. if (!parent.isValid())
    110. parent_item = _Root;
    111. else
    112. parent_item = static_cast<TreeItem*>(parent.internalPointer());
    113.  
    114. TreeItem *child_item = parent_item->GetChild(rowIndex);
    115.  
    116. if (child_item)
    117. return createIndex(rowIndex, columnIndex, child_item);
    118. else
    119. return QModelIndex();
    120. }
    121.  
    122. QModelIndex SqlTreeModel::GetParent( const QModelIndex& index ) const
    123. {
    124. return parent(index);
    125. }
    126.  
    127. QModelIndex SqlTreeModel::parent(const QModelIndex& index) const
    128. {
    129. if (!index.isValid())
    130. return QModelIndex();
    131.  
    132. TreeItem* child_item = static_cast<TreeItem*>(index.internalPointer());
    133. TreeItem* parent_item = child_item->GetParent();
    134.  
    135. if (parent_item == _Root)
    136. return QModelIndex();
    137.  
    138. return createIndex(parent_item->GetRowIndex(), 0, parent_item);
    139. }
    140.  
    141. int SqlTreeModel::rowCount(const QModelIndex& parent) const
    142. {
    143. TreeItem* parent_item;
    144. if (parent.column() > 0)
    145. return 0;
    146.  
    147. if (!parent.isValid())
    148. parent_item = _Root;
    149. else
    150. parent_item = static_cast<TreeItem*>(parent.internalPointer());
    151.  
    152. return parent_item->GetNumberOfChildren();
    153. }
    154.  
    155. int SqlTreeModel::columnCount(const QModelIndex& parent) const
    156. {
    157.  
    158. if (parent.isValid())
    159. return static_cast<TreeItem*>(parent.internalPointer())->GetNumberOfColumns();
    160. else
    161. return _Root->GetNumberOfColumns();
    162. }
    163.  
    164. void SqlTreeModel::Create(TreeItem* parent)
    165. {
    166. TreeItem* current_parent = parent;
    167.  
    168. while (_Query.next())
    169. {
    170. QString group_title = _GroupTitleFormat;
    171. const int group_columns_count = _GroupColumns.count();
    172. const int number_of_columns = _Query.record().count();
    173.  
    174. for (int i = 0; i < group_columns_count; ++i)
    175. {
    176. const int column_index = _GroupColumns.at(i);
    177.  
    178. QString column_arg;
    179. QTextStream arg_stream(&column_arg);
    180. arg_stream << "{" << column_index << "}";
    181.  
    182. group_title.replace(column_arg, _Query.value(column_index).toString());
    183. }
    184.  
    185. if (current_parent->GetData(0).toString() != group_title)
    186. {
    187. QList<QVariant> parent_data;
    188. parent_data << group_title;
    189.  
    190. for (int i = 1; i < number_of_columns; ++i)
    191. parent_data << "";
    192.  
    193. TreeItem* parent_item = new TreeItem(parent_data, parent);
    194. parent->AddChild(parent_item);
    195. current_parent = parent_item;
    196.  
    197. QList<QVariant> child_data;
    198.  
    199. for (int j = 0; j < number_of_columns; ++j)
    200. {
    201. if (_GroupColumns.indexOf(j) == -1)
    202. child_data << _Query.record().value(j);
    203. }
    204.  
    205. TreeItem* child_item = new TreeItem(child_data, current_parent);
    206. current_parent->AddChild(child_item);
    207. }
    208. else
    209. {
    210. QList<QVariant> child_data;
    211.  
    212. for (int i = 0; i < number_of_columns; ++i)
    213. {
    214. if (_GroupColumns.indexOf(i) == -1)
    215. child_data << _Query.record().value(i);
    216. }
    217.  
    218. TreeItem* child_item = new TreeItem(child_data, current_parent);
    219. current_parent->AddChild(child_item);
    220. }
    221. }
    222. }
    223.  
    224. } // namespace data
    225. } // namespace test
    To copy to clipboard, switch view to plain text mode 

    Use case:

    Qt Code:
    1. QList<int> group_column_indexes;
    2. group_column_indexes << 0; // group by column 0... can be any combination of column indexes
    3.  
    4. test::data::SqlTreeModel* model = new test::data::SqlTreeModel();
    5. model->SetQuery(query); // SELECT ... statement, for example
    6. model->SetGroupByIndexes(group_column_indexes);
    7. // Note, that you must format this using same indexes for grouping...
    8. // if we choose to hide columns 0, 3 & 4, then the code/format would be something like:
    9. //
    10. // group_column_indexes << 0 << 3 << 4
    11. // ...
    12. // model->SetGroupTitleFormat("Group {0} is grouped with {3} and {4}");
    13. model->SetGroupTitleFormat("Group {0}");
    14. model->Select();
    15.  
    16. _TrvPackages->setAllColumnsShowFocus(false);
    17. _TrvPackages->setModel(model);
    18.  
    19. for (int i = 0; i < _TrvPackages->model()->rowCount(); ++i)
    20. _TrvPackages->setFirstColumnSpanned(i, QModelIndex(), true);
    21.  
    22. _TrvPackages->expandAll();
    To copy to clipboard, switch view to plain text mode 

  14. The following 2 users say thank you to vladeck for this useful post:

    DmitryNik (4th December 2011), mandal (1st September 2009)

Similar Threads

  1. QTreeView with QStandardItemModel
    By steg90 in forum Newbie
    Replies: 3
    Last Post: 16th May 2007, 09:28
  2. Replies: 3
    Last Post: 19th April 2007, 11:42
  3. Window OS make distclean && qmake && make one line
    By patrik08 in forum General Programming
    Replies: 4
    Last Post: 22nd March 2007, 10:43
  4. Compiling with Qmake/Make
    By VireX in forum Newbie
    Replies: 25
    Last Post: 22nd February 2007, 05:57
  5. Optimizing filterAcceptsRow() to filter a tree
    By vfernandez in forum Qt Programming
    Replies: 1
    Last Post: 4th January 2007, 12:50

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
  •  
Qt is a trademark of The Qt Company.