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:
parent
9b8715d625
commit
cc56fda862
|
|
@ -14,6 +14,7 @@ Window {
|
||||||
property var procs: []
|
property var procs: []
|
||||||
property string outputText: ""
|
property string outputText: ""
|
||||||
property int selectedPid: -1
|
property int selectedPid: -1
|
||||||
|
property bool outputVisible: true
|
||||||
|
|
||||||
// Track the session we're displaying (synced from main window)
|
// Track the session we're displaying (synced from main window)
|
||||||
property string currentSessionId: ollie.activeSessionId
|
property string currentSessionId: ollie.activeSessionId
|
||||||
|
|
@ -106,113 +107,123 @@ Window {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process list
|
// Resizable split between process list and output
|
||||||
ListView {
|
SplitView {
|
||||||
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 {
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
Layout.minimumHeight: 100
|
orientation: Qt.Vertical
|
||||||
title: selectedPid > 0 ? "Output (PID " + selectedPid + ")" : "Output"
|
|
||||||
|
|
||||||
ScrollView {
|
// Process list
|
||||||
anchors.fill: parent
|
ListView {
|
||||||
TextArea {
|
id: procList
|
||||||
id: outputArea
|
SplitView.fillWidth: true
|
||||||
text: outputText
|
SplitView.minimumHeight: 80
|
||||||
readOnly: true
|
SplitView.preferredHeight: 180
|
||||||
font.family: "monospace"
|
model: procs
|
||||||
font.pointSize: 11
|
clip: true
|
||||||
wrapMode: TextEdit.Wrap
|
|
||||||
selectByMouse: true
|
ScrollBar.vertical: ScrollBar { policy: ScrollBar.AsNeeded }
|
||||||
placeholderText: "Select a process and click View Output"
|
|
||||||
|
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 = ""
|
outputText = ""
|
||||||
var out = ollie.procOutput(currentSessionId, currentAgentId, selectedPid)
|
var out = ollie.procOutput(currentSessionId, currentAgentId, selectedPid)
|
||||||
outputText = out.length > 0 ? out : "(no output)"
|
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 }
|
Item { Layout.fillWidth: true }
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue