10#include <config-libkleo.h>
12#include "filesystemwatcher.h"
14#include <libkleo/stl_util.h>
16#include <libkleo_debug.h>
19#include <QFileSystemWatcher>
20#include <QRegularExpression>
28class FileSystemWatcher::Private
30 FileSystemWatcher *
const q;
39 void onFileChanged(
const QString &path);
40 void onDirectoryChanged(
const QString &path);
44 void connectWatcher();
48 std::set<QString> m_seenPaths;
49 std::set<QString> m_cachedDirectories;
50 std::set<QString> m_cachedFiles;
54FileSystemWatcher::Private::Private(FileSystemWatcher *qq,
const QStringList &paths)
59 m_timer.setSingleShot(
true);
67 for (
const QString &entry : list) {
77 return is_matching(file, blacklist);
82 if (whitelist.
empty()) {
85 return is_matching(file, whitelist);
88void FileSystemWatcher::Private::onFileChanged(
const QString &path)
91 if (is_blacklisted(fi.fileName(), m_blacklist)) {
94 if (!is_whitelisted(fi.fileName(), m_whitelist)) {
97 qCDebug(LIBKLEO_LOG) <<
path;
99 m_seenPaths.insert(path);
101 m_seenPaths.erase(path);
103 m_cachedFiles.insert(path);
112 return is_blacklisted(entry, blacklist);
114 if (!whitelist.
empty()) {
115 end = std::remove_if(entries.
begin(), end, [&whitelist](
const QString &entry) {
116 return !is_whitelisted(entry, whitelist);
120 std::sort(entries.
begin(), entries.
end());
123 return dir.absoluteFilePath(entry);
132 std::set_difference(current.
begin(), current.
end(), seen.begin(), seen.end(), std::back_inserter(result));
136void FileSystemWatcher::Private::onDirectoryChanged(
const QString &path)
138 const QStringList newFiles = find_new_files(list_dir_absolute(path, m_blacklist, m_whitelist), m_seenPaths);
140 if (newFiles.
empty()) {
144 qCDebug(LIBKLEO_LOG) <<
"newFiles" << newFiles;
147 q->addPaths(newFiles);
149 m_cachedDirectories.insert(path);
153void FileSystemWatcher::Private::onTimeout()
155 std::set<QString> dirs;
156 std::set<QString> files;
158 dirs.swap(m_cachedDirectories);
159 files.swap(m_cachedFiles);
161 if (dirs.empty() && files.empty()) {
167 for (
const QString &i : std::as_const(dirs)) {
168 Q_EMIT q->directoryChanged(i);
170 for (
const QString &i : std::as_const(files)) {
175void FileSystemWatcher::Private::handleTimer()
177 if (m_timer.interval() == 0) {
184void FileSystemWatcher::Private::connectWatcher()
190 onDirectoryChanged(str);
197FileSystemWatcher::FileSystemWatcher(
QObject *p)
199 , d(new Private(this))
206 , d(new Private(this, paths))
211void FileSystemWatcher::setEnabled(
bool enable)
213 if (isEnabled() == enable) {
217 Q_ASSERT(!d->m_watcher);
219 if (!d->m_paths.empty()) {
220 d->m_watcher->addPaths(d->m_paths);
224 Q_ASSERT(d->m_watcher);
226 d->m_watcher =
nullptr;
230bool FileSystemWatcher::isEnabled()
const
232 return d->m_watcher !=
nullptr;
235FileSystemWatcher::~FileSystemWatcher()
239void FileSystemWatcher::setDelay(
int ms)
242 d->m_timer.setInterval(ms);
245int FileSystemWatcher::delay()
const
247 return d->m_timer.interval();
250void FileSystemWatcher::blacklistFiles(
const QStringList &paths)
252 d->m_blacklist += paths;
254 d->m_paths.erase(kdtools::separate_if(d->m_paths.begin(),
256 std::back_inserter(blacklisted),
259 return is_blacklisted(path, d->m_blacklist);
263 if (d->m_watcher && !blacklisted.
empty()) {
264 d->m_watcher->removePaths(blacklisted);
268void FileSystemWatcher::whitelistFiles(
const QStringList &patterns)
270 d->m_whitelist += patterns;
282 for (
const QString &path : paths) {
283 if (
QDir(path).exists()) {
284 result += list_dir_absolute(path, blacklist, whitelist);
287 return result + resolve(result, blacklist, whitelist);
290void FileSystemWatcher::addPaths(
const QStringList &paths)
295 const QStringList newPaths = paths + resolve(paths, d->m_blacklist, d->m_whitelist);
296 if (!newPaths.
empty()) {
299 d->m_paths += newPaths;
300 d->m_seenPaths.insert(newPaths.
begin(), newPaths.
end());
301 if (d->m_watcher && !newPaths.
empty()) {
302 d->m_watcher->addPaths(newPaths);
306void FileSystemWatcher::addPath(
const QString &path)
311void FileSystemWatcher::removePaths(
const QStringList &paths)
316 for (
const QString &i : paths) {
317 d->m_paths.removeAll(i);
320 d->m_watcher->removePaths(paths);
324void FileSystemWatcher::removePath(
const QString &path)
329#include "moc_filesystemwatcher.cpp"
KCOREADDONS_EXPORT Result match(QStringView pattern, QStringView str)
QString path(const QString &relativePath)
KIOCORE_EXPORT QString dir(const QString &fileClass)
const QList< QKeySequence > & end()
void directoryChanged(const QString &path)
void fileChanged(const QString &path)
iterator erase(const_iterator begin, const_iterator end)
iterator insert(const_iterator before, parameter_type value)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QRegularExpression fromWildcard(QStringView pattern, Qt::CaseSensitivity cs, WildcardConversionOptions options)
QString join(QChar separator) const const
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)