Results 1 to 19 of 19

Thread: QSql*Model + QTreeView : make a tree

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

    Question QSql*Model + QTreeView : make a tree

    Hello,

    I would like to have the data contained in an SQL table shown in a treeview (I already have that), but I would like items to be group (kind of filter) by types. See the exemple.

    Here is my table "MultimediaFiles" structure:
    - id,
    - name,
    - path,
    - type (can be, "picture", "video", "sound").

    So, I would like my records to be presented in a treeview like this :

    |-- Name --|-- Path --|
    ------------------------------------
    - picture
    |- foo.png C:\...
    - video
    |- bar.avi C:\...
    |- toto.mpg C:\...
    - sound
    |- huhu.wav ...
    |- haha.mp3 C:\...

    What I already did :

    Qt Code:
    1. SQL::SQL()
    2. {
    3. QSqlDatabase mDb = QSqlDatabase::addDatabase( "QMYSQL" );
    4. mDb.setHostName( "localhost" );
    5. mDb.setDatabaseName( "mydb" );
    6. mDb.open();
    7. setupModel();
    8. }
    9.  
    10. void SQL::setupModel()
    11. {
    12. pModel = new QSqlRelationalTableModel();
    13. pModel->setTable( "MultimediaFiles" );
    14. if( !pModel->select() )
    15. {
    16. qDebug() << "pb select";
    17. qDebug() << pModel->lastError().text();
    18. }
    19.  
    20. treeView->setModel( pModel );
    21. /*...*/
    22. treeView->show();
    23. }
    To copy to clipboard, switch view to plain text mode 

    But it doesn't act as I want : there is no node created.
    So, do I miss something, or do I need to make my own model, or add treeItems by hands ?



    Thanks in advance.

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,364
    Thanks
    3
    Thanked 5,013 Times in 4,791 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 model you used is a flat model and no matter what view you use it won't become structured just by itself. You need to provide a proxy model that will represent your table as a tree. See QAbstractProxyModel for details.

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

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

    Great, I take a look.

    Thank you.

  4. #4
    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 ?

  5. #5
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,364
    Thanks
    3
    Thanked 5,013 Times in 4,791 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.

  6. #6
    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 ?

  7. #7
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,364
    Thanks
    3
    Thanked 5,013 Times in 4,791 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.

  8. #8
    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 

  9. #9
    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

  10. #10
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,364
    Thanks
    3
    Thanked 5,013 Times in 4,791 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?

  11. #11
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Thanks
    28
    Thanked 975 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.

  12. #12
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,364
    Thanks
    3
    Thanked 5,013 Times in 4,791 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?

  13. #13
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Thanks
    28
    Thanked 975 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.

  14. #14
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,364
    Thanks
    3
    Thanked 5,013 Times in 4,791 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?

  15. #15
    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.

  16. #16
    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 

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

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

  18. #17
    Join Date
    Sep 2008
    Posts
    13
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

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

    Yesterday I was finally able to get my tree model working from my SQL query results. I have to say took me a while to see where I needed to be going. In the end I dump my results into a QAbstractTableModel, then build up a tree item model that gets it's data from this table. Then I use a QSortFilterProxyModel to display the tree. My code is a little ugly right now (I really need to subclass some of this), but I can use either a table model or a tree model to display the same search data.

    The QSortFilterProxyModel is a bit of overkill for this, but the nice thing is that it has already subclassed and connected everything to make sure that the proxy model updates whenever the table model does.

    If any one wants to see what I ended up doing let me know and I can post the code.

    -- amicitas

  19. #18
    Join Date
    Sep 2008
    Posts
    13
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

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

    Janus wanted to take a look-see at my code, so I figured I would post it for everyone. It is not particularly polished code, but it does the job.

    For this application I am doing a SQL query that returns a table of songs. Each record has a number of columns including artist, album & track. I want to turn this table into a tree. To do this I use a TableModel and a ProxyModel.

    Here is a basic description of what happens:
    1. An SQL query is performed.
    2. The results from the query, along with the column names is added to the HystrixSearchModel. This data is added as a table.
    3. A set of tree items is generated for the data.
    4. reset() is called to let both the HystrixSeachModel and the HystrixProxyModel know that the data has changed.
    5. The proxy model displays the data from the tree items.


    For most of this I followed along with the "Simple Tree Model Example" in the Qt documentation. I did not document in the code the stuff that is documented there.

    Since the file is too big to put in this post here is a link to it on sourceforge.
    (Note that this is written in Python using PyQt4, you C++ people will have to translate.)
    (as a hint though, python passes all mutable objects as pointers, so only references to the data are stored in the tree items.

    hystrix_model.py


    To use this model in a view I use:
    Qt Code:
    1. #
    2. # Create the View (HystrixTreeView is subclassed from QTreeView
    3. ui_search_view = HystrixTreeView(self)
    4.  
    5. # Create the data model
    6. search_model = hystrix_model.HystrixSearchModel()
    7.  
    8. # Create the proxy model
    9. proxy_model = hystrix_model.HystrixProxyModel()
    10.  
    11. # Connect the model
    12. proxy_model.setSourceModel(search_model)
    13.  
    14. ui_search_view.setModel(proxy_model)
    To copy to clipboard, switch view to plain text mode 


    In the code the tree items are built by: HystrixSearchModel.makeTreeItems

    I also have a routine in there called: HystrixSearchModel.makeIndexedTreeMap

    makeIndexedTreeMap is not actually used, but it is easier to see how I am building the tree in that routine. If you are having trouble figuring out what I am doing in makeTreeItems then look at makeIndexedTreeMap first.


    For my proxy model I subclass QSortFilterProxyModel. I don't actually use any of the filtering or sorting abilities, but that class already has all necessary parts of QAbstractProxyModel reimplemented and the signals, slots and events are all connected up. To use the QAbstractProxyModel directly requires a whole lot of work.

    If anyone has questions let me know and I will be happy to answer them.

    Good luck.

    -- amicitas
    (that code snippit is part of Hystrix Audio Hystrix Audio)

  20. #19
    Join Date
    Mar 2008
    Posts
    141
    Thanks
    10
    Thanked 9 Times in 9 Posts

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

    Hi,

    thx to amicitas and other posts in this thread I was able to build a tree from sql. But I am not using a model: On startup i execute a query for the parent items (children of the rootitem). My problem was, that I want to load only the data form the database that are visible at the beginning otherwise the whole thing is too slow. When the user clicks a parent (all of them have children) I execute another query to load the childitems. This is quite fast and works. My problem is, that i am not able to connect to the expanded() signal of the treeView. Right now I am hiding the decoration (setRootIsDecorated(false)) and use clicks on items within the view to expand or collapse. The expanding is done within the model ...
    Qt Code:
    1. connect(ui.treeView, SIGNAL(clicked(QModelIndex)), model, SLOT(expand(QModelIndex)));
    2.  
    3. connect(ui.treeView, SIGNAL(expanded(QModelIndex)), model, SLOT(expand(QModelIndex))); //<-- no way. infinite loop
    4.  
    5. void TreeModel::expand(const QModelIndex &index)
    6. {
    7. QModelIndex idx = proxy->mapToSource(index);
    8.  
    9. QModelIndex sourceIndex = idx.sibling(idx.row(), 0);
    10. QModelIndex proxyIndex = index.sibling(index.row(), 0);
    11.  
    12. if (!hasChildren(sourceIndex))
    13. return;
    14.  
    15. TreeItem *item = getItem(sourceIndex);
    16.  
    17. if (item->childCount() > 0) {
    18.  
    19. if (view->isExpanded(proxyIndex)) {
    20. view->collapse(proxyIndex);
    21. return;
    22. }
    23.  
    24. view->expand(proxyIndex);
    25.  
    26. }
    27.  
    28. else {
    29.  
    30.  
    31. .. execute query
    32.  
    33. setupModelData(q, item);
    34. view->expand(proxyIndex);
    35.  
    36. }
    37.  
    38. }
    To copy to clipboard, switch view to plain text mode 

    This is not a very nice solution. I'd rather prefer to use the default rootdecoration. But i can not find a way to get the expanded signal and load the data: Nothing is dispayed because the signal is emitted after the view is updated (At that point there is no data). If I call the expand slot again after the query I end up in an infinite loop ... I took a look at the Qt source code, but all parts that are required to cache the expansion (the click on the decoration [+] ) before the model is checked for children are part of QTreeViewPrivate. Sorry for the long explanation, but maybe someone has an idea :-)

Similar Threads

  1. QTreeView with QStandardItemModel
    By steg90 in forum Newbie
    Replies: 3
    Last Post: 16th May 2007, 10:28
  2. Replies: 3
    Last Post: 19th April 2007, 12:42
  3. Window OS make distclean && qmake && make one line
    By patrik08 in forum General Programming
    Replies: 4
    Last Post: 22nd March 2007, 11:43
  4. Compiling with Qmake/Make
    By VireX in forum Newbie
    Replies: 25
    Last Post: 22nd February 2007, 06:57
  5. Optimizing filterAcceptsRow() to filter a tree
    By vfernandez in forum Qt Programming
    Replies: 1
    Last Post: 4th January 2007, 13: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
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.