Wrong QModelIndex on QTreeView using custom QSortFilterProxy

Wrong QModelIndex on QTreeView using custom QSortFilterProxyModel

本文关键字:custom QSortFilterProxy using QTreeView QModelIndex on Wrong      更新时间:2023-10-16

我有一个基于充满子类化QStandardItem QStandardItemModelQTreeView。Item-sublcass只有另外两个数据指针,并且不会以任何其他方式影响项目,因此PTSModelItem的行为类似于QStandardItem

我通过子类化filterAcceptsRow()来使用自定义QSortFilterProxyModel来启用对自定义数据指针的过滤。

treeView显示正确,直到我启用过滤器。然后,List 元素永远不会被过滤掉,子元素在列表中完全缺失(不是子匹配)或完全显示(至少一个子匹配)。

我遇到的问题,即使source_row增加,filterAcceptsRow()中生成的索引始终是列表元素(rootItem的孩子)。

具有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());

返回的项目始终是List1List2,即使source_row为 0,1,2。

填充模型(列表项仅包含文本和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
}

QStandardItemModel 要求你不要使用 internalPointer() 方法,但

QStandardItemModel::itemFromIndex()

因此,通过将filterAcceptsRow中的项目检索更改为:

PTSModelItem* item = static_cast<PTSModelItem*>(static_cast<QStandardItemModel*>(sourceModel())->itemFromIndex(usedIndex));

答案是mapToSource。

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

用法示例

QModelIndex realIndex = mapToSource(index);