diff options
| author | Danilo M. <danix@danix.xyz> | 2026-10-16 11:29:09 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-10-16 11:29:09 +0200 |
| commit | f200f7007272129bf59fef3e0b0e0a19f5bd362c (patch) | |
| tree | 1a9b46f694b3722e9c4c6da5d6df0c082d126d40 /desktop/modules/git/GitPage.qml | |
| parent | e97d5dea1d2b36ee9882de8699b382cf4fef64ae (diff) | |
| download | quickshell-f200f7007272129bf59fef3e0b0e0a19f5bd362c.tar.gz quickshell-f200f7007272129bf59fef3e0b0e0a19f5bd362c.zip | |
feat(git): add keys per section with a + beside each heading
The single Add line at the bottom took a full section.key and left the
user to type the section right. Each heading now carries a + that opens a
key and value row under it; git config --add writes the key into that
existing section, among its neighbours, rather than at the end of the
file. The typed text lives on the page, not in the fields, so a failed add
keeps it across the reload that rebuilds every row. A new section is made
in the editor.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'desktop/modules/git/GitPage.qml')
| -rw-r--r-- | desktop/modules/git/GitPage.qml | 229 |
1 files changed, 128 insertions, 101 deletions
diff --git a/desktop/modules/git/GitPage.qml b/desktop/modules/git/GitPage.qml index c91f050..6edf085 100644 --- a/desktop/modules/git/GitPage.qml +++ b/desktop/modules/git/GitPage.qml @@ -36,6 +36,20 @@ Column { // the page is closed. Not named `gm`, the module's id (it would bind to itself). required property QtObject owner + // The section whose add row is open, and what is typed in it. The text + // lives here rather than in the fields because every reload rebuilds the + // rows, and a failed add should keep what was typed. + property string adding: "" + property string newKey: "" + property string newValue: "" + onAddingChanged: { newKey = ""; newValue = ""; errors = ({}); } + + function add() { + if (page.newKey.trim() === "") return; + page.write(["add", page.adding + "." + page.newKey.trim(), page.newValue], "add", + () => page.adding = ""); + } + function tag(e) { return e.name + "=" + e.value; } // One Process per call, so reads and writes never share one (a running @@ -98,6 +112,94 @@ Column { font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 4 } } + // The add row under a section's heading: key and value. Enter in the key + // moves to the value, Enter there adds, Escape closes the row. + Component { + id: addRow + Column { + spacing: 4 + + Item { + width: parent.width + height: 34 + + Rectangle { + id: keyBox + anchors.left: parent.left + width: parent.width * 0.32 + height: parent.height + radius: 8 + color: Theme.surface + TextInput { + id: keyIn + anchors { fill: parent; leftMargin: 10; rightMargin: 10 } + verticalAlignment: TextInput.AlignVCenter + clip: true + selectByMouse: true + color: Theme.text + font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2 } + text: page.newKey + onTextEdited: page.newKey = text + onAccepted: valIn.forceActiveFocus() + Keys.onEscapePressed: page.adding = "" + Component.onCompleted: forceActiveFocus() + Text { + anchors.verticalCenter: parent.verticalCenter + visible: parent.text === "" + text: "key" + color: Theme.subtext + font: parent.font + } + } + } + + Rectangle { + anchors { left: keyBox.right; leftMargin: 8; right: addBtn.left; rightMargin: 8 } + height: parent.height + radius: 8 + color: Theme.surface + TextInput { + id: valIn + anchors { fill: parent; leftMargin: 10; rightMargin: 10 } + verticalAlignment: TextInput.AlignVCenter + clip: true + selectByMouse: true + color: Theme.text + font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2 } + text: page.newValue + onTextEdited: page.newValue = text + onAccepted: page.add() + Keys.onEscapePressed: page.adding = "" + Text { + anchors.verticalCenter: parent.verticalCenter + visible: parent.text === "" + text: "value" + color: Theme.subtext + font: parent.font + } + } + } + + Button { + id: addBtn + anchors { right: parent.right; verticalCenter: parent.verticalCenter } + text: "Add" + enabled: page.newKey.trim() !== "" + onClicked: page.add() + } + } + + Text { + width: parent.width + visible: !!page.errors.add + text: page.errors.add ?? "" + wrapMode: Text.Wrap + color: Theme.red + font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 4 } + } + } + } + Repeater { model: page.entries @@ -110,14 +212,33 @@ Column { spacing: 4 enabled: !page.busy - // A section's heading, above its first row. - Text { + // A section's heading, above its first row, with + to add a key + // to it. git config --add writes into the existing section, so + // the new key lands with its neighbours in the file. + Item { + id: heading visible: row.index === 0 || page.entries[row.index - 1].section !== row.modelData.section - topPadding: 10 - bottomPadding: 2 - text: row.modelData.section - font { family: Theme.fontFamily; pixelSize: Theme.fontSize; bold: true } - color: Theme.text + width: parent.width + height: 40 + + Text { + anchors { left: parent.left; bottom: parent.bottom; bottomMargin: 6 } + text: row.modelData.section + font { family: Theme.fontFamily; pixelSize: Theme.fontSize; bold: true } + color: Theme.text + } + Button { + anchors { right: parent.right; bottom: parent.bottom; bottomMargin: 2 } + text: "+" + onClicked: page.adding = page.adding === row.modelData.section ? "" : row.modelData.section + } + } + + Loader { + width: parent.width + active: heading.visible && page.adding === row.modelData.section + visible: active + sourceComponent: addRow } // An Item with anchors, not a Row: a Row sizes to its children @@ -183,98 +304,4 @@ Column { } } } - - // Add: section.key and a value. The fields clear only when git took it. - Text { - topPadding: 10 - bottomPadding: 2 - text: "Add" - font { family: Theme.fontFamily; pixelSize: Theme.fontSize; bold: true } - color: Theme.text - } - - Item { - width: parent.width - height: 34 - enabled: !page.busy - - Rectangle { - id: newKeyBox - anchors { left: parent.left } - width: parent.width * 0.32 - height: parent.height - radius: 8 - color: Theme.surface - TextInput { - id: newKey - anchors { fill: parent; leftMargin: 10; rightMargin: 10 } - verticalAlignment: TextInput.AlignVCenter - clip: true - selectByMouse: true - color: Theme.text - font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2 } - // Typed text is cleared first, as a row's edit is undone; - // an empty field lets Escape through, to leave the page. - Keys.onEscapePressed: event => { - if (text !== "") text = ""; - else event.accepted = false; - } - Text { - anchors.verticalCenter: parent.verticalCenter - visible: parent.text === "" - text: "section.key" - color: Theme.subtext - font: parent.font - } - } - } - - Rectangle { - anchors { left: newKeyBox.right; leftMargin: 8; right: addBtn.left; rightMargin: 8 } - height: parent.height - radius: 8 - color: Theme.surface - TextInput { - id: newValue - anchors { fill: parent; leftMargin: 10; rightMargin: 10 } - verticalAlignment: TextInput.AlignVCenter - clip: true - selectByMouse: true - color: Theme.text - font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2 } - // Typed text is cleared first, as a row's edit is undone; - // an empty field lets Escape through, to leave the page. - Keys.onEscapePressed: event => { - if (text !== "") text = ""; - else event.accepted = false; - } - onAccepted: if (addBtn.enabled) addBtn.clicked() - Text { - anchors.verticalCenter: parent.verticalCenter - visible: parent.text === "" - text: "value" - color: Theme.subtext - font: parent.font - } - } - } - - Button { - id: addBtn - anchors { right: parent.right; verticalCenter: parent.verticalCenter } - text: "Add" - enabled: newKey.text.trim() !== "" - onClicked: page.write(["add", newKey.text.trim(), newValue.text], "add", - () => { newKey.text = ""; newValue.text = ""; }) - } - } - - Text { - width: parent.width - visible: !!page.errors.add - text: page.errors.add ?? "" - wrapMode: Text.Wrap - color: Theme.red - font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 4 } - } } |
