mirror of
https://github.com/noctalia-dev/noctalia-shell.git
synced 2026-05-11 17:08:27 +08:00
Merge pull request #533 from shouya/main
Add support for streaming command outputs in CustomButton
This commit is contained in:
@@ -1079,9 +1079,14 @@
|
||||
"description": "Command to execute when the button is middle-clicked."
|
||||
},
|
||||
"dynamic-text": "Dynamic text",
|
||||
"text-stream": {
|
||||
"label": "Stream",
|
||||
"description": "Streamed lines from the command will be displayed as text on the button."
|
||||
},
|
||||
"display-command-output": {
|
||||
"label": "Display Command Output",
|
||||
"description": "Enter a command to run at a regular interval. The first line of its output will be displayed as text."
|
||||
"description": "Enter a command to run at a regular interval. The first line of its output will be displayed as text.",
|
||||
"stream-description": "Enter a command to run continuously."
|
||||
},
|
||||
"refresh-interval": {
|
||||
"label": "Refresh interval",
|
||||
|
||||
@@ -36,6 +36,7 @@ Item {
|
||||
readonly property string rightClickExec: widgetSettings.rightClickExec || widgetMetadata.rightClickExec
|
||||
readonly property string middleClickExec: widgetSettings.middleClickExec || widgetMetadata.middleClickExec
|
||||
readonly property string textCommand: widgetSettings.textCommand !== undefined ? widgetSettings.textCommand : (widgetMetadata.textCommand || "")
|
||||
readonly property bool textStream: widgetSettings.textStream !== undefined ? widgetSettings.textStream : (widgetMetadata.textStream || false)
|
||||
readonly property int textIntervalMs: widgetSettings.textIntervalMs !== undefined ? widgetSettings.textIntervalMs : (widgetMetadata.textIntervalMs || 3000)
|
||||
readonly property bool hasExec: (leftClickExec || rightClickExec || middleClickExec)
|
||||
|
||||
@@ -83,29 +84,45 @@ Item {
|
||||
id: refreshTimer
|
||||
interval: Math.max(250, textIntervalMs)
|
||||
repeat: true
|
||||
running: (textCommand && textCommand.length > 0)
|
||||
running: !textStream && textCommand && textCommand.length > 0
|
||||
triggeredOnStart: true
|
||||
onTriggered: {
|
||||
if (!textCommand || textCommand.length === 0)
|
||||
return
|
||||
if (textProc.running)
|
||||
return
|
||||
textProc.command = ["sh", "-lc", textCommand]
|
||||
textProc.running = true
|
||||
onTriggered: root.runTextCommand()
|
||||
}
|
||||
|
||||
// Restart exited text stream commands after a delay
|
||||
Timer {
|
||||
id: restartTimer
|
||||
interval: 1000
|
||||
running: textStream && !textProc.running
|
||||
onTriggered: root.runTextCommand()
|
||||
}
|
||||
|
||||
SplitParser {
|
||||
id: textStdoutSplit
|
||||
onRead: (line) => _dynamicText = String(line || "").trim()
|
||||
}
|
||||
|
||||
StdioCollector {
|
||||
id: textStdoutCollect
|
||||
onStreamFinished: () => {
|
||||
var out = String(this.text || "").trim()
|
||||
if (out.indexOf("\n") !== -1) {
|
||||
out = out.split("\n")[0]
|
||||
}
|
||||
_dynamicText = out
|
||||
}
|
||||
}
|
||||
|
||||
Process {
|
||||
id: textProc
|
||||
stdout: StdioCollector {}
|
||||
stdout: textStream ? textStdoutSplit : textStdoutCollect
|
||||
stderr: StdioCollector {}
|
||||
onExited: (exitCode, exitStatus) => {
|
||||
var out = String(stdout.text || "").trim()
|
||||
if (out.indexOf("\n") !== -1) {
|
||||
out = out.split("\n")[0]
|
||||
}
|
||||
_dynamicText = out
|
||||
}
|
||||
if (textStream) {
|
||||
Logger.w("CustomButton", `Streaming text command exited (code: ${exitCode}), restarting...`)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onClicked() {
|
||||
@@ -133,4 +150,13 @@ Item {
|
||||
Logger.i("CustomButton", `Executing command: ${middleClickExec}`)
|
||||
}
|
||||
}
|
||||
|
||||
function runTextCommand() {
|
||||
if (!textCommand || textCommand.length === 0)
|
||||
return
|
||||
if (textProc.running)
|
||||
return
|
||||
textProc.command = ["sh", "-lc", textCommand]
|
||||
textProc.running = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ ColumnLayout {
|
||||
property var widgetMetadata: null
|
||||
|
||||
property string valueIcon: widgetData.icon !== undefined ? widgetData.icon : widgetMetadata.icon
|
||||
property bool valueTextStream: widgetData.textStream !== undefined ? widgetData.textStream : widgetMetadata.textStream
|
||||
|
||||
function saveSettings() {
|
||||
var settings = Object.assign({}, widgetData || {})
|
||||
@@ -22,6 +23,7 @@ ColumnLayout {
|
||||
settings.rightClickExec = rightClickExecInput.text
|
||||
settings.middleClickExec = middleClickExecInput.text
|
||||
settings.textCommand = textCommandInput.text
|
||||
settings.textStream = valueTextStream
|
||||
settings.textIntervalMs = parseInt(textIntervalInput.text || textIntervalInput.placeholderText, 10)
|
||||
return settings
|
||||
}
|
||||
@@ -90,11 +92,21 @@ ColumnLayout {
|
||||
label: I18n.tr("bar.widget-settings.custom-button.dynamic-text")
|
||||
}
|
||||
|
||||
NToggle {
|
||||
id: textStreamInput
|
||||
label: I18n.tr("bar.widget-settings.custom-button.text-stream.label")
|
||||
description: I18n.tr("bar.widget-settings.custom-button.text-stream.description")
|
||||
checked: valueTextStream
|
||||
onToggled: checked => valueTextStream = checked
|
||||
}
|
||||
|
||||
NTextInput {
|
||||
id: textCommandInput
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("bar.widget-settings.custom-button.display-command-output.label")
|
||||
description: I18n.tr("bar.widget-settings.custom-button.display-command-output.description")
|
||||
description: valueTextStream ?
|
||||
I18n.tr("bar.widget-settings.custom-button.display-command-output.stream-description") :
|
||||
I18n.tr("bar.widget-settings.custom-button.display-command-output.description")
|
||||
placeholderText: I18n.tr("placeholders.command-example")
|
||||
text: widgetData?.textCommand || widgetMetadata.textCommand
|
||||
}
|
||||
@@ -102,6 +114,7 @@ ColumnLayout {
|
||||
NTextInput {
|
||||
id: textIntervalInput
|
||||
Layout.fillWidth: true
|
||||
visible: !valueTextStream
|
||||
label: I18n.tr("bar.widget-settings.custom-button.refresh-interval.label")
|
||||
description: I18n.tr("bar.widget-settings.custom-button.refresh-interval.description")
|
||||
placeholderText: String(widgetMetadata.textIntervalMs || 3000)
|
||||
|
||||
@@ -83,6 +83,7 @@ Singleton {
|
||||
"rightClickExec": "",
|
||||
"middleClickExec": "",
|
||||
"textCommand": "",
|
||||
"textStream": false,
|
||||
"textIntervalMs": 3000
|
||||
},
|
||||
"KeyboardLayout": {
|
||||
|
||||
Reference in New Issue
Block a user