#include "LayoutRepository.h" #include "LayoutLoader.h" #include #include #include Q_LOGGING_CATEGORY(lcLayouts, "sloposk.layouts") void LayoutRepository::loadDirectory(const QString &dir) { const QDir directory(dir); for (const QString &file : directory.entryList({QStringLiteral("*.json")}, QDir::Files, QDir::Name)) { QString error; const auto layout = LayoutLoader::load(directory.filePath(file), &error); if (layout) add(*layout); else qCWarning(lcLayouts) << "Skipping" << directory.filePath(file) << ":" << error; } } void LayoutRepository::finalize(const QString &preferredLocale) { resolveBases(); m_layouts.removeIf([](const Layout &layout) { QString error; if (LayoutLoader::validate(layout, &error)) return false; qCWarning(lcLayouts) << "Dropping layout" << layout.id << ":" << error; return true; }); std::stable_partition(m_layouts.begin(), m_layouts.end(), [&](const Layout &layout) { return layout.locale == preferredLocale; }); } int LayoutRepository::indexOf(const QString &id) const { for (qsizetype i = 0; i < m_layouts.size(); ++i) { if (m_layouts[i].id == id) return int(i); } return -1; } void LayoutRepository::add(const Layout &layout) { const int existing = indexOf(layout.id); if (existing >= 0) m_layouts[existing] = layout; else m_layouts.append(layout); } void LayoutRepository::resolveBases() { // One level of inheritance keeps this simple and cycle-free. for (Layout &layout : m_layouts) { if (layout.base.isEmpty()) continue; const int baseIndex = indexOf(layout.base); if (baseIndex < 0) { qCWarning(lcLayouts) << "Layout" << layout.id << "has unknown base" << layout.base; continue; } for (const Layer &layer : m_layouts[baseIndex].layers) { if (!layout.layer(layer.name)) layout.layers.append(layer); } } }