0

The problem:
I am making a sort of file explorer, that has one view of the directories, and another view shows the files in the selected directory. So the idea was to have one QFileSystemModel, and apply two FileFilterProxyModel's on it, one to show only folders, one to show only files (for selected folder, no sub folders)

The folders view works fine. The files view works fine, for the first (root) folder, when the UI shows up. After that, any selection on the folder view results in invalid source index (getting the index from the folder view and transforming it back to the source model index works fine, but when I try to translate the index from the source to the file filter model it always returns an invalid index, except for the first time , which means the file view always shows only the root folder content.)

Here is my code:

The models initialization:

    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);

    }

And the reaction to selecting a folder: Note the comments in the code:

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);
}

I have found online few examples that did a very similar thing but they solved the issue by using two QFileSystemModel's, one for each view. To me this counters the idea of Qt Mode/View Framework since it should be possible to show the same data in differently filtered in multiple views.

I must be missing something, or overlooking something, would very much appreciate any pointers, and things to try. Thanks!

dkish
  • 319
  • 3
  • 13
  • Aside: why is only one of these proxies held in a member? I'd want to switch out `dynamic_cast(ui->pDetailViewWidget->model())` for `m_pOnlyFilesFilterModel` – Caleth Jun 19 '20 at 15:14
  • Ah, don't think much of it, this is WIP code, I am not sure that I need any members eventually. – dkish Jun 20 '20 at 18:19

1 Answers1

0

Presumably OnlyFilesFileterModel filters out everything that isn't a file, which will exclude subdirectories of your root directory.

mapFromSource will only return a valid index for a file.

You could add an intermediate model that presents only the direct children of a particular model's element, then you would set it's source root in 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();
    }
};
Caleth
  • 52,200
  • 2
  • 44
  • 75
  • I am not sure I follow your first sentence. It is true that OnlyFilesFileterModel is filtering out everything which is not a file. Do you mean to say that the index "hosekeeping" is taking the filtering in account? So that wen I do mapFromSrouce() it will return only an index the filter didn't filter our? That could explain the behavior, but I expected all the source indexes to be accessible, just not visible in a view. I will try your suggestion and post back. Many thanks! – dkish Jun 20 '20 at 18:17