1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qfilesystemwatcher_polling_p.h"
5
6#include <QtCore/qscopeguard.h>
7#include <QtCore/qtimer.h>
8
9#include <chrono>
10
11using namespace std::chrono_literals;
12
13QT_BEGIN_NAMESPACE
14
15static constexpr auto PollingInterval = 1s;
16
17QPollingFileSystemWatcherEngine::QPollingFileSystemWatcherEngine(QObject *parent)
18 : QFileSystemWatcherEngine(parent)
19{
20}
21
22QStringList QPollingFileSystemWatcherEngine::addPaths(const QStringList &paths,
23 QStringList *files,
24 QStringList *directories)
25{
26 QStringList unhandled;
27 for (const QString &path : paths) {
28 auto sg = qScopeGuard(f: [&]{ unhandled.push_back(t: path); });
29 QFileInfo fi(path);
30 if (!fi.exists())
31 continue;
32 if (fi.isDir()) {
33 if (directories->contains(str: path))
34 continue;
35 directories->append(t: path);
36 if (!path.endsWith(c: u'/'))
37 fi = QFileInfo(path + u'/');
38 this->directories.insert(key: path, value: fi);
39 } else {
40 if (files->contains(str: path))
41 continue;
42 files->append(t: path);
43 this->files.insert(key: path, value: fi);
44 }
45 sg.dismiss();
46 }
47
48 if ((!this->files.isEmpty() ||
49 !this->directories.isEmpty()) &&
50 !timer.isActive()) {
51 timer.start(duration: PollingInterval, obj: this);
52 }
53
54 return unhandled;
55}
56
57QStringList QPollingFileSystemWatcherEngine::removePaths(const QStringList &paths,
58 QStringList *files,
59 QStringList *directories)
60{
61 QStringList unhandled;
62 for (const QString &path : paths) {
63 if (this->directories.remove(key: path)) {
64 directories->removeAll(t: path);
65 } else if (this->files.remove(key: path)) {
66 files->removeAll(t: path);
67 } else {
68 unhandled.push_back(t: path);
69 }
70 }
71
72 if (this->files.isEmpty() &&
73 this->directories.isEmpty()) {
74 timer.stop();
75 }
76
77 return unhandled;
78}
79
80void QPollingFileSystemWatcherEngine::timerEvent(QTimerEvent *e)
81{
82 if (e->timerId() != timer.timerId())
83 return QFileSystemWatcherEngine::timerEvent(event: e);
84
85 for (auto it = files.begin(), end = files.end(); it != end; /*erasing*/) {
86 QString path = it.key();
87 QFileInfo fi(path);
88 if (!fi.exists()) {
89 it = files.erase(it);
90 emit fileChanged(path, removed: true);
91 continue;
92 } else if (it.value() != fi) {
93 it.value() = fi;
94 emit fileChanged(path, removed: false);
95 }
96 ++it;
97 }
98
99 for (auto it = directories.begin(), end = directories.end(); it != end; /*erasing*/) {
100 QString path = it.key();
101 QFileInfo fi(path);
102 if (!path.endsWith(c: u'/'))
103 fi = QFileInfo(path + u'/');
104 if (!fi.exists()) {
105 it = directories.erase(it);
106 emit directoryChanged(path, removed: true);
107 continue;
108 } else if (it.value() != fi) {
109 fi.refresh();
110 if (!fi.exists()) {
111 it = directories.erase(it);
112 emit directoryChanged(path, removed: true);
113 continue;
114 } else {
115 it.value() = fi;
116 emit directoryChanged(path, removed: false);
117 }
118 }
119 ++it;
120 }
121}
122
123QT_END_NAMESPACE
124
125#include "moc_qfilesystemwatcher_polling_p.cpp"
126

source code of qtbase/src/corelib/io/qfilesystemwatcher_polling.cpp