Skip to content

Commit 5b51a66

Browse files
authored
Merge pull request #724 from ultherego/feature/kubectl-ctx
feat(kubectl-ctx): add Kubernetes context & resource manager plugin
2 parents f00ff93 + f7a0509 commit 5b51a66

13 files changed

Lines changed: 1846 additions & 0 deletions

kubectl-ctx/BarWidget.qml

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import QtQuick
2+
import QtQuick.Layouts
3+
import Quickshell
4+
import qs.Commons
5+
import qs.Services.UI
6+
import qs.Widgets
7+
8+
Item {
9+
id: root
10+
11+
property var pluginApi: null
12+
property ShellScreen screen
13+
property string widgetId: ""
14+
property string section: ""
15+
property int sectionWidgetIndex: -1
16+
property int sectionWidgetsCount: 0
17+
18+
property var cfg: pluginApi?.pluginSettings || ({})
19+
property var defaults: pluginApi?.manifest?.metadata?.defaultSettings || ({})
20+
21+
readonly property string iconColorKey: cfg.iconColor ?? defaults.iconColor
22+
readonly property bool showErrorBadge: cfg.showErrorBadge ?? defaults.showErrorBadge ?? true
23+
readonly property var main: pluginApi?.mainInstance ?? null
24+
25+
readonly property string barPosition: Settings.getBarPositionForScreen(screen?.name)
26+
readonly property bool isVertical: barPosition === "left" || barPosition === "right"
27+
readonly property real capsuleHeight: Style.getCapsuleHeightForScreen(screen?.name)
28+
29+
implicitWidth: isVertical ? capsuleHeight : contentRow.implicitWidth + Style.marginM * 2
30+
implicitHeight: isVertical ? contentRow.implicitHeight + Style.marginM * 2 : capsuleHeight
31+
32+
NPopupContextMenu {
33+
id: contextMenu
34+
model: [
35+
{ "label": pluginApi?.tr("menu.settings"), "action": "settings", "icon": "settings" }
36+
]
37+
onTriggered: function(action) {
38+
contextMenu.close();
39+
PanelService.closeContextMenu(screen);
40+
if (action === "settings") {
41+
BarService.openPluginSettings(root.screen, pluginApi.manifest);
42+
}
43+
}
44+
}
45+
46+
MouseArea {
47+
anchors.fill: parent
48+
hoverEnabled: true
49+
cursorShape: Qt.PointingHandCursor
50+
acceptedButtons: Qt.LeftButton | Qt.RightButton
51+
onClicked: mouse => {
52+
if (mouse.button === Qt.RightButton) {
53+
PanelService.showContextMenu(contextMenu, root, screen);
54+
} else {
55+
if (pluginApi) pluginApi.openPanel(root.screen, root);
56+
}
57+
}
58+
}
59+
60+
RowLayout {
61+
id: contentRow
62+
anchors.centerIn: parent
63+
spacing: Style.marginS
64+
65+
NIcon {
66+
icon: "topology-star-3"
67+
pointSize: Style.fontSizeL
68+
color: {
69+
if (root.showErrorBadge && root.main?.hasCriticalPod) return Color.mError;
70+
return Color.resolveColorKey(root.iconColorKey);
71+
}
72+
}
73+
74+
NText {
75+
visible: !root.isVertical && root.main?.activeContext !== undefined && root.main?.activeContext !== ""
76+
text: {
77+
var ctx = root.main?.activeContext ?? "";
78+
var ns = root.main?.activeNamespace ?? "";
79+
if (ctx === "") return "";
80+
if (ns === "") return ctx;
81+
return ctx + " / " + ns;
82+
}
83+
pointSize: Style.fontSizeS
84+
color: Color.mOnSurface
85+
elide: Text.ElideRight
86+
Layout.maximumWidth: capsuleHeight * 3
87+
}
88+
89+
// Error badge dot
90+
Rectangle {
91+
visible: root.showErrorBadge && (root.main?.hasCriticalPod ?? false)
92+
width: Math.round(Style.fontSizeS * 0.6)
93+
height: width
94+
radius: width / 2
95+
color: Color.mError
96+
Layout.alignment: Qt.AlignVCenter
97+
}
98+
}
99+
}

kubectl-ctx/ContextRow.qml

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import QtQuick
2+
import QtQuick.Layouts
3+
import qs.Commons
4+
import qs.Widgets
5+
6+
Item {
7+
id: root
8+
9+
property var pluginApi: null
10+
property string contextName: ""
11+
property bool isActive: false
12+
property bool highlighted: false
13+
14+
signal activated(string name)
15+
16+
implicitHeight: Math.round(rowContent.implicitHeight + Style.marginS * 2)
17+
18+
Rectangle {
19+
anchors.fill: parent
20+
radius: Style.radiusM
21+
color: {
22+
if (root.isActive) return Qt.alpha(Color.mPrimary, 0.15);
23+
if (root.highlighted) return Qt.alpha(Color.mPrimary, 0.08);
24+
if (hoverArea.containsMouse) return Qt.alpha(Color.mOnSurface, 0.06);
25+
return "transparent";
26+
}
27+
}
28+
29+
RowLayout {
30+
id: rowContent
31+
anchors {
32+
left: parent.left
33+
right: parent.right
34+
verticalCenter: parent.verticalCenter
35+
leftMargin: Style.marginM
36+
rightMargin: Style.marginM
37+
}
38+
spacing: Style.marginS
39+
40+
// Active indicator dot
41+
Rectangle {
42+
width: Math.round(Style.fontSizeS * 0.55)
43+
height: width
44+
radius: width / 2
45+
color: root.isActive ? Color.mPrimary : "transparent"
46+
border.width: root.isActive ? 0 : Style.borderS
47+
border.color: Color.mOnSurfaceVariant
48+
opacity: root.isActive ? 1.0 : 0.4
49+
Layout.alignment: Qt.AlignVCenter
50+
}
51+
52+
NText {
53+
text: root.contextName
54+
pointSize: Style.fontSizeM
55+
font.weight: root.isActive ? Font.DemiBold : Font.Normal
56+
color: root.isActive ? Color.mPrimary : Color.mOnSurface
57+
elide: Text.ElideRight
58+
Layout.fillWidth: true
59+
Layout.alignment: Qt.AlignVCenter
60+
}
61+
62+
NIcon {
63+
visible: root.isActive
64+
icon: "check"
65+
pointSize: Style.fontSizeM
66+
color: Color.mPrimary
67+
Layout.alignment: Qt.AlignVCenter
68+
}
69+
}
70+
71+
MouseArea {
72+
id: hoverArea
73+
anchors.fill: parent
74+
hoverEnabled: true
75+
cursorShape: Qt.PointingHandCursor
76+
onPressed: {
77+
root.activated(root.contextName);
78+
}
79+
}
80+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import QtQuick
2+
import Quickshell
3+
import qs.Widgets
4+
5+
NIconButtonHot {
6+
property ShellScreen screen
7+
property var pluginApi: null
8+
9+
icon: "topology-star-3"
10+
tooltipText: pluginApi?.tr("widget.tooltip")
11+
onClicked: {
12+
if (pluginApi) {
13+
pluginApi.togglePanel(screen, this);
14+
}
15+
}
16+
}

kubectl-ctx/DeleteConfirm.qml

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import QtQuick
2+
import QtQuick.Layouts
3+
import qs.Commons
4+
import qs.Widgets
5+
6+
Item {
7+
id: root
8+
9+
property var pluginApi: null
10+
property string resourceKind: ""
11+
property string resourceName: ""
12+
13+
signal confirmed(string kind, string name)
14+
signal cancelled()
15+
16+
implicitHeight: Math.round(confirmContent.implicitHeight + Style.marginL * 2)
17+
18+
ColumnLayout {
19+
id: confirmContent
20+
anchors {
21+
left: parent.left
22+
right: parent.right
23+
verticalCenter: parent.verticalCenter
24+
margins: Style.marginL
25+
}
26+
spacing: Style.marginM
27+
28+
NIcon {
29+
icon: "alert-triangle"
30+
pointSize: Style.fontSizeXXL
31+
color: Color.mError
32+
Layout.alignment: Qt.AlignHCenter
33+
}
34+
35+
NText {
36+
text: pluginApi?.tr("delete.title")
37+
pointSize: Style.fontSizeL
38+
font.weight: Font.DemiBold
39+
color: Color.mOnSurface
40+
Layout.alignment: Qt.AlignHCenter
41+
}
42+
43+
NText {
44+
text: pluginApi?.tr("delete.confirm", { "resource": root.resourceKind + "/" + root.resourceName })
45+
pointSize: Style.fontSizeM
46+
color: Color.mOnSurfaceVariant
47+
wrapMode: Text.WordWrap
48+
Layout.fillWidth: true
49+
Layout.alignment: Qt.AlignHCenter
50+
horizontalAlignment: Text.AlignHCenter
51+
}
52+
53+
RowLayout {
54+
Layout.fillWidth: true
55+
spacing: Style.marginM
56+
57+
NButton {
58+
Layout.fillWidth: true
59+
text: pluginApi?.tr("delete.cancel")
60+
onClicked: root.cancelled()
61+
}
62+
63+
NButton {
64+
Layout.fillWidth: true
65+
text: pluginApi?.tr("delete.yes")
66+
backgroundColor: Color.mError
67+
textColor: Color.mOnError
68+
onClicked: root.confirmed(root.resourceKind, root.resourceName)
69+
}
70+
}
71+
}
72+
}

0 commit comments

Comments
 (0)