Description comes from a patch that I'll post on reviewboard shortly. Note that this problem results in folders not getting displayed in kmail if you're unlucky enough (it's fairly random), so it's somewhat critical. The model was not working properly and didn't include all items under some circumstances. This patch fixes the following scenarios in particular: * The change in sourceDataChanged is required to fix the shortcut condition. The idea is that if the parent is already part of the model (it must be if acceptRow returns true), we can directly invoke dataChanged on the parent, resulting in the changed index getting reevaluated. However, because the recursive filterAcceptsRow version was used the shortcut was also used when only the current index matches the filter and the parent index is in fact not yet in the model. In this case we failed to call dataChanged on the right index and thus the complete branch was never added to the model. * The change in refreshAscendantMapping is required to include indexes that were included by descendants. The intended way how this was supposed to work is that we traverse the tree upwards and find the last index that is not yet part of the model. We would then call dataChanged on that index causing it and its descendants to get reevaluated. However, acceptRow does not reflect wether an index is already in the model or not. Consider the following model: - A - B - C - D If C is include in the model by default but D not and A & B only gets included due to C, we have the following model: - A - B - C - D If we then call refreshAscendantsMapping on D it will not consider B as already being part of the model. This results in the toplevel index A being considered lastAscendant, and a call to dataChanged on A results in a reevaluation of A only, which is already in the model. Thus D never gets added to the model. Unfortunately there is no way to probe QSortFilterProxyModel for indexes that are already part of the model. Even the const mapFromSource internally creates a mapping when called, and thus instead of revealing indexes that are not yet part of the model, it silently creates a mapping (without issuing the relevant signals!). As the only possible workaround we have to issues dataChanged for all ancestors which is ignored for indexes that are not yet mapped, and results in a rowsInserted signal for the correct indexes. It also results in superfluous dataChanged signals, since we don't know when to stop, but at least we have a properly behaving model this way. Reproducible: Always Steps to Reproduce: 1. Run the unitests
Git commit 0df92439241a76c6a67efa9485bd95c3c25d63a0 by Christian Mollekopf. Committed on 22/01/2015 at 14:04. Pushed by cmollekopf into branch 'KDE/4.14'. KRecursiveFilterProxyModel: Fixed the model The model was not working properly and didn't include all items under some circumstances. This patch fixes the following scenarios in particular: * The change in sourceDataChanged is required to fix the shortcut condition. The idea is that if the parent is already part of the model (it must be if acceptRow returns true), we can directly invoke dataChanged on the parent, resulting in the changed index getting reevaluated. However, because the recursive filterAcceptsRow version was used the shortcut was also used when only the current index matches the filter and the parent index is in fact not yet in the model. In this case we failed to call dataChanged on the right index and thus the complete branch was never added to the model. * The change in refreshAscendantMapping is required to include indexes that were included by descendants. The intended way how this was supposed to work is that we traverse the tree upwards and find the last index that is not yet part of the model. We would then call dataChanged on that index causing it and its descendants to get reevaluated. However, acceptRow does not reflect wether an index is already in the model or not. Consider the following model: - A - B - C - D If C is included in the model by default but D not, and A & B only get included due to C, we have the following model: - A - B - C If we then call refreshAscendantsMapping on D it will not consider B as already being part of the model. This results in the toplevel index A being considered lastAscendant, and a call to dataChanged on A results in a reevaluation of A only, which is already in the model. Thus D never gets added to the model. Unfortunately there is no way to probe QSortFilterProxyModel for indexes that are already part of the model. Even the const mapFromSource internally creates a mapping when called, and thus instead of revealing indexes that are not yet part of the model, it silently creates a mapping (without issuing the relevant signals!). As the only possible workaround we have to issues dataChanged for all ancestors which is ignored for indexes that are not yet mapped, and results in a rowsInserted signal for the correct indexes. It also results in superfluous dataChanged signals, since we don't know when to stop, but at least we have a properly behaving model this way. REVIEW: 120119 M +9 -19 kdeui/itemviews/krecursivefilterproxymodel.cpp M +1 -0 kdeui/tests/CMakeLists.txt A +220 -0 kdeui/tests/krecursivefilterproxymodeltest.cpp [License: LGPL (v2+)] http://commits.kde.org/kdelibs/0df92439241a76c6a67efa9485bd95c3c25d63a0