Files
sloposk/src/layout/LayoutRepository.cpp
T
ericek111andClaude Opus 5.5 be14bbcc62 Layouts, iPad-style rendering, taps, shift and layers
- JSON layouts (en-US, sv-SE inheriting number/symbol layers via base)
- LayoutModel + KeyGeometry: proportional rows, nearest-key hit testing
- KeyboardSurface: multi-pointer touch/mouse routing to the controller
- KeyboardController + ShiftState: iOS shift/caps-lock, layers, globe, dismiss
- QML view with light/dark iPad palette and drag handle
- DevHooks: SLOPOSK_AUTOTYPE, SLOPOSK_SCREENSHOT for headless checks
- Unit tests for shift, loader, geometry and controller

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 14:50:21 +02:00

76 lines
2.1 KiB
C++

#include "LayoutRepository.h"
#include "LayoutLoader.h"
#include <QDir>
#include <QLoggingCategory>
#include <algorithm>
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);
}
}
}