more unfinished changes, process tab for dashboard
This commit is contained in:
@@ -0,0 +1,191 @@
|
||||
#include "rootnodes.hpp"
|
||||
|
||||
#include <qjsondocument.h>
|
||||
#include <qsavefile.h>
|
||||
|
||||
#include "../toaster.hpp"
|
||||
#include "common.hpp"
|
||||
#include "migration.hpp"
|
||||
|
||||
namespace ZShell::config {
|
||||
|
||||
using Qt::StringLiterals::operator""_s;
|
||||
|
||||
namespace {
|
||||
|
||||
QString nameFor(const QString& key) {
|
||||
return key.isEmpty() ? u"global"_s : key;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace detail {
|
||||
|
||||
void loaded(ConfigKind kind, settings::RootNode* layer, const QString& screen) {
|
||||
if (kind != ConfigKind::Shell || !screen.isEmpty()) return;
|
||||
|
||||
auto* const config = static_cast<ConfigRoot*>(layer);
|
||||
if (!config->utilities()->toasts()->configLoaded()) return;
|
||||
|
||||
const auto issues = static_cast<int>(config->diagnostics().count());
|
||||
const auto message = issues > 0
|
||||
? QStringLiteral("Config loaded with %1 issue%2")
|
||||
.arg(issues)
|
||||
.arg(issues == 1 ? "" : "s")
|
||||
: QStringLiteral("Config loaded successfully!");
|
||||
Toaster::instance()->toast(
|
||||
QStringLiteral("Config loaded"),
|
||||
message,
|
||||
issues > 0 ? QStringLiteral("settings_alert")
|
||||
: QStringLiteral("rule_settings"),
|
||||
issues > 0 ? Toast::Type::Warning : Toast::Type::Info);
|
||||
}
|
||||
|
||||
void loadFailed(ConfigKind kind, const QString& error, const QString& screen) {
|
||||
QString title;
|
||||
if (kind == ConfigKind::Tokens)
|
||||
title = screen.isEmpty()
|
||||
? QStringLiteral("Failed to parse token config")
|
||||
: QStringLiteral("Failed to parse token config for %1")
|
||||
.arg(screen);
|
||||
else
|
||||
title =
|
||||
screen.isEmpty()
|
||||
? QStringLiteral("Failed to parse config")
|
||||
: QStringLiteral("Failed to parse config for %1").arg(screen);
|
||||
Toaster::instance()->toast(
|
||||
title, error, QStringLiteral("settings_alert"), Toast::Type::Warning);
|
||||
}
|
||||
|
||||
void saveFailed(ConfigKind kind, const QString& error, const QString& screen) {
|
||||
if (kind != ConfigKind::Shell) return;
|
||||
|
||||
const auto title =
|
||||
screen.isEmpty()
|
||||
? QStringLiteral("Failed to save config")
|
||||
: QStringLiteral("Failed to save config for %1").arg(screen);
|
||||
Toaster::instance()->toast(
|
||||
title, error, QStringLiteral("settings_alert"), Toast::Type::Error);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
ConfigRoot::ConfigRoot(
|
||||
const QString& path, ConfigRoot* fallback, QObject* parent)
|
||||
: RootNode(path, fallback, parent) {
|
||||
migrateFile(path);
|
||||
bindTokens();
|
||||
qCDebug(lcConfig) << "Created config root for" << nameFor(key());
|
||||
}
|
||||
|
||||
void ConfigRoot::migrateFile(const QString& path) {
|
||||
QFile file(path);
|
||||
if (!file.exists() || !file.open(QIODevice::ReadOnly)) return;
|
||||
|
||||
const auto doc = QJsonDocument::fromJson(file.readAll());
|
||||
if (!doc.isObject()) return;
|
||||
|
||||
const QJsonObject raw = doc.object();
|
||||
const QJsonObject migrated = ConfigMigrations::apply(raw);
|
||||
if (migrated == raw) return;
|
||||
|
||||
file.close();
|
||||
|
||||
QSaveFile save(path);
|
||||
if (!save.open(QIODevice::WriteOnly)) {
|
||||
qCWarning(lcConfig) << "Failed to open" << path
|
||||
<< "for migration write:" << save.errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
if (save.write(QJsonDocument(migrated).toJson(QJsonDocument::Indented)) !=
|
||||
save.size()) {
|
||||
qCWarning(lcConfig)
|
||||
<< "Failed to write migrated config:" << save.errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!save.commit()) {
|
||||
qCWarning(lcConfig)
|
||||
<< "Failed to commit migrated config:" << save.errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(lcConfig) << "Migrated config file" << path;
|
||||
}
|
||||
|
||||
void ConfigRoot::bindTokens() {
|
||||
qCDebug(lcConfig) << "Binding appearance to token values for"
|
||||
<< nameFor(key());
|
||||
|
||||
auto* const tokens = TokensSingleton::instance()->appearance();
|
||||
m_appearance->rounding()->bindTokens(tokens->rounding());
|
||||
m_appearance->spacing()->bindTokens(tokens->spacing());
|
||||
m_appearance->padding()->bindTokens(tokens->padding());
|
||||
m_appearance->anim()->durations()->bindTokens(tokens->animDurations());
|
||||
}
|
||||
|
||||
TokensRoot::TokensRoot(
|
||||
const QString& path, TokensRoot* fallback, QObject* parent)
|
||||
: RootNode(path, fallback, parent) {
|
||||
qCDebug(lcConfig) << "Created tokens root for" << nameFor(key());
|
||||
}
|
||||
|
||||
#define SINGLETON_IMPL(Type, Root, file, kind) \
|
||||
Type* Type::instance() { \
|
||||
static Type instance; \
|
||||
return &instance; \
|
||||
} \
|
||||
\
|
||||
Type* Type::create(QQmlEngine*, QJSEngine*) { \
|
||||
QQmlEngine::setObjectOwnership(instance(), QQmlEngine::CppOwnership); \
|
||||
return instance(); \
|
||||
} \
|
||||
\
|
||||
Root* Type::forScreen(const QString& screen) { \
|
||||
bool created; \
|
||||
auto* const layer = m_layers.get(screen, this, &created); \
|
||||
if (created) initLayer(layer); \
|
||||
return layer; \
|
||||
} \
|
||||
\
|
||||
Type::Type(QObject* parent) \
|
||||
: Root(configDir() + u'/' + file, nullptr, parent) \
|
||||
, m_layers(monitorConfigDir(), file, this) { \
|
||||
initLayer(this); \
|
||||
} \
|
||||
\
|
||||
void Type::onTreeLoaded(settings::RootNode* layer) { \
|
||||
detail::loaded( \
|
||||
kind, layer, m_layers.nameFor(static_cast<Root*>(layer))); \
|
||||
} \
|
||||
\
|
||||
void Type::onTreeLoadFailed( \
|
||||
settings::RootNode* layer, const QString& error) { \
|
||||
detail::loadFailed( \
|
||||
kind, error, m_layers.nameFor(static_cast<Root*>(layer))); \
|
||||
} \
|
||||
\
|
||||
void Type::onTreeSaveFailed( \
|
||||
settings::RootNode* layer, const QString& error) { \
|
||||
detail::saveFailed( \
|
||||
kind, error, m_layers.nameFor(static_cast<Root*>(layer))); \
|
||||
} \
|
||||
\
|
||||
void Type::initLayer(Root* layer) { \
|
||||
QObject::connect(layer, &Root::treeLoaded, this, &Type::onTreeLoaded); \
|
||||
QObject::connect( \
|
||||
layer, &Root::treeLoadFailed, this, &Type::onTreeLoadFailed); \
|
||||
QObject::connect( \
|
||||
layer, &Root::treeSaveFailed, this, &Type::onTreeSaveFailed); \
|
||||
layer->load(); \
|
||||
}
|
||||
|
||||
SINGLETON_IMPL(
|
||||
ConfigSingleton, ConfigRoot, u"config.json"_s, detail::ConfigKind::Shell)
|
||||
SINGLETON_IMPL(
|
||||
TokensSingleton, TokensRoot, u"tokens.json"_s, detail::ConfigKind::Tokens)
|
||||
|
||||
#undef SINGLETON_IMPL
|
||||
|
||||
} // namespace ZShell::config
|
||||
Reference in New Issue
Block a user