通过项目数据从QStandardItemModel查找/删除行

时间:2019-06-30 21:24:56

标签: c++ qt5 qstandarditemmodel qstandarditem

我有一个QStandardItemModel,其中只有一列(代表一个列表)。列表中的每个项目都有一个唯一的整数ID,作为QStandardItem的数据存储(通过QStandardItem::setData,我猜默认是通过Qt::UserRole+1来存储的。)

给出这些ID之一,我想从模型中查找并删除相应的行。现在我正在这样做:

void NetworkManager::removeSessionFromModel (QStandardItemModel *model, int sessionId) {

    foreach (const QStandardItem *item, model->findItems("*", Qt::MatchWildcard)) {
        if (item->data() == sessionId) {
            model->removeRow(item->index().row());
            break;
        }
    }

}

它工作正常,但是该功能的每一行都让我畏缩。有没有一种更清洁的方法可以做到这一点?

3 个答案:

答案 0 :(得分:4)

直接遍历QStandardItemModel怎么样?像这样:

void NetworkManager::removeSessionFromModel (QStandardItemModel *model, int sessionId) 
{
    for (int i = 0; i < model->rowCount(); ++i)
    {
        if (model->item(i)->data() == sessionId)
        {
            model->removeRow(i);
            break;
        }
    } 
}

不确定QStandardItemModel在随机访问下的行为,也许您的方法更有效。

编辑:

实际上,有一个函数可以执行您想要的操作:QAbstractItemModel::match

它返回一个QModelIndexList,其中所有条目在给定角色中具有匹配的数据。

void NetworkManager::removeSessionFromModel (QStandardItemModel *model, int sessionId)
{
    QModelIndexList list = model->match(model->index(0, 0), Qt::UserRole + 1, sessionId);

    if (!list.empty())
        model->removeRow(list .first().row());
}

可以按照以下步骤将数据设置为特定角色:

model->setData(model->index(row, col), QVariant(13), Qt::UserRole + 1);

答案 1 :(得分:2)

您需要从商品ID中获取行索引。

一种更有效的方法是使用QMap,将行索引作为值,并将项目ID作为键。

在这种情况下,每次添加/删除行时,您还需要维护地图值。

如果列表中没有3百万个项目,请保持简洁并使用代码。 通过优化此代码,您可能还增加了复杂性并降低了可维护性,得到的是0.05毫秒而不是0.06毫秒。

在GUI代码中,我经常有这样的代码:很简单,每个人都立即得到它并且可以完成工作。它也足够快。

答案 2 :(得分:1)

您使用的findItems错误,仅通过传递您要搜索的值就可以返回所需的项目。如果您像现在这样操作就称呼它,那么您至少要遍历两次项目,因为findItems必须遍历所有项目以找到与您的模式相匹配的项目,在这种情况下,所有项目都应匹配,然后您再次迭代返回的项目以找到sessionId

void NetworkManager::removeSessionFromModel (QStandardItemModel *model, int sessionId) {

    auto items = model->findItems(QString::number(sessionId));
    if (!items.empty()) {
        auto row = items.first()->index().row();
        model->removeRow(row);
    }
}

您也可以使用match方法,因为findItems在内部使用该方法,因此避免分配StandardItem只是为了获取其索引。同样,在找到与模式匹配的项目数(在这种情况下为match的值)之后,sessionId会立即返回,因此它并不总是迭代所有项目。这样更有效。显然,如果在迭代所有项目后都找不到该值,它将返回一个空列表。

auto start = model->index(0, 0);
auto indexes = model->match(start, Qt::UserRole + 1, QString::number(sessionId), 1, Qt::MatchExactly);
if (!indexes.empty()) {
    auto row = indexes.first().row();
    model->removeRow(row);
}