Add quick toggles to the grab bar

Beside the gear: full keyboard, hold keys, and the numeric keypad,
navigation and function key sections, each behind a drawn icon and lit
while on. Section toggles hide when the layout lacks the section. The
grab pill narrows when a small window leaves it less room.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-31 00:29:48 +01:00
co-authored by Claude Opus 5.5
parent b94463a277
commit ac5f43ca5f
5 changed files with 197 additions and 1 deletions
+143
View File
@@ -0,0 +1,143 @@
import QtQuick
import Sloposk
// One-tap switches for the most changed key options, beside the gear.
// Icons are drawn from boxes so they don't depend on the fonts installed.
Row {
id: toggles
required property Settings settings
required property LayoutModel layoutModel
function hasSection(id) {
return layoutModel.sections.some(s => s.id === id);
}
// Shows or hides one of the template's optional sections; absent from
// layouts without it.
component SectionToggle: BarToggle {
required property string section
visible: toggles.hasSection(section)
checked: toggles.settings.visibleSections.includes(section)
onToggled: checked => toggles.settings.setSectionVisible(section, checked)
}
// A grid of tiny keys, optionally in a keyboard outline.
component KeyGrid: Item {
id: keyGrid
required property color color
required property int columns
required property int rows
property bool framed: false
anchors.fill: parent
Rectangle {
anchors.fill: parent
visible: keyGrid.framed
radius: 2
color: "transparent"
border { width: 1.5; color: keyGrid.color }
}
Grid {
readonly property real key: keyGrid.framed ? 2 : 3
anchors.centerIn: parent
columns: keyGrid.columns
spacing: 1
Repeater {
model: keyGrid.columns * keyGrid.rows
Rectangle {
width: parent.key
height: parent.key
radius: 0.5
color: keyGrid.color
}
}
}
}
// A key outline with a label on it.
component LabelledKey: Rectangle {
property alias label: caption.text
property alias textColor: caption.color
anchors.centerIn: parent
width: 20
height: 14
radius: 3
color: "transparent"
border { width: 1.5; color: caption.color }
Text {
id: caption
anchors.centerIn: parent
font { pixelSize: 9; bold: true }
}
}
BarToggle {
id: full
label: qsTr("Full Keyboard")
checked: toggles.settings.fullKeyboard
onToggled: checked => toggles.settings.fullKeyboard = checked
KeyGrid { color: full.foreground; columns: 6; rows: 3; framed: true }
}
BarToggle {
id: hold
label: qsTr("Hold Keys")
checked: toggles.settings.holdKeys
onToggled: checked => toggles.settings.holdKeys = checked
// A fingertip resting on a key, holding it down.
Rectangle {
anchors { horizontalCenter: parent.horizontalCenter; bottom: parent.bottom }
width: 18
height: 8
radius: 2
color: "transparent"
border { width: 1.5; color: hold.foreground }
}
Rectangle {
anchors { horizontalCenter: parent.horizontalCenter; top: parent.top; topMargin: 1 }
width: 8
height: 11
radius: 4
color: hold.foreground
}
}
SectionToggle {
id: numpad
section: "numpad"
label: qsTr("Numeric Keypad")
KeyGrid { color: numpad.foreground; columns: 3; rows: 3 }
}
SectionToggle {
id: navigation
section: "navigation"
label: qsTr("Navigation Keys")
// The inverted T of the arrow keys.
Repeater {
model: [[1, 0], [0, 1], [1, 1], [2, 1]]
Rectangle {
required property var modelData
x: 1.5 + modelData[0] * 6
y: 1.5 + modelData[1] * 6
width: 5
height: 5
radius: 1
color: navigation.foreground
}
}
}
SectionToggle {
id: fn
section: "function"
label: qsTr("Function Keys")
LabelledKey { label: "Fn"; textColor: fn.foreground }
}
}