在一个 QFileSystemModel 上应用两个 FileFilterProxyModel

Posted

技术标签:

【中文标题】在一个 QFileSystemModel 上应用两个 FileFilterProxyModel【英文标题】:Applying two FileFilterProxyModel on one QFileSystemModel 【发布时间】:2020-06-17 18:47:56 【问题描述】:

问题: 我正在制作一种文件资源管理器,它有一个目录视图,另一个视图显示所选目录中的文件。 所以想法是有一个QFileSystemModel,并在上面应用两个FileFilterProxyModel,一个只显示文件夹,一个只显示文件(对于选定的文件夹,没有子文件夹)

文件夹视图工作正常。 当 UI 显示时,文件视图对于第一个(根)文件夹工作正常。 之后,文件夹视图上的任何选择都会导致源索引无效(从文件夹视图获取索引并将其转换回源模型索引工作正常,但是当我尝试将索引从源转换为文件过滤器模型时它总是返回一个无效的索引,除了第一次,这意味着文件视图总是只显示根文件夹的内容。)

这是我的代码:

模型初始化:

    void MainWindow::initFilesystemModel()
    
        m_pFileSystemModel = new QFileSystemModel(this);
        m_pFileSystemModel->setFilter(QDir::AllDirs|QDir::NoDotAndDotDot|QDir::Hidden|QDir::Drives|QDir::Files);
        m_pFileSystemModel->setRootPath(QDir::rootPath());

        m_pOnlyFoldersFilterModel = new FileFilterProxyModel(ui->pFolderTreeView);
        m_pOnlyFoldersFilterModel->setSourceModel(m_pFileSystemModel);

        QSortFilterProxyModel* onlyFilesModel = new OnlyFilesFileterModel(ui->pDetailViewWidget);
        onlyFilesModel->setSourceModel(m_pFileSystemModel);

        ui->pFolderTreeView->setModel(m_pOnlyFoldersFilterModel);
        ui->pDetailViewWidget->setModel(onlyFilesModel);

        connect(ui->pFolderTreeView, &QTreeView::pressed, this , &MainWindow::onFolderSelected);

    

以及选择文件夹的反应: 注意代码中的 cmets:

void MainWindow::onFolderSelected(const QModelIndex &index)

    QModelIndex sourceIndex = m_pOnlyFoldersFilterModel->mapToSource(index); //sourceIndex is valid and correct

    QModelIndex rootIndex = dynamic_cast<QSortFilterProxyModel*>(ui->pDetailViewWidget->model())->mapFromSource(sourceIndex); //rootIndex is always invalid  -1,-1

    ui->pDetailViewWidget->setRootIndex(rootIndex);

我在网上找到了一些做非常相似的事情的例子,但他们通过使用两个 QFileSystemModel 解决了这个问题,每个视图一个。 对我来说,这与 Qt 模式/视图框架的想法背道而驰,因为它应该可以在多个视图中以不同的过滤方式显示相同的数据。

我一定是遗漏了一些东西,或者忽略了一些东西,非常感谢任何指点和尝试的东西。 谢谢!

【问题讨论】:

旁白:为什么会员中只有一个代理?我想将dynamic_cast&lt;QSortFilterProxyModel*&gt;(ui-&gt;pDetailViewWidget-&gt;model()) 换成m_pOnlyFilesFilterModel 啊,别想太多,这是WIP代码,我不确定我最终是否需要任何成员。 【参考方案1】:

大概OnlyFilesFileterModel 过滤掉所有不是文件的东西,这将排除根目录的子目录。

mapFromSource 只会返回文件的有效索引。

您可以添加一个仅显示特定模型元素的直接子元素的中间模型,然后将其源根设置为 onFolderSelected

class TreeToTableProxyModel : public QAbstractProxyModel

    QModelIndex sourceRoot;
public:
    QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override
    
        if (sourceIndex.parent() != sourceRoot) return QModelIndex();
        return index(sourceIndex.row(), sourceIndex.column());
    

    QModelIndex mapToSource(const QModelIndex &proxyIndex) const override
    
        if (!proxyIndex.isValid()) return QModelIndex();
        return sourceModel().index(proxyIndex.row(), proxyIndex.column(), sourceRoot);
    

    void setSourceRoot(const QModelIndex &sourceIndex) 
     
        beginResetModel();
        sourceRoot = sourceIndex;
        endResetModel();
    
;

【讨论】:

我不确定我是否遵循您的第一句话。确实,OnlyFilesFileterModel 过滤掉了所有不是文件的东西。您的意思是说索引“hosekeeping”正在考虑过滤吗?所以当我做 mapFromSrouce() 时,它只会返回一个过滤器没有过滤我们的索引?这可以解释这种行为,但我希望所有源索引都可以访问,只是在视图中不可见。我会尝试你的建议并回复。非常感谢!

以上是关于在一个 QFileSystemModel 上应用两个 FileFilterProxyModel的主要内容,如果未能解决你的问题,请参考以下文章

在 QFileSystemModel() 中列出文件的最佳方法?

遍历 QTreeView + QFileSystemModel 上具有所需文件扩展名的所有项目

基于Qt的QFileSystemModel做一个带checkbox的文件树

7.qfilesystemmodel rowcount 为什么为0? 一个简单的model类的例子

在 QFileSystemModel 中查找第 n 个文件/文件夹

编译QFileSystemModel