Skip to content

Commit 47b37bc

Browse files
committed
changed to the use of the curses library
1 parent 12d9f16 commit 47b37bc

File tree

5 files changed

+81
-43
lines changed

5 files changed

+81
-43
lines changed

main.py

Lines changed: 41 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
1+
import curses
12
import time
23
from cpu_monitor import CPUMonitor
34
from memory_monitor import MemoryMonitor
45
from network_monitor import NetworkMonitor
56
from system_info import SystemInfo
67
from processes import ProcessMonitor
78

8-
# ANSI color escape codes
9-
COLOR_RESET = "\033[0m"
10-
COLOR_YELLOW = "\033[93m" # Yellow for CPU
11-
COLOR_GREEN = "\033[92m" # Green for Memory
12-
COLOR_BLUE = "\033[94m" # Blue for Bandwidth
13-
COLOR_CYAN = "\033[96m" # Cyan for Headers
9+
def main(stdscr):
10+
# Clear screen
11+
stdscr.clear()
12+
curses.curs_set(0) # Hide the cursor
1413

15-
def main():
1614
cpu_monitor = CPUMonitor()
1715
memory_monitor = MemoryMonitor()
1816
network_monitor = NetworkMonitor()
@@ -21,46 +19,58 @@ def main():
2119

2220
try:
2321
while True:
22+
# Get screen dimensions
23+
height, width = stdscr.getmaxyx()
24+
half_width = width // 2
25+
2426
# Get real-time data
2527
cpu_output = cpu_monitor.get_cpu_usage()
2628
memory_output = memory_monitor.get_memory_usage()
2729
bandwidth_output = network_monitor.get_bandwidth_usage()
2830
sys_info_output = system_info.get_system_info()
2931
processes_output = process_monitor.get_running_processes(num_processes=10)
3032

31-
# Apply colors to entire output strings
32-
cpu_output = f"{COLOR_YELLOW}{cpu_output}{COLOR_RESET}"
33-
memory_output = f"{COLOR_GREEN}{memory_output}{COLOR_RESET}"
34-
bandwidth_output = f"{COLOR_BLUE}{bandwidth_output.replace('Received', '↓').replace('Sent', '↑')}{COLOR_RESET}"
35-
sys_info_output = f"{COLOR_CYAN}{sys_info_output}{COLOR_RESET}"
36-
processes_output = "\n".join([f"{COLOR_CYAN}Running Processes{COLOR_RESET}", "-----------------"] + processes_output)
37-
3833
# Clear screen
39-
print("\033c", end='')
34+
stdscr.clear()
4035

41-
# Print headers
42-
print(f"{COLOR_CYAN}CPU & Memory Network{COLOR_RESET}")
43-
print(f"{COLOR_CYAN}------------- -------{COLOR_RESET}")
36+
# Define color pairs
37+
curses.start_color()
38+
curses.init_pair(1, curses.COLOR_YELLOW, curses.COLOR_BLACK)
39+
curses.init_pair(2, curses.COLOR_GREEN, curses.COLOR_BLACK)
40+
curses.init_pair(3, curses.COLOR_BLUE, curses.COLOR_BLACK)
41+
curses.init_pair(4, curses.COLOR_CYAN, curses.COLOR_BLACK)
42+
curses.init_pair(5, curses.COLOR_RED, curses.COLOR_BLACK)
4443

45-
# Print meters and system info
46-
print(f"{cpu_output} {bandwidth_output}")
47-
print(f"{memory_output}")
48-
print(f"{COLOR_CYAN}System Info{COLOR_RESET}")
49-
print(f"{COLOR_CYAN}-----------{COLOR_RESET}")
50-
sys_info_lines = [line[:40] for line in sys_info_output.split("\n")]
51-
for line in sys_info_lines:
52-
print(line)
44+
# Print CPU and Memory Usage
45+
stdscr.addstr(0, 0, "CPU Usage", curses.color_pair(4))
46+
stdscr.addstr(1, 0, cpu_output[:half_width], curses.color_pair(1))
47+
stdscr.addstr(2, 0, "Memory Usage", curses.color_pair(4))
48+
stdscr.addstr(3, 0, memory_output[:half_width], curses.color_pair(2))
5349

54-
# Print Running Processes
55-
print(processes_output)
50+
# Print Bandwidth Usage
51+
stdscr.addstr(0, half_width, "Network Usage", curses.color_pair(4))
52+
stdscr.addstr(1, half_width, bandwidth_output.replace('Received', '↓').replace('Sent', '↑')[:half_width], curses.color_pair(3))
5653

57-
# Move cursor to the top
58-
print("\033[6A", end='')
54+
# Print System Info
55+
stdscr.addstr(5, 0, "System Info", curses.color_pair(4))
56+
stdscr.addstr(6, 0, "-----------", curses.color_pair(4))
57+
sys_info_lines = [line[:half_width] for line in sys_info_output.split("\n")]
58+
for idx, line in enumerate(sys_info_lines):
59+
if 7 + idx < height:
60+
stdscr.addstr(7 + idx, 0, line, curses.color_pair(4))
61+
62+
# Print Running Processes
63+
stdscr.addstr(5, half_width, "Running Processes", curses.color_pair(4))
64+
stdscr.addstr(6, half_width, "-----------------", curses.color_pair(4))
65+
for idx, process in enumerate(processes_output):
66+
if 7 + idx < height:
67+
stdscr.addstr(7 + idx, half_width, process[:half_width], curses.color_pair(5))
5968

69+
stdscr.refresh()
6070
time.sleep(0.5) # Wait for 0.5 seconds before updating again
6171

6272
except KeyboardInterrupt:
6373
print("\nExiting...")
6474

6575
if __name__ == "__main__":
66-
main()
76+
curses.wrapper(main)

memory_monitor.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,3 @@ def _format_usage(self, memory):
1212
memory_percent = memory / 100.0
1313
memory_visual = '#' * int(memory_percent * self.bars) + '-' * (self.bars - int(memory_percent * self.bars))
1414
return f"Memory: [{memory_visual}] {memory:.2f}%"
15-
16-
def get_memory_percentage(self):
17-
return psutil.virtual_memory().percent

network_monitor.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ def get_bandwidth_usage(self):
1515
self.last_received = bytes_received
1616
self.last_sent = bytes_sent
1717

18-
received = new_received / 1024
19-
sent = new_sent / 1024
20-
total = (new_received + new_sent) / 1024
18+
received_kb = new_received / 1024
19+
sent_kb = new_sent / 1024
20+
total_kb = (new_received + new_sent) / 1024
2121

22-
return f"Received: {received:.2f} KB | Sent: {sent:.2f} KB | Total: {total:.2f} KB"
22+
return f"Received: {received_kb:.2f} KB | Sent: {sent_kb:.2f} KB | Total: {total_kb:.2f} KB"

processes.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import psutil
2+
3+
class ProcessMonitor:
4+
def get_running_processes(self, num_processes=10):
5+
processes = psutil.process_iter(attrs=['name', 'pid', 'username'])
6+
process_info = []
7+
for process in processes:
8+
try:
9+
name = process.info['name']
10+
pid = process.info['pid']
11+
username = process.info['username']
12+
process_info.append(f"{name} (PID: {pid}, User: {username})")
13+
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
14+
continue
15+
if len(process_info) >= num_processes:
16+
break
17+
return process_info
18+
19+
# Example usage:
20+
if __name__ == "__main__":
21+
process_monitor = ProcessMonitor()
22+
processes = process_monitor.get_running_processes()
23+
for process in processes:
24+
print(process)

system_info.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import psutil
33
import time
44
import socket
5+
import subprocess
56

67
class SystemInfo:
78
def get_system_info(self):
@@ -21,7 +22,6 @@ def get_system_info(self):
2122
battery_status = self._get_battery_status()
2223
battery_health = self._get_battery_health()
2324

24-
# Apply color to system information output
2525
sys_info_output = (
2626
f"OS: {os_name}\n"
2727
f"Python: {python_version}\n"
@@ -84,8 +84,8 @@ def _get_battery_health(self):
8484
["ioreg", "-r", "-c", "AppleSmartBattery", "-k", "DesignCapacity", "-k", "MaxCapacity"],
8585
universal_newlines=True
8686
)
87-
design_capacity = int(health_info.split('DesignCapacity')[1].split('= ')[1].split('\n')[0])
88-
max_capacity = int(health_info.split('MaxCapacity')[1].split('= ')[1].split('\n')[0])
87+
design_capacity = int(self._parse_health_info(health_info, 'DesignCapacity'))
88+
max_capacity = int(self._parse_health_info(health_info, 'MaxCapacity'))
8989
health_percent = (max_capacity / design_capacity) * 100
9090
return f"{health_percent:.2f}%"
9191
elif os_name == 'Windows': # Windows
@@ -96,8 +96,8 @@ def _get_battery_health(self):
9696
# Read and parse the battery_report.html to get battery health information
9797
with open("battery_report.html", "r") as file:
9898
report = file.read()
99-
design_capacity = int(report.split('DESIGN CAPACITY')[1].split('<td>')[1].split(' mWh')[0].replace(',', ''))
100-
full_charge_capacity = int(report.split('FULL CHARGE CAPACITY')[1].split('<td>')[1].split(' mWh')[0].replace(',', ''))
99+
design_capacity = int(self._parse_battery_report(report, 'DESIGN CAPACITY'))
100+
full_charge_capacity = int(self._parse_battery_report(report, 'FULL CHARGE CAPACITY'))
101101
health_percent = (full_charge_capacity / design_capacity) * 100
102102
return f"{health_percent:.2f}%"
103103
elif os_name == 'Linux': # Linux
@@ -111,3 +111,10 @@ def _get_battery_health(self):
111111
return "Unsupported OS"
112112
except Exception as e:
113113
return f"Error retrieving battery health: {e}"
114+
115+
def _parse_health_info(self, health_info, key):
116+
return health_info.split(f"{key} = ")[1].split('\n')[0].strip()
117+
118+
def _parse_battery_report(self, report, key):
119+
return report.split(f'{key}')[1].split('<td>')[1].split(' mWh')[0].replace(',', '')
120+

0 commit comments

Comments
 (0)