Неправильный индекс QModelIndex в QTreeView с использованием пользовательской модели QSortFilterProxyModel

У меня есть QTreeView на основе QStandardItemModel, заполненного подклассами QStandardItem. Подкласс Item просто имеет еще два указателя данных и не влияет на элемент каким-либо другим образом, поэтому PTSModelItem ведет себя как QStandardItem.

Я использую пользовательский QSortFilterProxyModel, создав подкласс filterAcceptsRow(), чтобы включить фильтрацию пользовательских указателей данных.

treeView отображается правильно, пока я не включу фильтр. Тогда элемент списка никогда не отфильтровывается, а дочерние элементы полностью отсутствуют в списке (не соответствуют дочерним элементам) или полностью отображаются (по крайней мере, один дочерний элемент соответствует).

Проблема, с которой я сталкиваюсь, заключается в том, что сгенерированный индекс в filterAcceptsRow() всегда является элементом списка (дочерним элементом rootItem) даже при увеличении source_row.

Модель со значениями параметров для filterAcceptsRow(int source_row, QModelIndex source_parent):

RootItem (invisible)
|-List1            
| |-Child1         
| |-Child2
| |-Child3
|-List2
| |-Child1
| |-Child4

Проблема в том, что, независимо от исходной строки, вызов

QModelIndex itemIndex = sourceModel()->index(source_row,i,source_parent);
if(!itemIndex.isValid())
     continue;
PTSModelItem* item = static_cast<PTSModelItem*>(itemIndex.internalPointer());

Возвращаемый элемент всегда List1 или List2, даже если source_row равен 0,1,2.

Заполнение модели (listitem просто содержит текст и QList из "childText":

QStandardItemModel *model = new QStandardItemModel();
QStandardItem *rootItem = model->invisibleRootItem();
foreach(PTSItem* listItem, modelItemList)
{
    PTSModelItem *item = new PTSModelItem(tr("List: %1").arg(listItem->getListNumber()),listItem,0,PTSModelItem::ITEM_TYPE_LISTNUMBER);
    item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
    rootItem->appendRow(item);

    PTSModelItem *identTitle = new PTSModelItem("",listItem,0,PTSModelItem::ITEM_TYPE_IDENTEMPTY);
    identTitle->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
    rootItem->setChild(item->row(),1,identTitle);

    PTSModelItem *readDateItem = new PTSModelItem(tDateString,listItem,0,PTSModelItem::ITEM_TYPE_CREATED);
    readDateItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
    rootItem->setChild(item->row(),2,readDateItem);

    PTSModelItem *writeDateItem = new PTSModelItem(tDateString,listItem,0,PTSModelItem::ITEM_TYPE_LASTSET);
    writeDateItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
    rootItem->setChild(item->row(),3,writeDateItem);

    for(int i=0; i<listItem->size();i++)
    {
        QList<QStandardItem*> childItems;

        PTSModelItem *toolItem = new PTSModelItem(tr("T%1").arg(listItem->getToolNumber(i)),listItem,i,PTSModelItem::ITEM_TYPE_TOOLNUMBER);
        toolItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
        childItems.append(toolItem);

        PTSModelItem *identItem = new PTSModelItem(listItem->getIdentNumber(i),listItem,i,PTSModelItem::ITEM_TYPE_IDENTNUMBER);
        identItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
        childItems.append(identItem);

        PTSModelItem *readDate = new PTSModelItem("",listItem,i,PTSModelItem::ITEM_TYPE_CREATEDVALID);
        readDate->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
        childItems.append(readDate);

        PTSModelItem *writeDate = new PTSModelItem("",listItem,i,PTSModelItem::ITEM_TYPE_LASTSETVALID);
        writeDate->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
        childItems.append(writeDate);

        item->appendRow(childItems);
    }
}

Реализация фильтра:

bool PTSFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{

    QModelIndex itemIndex = sourceModel()->index(source_row,0,source_parent);
    if(!itemIndex.isValid())
        return false;
    PTSModelItem* item = static_cast<PTSModelItem*>(itemIndex.internalPointer());

    QString text = item->text();              // THIS always return ListN
    if(item->type() == QStandardItem::Type)
    {
        if(item == static_cast<QStandardItemModel*>(sourceModel())->invisibleRootItem())
            return true;
    }

    //Custom filtering starts here but breaks, since item is always only the List-element
}

person Sebastian Lange    schedule 07.03.2015    source источник


Ответы (2)


QStandardItemModel требует, чтобы вы не использовали метод internalPointer(), а

QStandardItemModel::itemFromIndex()

Итак, проблема решена путем изменения поиска элемента в filterAcceptsRow на:

PTSModelItem* item = static_cast<PTSModelItem*>(static_cast<QStandardItemModel*>(sourceModel())->itemFromIndex(usedIndex));
person Sebastian Lange    schedule 07.03.2015

Ответ: mapToSource.

QModelIndex QSortFilterProxyModel::mapToSource(const QModelIndex &proxyIndex) const

Пример использования:

QModelIndex realIndex = mapToSource(index);

person Doug Beney    schedule 27.11.2018