aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--desktop/modules/git/GitPage.qml229
-rw-r--r--desktop/modules/git/README.md4
2 files changed, 131 insertions, 102 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 }
- }
}
diff --git a/desktop/modules/git/README.md b/desktop/modules/git/README.md
index e5a4370..65f2a8a 100644
--- a/desktop/modules/git/README.md
+++ b/desktop/modules/git/README.md
@@ -5,7 +5,9 @@ page's "More git settings" button. Back returns to the user page.
One row per value, grouped by section in file order, so a key set several
times shows several rows. Enter saves a row, Escape undoes an edit, Remove
-drops that one value, and the Add row takes `section.key` and a value.
+drops that one value, and `+` beside a section's heading adds a key to
+that section, where `git config --add` writes it among its neighbours. A
+new section is made in the editor.
"Edit in editor" opens the file in Sublime Text.
`gitcfg` does every read and write, through `git config`, so the file keeps