aboutsummaryrefslogtreecommitdiffstats
path: root/desktop/modules/git/GitPage.qml
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-10-16 11:29:09 +0200
committerDanilo M. <danix@danix.xyz>2026-10-16 11:29:09 +0200
commitf200f7007272129bf59fef3e0b0e0a19f5bd362c (patch)
tree1a9b46f694b3722e9c4c6da5d6df0c082d126d40 /desktop/modules/git/GitPage.qml
parente97d5dea1d2b36ee9882de8699b382cf4fef64ae (diff)
downloadquickshell-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.qml229
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 }
- }
}