Hi everybody.

I know that similar posts were here on the forum but as I saw usually threads were finished with the conclusion that maybe different model should be used instead of QAbstractProxyModel.

The problem :
Right now I've a tree model based on QAbstractItemModel which is used to hold objects of TreeModelItem type ( obvious isn't it ? ). There is no problem to create such a model here is the model and item code.

BaseTreeModel.cpp
Qt Code:
  1. #include "BaseTreeModel.h"
  2. #include "TreeModelItem.h"
  3. #include <QDebug>
  4.  
  5. BaseTreeModel::BaseTreeModel() {
  6. // fake structure
  7. QList<QVariant *> fakeData1;
  8. fakeData1.push_back(new QVariant("fakeData11"));
  9. fakeData1.push_back(new QVariant("fakeData22"));
  10.  
  11.  
  12. QList<QVariant *> fakeData2;
  13. fakeData2.push_back(new QVariant(1111));
  14. fakeData2.push_back(new QVariant(2222));
  15.  
  16.  
  17. rootItem = new TreeModelItem(fakeData1, 0);
  18.  
  19. for (int i = 0;i<1;i++){
  20. TreeModelItem *item = new TreeModelItem(fakeData1, rootItem);
  21. rootItem->appendChild(item);
  22. for (int j=0;j<1;j++)
  23. item->appendChild( new TreeModelItem(fakeData2, item) );
  24. }
  25.  
  26. }
  27.  
  28. BaseTreeModel::~BaseTreeModel() {
  29. }
  30.  
  31. // Minimum implementation for ReadOnly model
  32. QModelIndex BaseTreeModel::index ( int row, int column, const QModelIndex & parent ) const {
  33. if (!hasIndex(row, column, parent))
  34. return QModelIndex();
  35.  
  36. TreeModelItem *parent_item;
  37. if (!parent.isValid()){
  38. parent_item = rootItem;
  39. } else {
  40. parent_item = static_cast<TreeModelItem*>(parent.internalPointer());
  41. }
  42.  
  43. TreeModelItem *child_item = parent_item->childAt(row);
  44.  
  45. if (child_item) {
  46. return createIndex(row, column, child_item);
  47. } else {
  48. return QModelIndex();
  49. }
  50. }
  51.  
  52. QModelIndex BaseTreeModel::parent ( const QModelIndex & index ) const {
  53. if (!index.isValid())
  54. return QModelIndex();
  55.  
  56. TreeModelItem* child_item = static_cast<TreeModelItem*>(index.internalPointer());
  57. TreeModelItem* parent_item = child_item->parent();
  58.  
  59. if (parent_item == rootItem)
  60. return QModelIndex();
  61.  
  62. return createIndex(parent_item->row(), 0, parent_item);
  63. }
  64.  
  65. QVariant BaseTreeModel::data ( const QModelIndex & index, int role) const {
  66. if (!index.isValid())
  67. return QVariant();
  68.  
  69. if (role != Qt::DisplayRole)
  70. return QVariant();
  71.  
  72. TreeModelItem* item = static_cast<TreeModelItem*>(index.internalPointer());
  73. QModelIndex p = index.parent();
  74.  
  75. if( item->childCount() && index.column() != 0)
  76. return QVariant();
  77. else
  78. return item->data( index.column() );
  79.  
  80. }
  81.  
  82. int BaseTreeModel::columnCount ( const QModelIndex & parent) const {
  83. if ( parent.isValid() ) {
  84. return static_cast<TreeModelItem*>(parent.internalPointer())->columnCount();
  85. } else {
  86. return rootItem ? rootItem->columnCount(): 0;
  87. }
  88.  
  89.  
  90. }
  91.  
  92. QVariant BaseTreeModel::headerData ( int section, Qt::Orientation orientation, int role ) const {
  93. if ( orientation == Qt::Horizontal && role == Qt::DisplayRole) {
  94. return rootItem->data(section);
  95. }
  96. return QVariant();
  97. }
  98.  
  99. int BaseTreeModel::rowCount ( const QModelIndex & parent ) const {
  100. TreeModelItem* parent_item;
  101. if (parent.column() > 0)
  102. return 0;
  103.  
  104. if (!parent.isValid())
  105. parent_item = rootItem;
  106. else
  107. parent_item = static_cast<TreeModelItem*>(parent.internalPointer());
  108.  
  109. return parent_item->childCount();
  110. }
  111.  
  112. bool BaseTreeModel::hasChildren ( const QModelIndex & parent ) const {
  113. if ( parent.isValid() ) {
  114. bool retVal = static_cast<TreeModelItem*>(parent.internalPointer())->childCount();
  115. return retVal;
  116. } else {
  117. return (bool)(rootItem->childCount());
  118. }
  119. }
  120.  
  121. Qt::ItemFlags BaseTreeModel::flags ( const QModelIndex & index ) const {
  122. if (!index.isValid())
  123. return 0;
  124. return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
  125. }
To copy to clipboard, switch view to plain text mode 

BaseTreeModel.h
Qt Code:
  1. class TreeModelItem;
  2.  
  3. #ifndef BASETREEMODEL_H
  4. #define BASETREEMODEL_H
  5.  
  6. #include <QAbstractItemModel>
  7.  
  8. class BaseTreeModel : public QAbstractItemModel {
  9. public :
  10. BaseTreeModel();
  11. ~BaseTreeModel();
  12.  
  13. // Minimum implementation for ReadOnly model
  14. virtual QModelIndex index ( int row, int column, const QModelIndex & parent = QModelIndex() ) const;
  15. virtual QModelIndex parent ( const QModelIndex & index ) const ;
  16. virtual QVariant data ( const QModelIndex & index, int role = Qt::DisplayRole ) const ;
  17. virtual QVariant headerData ( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const ;
  18. virtual int rowCount ( const QModelIndex & parent = QModelIndex() ) const;
  19. virtual int columnCount ( const QModelIndex & parent = QModelIndex() ) const ;
  20. virtual bool hasChildren ( const QModelIndex & parent = QModelIndex() ) const ;
  21. virtual Qt::ItemFlags flags ( const QModelIndex & index ) const ;
  22.  
  23. private :
  24. // internal model structure let's name it cache :)
  25. TreeModelItem *rootItem;
  26.  
  27. };
  28.  
  29. #endif // BASETREEMODEL_H
To copy to clipboard, switch view to plain text mode 

And the model item that is stored internally
TreeModelItem.cpp
Qt Code:
  1. #include "TreeModelItem.h"
  2. #include <QDebug>
  3.  
  4. TreeModelItem::TreeModelItem(QList<QVariant *> data, TreeModelItem *parent) : itemData(data), parentItem(parent) {
  5.  
  6. }
  7.  
  8. TreeModelItem::~TreeModelItem(){
  9.  
  10. }
  11.  
  12. void TreeModelItem::appendChild(TreeModelItem * child){
  13. childItems.append(child);
  14. }
  15.  
  16. void TreeModelItem::removeChild(TreeModelItem * child){
  17. childItems.removeOne( child );
  18. }
  19.  
  20. TreeModelItem * TreeModelItem::childAt(int row){
  21. if ( childItems.count() > row )
  22. return childItems.at( row );
  23. else
  24. return NULL;
  25. }
  26.  
  27. int TreeModelItem::childCount() const {
  28. return childItems.count();
  29. }
  30.  
  31. int TreeModelItem::columnCount() const {
  32. return itemData.count();
  33. }
  34.  
  35. QVariant TreeModelItem::data(int column) const {
  36. return *itemData.at( column );
  37. }
  38.  
  39. int TreeModelItem::row() const {
  40. if (parentItem)
  41. return parentItem->childItems.indexOf(const_cast<TreeModelItem*>(this));
  42.  
  43. return 0;
  44. }
  45.  
  46. TreeModelItem * TreeModelItem::parent(){
  47. return parentItem;
  48. }
  49.  
  50. void TreeModelItem::clear(){
  51. this->itemData.clear();
  52. }
To copy to clipboard, switch view to plain text mode 

TreeModelItem.h
Qt Code:
  1. #ifndef TREEMODELITEM_H
  2. #define TREEMODELITEM_H
  3.  
  4. #include <QList>
  5. #include <QVariant>
  6.  
  7. class TreeModelItem {
  8. public:
  9. TreeModelItem(QList<QVariant *> data, TreeModelItem *parent = 0);
  10. ~TreeModelItem();
  11. void appendChild(TreeModelItem * child);
  12. void removeChild(TreeModelItem * child);
  13.  
  14. TreeModelItem *childAt(int row);
  15.  
  16. int childCount() const;
  17. int columnCount() const;
  18. QVariant data(int column) const;
  19. int row() const;
  20.  
  21. TreeModelItem *parent();
  22. void updateColumn(int column, QVariant *data);
  23. void updateItem( const QMap<int, QVariant *> &data);
  24. void clear();
  25.  
  26. private:
  27. QList<TreeModelItem *> childItems;
  28. QList<QVariant *> itemData;
  29. TreeModelItem *parentItem;
  30. };
  31.  
  32. #endif // TREEMODELITEM_H
To copy to clipboard, switch view to plain text mode 

This tree is working. The structure right now is build in the constructor but only for the test purposes.

I want to create the base proxy model which will be transparent. I don't to have any fancy things inside at the firs step. If I've take QSortFilterProxyModel everything is Ok. But with QAbstractProxyModel it wan't work. I've implemented all the necessary virtual methods but I think that I'm doing this wrong. So the first step is to create transparent proxy based on QAbstaractProxyModel to understand the concept of source <-> proxy mapping.
Then later I want to create proxy for different aggregation/grouping, model flatten to table, adding a virtual columns etc..

Could somebody can help me with this issue to guide how to implement mapToSource, mapFromSource and index, parent etc... in this proxy on my model arch.