Optional PC key blocks: function row, navigation, numeric keypad
- Template sections placed above or to the right of the typing keys; the user picks any mix in settings, typing keys included - keysym keys send XKB keysyms on press, optionally repeating - Geometry lays blocks side by side with one key unit; stretch keys are resolved at layout time so composed blocks line up - Toggling a block resizes the window so keys keep their size Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+60
-10
@@ -16,6 +16,7 @@ QString keyTypeName(KeyType type)
|
||||
case KeyType::Globe: return QStringLiteral("globe");
|
||||
case KeyType::Dismiss: return QStringLiteral("dismiss");
|
||||
case KeyType::Spacer: return QStringLiteral("spacer");
|
||||
case KeyType::Keysym: return QStringLiteral("keysym");
|
||||
case KeyType::Letters: break; // expanded before it reaches the model
|
||||
}
|
||||
return {};
|
||||
@@ -89,6 +90,27 @@ void LayoutModel::setLayer(const QString &layerName)
|
||||
Q_EMIT layerChanged();
|
||||
}
|
||||
|
||||
void LayoutModel::setVisibleSections(const QStringList &ids)
|
||||
{
|
||||
if (ids == m_visibleSections)
|
||||
return;
|
||||
m_visibleSections = ids;
|
||||
rebuild();
|
||||
}
|
||||
|
||||
QVariantList LayoutModel::sections() const
|
||||
{
|
||||
QVariantList list;
|
||||
for (const Section §ion : m_layout.sections)
|
||||
list.append(QVariantMap{{QStringLiteral("id"), section.id}, {QStringLiteral("name"), section.name}});
|
||||
return list;
|
||||
}
|
||||
|
||||
qreal LayoutModel::totalUnits() const
|
||||
{
|
||||
return ::totalUnits(m_blocks);
|
||||
}
|
||||
|
||||
void LayoutModel::setSize(QSizeF size)
|
||||
{
|
||||
if (size == m_size)
|
||||
@@ -140,12 +162,39 @@ int LayoutModel::keyAt(QPointF pos) const
|
||||
return nearest;
|
||||
}
|
||||
|
||||
QList<Block> LayoutModel::composeBlocks() const
|
||||
{
|
||||
const auto shown = [this](const QString &id) { return m_visibleSections.contains(id); };
|
||||
const Layer *layer = m_layout.layer(m_layerName);
|
||||
|
||||
Block main;
|
||||
for (const Section §ion : m_layout.sections) {
|
||||
if (section.placement == Section::Placement::Above && shown(section.id))
|
||||
main += section.rows;
|
||||
}
|
||||
if (layer && shown(MainSectionId))
|
||||
main += layer->rows;
|
||||
|
||||
QList<Block> blocks;
|
||||
if (!main.isEmpty())
|
||||
blocks.append(main);
|
||||
for (const Section §ion : m_layout.sections) {
|
||||
if (section.placement == Section::Placement::Right && shown(section.id))
|
||||
blocks.append(section.rows);
|
||||
}
|
||||
// Never show nothing.
|
||||
if (blocks.isEmpty() && layer)
|
||||
blocks.append(layer->rows);
|
||||
return blocks;
|
||||
}
|
||||
|
||||
void LayoutModel::rebuild()
|
||||
{
|
||||
beginResetModel();
|
||||
m_blocks = composeBlocks();
|
||||
m_keys.clear();
|
||||
if (const Layer *layer = m_layout.layer(m_layerName)) {
|
||||
for (const Row &row : layer->rows) {
|
||||
for (const Block &block : std::as_const(m_blocks)) {
|
||||
for (const Row &row : block) {
|
||||
for (const KeyDef &key : row) {
|
||||
if (key.type != KeyType::Spacer)
|
||||
m_keys.append(key);
|
||||
@@ -161,17 +210,18 @@ void LayoutModel::rebuild()
|
||||
void LayoutModel::relayout()
|
||||
{
|
||||
m_rects.clear();
|
||||
const Layer *layer = m_layout.layer(m_layerName);
|
||||
if (!layer || m_size.isEmpty())
|
||||
if (m_size.isEmpty())
|
||||
return;
|
||||
|
||||
const QList<QRectF> all = computeKeyRects(*layer, m_size);
|
||||
const QList<QRectF> all = computeKeyRects(m_blocks, m_size);
|
||||
qsizetype i = 0;
|
||||
for (const Row &row : layer->rows) {
|
||||
for (const KeyDef &key : row) {
|
||||
if (key.type != KeyType::Spacer)
|
||||
m_rects.append(all[i]);
|
||||
++i;
|
||||
for (const Block &block : std::as_const(m_blocks)) {
|
||||
for (const Row &row : block) {
|
||||
for (const KeyDef &key : row) {
|
||||
if (key.type != KeyType::Spacer)
|
||||
m_rects.append(all[i]);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user