我正在使用非本机QFileDialog
(用于选择目录路径),我需要添加一些自定义驱动器。我现在甚至不需要在这些驱动器内显示任何内容,我只需要在顶层显示这些驱动器(最好是我的图标),并在用户选择时在结果中输出一些特殊字符串。
实现此目的的最简单方法是什么?
我已在documentation中读到可以使用代理模型,但我不了解如何实现此模型,所有示例都只显示已经可用项目的过滤和排序。< / p>
答案 0 :(得分:3)
您需要设置代理模型。
基本上您的任务是添加一行QAbstractProxyModel
。这比删除行要困难得多。
如果我们查看QFileDialog::setProxyModel
的源代码,我们会发现:
proxyModel->setParent(this);
d->proxyModel = proxyModel;
proxyModel->setSourceModel(d->model);
由此我们知道QFileDialog
有一个内部模型,它自动设置为代理模型的源。查看private header,我们发现源模型的类型为QFileSystemModel
。因此,我们可以期望我们的代理模型需要能够提供与源模型相同的角色。 docs有一个列表:FileIconRole
,FileNameRole
,FilePathRole
,FilePermissionRole
。
更糟糕的是,QFileDialog
sometimes 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真正需要的是一种将多个模型合二为一的方法,但我还没有见过这样的课程,因此你必须这么做。
答案 1 :(得分:2)
如果我理解正确,您想在文件对话框左侧的侧栏添加其他驱动器吗?
您正在寻找的功能是QFileDialog::setSidebarUrls
#include <QApplication>
#include <QMainWindow>
#include <QHBoxLayout>
#include <QPushButton>
#include <QFileDialog>
int main(int argc, char** argv)
{
QApplication app(argc, argv);
QMainWindow window;
QWidget widget;
QHBoxLayout layout(&widget);
QPushButton open("open");
layout.addWidget(&open);
QObject::connect(&open, &QPushButton::clicked, [&]()
{
QFileDialog dialog;
dialog.setOption(QFileDialog::DontUseNativeDialog);
QList<QUrl> drives;
drives << QUrl::fromLocalFile(QDir("D:").absolutePath());
drives << QUrl::fromLocalFile(QDir("E:").absolutePath());
drives << QUrl::fromLocalFile(QDir("foobar").absolutePath());
dialog.setSidebarUrls(drives);
dialog.exec();
});
window.setCentralWidget(&widget);
window.show();
return app.exec();
}
结果如下所示:
但是,如果您添加的驱动器不存在/无法访问,则它们将显示为灰色。