如何从文件路径的QStringList制作QStandardItemModel

问题描述

我是C ++和Qt的新手,似乎找不到合适的解决方案。我想使用QStandardItemmodel创建一个QTreeView。我有一个文件/文件夹路径的列表(在QStringList中),其格式如下:

Arena/Main/00078/a.txt
Arena/Main/00080/b.txt
Arena/Main/00080/collision/c.txt
Arena/Main/00080/light/d.txt
Arena/Main/00081/e.txt
Characters/f.txt
Characters/Main/g.txt
Characters/Main/someFolder/h.txt

我以前使用QFileSystemModel并创建了实际的临时目录,作为一种变通方法遍历列表:

   QDir dir(temp_path);
    if (!dir.exists(dir_string)){
         dir.mkpath(dir_string);
    }
        
    QFile file(filepath_str);
    file.open(qiodevice::writeonly);

哪个给了我这样的工作结果:https://i.stack.imgur.com/ITzJz.png

但是,该列表最多可以包含10,000+个文件,这使它成为更长的后退解决方法。我想使用从路径列表创建的QStandardItemmodel以类似的方式填充QTreeView。

解决方法

您可以将创建的路径存储在这样的地图中:

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QMap>
#include <QStandardItemModel>

class QStandardItem;

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    void addPathRecusively(const QStringList &path_parts,QStandardItem *parent,int layer = 1);

    QMap<QString,QStandardItem*> path_item_map_;
    QStandardItemModel model_;
};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"

#include <QStringList>
#include <QTreeView>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QStringList filenames =
    {
        "Arena/Main/00078/a1.txt","Arena/Main/00078/a2.txt","Arena/Main/00080/b.txt","Arena/Main/00080/collision/c.txt","Arena/Main/00080/light/d.txt","Arena/Main/00081/e1.txt","Arena/Main/00081/e2.txt","Arena/Main/00081/e3.txt","Characters/f.txt","Characters/Main/g.txt","Characters/Main/someFolder/h.txt",};

    for (auto &filename : filenames)
    {
        QStringList parts = filename.split("/");
        parts.pop_back();
        addPathRecusively(parts,model_.invisibleRootItem());
    }

    QTreeView *view = new QTreeView{this};
    view->setModel(&model_);
    this->setCentralWidget(view);
    this->resize(500,500);
}

MainWindow::~MainWindow()
{
}

void MainWindow::addPathRecusively(const QStringList &path_parts,int layer)
{
    QStringList path_parts_to_layer;
    std::copy(path_parts.begin(),path_parts.begin() + layer,std::back_inserter(path_parts_to_layer));
    QString path = path_parts_to_layer.join("/");
    auto item = path_item_map_.value(path);
    if (item == nullptr)
    {
        item = new QStandardItem{path_parts_to_layer.last()};
        path_item_map_.insert(path,item);
        parent->appendRow({item,new QStandardItem});
    }

    if (path_parts.length() == layer)
    {
        auto file_count_index = model_.indexFromItem(item).siblingAtColumn(1);
        model_.setData(file_count_index,file_count_index.data().toInt() + 1,Qt::DisplayRole);
    }
    else
        addPathRecusively(path_parts,item,layer + 1);
}