[Interest] Issue with QSortFilterProxyModel and Delegate
André Somers
andre at familiesomers.nl
Thu May 10 13:52:20 CEST 2012
Op 10-5-2012 13:45, David Boosalis schreef:
> Hope someone can help me here. I have a QTableView for which I use my
> own QSortFilterProxyModel and own Delegate which is based on
> QStyledItemDelegate. My issue is in the Delegates::paintEvent()
> I get core dumps if I have the following (Not using a proxy filter it
> works by the way):
>
> void DataDelegate::paint(QPainter *painter,
> const QStyleOptionViewItem &option,
> const QModelIndex &index) const
> {
> QStandardItem *item = 0;
> if (!index.isValid()) {
> qWarning() << "Invalid index" << __FILE__ << __LINE__;
> return;
> }
> QStyledItemDelegate::paint(painter,option,index);
> QStandardItemModel *m = (QStandardItemModel *) index.model();
> bool isWatched = index.data(Qt::UserRole+4).toBool();
> if ( (isWatched) && (index.column() == 0)) {
> item = (QStandardItem *) m->itemFromIndex(index); //
> <--------------- CORE DUMPS HERE------------------
> if (!item) {
> return;
> }
> .// continue to do some custom painting...
> ------------------------------------------------------------------------------------------------------------------------
>
> Now if I do something like this:
> void DataDelegate::paint(QPainter *painter,
> const QStyleOptionViewItem &option,
> const QModelIndex &proxyIndex) const
> {
> QStandardItem *item = 0;
> if (!proxyIndex.isValid()) {
> qWarning() << "Invalid proxy index" << __FILE__ << __LINE__;
> return;
> }
> QStyledItemDelegate::paint(painter,option,proxyIndex);
> if (!proxyFilter) { // store in Delegate class and is pointer to a
> class derived from QSortFilterProxyModel
> qWarning() << "Invalid model for data delegate" << __FILE__ <<
> __LINE__;
> return;
> }
> QModelIndex index = proxyFilter->mapToSource(proxyIndex);
> if (!index.isValid()) {
> // qWarning() << "Invalid index for data delegate" << __FILE__ <<
> __LINE__;
> return;
> }
> QStandardItemModel *m = (QStandardItemModel *) index.model();
> bool isWatched = index.data(Qt::UserRole+4).toBool();
> if ( (isWatched) && (index.column() == 0)) {
> item = (QStandardItem *) m->itemFromIndex(index); //
> if (!item) {
> return;
> }
> // continue to do some custom painting....
>
>
> This works, with the following ugly exception. I get a lot of run
> time warnings
> " QSortFilterProxy Model: index from wrong model passed to mapToSource"
>
> Despite these warnings I doI get my custom painting to occur. I would
> like to figure out a way to do it right so that I do not get thousands
> of these warning messages at runitme.
>
> Any suggestions on how to properly do a Delegate::paint() on a
> QTableView with a custom QSortFilterProxyModel is greatly appreciated.
>
>
> -David
That seems completely logical to me. As you found out, you need to check
any pointer you get back to see if it is not 0 before you dereference
it. In your case, your issue is that you're mixing indexes from your
proxy model and your source model. Don't do that. They can be mapped to
each other, but only by the proxy model itself.
Instead of trying to get a QStandardItem*, why don't use simply use the
actual data exposed throught the model API itself? Any data you need for
rendering should be available through the data() or flags() method.
Nothing more. What you are doing is tightly binding your delegate to the
model that feeds the data to the view. That will break down as soon as
you decide to change the model (or, as in your case, put a proxy between
the model and the view). Instead, you should limit yourself to the
interface you get from QAbstractItemModel. That is the only thing your
delegate should know about.
André
More information about the Interest
mailing list