赞
踩
qt 提供了很多种便利类来实现本地的文件系统管理,比如QDirModel
和QFileSystemModel
,qml中又提供了FolderListModel 。需要包含Qt.labs.folderlistmodel 2.0
笔者的环境没有安装Qt.labs.folderlistmodel 2.0 所以只能在QDirModel
和 QFileSystemModel
来选择,缺点是pro 文件中要添加QT += widgets, 因为该模块实现需要依赖widgets。
对于 QDirModel和 QFileSystemModel的选择
在QDirModel文档中说明
此类已过时。它提供了保持旧的源代码工作。我们强烈建议不要在新代码中使用它。
所以最终选择了QFileSystemModel
QFileSystemModel 采用单独的线程获取目录文件结构,而 QDirModel 不使用单独的线程。使用单独的线程就不会阻碍主线程,所以推荐使用 QFileSystemModel
本文章代码参考了git上一个demo,但是添加了一些代码,主要是可以返回上一级
参考代码的git地址 : https://github.com/junyius1/filesystembrowser
main.cpp
#include <QApplication> #include <QQmlApplicationEngine> #include <QtQml> #include <QFileSystemModel> #include <QDateTime> #include <QDesktopServices> #include <QUrl> #include <QDirModel> #include <QQuickView> 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赋值呢?导致多次打印。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。