-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgui.py
166 lines (138 loc) · 5.32 KB
/
gui.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
import os
import sys
import subprocess
from PySide6.QtWidgets import (
QApplication,
QVBoxLayout,
QWidget,
QTableWidget,
QTableWidgetItem,
QHeaderView,
QMessageBox,
QPushButton,
)
from PySide6.QtCore import Qt, QSettings
class SystemdServiceLister(QWidget):
def __init__(self):
super().__init__()
self.settings = QSettings(os.getenv("USER"), "systemd-gui")
self.initUI()
def initUI(self):
self.setWindowTitle("User Systemd GUI by ChatGPT")
self.table = QTableWidget(0, 5)
self.table.setHorizontalHeaderLabels(
["Service", "Loaded", "Active", "Sub", "Toggle"]
)
# Change the section resize mode to Interactive so the user can resize the columns
self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Interactive)
layout = QVBoxLayout(self)
layout.addWidget(self.table)
self.list_services()
# Set the size of the window to 500x500 pixels
self.resize(650, 500)
# Restore column widths
for i in range(self.table.columnCount()):
width = self.settings.value(
f"column_{i}_width", 100, type=int
) # Default width is 100
self.table.setColumnWidth(i, width)
def closeEvent(self, event):
# Save column widths
for i in range(self.table.columnCount()):
self.settings.setValue(f"column_{i}_width", self.table.columnWidth(i))
event.accept()
def list_services(self):
result = subprocess.run(
["systemctl", "--user", "--all", "list-units", "--type=service"],
capture_output=True,
text=True,
)
lines = result.stdout.splitlines()
# Ignore the summary lines at the end
lines = [
line
for line in lines
if line
and not any(map(line.__contains__, ["JOB", "LOAD", "ACTIVE", "SUB"]))
and not "loaded units listed" in line
and not "To show all installed unit files" in line
]
self.table.setRowCount(len(lines))
for i, line in enumerate(lines):
words = line.split()
if len(words) > 0:
if words[0].startswith("●"):
words.pop(0)
service = words[0]
loaded = words[1]
active = words[2]
sub = words[3]
self.table.setItem(i, 0, QTableWidgetItem(service))
self.table.setItem(i, 1, QTableWidgetItem(loaded))
self.table.setItem(i, 2, QTableWidgetItem(active))
self.table.setItem(i, 3, QTableWidgetItem(sub))
# Determine the action based on the service status
action = "stop" if sub == "running" else "start"
button = QPushButton(action.capitalize())
button.clicked.connect(self.create_service_action(service, action, i))
# Color button red if stop and green if start
if action == "stop":
button.setStyleSheet("background-color: #8b0000;")
else:
button.setStyleSheet("background-color: green;")
self.table.setCellWidget(i, 4, button)
def create_service_action(self, service, action, row):
def service_action():
result = subprocess.run(
["systemctl", "--user", action, service], capture_output=True, text=True
)
if result.returncode == 0:
QMessageBox.information(
self,
f"{action.capitalize()} Service",
f"Successfully {action}ed {service}",
)
self.update_service_status(service, row)
else:
QMessageBox.critical(
self,
f"{action.capitalize()} Service",
f"Failed to {action} {service}\n\n{result.stderr}",
)
return service_action
def update_service_status(self, service, row):
result = subprocess.run(
[
"systemctl",
"--user",
"show",
"--property=LoadState,ActiveState,SubState",
service,
],
capture_output=True,
text=True,
)
lines = result.stdout.splitlines()
loaded = lines[0].split("=")[1]
active = lines[1].split("=")[1]
sub = lines[2].split("=")[1]
self.table.setItem(row, 1, QTableWidgetItem(loaded))
self.table.setItem(row, 2, QTableWidgetItem(active))
self.table.setItem(row, 3, QTableWidgetItem(sub))
# Update the enabled status of the button
button = self.table.cellWidget(row, 4)
action = "stop" if sub == "running" else "start"
if action == "stop":
button.setStyleSheet("background-color: #8b0000;")
else:
button.setStyleSheet("background-color: green;")
button.setText(action.capitalize())
button.clicked.disconnect()
button.clicked.connect(self.create_service_action(service, action, row))
def main():
app = QApplication(sys.argv)
window = SystemdServiceLister()
window.show()
sys.exit(app.exec())
if __name__ == "__main__":
main()