Применение двух FileFilterProxyModel к одной QFileSystemModel - PullRequest
0 голосов
/ 17 июня 2020

Проблема:
Я делаю своего рода проводник файлов, в котором есть одно представление каталогов, а другое представление показывает файлы в выбранном каталоге. Итак, идея заключалась в том, чтобы иметь один QFileSystemModel и применить к нему два FileFilterProxyModel, один для отображения только папок, другой для отображения только файлов (для выбранной папки, без подпапок)

Просмотр папок работает нормально. Просмотр файлов отлично работает для первой (root) папки, когда отображается пользовательский интерфейс. После этого любой выбор в представлении папки приводит к неверному исходному индексу (получение индекса из представления папки и его преобразование обратно в индекс исходной модели работает нормально, но когда я пытаюсь перевести индекс из источника в модель фильтра файлов он всегда возвращает неверный индекс, за исключением первого раза, что означает, что в представлении файла всегда отображается только содержимое папки root.)

Вот мой код:

Инициализация модели:

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

    }

И реакция на выбор папки: обратите внимание на комментарии в коде:

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 Mode / View Framework, поскольку должна быть возможность отображать одни и те же данные в разных фильтрах в нескольких представлениях.

Я, должно быть, что-то упускаю или что-то упускаю, был бы очень признателен указатели и вещи, которые стоит попробовать. Спасибо!

1 Ответ

0 голосов
/ 19 июня 2020

Предположительно OnlyFilesFileterModel отфильтровывает все, что не является файлом, что исключает подкаталоги вашего каталога root.

mapFromSource вернет только допустимый индекс для файла.

Вы можете добавить промежуточную модель, которая представляет только прямых дочерних элементов конкретного элемента модели, тогда вы должны установить ее источник root дюйм 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();
    }
};
...