tgoetz
17th May 2017, 20:17
[SIZE=2]Hello,
I'm using QTreeView with a QAbstractItemModel to display my data in a hierarchical tree. Each object has a couple of properties like owner and type and I'm using these properties to create dummy items in my tree to group the data, like this:
root
- type_1
- object_1
- object_2
- type_2
- object_n
Now the user should be able to re-group the data, i.e. by owner not type like this:
root
- owner_1
- object_2
- object_3
- owner_2
- object_1
I have added a resortTree(mode) method to my AbstractItemModel class and the class also contains a std::vector of pointers to the object that is used to fill the tree the first time it is generated.
[SIZE=2]
class DatasetTreeModel: public QAbstractItemModel
{
Q_OBJECT
public:
enum TreeSortMode
{
DatasetType = 0,
DatasetOwner = 1,
DatasetCreation = 2,
};
DatasetTreeModel(std::vector<Dataset*> _data, TreeSortMode = DatasetType, QWidget* _pParent = NULL);
~DatasetTreeModel();
...
void resortTree(TreeSortMode = DatasetType);
private:
std::vector<Dataset*> m_vDatasets;
}
The implementation looks like this:
void DatasetTreeModel::resortTree(TreeSortMode _sorting)
{
switch (_sorting)
{
case DatasetType:
{
// creates dummy parent items for the actual objects
for (int j = 0; j < (int) Dataset::NumberOfTypes; j++)
{
m_pRootItem->insertChildren(m_pRootItem->childCount(), 1);
m_pRootItem->child(m_pRootItem->childCount() - 1)->setName(Dataset::typeToString((Dataset::DatasetTyp e) j));
m_pRootItem->child(m_pRootItem->childCount() - 1)->setType(Dataset::undefined);
}
// inserts the actual objects as children to the matching dummy parents
for (int i = 0; i < m_vDatasets.size(); i++)
{
Dataset::DatasetType type = m_vDatasets[i]->getType();
DatasetTreeItem* parent = m_pRootItem->child(type);
if (!parent->insertChildren(parent->childCount(), 1))
{
std::cerr << "Error inserting child into Dataset tree" << std::endl;
}
if (!parent->child(parent->childCount() - 1)->setDataset(m_vDatasets[i]))
{
std::cerr << "Error inserting Dataset object into DatasetTreeItem" << std::endl;
}
}
break;
}
case DatasetOwner:
{
...
}
}
}
The method works well when I call it the first time. However, when I call the method again, I get an memory access error because the std::vector with the objects somehow got corrupted. I can't find any place where this corruption can happen, however, all activities on it are read-only with one single exception:
DatasetTreeModel::DatasetTreeModel(std::vector<Dataset*> _data, TreeSortMode _sorting, QWidget* _pParent)
: QAbstractItemModel(_pParent)
{
m_pRootItem = new DatasetTreeItem(QString("%1 Files").arg(_data.size()));
m_pRootItem->setType(Dataset::undefined);
m_vDatasets = _data;
resortTree(_sorting);
}
I'm not set on using this method, if there is any way to restructure a tree efficiently in the way I've described it, I'm happy to use that one.
Thanks!
I'm using QTreeView with a QAbstractItemModel to display my data in a hierarchical tree. Each object has a couple of properties like owner and type and I'm using these properties to create dummy items in my tree to group the data, like this:
root
- type_1
- object_1
- object_2
- type_2
- object_n
Now the user should be able to re-group the data, i.e. by owner not type like this:
root
- owner_1
- object_2
- object_3
- owner_2
- object_1
I have added a resortTree(mode) method to my AbstractItemModel class and the class also contains a std::vector of pointers to the object that is used to fill the tree the first time it is generated.
[SIZE=2]
class DatasetTreeModel: public QAbstractItemModel
{
Q_OBJECT
public:
enum TreeSortMode
{
DatasetType = 0,
DatasetOwner = 1,
DatasetCreation = 2,
};
DatasetTreeModel(std::vector<Dataset*> _data, TreeSortMode = DatasetType, QWidget* _pParent = NULL);
~DatasetTreeModel();
...
void resortTree(TreeSortMode = DatasetType);
private:
std::vector<Dataset*> m_vDatasets;
}
The implementation looks like this:
void DatasetTreeModel::resortTree(TreeSortMode _sorting)
{
switch (_sorting)
{
case DatasetType:
{
// creates dummy parent items for the actual objects
for (int j = 0; j < (int) Dataset::NumberOfTypes; j++)
{
m_pRootItem->insertChildren(m_pRootItem->childCount(), 1);
m_pRootItem->child(m_pRootItem->childCount() - 1)->setName(Dataset::typeToString((Dataset::DatasetTyp e) j));
m_pRootItem->child(m_pRootItem->childCount() - 1)->setType(Dataset::undefined);
}
// inserts the actual objects as children to the matching dummy parents
for (int i = 0; i < m_vDatasets.size(); i++)
{
Dataset::DatasetType type = m_vDatasets[i]->getType();
DatasetTreeItem* parent = m_pRootItem->child(type);
if (!parent->insertChildren(parent->childCount(), 1))
{
std::cerr << "Error inserting child into Dataset tree" << std::endl;
}
if (!parent->child(parent->childCount() - 1)->setDataset(m_vDatasets[i]))
{
std::cerr << "Error inserting Dataset object into DatasetTreeItem" << std::endl;
}
}
break;
}
case DatasetOwner:
{
...
}
}
}
The method works well when I call it the first time. However, when I call the method again, I get an memory access error because the std::vector with the objects somehow got corrupted. I can't find any place where this corruption can happen, however, all activities on it are read-only with one single exception:
DatasetTreeModel::DatasetTreeModel(std::vector<Dataset*> _data, TreeSortMode _sorting, QWidget* _pParent)
: QAbstractItemModel(_pParent)
{
m_pRootItem = new DatasetTreeItem(QString("%1 Files").arg(_data.size()));
m_pRootItem->setType(Dataset::undefined);
m_vDatasets = _data;
resortTree(_sorting);
}
I'm not set on using this method, if there is any way to restructure a tree efficiently in the way I've described it, I'm happy to use that one.
Thanks!