33#include < utility>
44
55#include < qcontainerfwd.h>
6+ #include < qcryptographichash.h>
67#include < qdir.h>
78#include < qfileinfo.h>
89#include < qjsengine.h>
2122
2223QS_LOGGING_CATEGORY (logQmlScanner, " quickshell.qmlscanner" , QtWarningMsg);
2324
25+ bool QmlScanner::readAndHashFile (const QString& path, QByteArray& data) {
26+ auto file = QFile (path);
27+ if (!file.open (QFile::ReadOnly)) return false ;
28+ data = file.readAll ();
29+ this ->fileHashes .insert (path, QCryptographicHash::hash (data, QCryptographicHash::Md5));
30+ return true ;
31+ }
32+
33+ bool QmlScanner::hasFileContentChanged (const QString& path) const {
34+ auto it = this ->fileHashes .constFind (path);
35+ if (it == this ->fileHashes .constEnd ()) return true ;
36+
37+ auto file = QFile (path);
38+ if (!file.open (QFile::ReadOnly)) return true ;
39+
40+ auto newHash = QCryptographicHash::hash (file.readAll (), QCryptographicHash::Md5);
41+ return newHash != it.value ();
42+ }
43+
2444void QmlScanner::scanDir (const QDir& dir) {
2545 if (this ->scannedDirs .contains (dir)) return ;
2646 this ->scannedDirs .push_back (dir);
@@ -109,13 +129,13 @@ bool QmlScanner::scanQmlFile(const QString& path, bool& singleton, bool& interna
109129
110130 qCDebug (logQmlScanner) << " Scanning qml file" << path;
111131
112- auto file = QFile (path) ;
113- if (!file. open (QFile::ReadOnly | QFile::Text )) {
132+ QByteArray fileData ;
133+ if (!this -> readAndHashFile (path, fileData )) {
114134 qCWarning (logQmlScanner) << " Failed to open file" << path;
115135 return false ;
116136 }
117137
118- auto stream = QTextStream (&file );
138+ auto stream = QTextStream (&fileData );
119139 auto imports = QVector<QString>();
120140
121141 bool inHeader = true ;
@@ -219,8 +239,6 @@ bool QmlScanner::scanQmlFile(const QString& path, bool& singleton, bool& interna
219239 postError (" unclosed preprocessor if block" );
220240 }
221241
222- file.close ();
223-
224242 if (isOverridden) {
225243 this ->fileIntercepts .insert (path, overrideText);
226244 }
@@ -257,8 +275,11 @@ bool QmlScanner::scanQmlFile(const QString& path, bool& singleton, bool& interna
257275 continue ;
258276 }
259277
260- if (import .endsWith (" .js" )) this ->scannedFiles .push_back (cpath);
261- else this ->scanDir (cpath);
278+ if (import .endsWith (" .js" )) {
279+ this ->scannedFiles .push_back (cpath);
280+ QByteArray jsData;
281+ this ->readAndHashFile (cpath, jsData);
282+ } else this ->scanDir (cpath);
262283 }
263284
264285 return true ;
@@ -273,14 +294,12 @@ void QmlScanner::scanQmlRoot(const QString& path) {
273294bool QmlScanner::scanQmlJson (const QString& path) {
274295 qCDebug (logQmlScanner) << " Scanning qml.json file" << path;
275296
276- auto file = QFile (path) ;
277- if (!file. open (QFile::ReadOnly | QFile::Text )) {
297+ QByteArray data ;
298+ if (!this -> readAndHashFile (path, data )) {
278299 qCWarning (logQmlScanner) << " Failed to open file" << path;
279300 return false ;
280301 }
281302
282- auto data = file.readAll ();
283-
284303 // Importing this makes CI builds fail for some reason.
285304 QJsonParseError error; // NOLINT (misc-include-cleaner)
286305 auto json = QJsonDocument::fromJson (data, &error);
0 commit comments