launcher: python execution like calculator functionality
This commit is contained in:
parent
4897b37882
commit
47dfcf4baf
4 changed files with 150 additions and 2 deletions
|
|
@ -38,6 +38,14 @@ JsonObject {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
dangerous: false
|
dangerous: false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Python",
|
||||||
|
icon: "code",
|
||||||
|
description: "Execute Python one-liners",
|
||||||
|
command: ["autocomplete", "python"],
|
||||||
|
enabled: true,
|
||||||
|
dangerous: false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "Scheme",
|
name: "Scheme",
|
||||||
icon: "palette",
|
icon: "palette",
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ StyledListView {
|
||||||
const text = search.text;
|
const text = search.text;
|
||||||
const prefix = Config.launcher.actionPrefix;
|
const prefix = Config.launcher.actionPrefix;
|
||||||
if (text.startsWith(prefix)) {
|
if (text.startsWith(prefix)) {
|
||||||
for (const action of ["calc", "scheme", "variant"])
|
for (const action of ["calc", "python", "scheme", "variant"])
|
||||||
if (text.startsWith(`${prefix}${action} `))
|
if (text.startsWith(`${prefix}${action} `))
|
||||||
return action;
|
return action;
|
||||||
|
|
||||||
|
|
@ -92,6 +92,14 @@ StyledListView {
|
||||||
root.delegate: calcItem
|
root.delegate: calcItem
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
State {
|
||||||
|
name: "python"
|
||||||
|
|
||||||
|
PropertyChanges {
|
||||||
|
model.values: [0]
|
||||||
|
root.delegate: pythonItem
|
||||||
|
}
|
||||||
|
},
|
||||||
State {
|
State {
|
||||||
name: "scheme"
|
name: "scheme"
|
||||||
|
|
||||||
|
|
@ -239,6 +247,14 @@ StyledListView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: pythonItem
|
||||||
|
|
||||||
|
PythonItem {
|
||||||
|
list: root
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: schemeItem
|
id: schemeItem
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ Item {
|
||||||
Wallpapers.setWallpaper(currentItem.modelData.path);
|
Wallpapers.setWallpaper(currentItem.modelData.path);
|
||||||
root.visibilities.launcher = false;
|
root.visibilities.launcher = false;
|
||||||
} else if (text.startsWith(Config.launcher.actionPrefix)) {
|
} else if (text.startsWith(Config.launcher.actionPrefix)) {
|
||||||
if (text.startsWith(`${Config.launcher.actionPrefix}calc `))
|
if (text.startsWith(`${Config.launcher.actionPrefix}calc `) || text.startsWith(`${Config.launcher.actionPrefix}python `))
|
||||||
currentItem.onClicked();
|
currentItem.onClicked();
|
||||||
else
|
else
|
||||||
currentItem.modelData.onClicked(list.currentList);
|
currentItem.modelData.onClicked(list.currentList);
|
||||||
|
|
|
||||||
124
modules/launcher/items/PythonItem.qml
Normal file
124
modules/launcher/items/PythonItem.qml
Normal file
|
|
@ -0,0 +1,124 @@
|
||||||
|
import qs.components
|
||||||
|
import qs.services
|
||||||
|
import qs.config
|
||||||
|
import Quickshell
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property var list
|
||||||
|
readonly property string code: list.search.text.slice(`${Config.launcher.actionPrefix}python `.length)
|
||||||
|
|
||||||
|
function onClicked(): void {
|
||||||
|
// Execute Python code and copy result to clipboard
|
||||||
|
// Escape single quotes in code for shell safety
|
||||||
|
const escapedCode = root.code.replace(/'/g, "'\\''");
|
||||||
|
Quickshell.execDetached(["sh", "-c", `python3 -c '${escapedCode}' 2>&1 | wl-copy`]);
|
||||||
|
root.list.visibilities.launcher = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
implicitHeight: Config.launcher.sizes.itemHeight
|
||||||
|
|
||||||
|
anchors.left: parent?.left
|
||||||
|
anchors.right: parent?.right
|
||||||
|
|
||||||
|
StateLayer {
|
||||||
|
radius: Appearance.rounding.normal
|
||||||
|
|
||||||
|
function onClicked(): void {
|
||||||
|
root.onClicked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.margins: Appearance.padding.larger
|
||||||
|
|
||||||
|
spacing: Appearance.spacing.normal
|
||||||
|
|
||||||
|
MaterialIcon {
|
||||||
|
text: "code"
|
||||||
|
font.pointSize: Appearance.font.size.extraLarge
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
id: result
|
||||||
|
|
||||||
|
color: {
|
||||||
|
if (!root.code)
|
||||||
|
return Colours.palette.m3onSurfaceVariant;
|
||||||
|
return Colours.palette.m3onSurface;
|
||||||
|
}
|
||||||
|
|
||||||
|
text: root.code.length > 0 ? qsTr("Press Enter to execute: %1").arg(root.code) : qsTr("Type Python code to execute")
|
||||||
|
elide: Text.ElideLeft
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledRect {
|
||||||
|
color: Colours.palette.m3tertiary
|
||||||
|
radius: Appearance.rounding.normal
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
implicitWidth: (stateLayer.containsMouse ? label.implicitWidth + label.anchors.rightMargin : 0) + icon.implicitWidth + Appearance.padding.normal * 2
|
||||||
|
implicitHeight: Math.max(label.implicitHeight, icon.implicitHeight) + Appearance.padding.small * 2
|
||||||
|
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
|
||||||
|
StateLayer {
|
||||||
|
id: stateLayer
|
||||||
|
|
||||||
|
color: Colours.palette.m3onTertiary
|
||||||
|
|
||||||
|
function onClicked(): void {
|
||||||
|
const escapedCode = root.code.replace(/'/g, "'\\''");
|
||||||
|
Quickshell.execDetached(["app2unit", "--", ...Config.general.apps.terminal, "fish", "-C", `python3 -i -c '${escapedCode}'`]);
|
||||||
|
root.list.visibilities.launcher = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
id: label
|
||||||
|
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.right: icon.left
|
||||||
|
anchors.rightMargin: Appearance.spacing.small
|
||||||
|
|
||||||
|
text: qsTr("Open in terminal")
|
||||||
|
color: Colours.palette.m3onTertiary
|
||||||
|
font.pointSize: Appearance.font.size.normal
|
||||||
|
|
||||||
|
opacity: stateLayer.containsMouse ? 1 : 0
|
||||||
|
|
||||||
|
Behavior on opacity {
|
||||||
|
Anim {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialIcon {
|
||||||
|
id: icon
|
||||||
|
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: Appearance.padding.normal
|
||||||
|
|
||||||
|
text: "open_in_new"
|
||||||
|
color: Colours.palette.m3onTertiary
|
||||||
|
font.pointSize: Appearance.font.size.large
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on implicitWidth {
|
||||||
|
Anim {
|
||||||
|
easing.bezierCurve: Appearance.anim.curves.emphasized
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue