You were right, splitting mapping and filtering made it working.
Big thanks for the help.
Wojtek
You were right, splitting mapping and filtering made it working.
Big thanks for the help.
Wojtek
This thread is rather old but ....
I have the similar problem, a tree model subclassed from QStandardItemModel. I try to get familiar with the QAbstractProxyModel by subclassing it. At the first moment I just want to let it work in by-pass mode, all items should reach the view unchanged. But even that does not work, it crashed when I try to expand a node.
I reimplement the methods: index(), mapToSource(), mapFromSource() and parent() but somehow I dont really understand how the createIndex() method works in conjunction with parent() and index()
Can you give me an approach to this issue?
Thanks
Seroti
The only way to make generic tree models work through a proxy is to subclass either QIdentityProxyModel or QSortFilterProxyModel. In a general case going by subclassing QAbstractProxyModel will not work because there is no way to reliably reimplement parent().
@d_stranz: can you give me an example how you implemented the mapping foe your problem by subclassing the QAbstractProxyModel. It would help me alot to understand how to reimplement the required methods. Thanks
Last edited by Seroti; 18th August 2013 at 21:57.
@d_stranz: can you give me an example how you implemented the mapping foe your problem by subclassing the QAbstractProxyModel. It would help me alot to understand how to reimplement the required methods. Thanks
Added after 1 41 minutes:
But the QSortFilterProxyModel is subclassed from QAbstractProxyModel and it also works with a generic three model. If you dont filter anything, you get the original data from your source model, isn't it ? Can you explain your statement further? I really want to understand, especially whyThe only way to make generic tree models work through a proxy is to subclass either QIdentityProxyModel or QSortFilterProxyModel. In a general case going by subclassing QAbstractProxyModel will not work because there is no way to reliably reimplement parent().
As you stated in the previous replies, I cannot use QSortFilterProxyModel to do the mapping because it uses its own I cannot reimplement the maptoSource and mapFromSource methods, so for a non-generic tree model I have to subclass QAbstractProxyModel to do the mapping.
My problem in the following is rather simple for experienced Qt persons I think. But I do not really know how to start, especially the parent() & index() method
A tree model subclassed by QStandardItemModel.
Name--------------|Value-----|--SpecialValue
A --------------------------------------
|- B------------------------------------
---|-par1----------|---111----|
-------|par1.1-----|---1.1-----|
----|-par2---------|---222-----|
----|-parSpe-------|---XXX----|
----|-par3---------|---333-----|
-|-C---------------|------------
---|-D-------------|------------
----|--E-----------|-----------
-------|-par4 -----|--444-----|
-------|-par5 -----|--555-----|
----------|-par5.1-|--555.111-|
-------|-par6 -----|-----------|
-------|-parSpe---|--ZZZ-----|
-------|-par7 -----|--777-----|
I want to map the value XYZ of the "parSpe" item to the column "SpecialValue" of its parent, e.g of item "B" or "E" in this case. The item "parSpe" itself will not be displayed.
Name--------------|Value-----|--SpecialValue
A --------------------------------------
|- B---------------|----------|----XXX---
---|-par1----------|---111----|-------------
-------|par1.1-----|---1.1-----|--------------
----|-par2---------|---222-----|--------------
----|-par3---------|---333-----|--------------
-|-C---------------|-------------------------
---|-D-------------|-------------------------
----|--E-----------|-----------|-----ZZZ
-------|-par4 -----|--444-----|--------------
-------|-par5 -----|--555-----|--------------
----------|-par5.1-|--555.111-|--------------
-------|-par6 -----|-----------|--------------
-------|-par7 -----|--777-----|--------------
The upper level item A B C D E dont have any further items on column "Value" and "SpecialValue" per default. The column "SpecialValue" is thus a vitual column.
The hierahchy level of the items "parSpe" is not fix but the item "parSpe" itself can be detected by data(QtUserRole +x).
The row number of item "parSpe" is not fix, so I intend to code its row number during mapFromSource() (or after building the source tree) with setData(), so that I have a chance to map it back. Is it ok?
Is it a correct approach to subclass QAbstractProxyModel to solve this problem?
Can someone give me an example how to proceed? especially the parent() & index() method
Thanks in advance
That's why I said you could subclass that or QIdentityProxyModel. Qt internal classes have access to some APIs that external classes don't.
At some point you have to call createIndex() on the source model and that method is protected. QIdentityProxyModel works around it by being made a friend of QAbstractItemModel. Since you can't add friends to existing classes, your own class cannot repeat this pattern. The only thing you can do is to make a proxy model operate on your own subclass of QAbstractItemModel that will explicitly make createIndex() public (or expose some other equivalent method) which breaks one of the fundamental rules of Qt's model-view pattern that only the model itself can create valid indexes for its items.As you stated in the previous replies, I cannot use QSortFilterProxyModel to do the mapping because it uses its own I cannot reimplement the maptoSource and mapFromSource methods, so for a non-generic tree model I have to subclass QAbstractProxyModel to do the mapping.
The bottom line is that instead of putting your effort into subclassing QAbstractProxyModel, better subclass a class more suitable for your goal.
I don't understand why you want to use a proxy here. Why not implement a custom model whatsoever instead of using QStandardItemModel with a proxy?Is it a correct approach to subclass QAbstractProxyModel to solve this problem?
Seroti (19th August 2013)
The reason why I intended to do the index mapping by subclassing QAbstractProxyModel is that I avoid to touch the existing tree model, which is not implemented by myself.
I cannot use QIdentityProxyModel either because the overall project uses Qt of lower version.
According to your advices and due to the circumstances I have no choice but to touch the existing tree model at the end.
While we are at it, can you explain why ? I'm just interestedIn a general case going by subclassing QAbstractProxyModel will not work because there is no way to reliably reimplement parent().
Thanks a lot for your help & explanation
I didn't say that. Maybe if we had more information about the model, we might suggest a better approach. However based on the vague ascii art you gave us it is not possible to suggest anything better.
To create an index you need three values -- the index row, the index column and the index internal value (id or pointer). The only thing that differs between an index with row 0 and column 0 from its parent (or any other index that has rows and columns set to 0) is the internal value. QSortFilterProxyModel keeps an internal mapping of all nodes (twice -- once in each direction) between models to be able to return that value which then allows to find the index in the source model. QIdentityProxyModel in turn returns the internal value of the original model's index. But for that it needs to call mapToSource() with the index in the proxy. Since it doesn't have any information that lets it find the proper index in the base model, it just creates an index (on behalf of the source model) with the same row and column and the internal value and calls parent() on that, maps it back to itself and calls createIndex() using that value. Something along the lines of:While we are at it, can you explain why ? I'm just interested
Qt Code:
return createIndex(parentIndex.row(), parentIndex.column(), parentIndex.internalId()); } return sourceModel()->createIndex(proxyIndex.row(), proxyIndex.column(), proxyIndex.internalId()); // createIndex() is protected! }To copy to clipboard, switch view to plain text mode
You can work around this with a really nasty hack:
Qt Code:
public: QModelIndex myHackedCreateIndex(int row, int column, qint64 internalId) const { return createIndex(row, column, internalId); } }; const MyHackedModel *hackedModel = static_cast<const MyHackedModel*>(sourceModel()); // whaam! h4x0r! return hackedModel->myHackedCreateIndex(proxyIndex.row(), proxyIndex.column(), proxyIndex.internalId()); }To copy to clipboard, switch view to plain text mode
... but you know, it's a nasty... hackAnd if someone asks -- you don't know it from me.
Last edited by wysota; 19th August 2013 at 21:14.
tried a little bit about mapToSource() and mapToProxy() for QSortFilterProxyModel.
But somehow I decided to make a copy of data and move the data there.
Bookmarks