qml 实现展示本地文件系统

遍历本地文件

qt 提供了很多种便利类来实现本地的文件系统管理,比如QDirModelQFileSystemModel,qml中又提供了FolderListModel 。需要包含Qt.labs.folderlistmodel 2.0
笔者的环境没有安装Qt.labs.folderlistmodel 2.0 所以只能在QDirModelQFileSystemModel来选择,缺点是pro 文件中要添加QT += widgets, 因为该模块实现需要依赖widgets。

对于 QDirModel和 QFileSystemModel的选择
在QDirModel文档中说明

此类已过时。它提供了保持旧的源代码工作。我们强烈建议不要在新代码中使用它。

所以最终选择了QFileSystemModel
QFileSystemModel 采用单独的线程获取目录文件结构,而 QDirModel 不使用单独的线程。使用单独的线程就不会阻碍主线程,所以推荐使用 QFileSystemModel

核心代码

本文章代码参考了git上一个demo,但是添加了一些代码,主要是可以返回上一级
参考代码的git地址 : https://github.com/junyius1/filesystembrowser

main.cpp

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

static inline QString permissionString(const QFileInfo &fi)
{
    const QFile::Permissions permissions = fi.permissions();
    QString result = QLatin1String("----------");
    if (fi.isSymLink())
        result[0] = QLatin1Char('l');
    else if (fi.isDir())
        result[0] = QLatin1Char('d');
    if (permissions & QFileDevice::ReadUser)
        result[1] = QLatin1Char('r');
    if (permissions & QFileDevice::WriteUser)
        result[2] = QLatin1Char('w');
    if (permissions & QFileDevice::ExeUser)
        result[3] = QLatin1Char('x');
    if (permissions & QFileDevice::ReadGroup)
        result[4] = QLatin1Char('r');
    if (permissions & QFileDevice::WriteGroup)
        result[5] = QLatin1Char('w');
    if (permissions & QFileDevice::ExeGroup)
        result[6] = QLatin1Char('x');
    if (permissions & QFileDevice::ReadOther)
        result[7] = QLatin1Char('r');
    if (permissions & QFileDevice::WriteOther)
        result[8] = QLatin1Char('w');
    if (permissions & QFileDevice::ExeOther)
        result[9] = QLatin1Char('x');
    return result;
}

static inline QString sizeString(const QFileInfo &fi)
{
    if (!fi.isFile())
        return QString();
    const qint64 size = fi.size();
    if (size > 1024 * 1024 * 10)
        return QString::number(size / (1024 * 1024)) + QLatin1Char('M');
    if (size > 1024 * 10)
        return QString::number(size / 1024) + QLatin1Char('K');
    return QString::number(size);
}

class DisplayFileSystemModel : public QFileSystemModel {
    Q_OBJECT
public:
    explicit DisplayFileSystemModel(QObject *parent = nullptr)
        : QFileSystemModel(parent) {

    }

public Q_SLOTS:
    void onRootPathChanged(const QString &newPath)
    {
        qDebug()<< "=====" << "onRootPathChanged==="<<newPath;
    }
public:
    enum Roles  {
        SizeRole = Qt::UserRole + 4,
        DisplayableFilePermissionsRole = Qt::UserRole + 5,
        LastModifiedRole = Qt::UserRole + 6,
        UrlStringRole = Qt::UserRole + 7,
        //NameRole = Qt::UserRole + 8
    };
    Q_ENUM(Roles)

    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override
    {
        if (index.isValid() && role >= SizeRole) {
            switch (role) {
            case SizeRole:
                return QVariant(sizeString(fileInfo(index)));
            case DisplayableFilePermissionsRole:
                return QVariant(permissionString(fileInfo(index)));
            case LastModifiedRole:
                return QVariant(fileInfo(index).lastModified().toString(Qt::SystemLocaleShortDate));
            case UrlStringRole:
                return QVariant(QUrl::fromLocalFile(filePath(index)).toString());
            default:
                break;
            }
        }
        return QFileSystemModel::data(index, role);
    }

    QHash<int,QByteArray> roleNames() const override
    {
         QHash<int, QByteArray> result = QFileSystemModel::roleNames();
         result.insert(SizeRole, QByteArrayLiteral("size"));
         result.insert(DisplayableFilePermissionsRole, QByteArrayLiteral("displayableFilePermissions"));
         result.insert(LastModifiedRole, QByteArrayLiteral("lastModified"));
         //result.insert(NameRole,QByteArrayLiteral("name"));
         return result;
    }

public:
    Q_INVOKABLE bool _isDir(const QModelIndex &index)
    {
        return isDir(index);
    }

    Q_INVOKABLE QModelIndex  parentIndex(const QModelIndex &index)
    {
        return parent(index);
    }
};


int main(int argc, char ** argv)
{
    QApplication app(argc, argv);

    QQuickView view;
    QFileSystemModel *fsm = new DisplayFileSystemModel(&view);
//    QFileSystemModel *fsm = new QFileSystemModel(&view);
     QObject::connect(fsm, SIGNAL(rootPathChanged(const QString)), fsm,
            SLOT(onRootPathChanged(const QString)));
    QModelIndex lIndex = fsm->setRootPath(QDir::homePath());
//    fsm->setResolveSymlinks(true);
    view.rootContext()->setContextProperty("rootPathIndex", lIndex);
    view.rootContext()->setContextProperty("fileSystemModel", fsm);
    view.setSource(QUrl(QStringLiteral("qrc:/main.qml")));
    view.show();

    return app.exec();
}

#include "main.moc"

main.qml

import QtQuick 2.2
import QtQml.Models 2.2
import QtQuick.Controls 2.3


Rectangle
{
    id:root
    width: 500
    height: 800

    Button
    {
        id:back
        y:460
        z:100
        text: "back"
        onClicked:
        {
            console.log("back clicked")
            view.setParentModel();
        }
    }

    ListView {
        id: view
        width: 300
        height: 400


        function getParentModel()
        {
           return view.model.parentIndex
        }

        function setParentModel()
        {
            console.log(view.model.indexArray.length)
            if(view.model.indexArray.length === 1)
                return
            view.model.indexArray.pop();

            view.model.testIndex= fileSystemModel.parentIndex(view.model.rootIndex)
            view.model.rootIndex = view.model.testIndex
           console.log(view.model.indexArray.length,view.model.indexArray)
            
            //方法2
//            view.model.testIndex= view.model.indexArray[viewmodel.indexArray.length-1]
//            viewmodel.rootIndex = viewmodel.indexArray[viewmodel.indexArray.length-1]
//            view.model.rootIndex = view.model.testIndex
        }

        model: DelegateModel {
            property var testIndex
            property var parentIndex
            property var indexArray: new Array;  //方法2

            model: fileSystemModel
            rootIndex:{
                view.model.testIndex = rootPathIndex
                //方法2
                view.model.indexArray.push(rootPathIndex);
                console.log("set rootIndex==",view.model.indexArray.length ,view.model.testIndex)
                //return rootPathIndex
            }
            onRootIndexChanged:{
                view.model.rootIndex = view.model.testIndex
                 console.log("set onRootIndexChanged==",view.model.testIndex)
            }

            delegate: Rectangle {

                width: 200; height: 65


                Image{
                    id:img
                    source:fileSystemModel._isDir(view.model.modelIndex(index))? "qrc:/dir.png":"qrc:/listenItem.png"
                }

                Text{
                    text: fileName
                    anchors.verticalCenter: img.verticalCenter
                    anchors.left: img.right
                    anchors.leftMargin: 10
                }

                MouseArea {
                    anchors.fill: parent
                    onClicked: {
                        if (model.hasModelChildren){
                            console.log("clicked",view.model.testIndex);

                            view.model.testIndex= view.model.modelIndex(index)
                            view.model.rootIndex = view.model.modelIndex(index)
                            //方法2
                            view.model.indexArray.push(view.model.testIndex);
                            console.log("clikced ", view.model.indexArray.length)
                        }
                    }
                }
            }
        }
    }

}

上述代码实现了两种方法来返回上一层,最早是使用了一个array来记录各层级节点,
后来找到了获得父节点的方法,所以用了最新获得父节点的方式来实现。代码中有些还是不太明白,等有时间了再自信琢磨琢磨。
尤其是:

onRootIndexChanged:{
                view.model.rootIndex = view.model.testIndex
                 console.log("set onRootIndexChanged==",view.model.testIndex)
            }

既然rootIndex Changed了,为什么还需要给rootIndex赋值呢?导致多次打印。

效果如下

qml 实现展示本地文件系统_第1张图片

你可能感兴趣的:(《Qt,项目实战经历全记录》,qml,文件系统,QDirModel,FolderListModel)