如何在QFileSystemModel中显示文件夹的大小
在Qt里面,有一种Model/View框架,Model负责收集信息,View负责显示信息。QFileSystemModel可以读取文件大小,但是默认情况下不能读取文件夹大小。
QFileSystemModel里面有一个size()函数,获取一个index对应的文件的大小。
qint64 QFileSystemModel::size(const QModelIndex &index) const
{
Q_D(const QFileSystemModel);
if (!index.isValid())
return ;
return d->node(index)->size();
}
这里的Q_D指针通过宏定义指向QFileSystemModel的私有类:QFileSystemPrivate。
#define Q_D(Class) Class##Private * const d = d_func()
写一个类MyQFileSystemInfo继承QFileSystemInfo,重写它的size()函数,对具体文件直接返回文件大小,而对文件夹则递归加和计算每个子文件夹的大小以得到它的大小。
可惜,仍然还是不能在view中实时显示文件夹的大小,看来view中使用的size并不是model的size()函数。github的代码链接:https://github.com/1171597779/big_file_inspector。
在QFileSystemModelPrivate里面也有一个size()函数。
QString QFileSystemModelPrivate::size(const QModelIndex &index) const
{
if (!index.isValid())
return QString();
const QFileSystemNode *n = node(index);
if (n->isDir()) {
#ifdef Q_OS_MAC
return QLatin1String("--");
#else
return QLatin1String("");
#endif
// Windows - ""
// OS X - "--"
// Konqueror - "4 KB"
// Nautilus - "9 items" (the number of children)
}
return size(n->size());
}
上面函数的17行调用了重载size()函数:
QString QFileSystemModelPrivate::size(qint64 bytes)
{
// According to the Si standard KB is 1000 bytes, KiB is 1024
// but on windows sizes are calculated by dividing by 1024 so we do what they do.
const qint64 kb = ;
const qint64 mb = * kb;
const qint64 gb = * mb;
const qint64 tb = * gb;
if (bytes >= tb)
return QFileSystemModel::tr("%1 TB").arg(QLocale().toString(qreal(bytes) / tb, 'f', ));
if (bytes >= gb)
return QFileSystemModel::tr("%1 GB").arg(QLocale().toString(qreal(bytes) / gb, 'f', ));
if (bytes >= mb)
return QFileSystemModel::tr("%1 MB").arg(QLocale().toString(qreal(bytes) / mb, 'f', ));
if (bytes >= kb)
return QFileSystemModel::tr("%1 KB").arg(QLocale().toString(bytes / kb));
return QFileSystemModel::tr("%1 bytes").arg(QLocale().toString(bytes));
}
QFileSystemModel的头文件里声明了私有类QFileSystemPrivate,转到这个私有类的头文件里面去,在这个类里定义了另外一个类QFileSystemNode。在这个类的构造函数中,出现一个QExtendedInformation*指针类型的info实参。这个实参在QFileSystemPrivate类里面是一个公有成员,文件或者文件夹的大小就是通过下面的QFileSystemNode的内联函数实现的。
inline qint64 size() const { if (info && !info->isDir()) return info->size(); return ; }
QExtendedinformation类中存在一个QFileInfo类的成员mFileInfo,并通过size()方法来根据具体情况获取文件大小:
qint64 size() const {
qint64 size = -;
if (type() == QExtendedInformation::Dir)
size = ;
if (type() == QExtendedInformation::File)
size = mFileInfo.size();
if (!mFileInfo.exists() && !mFileInfo.isSymLink())
size = -;
return size;
}
而QFileInfo的size()方法如下:
qint64 QFileInfo::size() const
{
Q_D(const QFileInfo);
if (d->isDefaultConstructed)
return ;
if (d->fileEngine == ) {
if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::SizeAttribute))
QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::SizeAttribute);
return d->metaData.size();
}
if (!d->getCachedFlag(QFileInfoPrivate::CachedSize)) {
d->setCachedFlag(QFileInfoPrivate::CachedSize);
d->fileSize = d->fileEngine->size();
}
return d->fileSize;
}
问题来了,要计算一个文件夹的大小,需要很长的时间,不能用内联函数,因此需要重载一下,放弃内联函数的写法。
总结一下,QFileSystemModel里面的size()调用QFileSystemModelPrivate的size(),而这个函数里会使用的QFileSystemNode的内联函数size(),这里面又转到QExtendedinformation里面去,最后是QFileInfo的size()方法。通过重写QFileSystemModel的size()函数并不能实现treeview中文件夹大小的实时显示,需要找出treeview中什么时候调用size()函数。
从QFileSystemModelPrivate类的init()函数可以看到一些端倪:
void QFileSystemModelPrivate::init()
{
Q_Q(QFileSystemModel);
qRegisterMetaType<QVector<QPair<QString,QFileInfo> > >();
#ifndef QT_NO_FILESYSTEMWATCHER
q->connect(&fileInfoGatherer, SIGNAL(newListOfFiles(QString,QStringList)),
q, SLOT(_q_directoryChanged(QString,QStringList)));
q->connect(&fileInfoGatherer, SIGNAL(updates(QString,QVector<QPair<QString,QFileInfo> >)),
q, SLOT(_q_fileSystemChanged(QString,QVector<QPair<QString,QFileInfo> >)));
q->connect(&fileInfoGatherer, SIGNAL(nameResolved(QString,QString)),
q, SLOT(_q_resolvedName(QString,QString)));
q->connect(&fileInfoGatherer, SIGNAL(directoryLoaded(QString)),
q, SIGNAL(directoryLoaded(QString)));
#endif // !QT_NO_FILESYSTEMWATCHER
q->connect(&delayedSortTimer, SIGNAL(timeout()), q, SLOT(_q_performDelayedSort()), Qt::QueuedConnection); roleNames.insertMulti(QFileSystemModel::FileIconRole, QByteArrayLiteral("fileIcon")); // == Qt::decoration
roleNames.insert(QFileSystemModel::FilePathRole, QByteArrayLiteral("filePath"));
roleNames.insert(QFileSystemModel::FileNameRole, QByteArrayLiteral("fileName"));
roleNames.insert(QFileSystemModel::FilePermissions, QByteArrayLiteral("filePermissions"));
}
通过看到QFileSystemModelPrivate里面的方法addNote()才看到一些希望:
QFileSystemModelPrivate::QFileSystemNode* QFileSystemModelPrivate::addNode(QFileSystemNode *parentNode, const QString &fileName, const QFileInfo& info)
{
// In the common case, itemLocation == count() so check there first
QFileSystemModelPrivate::QFileSystemNode *node = new QFileSystemModelPrivate::QFileSystemNode(fileName, parentNode);
#ifndef QT_NO_FILESYSTEMWATCHER
node->populate(info);
#else
Q_UNUSED(info)
#endif
#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
//The parentNode is "" so we are listing the drives
if (parentNode->fileName.isEmpty()) {
wchar_t name[MAX_PATH + ];
//GetVolumeInformation requires to add trailing backslash
const QString nodeName = fileName + QLatin1String("\\");
BOOL success = ::GetVolumeInformation((wchar_t *)(nodeName.utf16()),
name, MAX_PATH + , NULL, , NULL, NULL, );
if (success && name[])
node->volumeName = QString::fromWCharArray(name);
}
#endif
Q_ASSERT(!parentNode->children.contains(fileName));
parentNode->children.insert(fileName, node);
return node;
}
上面的node->populate(),这里面就提取了文件信息:
void populate(const QExtendedInformation &fileInfo) {
if (!info)
info = new QExtendedInformation(fileInfo.fileInfo());
(*info) = fileInfo;
}
如何在QFileSystemModel中显示文件夹的大小的更多相关文章
- 【聊技术】在Android中实现自适应文本大小显示
本周的聊技术话题和大家说说如何在Android中实现自适应文本大小显示. 想象一下,在布局中,通常显示文本的区域大小是固定的,但是文本长度并不总是固定的.比如列表中的文章标题.界面下方的按钮文本等等. ...
- iOS中计算磁盘缓存文件夹的大小
SDWebImage框架中在自动做磁盘缓存的过程中,底层实现了计算Cache的大小,框架的方法名称是getSize,但方法不容易被人理解,我就从新写了一下,附带注释 基本思想: 1. 先取出的Cach ...
- 通过命令“du–sk”, “du–Ask” 的区别,谈谈如何在有保护的文件系统中查看文件或文件夹的大小
我们都知道,在Windows中,右键单击一个文件或文件夹,选属性(Properties)可以看到这个文件或文件夹的大小.而这个大小是文件的原始大小,即逻辑大小(logical size).即一个1KB ...
- Linux中如何查看文件夹的大小
直接查看当前文件夹的大小: du –sh 只看文件夹的名字里包含某字符串的子文件夹的大小: du –h –d 1 | grep "BACKEND" 我的linux系统被阉割的比较厉 ...
- 如何在Linux中使用sFTP上传或下载文件与文件夹
如何在Linux中使用sFTP上传或下载文件与文件夹 sFTP(安全文件传输程序)是一种安全的交互式文件传输程序,其工作方式与 FTP(文件传输协议)类似. 然而,sFTP 比 FTP 更安全;它通过 ...
- 如何在Linux中自动删除或清理/tmp文件夹内容?
每个Linux系统都有一个名为的目录/tmp,该目录已挂载了单独的文件系统. 它具有称为tmpfs的特殊文件系统.这是一个虚拟文件系统,操作系统将在系统引导时自动挂载/tmp挂载点. 如果要根据应用程 ...
- [TC]Total Command显示文件夹大小
在Windows下计算文件夹的大小 按下 Alt +Shift +Enter 将会计算当前目录下的文件夹大小. 关于TC相关的知识:TC(Total Commander)文件管理神器
- 如何在Axure中使用FontAwesome字体图标
Font Awesome为您提供可缩放的矢量图标,您可以使用CSS所提供的所有特性对它们进行更改,包括:大小.颜色.阴影或者其它任何支持的效果. FontAwesome应用在web网页开发中非常方便, ...
- 如何在ROS中使用PCL—数据格式(1)
在ROS中点云的数据类型 在ROS中表示点云的数据结构有: sensor_msgs::PointCloud sensor_msgs::PointCloud2 pcl::PointCl ...
随机推荐
- Eclipse安装svn插件的几种方式(转)
1.在线安装: (1).点击 Help --> Install New Software... (2).在弹出的窗口中点击add按钮,输入Name(任意)和Location(插件的URL),点击 ...
- ili9325--LCD寄存器配置研究
2011-06-22 22:18:12 自己根据ili9325的规格书编写驱动.发现LCD屏没显示.于是怀疑是某些寄存器设置错误.要调试的话最好还是先熟悉寄存器的作用,调试的时候只要看到现象就能分析了 ...
- Beautiful Soup 学习手册
Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式 快速开始 下面的一段HTML代码将作为例 ...
- 2.0JAVA基础复习——JAVA语言的基础组成关键字和标识符
JAVA语言的基础组成有: 1.关键字:被赋予特殊含义的单词. 2.标识符:用来标识的符号. 3.注释:用来注释说明程序的文字. 4.常量和变量:内存存储区域的表示. 5.运算符:程序中用来运算的符号 ...
- dva构建react项目
第一步:安装 dva-cli 1 cnpm install dva-cli -g 第二步:采用dva来创建项目: 1 dva new react_two 2 cd react_two 用webstor ...
- JAVA值传递之基本数据类型和引用数据类型
#1.基本数据类型值传递 package 经典小Demo.值传递; public class Test { public static void main(String[] args) { int a ...
- C语言实例:数组与字符串
数组: #include <stdio.h> #include <stdlib.h> #define ARRAY_SIZE(Array) (sizeof (Array) / s ...
- Linux统计系统文件类型出现的次数
awk '/^UUID/{fs[$3]++}END{for(i in fs) {print i,fs[i]}}' /etc/fstab /^UUID/ 匹配确定行范围
- EJB到底是什么?
EJB到底是什么? 1. 我们不禁要问,什么是"服务集群"?什么是"企业级开发"? 既然说了EJB 是为了"服务集群"和"企业 ...
- (转载)Unity UGUI鼠标点击UI不受影响方法IsPointerOverGameObject
这几天在做捕鱼达人游戏时发现,当鼠标点击UI时,炮台的子弹也会发射子弹,这样会影响用户体验. 然后网上百度了一波,发现在UGUI系统上,EventSystem提供了一些方法.那就是EventSyste ...