PDA

View Full Version : QTreeView + QAbstractItemModel + QSortFilterProxyModel = insertRows fails



KanareykaVBusikah
10th September 2013, 14:07
Hi,

I have successfully implemented QTreeView + QAbstractItemModel (both subclassed) tree, and insertRows works fine - puts new rows where I expect with no problems.

Now I need to add filtering to this construction. I add my QSortFilterProxyModel subclass between view and model and it filters fine too.
But here I have a problem with insertRows - it just crashes, and debugging doesn't help much.

I would appreciate some working example of such construction - "QTreeView + QAbstractItemModel + QSortFilterProxyModel + insertRows".
Or maybe a link to documentation part, that explains how QAbstractItemModel and QSortFilterProxyModel work together when I need to add a row.

high_flyer
10th September 2013, 14:58
Why doesn't the debugger help much?
If you run in the debugger you should get exactly the crashing line, this usually is more then enough to know what the problem is.

KanareykaVBusikah
10th September 2013, 15:23
Well... it may be a bit long to explain... It behaves unexpectedly somehow, for example:



bool ExTreeProxy::insertRows(int position, int rows, const QModelIndex &parent)
{
ExObject *parentItem = parentItem = getItem(mapToSource(parent)); // here is the 2nd breakpoint
...
}



and here how the function is called:


QModelIndex index = mTree->selectionModel()->currentIndex(); // mTree is QTreeView
int row;
QModelIndex parent;
if (!index.isValid()){
row = 0;
parent = QModelIndex();
}
else {
row = index.row()+1;
parent = index.parent();
}
mProxyModel->insertRows(row, 1, parent); // here is the 1st breakpoint

And I set 2 breakpoints
- on line, where this function is called;
- on the 1st line of this funcion (just in case - because I did not know what else to do - see later).
Then I run application, make it stop on the 1st breakpoint and I press "Go into the function".
And I immediatelly get an exception "Runtime Error! The application has requested the Runtime to terminate it in an unusual way... etc..."
and then error in Qt Developer console:


QSortFilterProxyModel: index from wrong model passed to mapToSource
ASSERT: "!"QSortFilterProxyModel: index from wrong model passed to mapToSource"" in file itemmodels\qsortfilterproxymodel.cpp, line 380


But I only entered the function - so mapToSource can not be called yet. So I can not even check the parent - if it is correct for mapping or not...
And my breakpoint is on the first line of the function too... but it don't stop on the breakpoint too...

There are lot's of such strange things with debugger... Sometimes it helps, but most of time it makes me desperate, that's all.
Maybe because I am a newbie in Qt and C++. Maybe because there is really something wrong with it.

high_flyer
10th September 2013, 16:11
Why do you do:

ExObject *parentItem = parentItem = ... // here is the 2nd breakpoint
?
Even though it is legal code, it suggests to me you are doing things wrong...

Try clean rebuilding, that would be the first easy thing to do.

wysota
10th September 2013, 16:58
What does getItem() do? What does the implementation of insertRows() in the model look like?

KanareykaVBusikah
11th September 2013, 09:37
Why do you do:

ExObject *parentItem = parentItem = ... // here is the 2nd breakpoint
?
Even though it is legal code, it suggests to me you are doing things wrong...

Try clean rebuilding, that would be the first easy thing to do.

Oh, I'm sorry, this line is a missprint, it is of course this:


ExObject *parentItem = getItem(mapToSource(parent));


Tried to rebuild - no difference.

Added after 4 minutes:


What does getItem() do?



ExObject *ExTreeProxy::getItem(const QModelIndex &index) const
{
if (index.isValid()) {
ExObject *item = static_cast<ExObject*>(index.internalPointer());
if (item)
return item;
}
return (static_cast<ExTree*>(sourceModel()))->getItem(QModelIndex());
}


ExObject here is a tree element. ExTree derived from QAbstractItemModel.


What does the implementation of insertRows() in the model look like?

Here is the complete insertRows():


bool ExTreeProxy::insertRows(int position, int rows, const QModelIndex &parent)
{
ExObject *parentItem = getItem(mapToSource(parent));
bool success;

beginInsertRows(parent, position, position + rows - 1);
success = parentItem->insertChildren(position, rows, parentItem->columnCount());
endInsertRows();

if(success) emit layoutChanged();
return success;
}

wysota
11th September 2013, 09:59
What if you check if parent is a valid index before passing it to mapToSource? What is the model of the index passed there, anyway?

KanareykaVBusikah
11th September 2013, 12:21
What if you check if parent is a valid index before passing it to mapToSource?
I will try, but don't see the point of it - parent is being defined just before insertRows() is called - you can see, how it is done, in comment #3.
For me it looks fine, and debugger shows normal parent - when I breakpoint on "mProxyModel->insertRows(row, 1, parent)".


What is the model of the index passed there, anyway?
Sorry, I am not sure I understand fully what you mean.
Could you explain? Or maybe the call in comment #3 will help? Getting parent and insertRows() call are shown there.
It is taken from tree selection model - so, I think it is proxy model index. Am I wrong?

wysota
11th September 2013, 13:43
I will try, but don't see the point of it - parent is being defined just before insertRows() is called - you can see, how it is done, in comment #3.
And it can be an empty model index...


Sorry, I am not sure I understand fully what you mean.
What is the object returned from QModelIndex::model() for that index. Is it the proxy model instance or some other model.

KanareykaVBusikah
11th September 2013, 14:15
And it can be an empty model index...
It is not empty definitely, this I did have checked (debuger shows row index there and correct object data and so on).


What is the object returned from QModelIndex::model() for that index. Is it the proxy model instance or some other model.
Oh, thanks really! I did not grasp, I could check the model :)
Will try.

KanareykaVBusikah
3rd October 2013, 11:55
Hello again!
Sorry for long absence - there just was some important and pressing issues to be done in my life.

The idea of QModelIndex::model() helped me to understand some details, but I advanced only a little.
Now I see something in gdb output, that I can not understand and explain - I expect different to see.
I was sure I am experienced enough to understand, but no, what I see makes me completely desperate.

I made a pair of screenshot, so I hope you can help me to explain what I see - and WHY I see it.
These are screenshots of debugging insertRow.
To run the function - I a) select an item in my tree and b) enter some text (pSubject variable). Then the function is called.

9665
On this picture you see:
- I stoped at "QModelIndex index = index from selection model"
- Pressed "F10" to move to the next statement.
Now I see the correct index variable: column = 0, row = 9, model = ExTreeProxy (that is proxy model).
It is marked with red rectangles.
So, it's everything ok on this sceen.

Then come oddnesses:
9666

Here you see
1) mark "1" on the picture - shows what I get after statement "sourceIndex = map from index".
As I selected index - I see it in the tree, I get it correctly from selection model - so, I expect to have correct sourceIndex.
But I get invalid one.
2) mark "2" on the picture - shows what I get when I go into "else" branch.
There is an incorrect index (column=0, row=0). What is it? On what reason index changed?

I thought this might be some errors in debugger - and I have build gdb from source.
But this did not help. I see the same oddnesses again.

Can you help in any way? Explain why I see this for the beginning...