如何向QFileDialog添加自定义项?

时间:2017-06-15 12:53:40

标签: c++ windows qt

我正在使用非本机QFileDialog(用于选择目录路径),我需要添加一些自定义驱动器。我现在甚至不需要在这些驱动器内显示任何内容,我只需要在顶层显示这些驱动器(最好是我的图标),并在用户选择时在结果中输出一些特殊字符串。

enter image description here

实现此目的的最简单方法是什么?

我已在documentation中读到可以使用代理模型,但我不了解如何实现此模型,所有示例都只显示已经可用项目的过滤和排序。< / p>

2 个答案:

答案 0 :(得分:3)

一般信息

您需要设置代理模型。 基本上您的任务是添加一行QAbstractProxyModel。这比删除行要困难得多。

如果我们查看QFileDialog::setProxyModel的源代码,我们会发现:

proxyModel->setParent(this);
d->proxyModel = proxyModel;
proxyModel->setSourceModel(d->model);

由此我们知道QFileDialog有一个内部模型,它自动设置为代理模型的源。查看private header,我们发现源模型的类型为QFileSystemModel。因此,我们可以期望我们的代理模型需要能够提供与源模型相同的角色。 docs有一个列表:FileIconRoleFileNameRoleFilePathRoleFilePermissionRole

更糟糕的是,QFileDialog sometimes calls proxyModel.mapToSource() and proxyModel.mapFromSource()可以访问源索引。因为我们想要添加一行,所以我们的新索引没有相应的源索引(在源模型中)。这意味着我们必须编写自己的mapToSourcemapFromSource实现。

实施

我建议从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::dataQAbstractItemModel::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();
}

结果如下所示:

enter image description here

但是,如果您添加的驱动器不存在/无法访问,则它们将显示为灰色。