Использование QFileSystemModel для синхронизации двух представлений с разными элементами

Я создаю вид, похожий на проводник, с деревом каталогов / панелью навигации, используя QTreeView на левой стороне и вид значка на правой / основной стороне, используя QListView, На стороне дерева должны отображаться только каталоги (предпочтительно непустые каталоги... но это другая история), а в значке отображаются только файлы с определенным фильтром имен и без каталогов. И я изо всех сил пытаюсь сделать это правильно.

Первое: я не знаю, стоит ли мне использовать один или два QFileSystemModels для этого. Используя один я фильтрую с двумя прикрепленными QSortFilterProxyModels для каждого представления - но у меня больше нет свойств файловой системы.... и использование только RegEx для этого является своего рода ограничением. И использование двух моделей оказалось трудным, потому что я не могу нанести на карту QModelIndex из одной модели в другую, потому что модели содержат разные элементы. Например, когда я нажимаю на каталог слева, корневой путь справа должен обновляться. Но каталог не входит в модель... так что это не работает.

Любые идеи о том, как сделать это правильно? Спасибо!

1 ответ

Решение

Как может взаимодействовать представление дерева каталогов файлов и представление навигации по файлам?

Не настаиваю на том, что это единственный способ, но у меня работает:

  • Одна модель просмотра фильтрует только каталоги, а другая - только файлы
  • Каждое представление (дерево каталогов и файловая навигация) использует отдельный объект файловой модели того же типа, указывающий на некоторый корень
  • Синхронизируйте представления, используя путь в файловой системе: когда одно из представлений меняет выбор (в вашем представлении дерева случаев) пользователем, щелчок другого выбирается по тому же пути.
  • Имейте в виду, что имея QSortFilterProxyModel сначала мы должны получить текущую позицию просмотра оттуда

void MyFileSystemWidget::startViews()
{
    // First, initialize QTreeView and QTableView each with own
    // QFileSystemModel/QSortFilterProxyModel(MySortFilterProxyModel)
    // with individual selection e.g. QDir::Files or QDir::Dirs
    //// //// ////

    // Make models to point at the same root to start
    const QModelIndex rootTreeViewIdx = m_pTreeSortFilterProxyModel->mapFromSource( m_pTreeDataModel->index(rootDir.path()) );
    m_pTreeView->setRootIndex(rootTreeViewIdx);
    m_pTreeView->setCurrentIndex(rootTreeViewIdx);

    const QModelIndex rootFileViewIdx = m_pListSortFilterProxyModel->mapFromSource( m_pListDataModel->index(rootDir.path()) );
    m_pTableView->setRootIndex(rootFileViewIdx);

    // now connect tree view clicked signal 
    connect(m_pTreeView, SIGNAL(clicked(QModelIndex)),  SLOT(onTreeViewClicked(QModelIndex)));
}


void MyFileSystemWidget::onTreeViewClicked(const QModelIndex& treeIndex)
{
        // see MySortFilterProxyModel::sourceFileInfo
        QString modelPath = m_pTreeSortFilterProxyModel->sourceFileInfo( treeIndex ).absoluteFilePath();
        if (modelPath.isEmpty())
            return;
        // see MySortFilterProxyModel::setSourceModelRootPath
        const QModelIndex proxyIndex = m_pListSortFilterProxyModel->setSourceModelRootPath(modelPath);
        m_pTableView->setRootIndex(proxyIndex);
}


QFileInfo MySortFilterProxyModel::sourceFileInfo(const QModelIndex& index)
{
    if (!index.isValid())
        return QFileInfo();
    const QModelIndex proxyIndex = mapToSource( index );
    if (!proxyIndex.isValid())
        return QFileInfo();
    return static_cast<QFileSystemModel*>(sourceModel())->fileInfo(proxyIndex);
}


QModelIndex MySortFilterProxyModel::setSourceModelRootPath(const QString& modelPath)
{
    const QModelIndex fmIndex = static_cast<QFileSystemModel*>(sourceModel())->setRootPath(modelPath);
    return mapFromSource( fmIndex );
}
Другие вопросы по тегам