由于Qt的体系过于庞大,即使是某个模块,分析起来也十分困难。对于QFileSystemModel,我们在这里对单个重要函数慢慢分析
1
/*! 2 \internal 3 4 The thread has received new information about files, 5 update and emit dataChanged if it has actually changed. 6 */ 7 void QFileSystemModelPrivate::_q_fileSystemChanged(const QString &path, const QVector<QPair<QString, QFileInfo> > &updates) 8 { 9 #ifndef QT_NO_FILESYSTEMWATCHER 10 Q_Q(QFileSystemModel); 11 QVector<QString> rowsToUpdate; 12 QStringList newFiles; 13 QFileSystemModelPrivate::QFileSystemNode *parentNode = node(path, false); 14 QModelIndex parentIndex = index(parentNode); 15 for (const auto &update : updates) { 16 QString fileName = update.first; 17 Q_ASSERT(!fileName.isEmpty()); 18 QExtendedInformation info = fileInfoGatherer.getInfo(update.second); 19 bool previouslyHere = parentNode->children.contains(fileName); 20 if (!previouslyHere) { 21 addNode(parentNode, fileName, info.fileInfo()); 22 } 23 QFileSystemModelPrivate::QFileSystemNode * node = parentNode->children.value(fileName); 24 bool isCaseSensitive = parentNode->caseSensitive(); 25 if (isCaseSensitive) { 26 if (node->fileName != fileName) 27 continue; 28 } else { 29 if (QString::compare(node->fileName,fileName,Qt::CaseInsensitive) != 0) 30 continue; 31 } 32 if (isCaseSensitive) { 33 Q_ASSERT(node->fileName == fileName); 34 } else { 35 node->fileName = fileName; 36 } 37 38 if (*node != info ) { 39 node->populate(info); 40 bypassFilters.remove(node); 41 // brand new information. 42 if (filtersAcceptsNode(node)) { 43 if (!node->isVisible) { 44 newFiles.append(fileName); 45 } else { 46 rowsToUpdate.append(fileName); 47 } 48 } else { 49 if (node->isVisible) { 50 int visibleLocation = parentNode->visibleLocation(fileName); 51 removeVisibleFile(parentNode, visibleLocation); 52 } else { 53 // The file is not visible, don't do anything 54 } 55 } 56 } 57 } 58 59 // bundle up all of the changed signals into as few as possible. 60 std::sort(rowsToUpdate.begin(), rowsToUpdate.end()); 61 QString min; 62 QString max; 63 for (int i = 0; i < rowsToUpdate.count(); ++i) { 64 QString value = rowsToUpdate.at(i); 65 //##TODO is there a way to bundle signals with QString as the content of the list? 66 /*if (min.isEmpty()) { 67 min = value; 68 if (i != rowsToUpdate.count() - 1) 69 continue; 70 } 71 if (i != rowsToUpdate.count() - 1) { 72 if ((value == min + 1 && max.isEmpty()) || value == max + 1) { 73 max = value; 74 continue; 75 } 76 }*/ 77 max = value; 78 min = value; 79 int visibleMin = parentNode->visibleLocation(min); 80 int visibleMax = parentNode->visibleLocation(max); 81 if (visibleMin >= 0 82 && visibleMin < parentNode->visibleChildren.count() 83 && parentNode->visibleChildren.at(visibleMin) == min 84 && visibleMax >= 0) { 85 QModelIndex bottom = q->index(translateVisibleLocation(parentNode, visibleMin), 0, parentIndex); 86 QModelIndex top = q->index(translateVisibleLocation(parentNode, visibleMax), 3, parentIndex); 87 emit q->dataChanged(bottom, top); 88 } 89 90 /*min = QString(); 91 max = QString();*/ 92 } 93 94 if (newFiles.count() > 0) { 95 addVisibleFiles(parentNode, newFiles); 96 } 97 98 if (newFiles.count() > 0 || (sortColumn != 0 && rowsToUpdate.count() > 0)) { 99 forceSort = true; 100 delayedSort(); 101 } 102 #else 103 Q_UNUSED(path) 104 Q_UNUSED(updates) 105 #endif // !QT_NO_FILESYSTEMWATCHER 106 }

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

1 /*
2    Avoid "unused parameter" warnings
3 */
4 #define Q_UNUSED(x) (void)x;

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

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

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

 40 #ifndef QFILEINFOGATHERER_H
 41 #define QFILEINFOGATHERER_H
 42 
 43 //
 44 //  W A R N I N G
 45 //  -------------
 46 //
 47 // This file is not part of the Qt API.  It exists purely as an
 48 // implementation detail.  This header file may change from version to
 49 // version without notice, or even be removed.
 50 //
 51 // We mean it.
 52 //
 53 
 54 #include <QtWidgets/private/qtwidgetsglobal_p.h>
 55 
 56 #include <qthread.h>
 57 #include <qmutex.h>
 58 #include <qwaitcondition.h>
 59 #include <qfilesystemwatcher.h>
 60 #include <qfileiconprovider.h>
 61 #include <qpair.h>
 62 #include <qstack.h>
 63 #include <qdatetime.h>
 64 #include <qdir.h>
 65 #include <qelapsedtimer.h>
 66 
 67 #include <private/qfilesystemengine_p.h>
 68 
 69 QT_REQUIRE_CONFIG(filesystemmodel);
 70 
 71 QT_BEGIN_NAMESPACE
 72 
 73 class QExtendedInformation {
 74 public:
 75     enum Type { Dir, File, System };
 76 
 77     QExtendedInformation() {}
 78     QExtendedInformation(const QFileInfo &info) : mFileInfo(info) {}
 79 
 80     inline bool isDir() { return type() == Dir; }
 81     inline bool isFile() { return type() == File; }
 82     inline bool isSystem() { return type() == System; }
 83 
 84     bool operator ==(const QExtendedInformation &fileInfo) const {
 85        return mFileInfo == fileInfo.mFileInfo
 86        && displayType == fileInfo.displayType
 87        && permissions() == fileInfo.permissions();
 88     }
 89 
 90 #ifndef QT_NO_FSFILEENGINE
 91     bool isCaseSensitive() const {
 92         return QFileSystemEngine::isCaseSensitive();
 93     }
 94 #endif
 95 
 96     QFile::Permissions permissions() const {
 97         return mFileInfo.permissions();
 98     }
 99 
100     Type type() const {
101         if (mFileInfo.isDir()) {
102             return QExtendedInformation::Dir;
103         }
104         if (mFileInfo.isFile()) {
105             return QExtendedInformation::File;
106         }
107         if (!mFileInfo.exists() && mFileInfo.isSymLink()) {
108             return QExtendedInformation::System;
109         }
110         return QExtendedInformation::System;
111     }
112 
113     bool isSymLink(bool ignoreNtfsSymLinks = false) const
114     {
115         if (ignoreNtfsSymLinks) {
116 #ifdef Q_OS_WIN
117             return !mFileInfo.suffix().compare(QLatin1String("lnk"), Qt::CaseInsensitive);
118 #endif
119         }
120         return mFileInfo.isSymLink();
121     }
122 
123     bool isHidden() const {
124         return mFileInfo.isHidden();
125     }
126 
127     QFileInfo fileInfo() const {
128         return mFileInfo;
129     }
130 
131     QDateTime lastModified() const {
132         return mFileInfo.lastModified();
133     }
134 
135     qint64 size() const {
136         qint64 size = -1;
137         if (type() == QExtendedInformation::Dir)
138             size = 0;
139         if (type() == QExtendedInformation::File)
140             size = mFileInfo.size();
141         if (!mFileInfo.exists() && !mFileInfo.isSymLink())
142             size = -1;
143         return size;
144     }
145 
146     QString displayType;
147     QIcon icon;
148 
149 private :
150     QFileInfo mFileInfo;
151 };
152 
153 class QFileIconProvider;
154 
155 class Q_AUTOTEST_EXPORT QFileInfoGatherer : public QThread
156 {
157 Q_OBJECT
158 
159 Q_SIGNALS:
160     void updates(const QString &directory, const QVector<QPair<QString, QFileInfo> > &updates);
161     void newListOfFiles(const QString &directory, const QStringList &listOfFiles) const;
162     void nameResolved(const QString &fileName, const QString &resolvedName) const;
163     void directoryLoaded(const QString &path);
164 
165 public:
166     explicit QFileInfoGatherer(QObject *parent = 0);
167     ~QFileInfoGatherer();
168 
169     // only callable from this->thread():
170     void clear();
171     void removePath(const QString &path);
172     QExtendedInformation getInfo(const QFileInfo &info) const;
173     QFileIconProvider *iconProvider() const;
174     bool resolveSymlinks() const;
175 
176 public Q_SLOTS:
177     void list(const QString &directoryPath);
178     void fetchExtendedInformation(const QString &path, const QStringList &files);
179     void updateFile(const QString &path);
180     void setResolveSymlinks(bool enable);
181     void setIconProvider(QFileIconProvider *provider);
182 
183 private Q_SLOTS:
184     void driveAdded();
185     void driveRemoved();
186 
187 private:
188     void run() Q_DECL_OVERRIDE;
189     // called by run():
190     void getFileInfos(const QString &path, const QStringList &files);
191     void fetch(const QFileInfo &info, QElapsedTimer &base, bool &firstTime, QVector<QPair<QString, QFileInfo> > &updatedFiles, const QString &path);
192 
193 private:
194     mutable QMutex mutex;
195     // begin protected by mutex
196     QWaitCondition condition;
197     QStack<QString> path;
198     QStack<QStringList> files;
199     // end protected by mutex
200     QAtomicInt abort;
201 
202 #ifndef QT_NO_FILESYSTEMWATCHER
203     QFileSystemWatcher *watcher;
204 #endif
205 #ifdef Q_OS_WIN
206     bool m_resolveSymlinks; // not accessed by run()
207 #endif
208     QFileIconProvider *m_iconProvider; // not accessed by run()
209     QFileIconProvider defaultProvider;
210 };
211 
212 QT_END_NAMESPACE
213 #endif // QFILEINFOGATHERER_H