如何在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 ...
随机推荐
- 【Spark-core学习之七】 Spark广播变量、累加器
环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk1.8 scala-2.10.4(依赖jdk1.8) spark ...
- FangDD Java编程规范
我们采用<Oracle/Sun原生的Java编程规范>和<Google Java编程规范> Google Java编程风格指南 January 20, 2014 作者:Haws ...
- 修复svn hook导致的字符集错误
修改pre-commit钩子,如果返回中文信息,可能会报如下错误: Error output could not be translated from the native locale to UTF ...
- 转:C#使用Dotfuscator混淆代码的加密方法
Author:flymorn Source:flymornCategories:C#编程 PostTime:2011-9-16 1:04:49 正 文: C#编写的代码如果不进行一定程度的混淆和加 ...
- websocket 二合一
server from flask import Flask, request, render_template from geventwebsocket.handler import WebSock ...
- Sql Server性能定位及改善
使用SQL Server做为后台数据库的应用程序,当程序操作起来很慢的时候,可能是数据库操作被某个进程Block住了,可以使用以下语句查询目前正在运行的进程 select request_sessio ...
- Linux操作oracle——关闭、停止、重启
基础命令: 在此之前,先介绍一下切换到oracle用户的命令 su - oracle (注意空格) 一.启动监听.启动数据库1.1启动监听1.切换到oracle用户下 2.启动监听: lsnrctl ...
- python scrapy baidu image【转】
原 https://github.com/vivianLL/baidupictures #!/usr/bin/env Python # coding=utf-8 #__author__ = 'leil ...
- 王之泰201771010131《面向对象程序设计(java)》第六周学习总结
第一部分:理论知识学习部分 第五章 第五章学习内容主要分为七个模块,分别为: 1.类.超类和子类: a. 类继承的格式: class 新类名extends已有类名. b. 已有类称为:超类(super ...
- UVA1328 Period
思路 KMP算法的next数组是该字符串的最长的相同的前缀和后缀的长度 所以i-next[i]是最小的循环节长度 然后如果next[i]不为0,则证明一定有循环(不一定完整) 然后如果整除,就是完整的 ...