QFileSystemModelPrivate

QFileSystemModelPrivate

由于Qt的体系过于庞大,即使是某个模块,分析起来也十分困难。对于QFileSystemModel,我们在这里对单个重要函数慢慢分析
1 /*!
\internal The thread has received new information about files,
update and emit dataChanged if it has actually changed.
*/
void QFileSystemModelPrivate::_q_fileSystemChanged(const QString &path, const QVector<QPair<QString, QFileInfo> > &updates)
{
#ifndef QT_NO_FILESYSTEMWATCHER
Q_Q(QFileSystemModel);
QVector<QString> rowsToUpdate;
QStringList newFiles;
QFileSystemModelPrivate::QFileSystemNode *parentNode = node(path, false);
QModelIndex parentIndex = index(parentNode);
for (const auto &update : updates) {
QString fileName = update.first;
Q_ASSERT(!fileName.isEmpty());
QExtendedInformation info = fileInfoGatherer.getInfo(update.second);
bool previouslyHere = parentNode->children.contains(fileName);
if (!previouslyHere) {
addNode(parentNode, fileName, info.fileInfo());
}
QFileSystemModelPrivate::QFileSystemNode * node = parentNode->children.value(fileName);
bool isCaseSensitive = parentNode->caseSensitive();
if (isCaseSensitive) {
if (node->fileName != fileName)
continue;
} else {
if (QString::compare(node->fileName,fileName,Qt::CaseInsensitive) != )
continue;
}
if (isCaseSensitive) {
Q_ASSERT(node->fileName == fileName);
} else {
node->fileName = fileName;
} if (*node != info ) {
node->populate(info);
bypassFilters.remove(node);
// brand new information.
if (filtersAcceptsNode(node)) {
if (!node->isVisible) {
newFiles.append(fileName);
} else {
rowsToUpdate.append(fileName);
}
} else {
if (node->isVisible) {
int visibleLocation = parentNode->visibleLocation(fileName);
removeVisibleFile(parentNode, visibleLocation);
} else {
// The file is not visible, don't do anything
}
}
}
} // bundle up all of the changed signals into as few as possible.
std::sort(rowsToUpdate.begin(), rowsToUpdate.end());
QString min;
QString max;
for (int i = ; i < rowsToUpdate.count(); ++i) {
QString value = rowsToUpdate.at(i);
//##TODO is there a way to bundle signals with QString as the content of the list?
/*if (min.isEmpty()) {
min = value;
if (i != rowsToUpdate.count() - 1)
continue;
}
if (i != rowsToUpdate.count() - 1) {
if ((value == min + 1 && max.isEmpty()) || value == max + 1) {
max = value;
continue;
}
}*/
max = value;
min = value;
int visibleMin = parentNode->visibleLocation(min);
int visibleMax = parentNode->visibleLocation(max);
if (visibleMin >=
&& visibleMin < parentNode->visibleChildren.count()
&& parentNode->visibleChildren.at(visibleMin) == min
&& visibleMax >= ) {
QModelIndex bottom = q->index(translateVisibleLocation(parentNode, visibleMin), , parentIndex);
QModelIndex top = q->index(translateVisibleLocation(parentNode, visibleMax), , parentIndex);
emit q->dataChanged(bottom, top);
} /*min = QString();
max = QString();*/
} if (newFiles.count() > ) {
addVisibleFiles(parentNode, newFiles);
} if (newFiles.count() > || (sortColumn != && rowsToUpdate.count() > )) {
forceSort = true;
delayedSort();
}
#else
Q_UNUSED(path)
Q_UNUSED(updates)
#endif // !QT_NO_FILESYSTEMWATCHER
}

  针对程序,一一作出解释:Q_UNUSED宏,避免因为某个变量没有使用,而编译器报错:

 /*
Avoid "unused parameter" warnings
*/
#define Q_UNUSED(x) (void)x;

  接下来,解释下面这句,位于主代码18行的:

QExtendedInformation info = fileInfoGatherer.getInfo(update.second);

  找到它所在的头文件qfileinfogatherer_p.h

 #ifndef QFILEINFOGATHERER_H
#define QFILEINFOGATHERER_H //
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
// #include <QtWidgets/private/qtwidgetsglobal_p.h> #include <qthread.h>
#include <qmutex.h>
#include <qwaitcondition.h>
#include <qfilesystemwatcher.h>
#include <qfileiconprovider.h>
#include <qpair.h>
#include <qstack.h>
#include <qdatetime.h>
#include <qdir.h>
#include <qelapsedtimer.h> #include <private/qfilesystemengine_p.h> QT_REQUIRE_CONFIG(filesystemmodel); QT_BEGIN_NAMESPACE class QExtendedInformation {
public:
enum Type { Dir, File, System }; QExtendedInformation() {}
QExtendedInformation(const QFileInfo &info) : mFileInfo(info) {} inline bool isDir() { return type() == Dir; }
inline bool isFile() { return type() == File; }
inline bool isSystem() { return type() == System; } bool operator ==(const QExtendedInformation &fileInfo) const {
return mFileInfo == fileInfo.mFileInfo
&& displayType == fileInfo.displayType
&& permissions() == fileInfo.permissions();
} #ifndef QT_NO_FSFILEENGINE
bool isCaseSensitive() const {
return QFileSystemEngine::isCaseSensitive();
}
#endif QFile::Permissions permissions() const {
return mFileInfo.permissions();
} Type type() const {
if (mFileInfo.isDir()) {
return QExtendedInformation::Dir;
}
if (mFileInfo.isFile()) {
return QExtendedInformation::File;
}
if (!mFileInfo.exists() && mFileInfo.isSymLink()) {
return QExtendedInformation::System;
}
return QExtendedInformation::System;
} bool isSymLink(bool ignoreNtfsSymLinks = false) const
{
if (ignoreNtfsSymLinks) {
#ifdef Q_OS_WIN
return !mFileInfo.suffix().compare(QLatin1String("lnk"), Qt::CaseInsensitive);
#endif
}
return mFileInfo.isSymLink();
} bool isHidden() const {
return mFileInfo.isHidden();
} QFileInfo fileInfo() const {
return mFileInfo;
} QDateTime lastModified() const {
return mFileInfo.lastModified();
} 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;
} QString displayType;
QIcon icon; private :
QFileInfo mFileInfo;
}; class QFileIconProvider; class Q_AUTOTEST_EXPORT QFileInfoGatherer : public QThread
{
Q_OBJECT Q_SIGNALS:
void updates(const QString &directory, const QVector<QPair<QString, QFileInfo> > &updates);
void newListOfFiles(const QString &directory, const QStringList &listOfFiles) const;
void nameResolved(const QString &fileName, const QString &resolvedName) const;
void directoryLoaded(const QString &path); public:
explicit QFileInfoGatherer(QObject *parent = );
~QFileInfoGatherer(); // only callable from this->thread():
void clear();
void removePath(const QString &path);
QExtendedInformation getInfo(const QFileInfo &info) const;
QFileIconProvider *iconProvider() const;
bool resolveSymlinks() const; public Q_SLOTS:
void list(const QString &directoryPath);
void fetchExtendedInformation(const QString &path, const QStringList &files);
void updateFile(const QString &path);
void setResolveSymlinks(bool enable);
void setIconProvider(QFileIconProvider *provider); private Q_SLOTS:
void driveAdded();
void driveRemoved(); private:
void run() Q_DECL_OVERRIDE;
// called by run():
void getFileInfos(const QString &path, const QStringList &files);
void fetch(const QFileInfo &info, QElapsedTimer &base, bool &firstTime, QVector<QPair<QString, QFileInfo> > &updatedFiles, const QString &path); private:
mutable QMutex mutex;
// begin protected by mutex
QWaitCondition condition;
QStack<QString> path;
QStack<QStringList> files;
// end protected by mutex
QAtomicInt abort; #ifndef QT_NO_FILESYSTEMWATCHER
QFileSystemWatcher *watcher;
#endif
#ifdef Q_OS_WIN
bool m_resolveSymlinks; // not accessed by run()
#endif
QFileIconProvider *m_iconProvider; // not accessed by run()
QFileIconProvider defaultProvider;
}; QT_END_NAMESPACE
#endif // QFILEINFOGATHERER_H
05-11 14:02