PDA

View Full Version : Deriving QAbstractProxyModel : table to tree



moijhd
5th October 2015, 19:51
Hi,

I'd like to make a tree from a table. How to reimplement the map functions ?

I see this question a lot but no answer. I would be okay with an example.

Thanks,

d_stranz
14th October 2015, 03:45
Making a tree from a table makes no sense. Trees are hierarchical, with a root node (usually invisible), top level nodes, children of the top level nodes, and so forth. Tables are flat - every row in the table would become a top-level tree node with no children below them.

It is more common to want to flatten a tree into a table, by turning each leaf node into a row, with columns containing the repeating parent items. There is a kptflatproxymodel class in KDE that does exactly this.

Maybe you need to explain some more what exactly you want your tree to look like, and maybe that will help you understand what the map functions should do.

moijhd
15th October 2015, 17:48
Hi,

What I am trying to achieve is basic (I think, still can't do it...).

Table :



Id | n0 | n1
1 | 1 | 1
2 | 1 | 2
3 | 2 | 1
4 | 2 | 2


Expected tree with grouping by n0 :



Id | n0 | n1
+ 1 | 1 | -
+---1 | 1 | 1
+---2 | 1 | 2
+ 3 | 2 | -
+---3 | 2 | 1
+---4 | 2 | 2


The table structure is a constraint.

anda_skoa
15th October 2015, 18:14
Your proxy needs to hold a tree structure of data that it can use to map between the source and its own indexes.

If the depth is always just 2, then a list of nodes should be sufficient, where each node holds range of source rows belonging to a certain top level know (assuming n0 is sorted)

Something like


struct TopLevel {
int beginRow;
int endRow;
};


It is best to do this on paper first.
Your example would be something like a


[(0, 1), (2, 3)]

Each top level index in our proxy refers to one of these structs, their children one entry per index in the struct's range.

Cheers,
_

moijhd
16th October 2015, 22:15
Okay for the structure (I can't actually do it because I have millions of rows but let's forget about that for the moment).

Now, if I am able to define which index (source or proxy) is top level, how do I map ie what should I return ?

In the following code, we assume that the Qt::UserRole + i are well defined :



QModelIndex
ProxyModel::mapFromSource(
const QModelIndex &sourceIndex
) const
{
// Check if the index is valid
if(!sourceIndex.isValid())
{
// Not a valid index
return QModelIndex();
}

// Check if the index is a top level node in the proxy
if(sourceIndex.data(Qt::UserRole).toBool())
{
// Row in the proxy
int proxyRow;

// Get the row in the proxy
proxyRow = sourceIndex.data(Qt::UserRole + 1);

// This is a top level node in the proxy
return index(
proxyRow,
0
);
}
else
{
// This is a node under a top level node in the proxy
// Let's ignore it for now
return QModelIndex();
}
}

QModelIndex
ProxyModel::mapToSource(
const QModelIndex &proxyIndex
) const
{
// Check if the index is valid
if(!proxyIndex.isValid())
{
// Not a valid index
return QModelIndex();
}

// Check if the index has a parent
if(proxyIndex.parent() == QModelIndex())
{
// Row in the source
int sourceRow;

// Get the row in the proxy
sourceRow = proxyIndex.data(Qt::UserRole + 2);

// Top level node in the proxy
return sourceModel()->index(
sourceRow,
0
);
}
else
{
// This is a node under a top level node in the proxy
// Let's ignore it for now
return QModelIndex();
}
}


Is this correct ?