一般信息
你是对的,你需要设置一个代理模型。
基本上,您的任务是添加带有QAbstractProxyModel 的行。这比删除行要困难得多。
如果我们查看QFileDialog::setProxyModel的源代码,我们会发现:
proxyModel->setParent(this);
d->proxyModel = proxyModel;
proxyModel->setSourceModel(d->model);
由此我们知道QFileDialog有一个内部模型,它被自动设置为代理模型的来源。查看private header,我们发现源模型的类型是QFileSystemModel。因此,我们可以期望我们的代理模型需要能够提供与源模型相同的角色。 docs 有一个列表:FileIconRole、FileNameRole、FilePathRole、FilePermissionRole。
更糟糕的是,QFileDialogsometimes calls proxyModel.mapToSource() and proxyModel.mapFromSource() 访问源索引。因为我们要添加一行,所以我们的新索引没有对应的源索引(在源模型中)。这意味着我们必须编写自己的 mapToSource 和 mapFromSource 实现。
实施
我建议从QIdentityProxyModel 开始,因为您可以对刚刚传递给源模型的所有索引使用可用的方法。
我不确切知道您需要重新实现多少方法,以及您多久可以使用QIdentityProxyModel 提供的方法。从简单的东西开始:
int MyDriveProxyModel::rowCount(const QModelIndex &parent = QModelIndex()) const {
if (parent.isValid()) {
return QIdentityProxyModel::rowCount(parent);
} else {
return QIdentityProxyModel::rowCount(parent) + 1;
}
}
然后重新实现这两种映射方式:
QModelIndex MyDriveProxyModel::mapToSource(const QModelIndex &proxyIndex) const {
if (this_index_belongs_to_the_added_row) { // there are many ways for this
return this->createIndex(proxyIndex.row(), proxyIndex.column(), /* some_data */);
}
return QIdentityProxyModel::mapToSource(proxyIndex);
}
QModelIndex MyDriveProxyModel::mapFromSource(const QModelIndex &proxyIndex) const {
...
}
一旦这工作,您需要以类似的方式至少实现QAbstractItemModel::data 和QAbstractItemModel::flags。
结论
这应该是可行的,但工作量很大,很容易出错。 Qt 真正需要的似乎是将多个模型组合成一个的方法,但我还没有见过这样的类,因此你必须努力做到这一点。