如何将自定义项目添加到QFileDialog?
我正在使用非本地QFileDialog
(用于选择目录路径),我需要添加一些自定义驱动器。 我甚至不需要在这些驱动器中显示任何内容,我只需要在顶层显示这些驱动器(最好是使用我的图标),并在用户选择它时在结果中输出一些特殊的字符串。
实现这个最简单的方法是什么?
我已经阅读过可以使用代理模型的文档,但我不明白如何实现这种模型,所有示例仅显示对已有项目进行过滤和排序。
如果我理解正确,你想添加额外的驱动器到文件对话框左侧的侧栏上?
你正在寻找的功能是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();
}
结果如下所示:
但是,如果您添加的驱动器不存在/无法访问,则它们将显示为灰色。
一般信息
你是对的,你需要设置一个代理模型。 基本上你的任务是用QAbstractProxyModel
添加一行。 这比删除行要困难得多。
如果我们看一下QFileDialog::setProxyModel
的源代码,我们发现这个:
proxyModel->setParent(this);
d->proxyModel = proxyModel;
proxyModel->setSourceModel(d->model);
由此我们知道QFileDialog
有一个自动设置为代理模型源的内部模型。 查看私有头文件,我们发现源模型的类型是QFileSystemModel
。 因此,我们可以期望我们的代理模型需要能够提供与源模型相同的角色。 该文档具有它们的列表: FileIconRole
, FileNameRole
, FilePathRole
, FilePermissionRole
。
更糟糕的是, QFileDialog
有时会调用proxyModel.mapToSource()
和proxyModel.mapFromSource()
来访问源索引。 因为我们要添加一行,所以我们的新索引没有相应的源索引(在源模型中)。 这意味着我们必须编写我们自己的mapToSource
和mapFromSource
的实现。
履行
我建议从QIdentityProxyModel
开始,因为你可以使用可用的方法来处理所有刚刚传递给源模型的索引。
我不清楚你需要重新实现多少种方法,以及你可以多久使用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真正需要的是一种将多个模型合并为一个的方法,但我还没有看到过这样的类,因此您必须这样做。
链接地址: http://www.djcxy.com/p/96515.html