[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