feat: watch parent dirs recursively for changes
This commit is contained in:
parent
b987a39d79
commit
3e1b235a75
2 changed files with 56 additions and 12 deletions
|
|
@ -4,9 +4,18 @@
|
||||||
#include <qfile.h>
|
#include <qfile.h>
|
||||||
#include <qfileinfo.h>
|
#include <qfileinfo.h>
|
||||||
#include <qjsondocument.h>
|
#include <qjsondocument.h>
|
||||||
|
#include <qstandardpaths.h>
|
||||||
|
|
||||||
namespace caelestia::config {
|
namespace caelestia::config {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
QString watchRoot() {
|
||||||
|
return QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
RootConfig::RootConfig(QObject* parent)
|
RootConfig::RootConfig(QObject* parent)
|
||||||
: ConfigObject(parent) {}
|
: ConfigObject(parent) {}
|
||||||
|
|
||||||
|
|
@ -38,6 +47,10 @@ void RootConfig::setupFileBackend(const QString& path) {
|
||||||
auto json = toJsonObject();
|
auto json = toJsonObject();
|
||||||
file.write(QJsonDocument(json).toJson(QJsonDocument::Indented));
|
file.write(QJsonDocument(json).toJson(QJsonDocument::Indented));
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
|
// Update watches — save may have created directories
|
||||||
|
updateWatch();
|
||||||
|
|
||||||
emit saved();
|
emit saved();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -52,14 +65,51 @@ void RootConfig::setupFileBackend(const QString& path) {
|
||||||
m_reloadDebounce->setInterval(50);
|
m_reloadDebounce->setInterval(50);
|
||||||
connect(m_reloadDebounce, &QTimer::timeout, this, &RootConfig::reload);
|
connect(m_reloadDebounce, &QTimer::timeout, this, &RootConfig::reload);
|
||||||
|
|
||||||
connect(m_watcher, &QFileSystemWatcher::fileChanged, this, &RootConfig::onFileChanged);
|
connect(m_watcher, &QFileSystemWatcher::directoryChanged, this, &RootConfig::onWatcherEvent);
|
||||||
|
connect(m_watcher, &QFileSystemWatcher::fileChanged, this, &RootConfig::onWatcherEvent);
|
||||||
|
|
||||||
qCDebug(lcConfig) << "Setting up file backend for" << metaObject()->className() << "at" << path;
|
qCDebug(lcConfig) << "Setting up file backend for" << metaObject()->className() << "at" << path;
|
||||||
|
|
||||||
|
updateWatch();
|
||||||
reload();
|
reload();
|
||||||
|
}
|
||||||
|
|
||||||
if (QFile::exists(m_filePath))
|
void RootConfig::updateWatch() {
|
||||||
m_watcher->addPath(m_filePath);
|
auto targetDir = QFileInfo(m_filePath).absolutePath();
|
||||||
|
|
||||||
|
// Find the nearest existing directory, walking up toward the watch root
|
||||||
|
auto dir = targetDir;
|
||||||
|
while (!QFile::exists(dir) && dir != watchRoot() && !dir.isEmpty()) {
|
||||||
|
auto parent = QFileInfo(dir).absolutePath();
|
||||||
|
if (parent == dir)
|
||||||
|
break; // reached filesystem root
|
||||||
|
dir = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update directory watch if it changed
|
||||||
|
if (dir != m_watchedDir) {
|
||||||
|
if (!m_watchedDir.isEmpty())
|
||||||
|
m_watcher->removePath(m_watchedDir);
|
||||||
|
|
||||||
|
m_watchedDir = dir;
|
||||||
|
|
||||||
|
if (QFile::exists(dir))
|
||||||
|
m_watcher->addPath(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Watch the file itself if it exists (for in-place modifications)
|
||||||
|
if (QFile::exists(m_filePath)) {
|
||||||
|
if (!m_watcher->files().contains(m_filePath))
|
||||||
|
m_watcher->addPath(m_filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RootConfig::onWatcherEvent() {
|
||||||
|
// Re-evaluate what to watch — directories may have been created or deleted
|
||||||
|
updateWatch();
|
||||||
|
|
||||||
|
if (!m_recentlySaved)
|
||||||
|
m_reloadDebounce->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RootConfig::saveToFile() {
|
void RootConfig::saveToFile() {
|
||||||
|
|
@ -106,14 +156,6 @@ std::optional<QString> RootConfig::reloadFromFile() {
|
||||||
return QString(); // success
|
return QString(); // success
|
||||||
}
|
}
|
||||||
|
|
||||||
void RootConfig::onFileChanged() {
|
|
||||||
if (!m_watcher->files().contains(m_filePath))
|
|
||||||
m_watcher->addPath(m_filePath);
|
|
||||||
|
|
||||||
if (!m_recentlySaved)
|
|
||||||
m_reloadDebounce->start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void RootConfig::save() {
|
void RootConfig::save() {
|
||||||
saveToFile();
|
saveToFile();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,9 +33,11 @@ signals:
|
||||||
void saveFailed(const QString& error);
|
void saveFailed(const QString& error);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void onFileChanged();
|
void updateWatch();
|
||||||
|
void onWatcherEvent();
|
||||||
|
|
||||||
QString m_filePath;
|
QString m_filePath;
|
||||||
|
QString m_watchedDir;
|
||||||
bool m_recentlySaved = false;
|
bool m_recentlySaved = false;
|
||||||
|
|
||||||
QFileSystemWatcher* m_watcher = nullptr;
|
QFileSystemWatcher* m_watcher = nullptr;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue