gui: procs output panel resizable and toggle-able

- SplitView allows dragging the divider between process list and output
- Show/Hide Output button toggles output panel visibility
- View Output and double-click auto-show the panel if hidden
This commit is contained in:
Levi Neely 2026-10-09 09:43:25 +02:00
parent 9b8715d625
commit cc56fda862
1 changed files with 122 additions and 104 deletions

View File

@ -14,6 +14,7 @@ Window {
property var procs: []
property string outputText: ""
property int selectedPid: -1
property bool outputVisible: true
// Track the session we're displaying (synced from main window)
property string currentSessionId: ollie.activeSessionId
@ -106,113 +107,123 @@ Window {
}
}
// Process list
ListView {
id: procList
Layout.fillWidth: true
Layout.preferredHeight: 180
Layout.minimumHeight: 100
model: procs
clip: true
ScrollBar.vertical: ScrollBar { policy: ScrollBar.AsNeeded }
delegate: Rectangle {
width: procList.width
height: 44
color: selectedPid === modelData.pid ? palette.highlight : (index % 2 ? palette.alternateBase : palette.base)
MouseArea {
anchors.fill: parent
onClicked: selectedPid = modelData.pid
onDoubleClicked: {
selectedPid = modelData.pid
var out = ollie.procOutput(currentSessionId, currentAgentId, selectedPid)
outputText = out.length > 0 ? out : "(no output)"
}
}
RowLayout {
anchors.fill: parent
anchors.margins: 8
spacing: 12
// Status indicator
Rectangle {
width: 10
height: 10
radius: 5
color: modelData.status === "running" ? "#4CAF50" : (modelData.exitCode === 0 ? "#9E9E9E" : "#F44336")
}
// PID
Label {
text: modelData.pid
font.family: "monospace"
Layout.preferredWidth: 50
}
// Tool
Label {
text: modelData.tool
font.weight: Font.Medium
Layout.preferredWidth: 80
elide: Text.ElideRight
}
// Command
Label {
text: modelData.cmd
Layout.fillWidth: true
elide: Text.ElideMiddle
opacity: 0.8
}
// Runtime
Label {
text: formatRuntime(modelData.runtime)
font.family: "monospace"
Layout.preferredWidth: 55
horizontalAlignment: Text.AlignRight
}
// Exit code (if exited)
Label {
visible: modelData.status !== "running"
text: modelData.exitCode === 0 ? "✓" : "exit " + modelData.exitCode
font.family: "monospace"
color: modelData.exitCode === 0 ? "#4CAF50" : "#F44336"
Layout.preferredWidth: 45
}
}
}
Label {
anchors.centerIn: parent
visible: procs.length === 0
text: currentSessionId ? "No background processes" : "No session selected"
opacity: 0.5
}
}
// Output pane (always visible)
GroupBox {
// Resizable split between process list and output
SplitView {
Layout.fillWidth: true
Layout.fillHeight: true
Layout.minimumHeight: 100
title: selectedPid > 0 ? "Output (PID " + selectedPid + ")" : "Output"
orientation: Qt.Vertical
ScrollView {
anchors.fill: parent
TextArea {
id: outputArea
text: outputText
readOnly: true
font.family: "monospace"
font.pointSize: 11
wrapMode: TextEdit.Wrap
selectByMouse: true
placeholderText: "Select a process and click View Output"
// Process list
ListView {
id: procList
SplitView.fillWidth: true
SplitView.minimumHeight: 80
SplitView.preferredHeight: 180
model: procs
clip: true
ScrollBar.vertical: ScrollBar { policy: ScrollBar.AsNeeded }
delegate: Rectangle {
width: procList.width
height: 44
color: selectedPid === modelData.pid ? palette.highlight : (index % 2 ? palette.alternateBase : palette.base)
MouseArea {
anchors.fill: parent
onClicked: selectedPid = modelData.pid
onDoubleClicked: {
selectedPid = modelData.pid
var out = ollie.procOutput(currentSessionId, currentAgentId, selectedPid)
outputText = out.length > 0 ? out : "(no output)"
outputVisible = true
}
}
RowLayout {
anchors.fill: parent
anchors.margins: 8
spacing: 12
// Status indicator
Rectangle {
width: 10
height: 10
radius: 5
color: modelData.status === "running" ? "#4CAF50" : (modelData.exitCode === 0 ? "#9E9E9E" : "#F44336")
}
// PID
Label {
text: modelData.pid
font.family: "monospace"
Layout.preferredWidth: 50
}
// Tool
Label {
text: modelData.tool
font.weight: Font.Medium
Layout.preferredWidth: 80
elide: Text.ElideRight
}
// Command
Label {
text: modelData.cmd
Layout.fillWidth: true
elide: Text.ElideMiddle
opacity: 0.8
}
// Runtime
Label {
text: formatRuntime(modelData.runtime)
font.family: "monospace"
Layout.preferredWidth: 55
horizontalAlignment: Text.AlignRight
}
// Exit code (if exited)
Label {
visible: modelData.status !== "running"
text: modelData.exitCode === 0 ? "✓" : "exit " + modelData.exitCode
font.family: "monospace"
color: modelData.exitCode === 0 ? "#4CAF50" : "#F44336"
Layout.preferredWidth: 45
}
}
}
Label {
anchors.centerIn: parent
visible: procs.length === 0
text: currentSessionId ? "No background processes" : "No session selected"
opacity: 0.5
}
}
// Output pane (toggle-able)
GroupBox {
id: outputPane
visible: outputVisible
SplitView.fillWidth: true
SplitView.fillHeight: true
SplitView.minimumHeight: 60
title: selectedPid > 0 ? "Output (PID " + selectedPid + ")" : "Output"
ScrollView {
anchors.fill: parent
TextArea {
id: outputArea
text: outputText
readOnly: true
font.family: "monospace"
font.pointSize: 11
wrapMode: TextEdit.Wrap
selectByMouse: true
placeholderText: "Select a process and click View Output"
}
}
}
}
@ -236,9 +247,16 @@ Window {
outputText = ""
var out = ollie.procOutput(currentSessionId, currentAgentId, selectedPid)
outputText = out.length > 0 ? out : "(no output)"
outputVisible = true
}
}
Button {
text: outputVisible ? "Hide Output" : "Show Output"
icon.name: outputVisible ? "go-up" : "go-down"
onClicked: outputVisible = !outputVisible
}
Item { Layout.fillWidth: true }
Button {