PDA

View Full Version : QSortFilterProxyModel Crashing with QTableView when Row Changed



TabletopLaptop
14th June 2016, 18:25
I am new to Qt, so this could be an error on my end. I am having a strange issue with my application where when I change a row of the table to something that would now be filtered out of the table by the QSortFilterProxyModel, the application crashes. I have attached my code as I think it is pretty minimal test case.

Ways to cause crash:
1. "search" filtering
a. type amy in search bar
b. edit customer name, change to henry
c. click away and it will crash
2. "open job" filtering
a. be on open jobs tab
b. change status of job to 8
c. click away and it will crash

I believe the crash is an index out of bounds on a vector that occurs when the filter removes that row from the table. I have no idea how to make it have this behavior without crashing.

The relevant code is in the MainWindow constructor.

Any help is much appreciated.

11979

jefftee
16th June 2016, 16:07
Let me preface my comments by stating that I have never attempted what you appear to be doing, which is having multiple QSortFilterProxyModel's chained/used. Not saying it shouldn't work, but right off the bat it seems odd to me... :) Is there a reason your OpenJobSortFilterProxyModel isn't used for both the sorting and filtering you're trying to achieve by instead attempting to use using multiple QSortFilterProxyModel's?

I believe because you're using multiple views with multiple QSortFilterProxyFilter's that all have the same underlying data model, that is why your app is crashing. I would suggest that you simplify and once you get that working, and only then add in complexity.

For example, take one of your views, use one QSortFilterProxyFilter subclass for the QSqlModel data model. Make that work without failing, then try to add in additional functionality.

Good luck.

d_stranz
16th June 2016, 16:35
In principle, there is no problem with chaining multiple QSortFilterProxyModel instances by using one as the source model for the next. If your model is a bag of marbles, your can write a sort/filter to pull out all of the green and blue ones. That gets chained to a successive sort filter that pulls out just the blue ones and sorts them by decreasing prettiness.

The trick is getting the correct mapping of model indexes up and down the chain. If changes in the source model are not propagated correctly down the chain when rows are added or removed, then the model indexes used by the views that display the sort / filter results will refer to invalid entries in the source model.

I did exactly this kind of thing: a tree-shaped model was flattened into a table-shaped model using a proxy. This table model had another proxy to support sorting and filtering and adding "phantom" columns containing data that wasn't in the original model but could be computed on the fly from values stored in other data elements that were present. Finally, a set of additional proxies selected out pairs of columns in the table so the data in them could be plotted in x,y scatterplots (each of which was derived from QAbstractItemView). The most difficult part was getting all of the model index lookups correct, particularly when the table was sorted or had the columns rearranged in the UI.

That said, I agree with Jefftee: build up from a simple case - one model and one view, and ensure it works. Then insert a sort / filter in between the model and view and ensure that works under all test conditions. Repeat with additional proxies and views until the whole thing works correctly.

jefftee
16th June 2016, 17:43
In principle, there is no problem with chaining multiple QSortFilterProxyModel instances by using one as the source model for the next.
Thanks @d_stranz, I suspected that it should work and be supported, but had not done so myself... One odd part about the OP's code/project he attached, was that he had created a QSortFilterProxyModel subclass but it wasn't actually used in his code (no doubt they are trying lots of different things to make it work).

In the version of the code he uploaded. Their code simply created multiple QSortFilterProxyModel instances using "new QSortFilterProxyModel", so no subclassing going on, which I think is relevant to your point about keeping model indexes straight. The crash is a QVector index out of bounds error, which my guess is related to one view/model changing the underlying data model, which is used by other views/models and they're not being informed that the underlying data has changed, etc.

TabletopLaptop
18th June 2016, 02:24
In principle, there is no problem with chaining multiple QSortFilterProxyModel instances by using one as the source model for the next. If your model is a bag of marbles, your can write a sort/filter to pull out all of the green and blue ones. That gets chained to a successive sort filter that pulls out just the blue ones and sorts them by decreasing prettiness.

The trick is getting the correct mapping of model indexes up and down the chain. If changes in the source model are not propagated correctly down the chain when rows are added or removed, then the model indexes used by the views that display the sort / filter results will refer to invalid entries in the source model.

I did exactly this kind of thing: a tree-shaped model was flattened into a table-shaped model using a proxy. This table model had another proxy to support sorting and filtering and adding "phantom" columns containing data that wasn't in the original model but could be computed on the fly from values stored in other data elements that were present. Finally, a set of additional proxies selected out pairs of columns in the table so the data in them could be plotted in x,y scatterplots (each of which was derived from QAbstractItemView). The most difficult part was getting all of the model index lookups correct, particularly when the table was sorted or had the columns rearranged in the UI.

That said, I agree with Jefftee: build up from a simple case - one model and one view, and ensure it works. Then insert a sort / filter in between the model and view and ensure that works under all test conditions. Repeat with additional proxies and views until the whole thing works correctly.


Thanks @d_stranz, I suspected that it should work and be supported, but had not done so myself... One odd part about the OP's code/project he attached, was that he had created a QSortFilterProxyModel subclass but it wasn't actually used in his code (no doubt they are trying lots of different things to make it work).

In the version of the code he uploaded. Their code simply created multiple QSortFilterProxyModel instances using "new QSortFilterProxyModel", so no subclassing going on, which I think is relevant to your point about keeping model indexes straight. The crash is a QVector index out of bounds error, which my guess is related to one view/model changing the underlying data model, which is used by other views/models and they're not being informed that the underlying data has changed, etc.

Thanks to both of you for replying. I changed it to just being the QSqlTableModel and everything worked (I am not able to remove stuff from view in any way). I then changed it to just the search filter and it was crashing; I also did the same with the open jobs filter only on top of the sql model and it was giving me the same index out of bounds error. I even tried turning off the dynamic sort filter and same error. I honestly have no idea where this is going wrong.

jefftee
18th June 2016, 03:18
Re-post your code with only the search filter please.

TabletopLaptop
20th June 2016, 16:11
Re-post your code with only the search filter please.

Here is a cleaned up example case I made. The issue is when editing data currently in the table that will disappear when the edit is submitted.
11990