diff --git a/cpu_monitor_gui.py b/cpu_monitor_gui.py index a2486d5..a333cd9 100755 --- a/cpu_monitor_gui.py +++ b/cpu_monitor_gui.py @@ -3,26 +3,10 @@ import tkinter as tk from tkinter import ttk -import subprocess -import tempfile -import os import time import psutil -import gi -try: - gi.require_version('AyatanaAppIndicator3', '0.1') - from gi.repository import AyatanaAppIndicator3, GLib, Gtk - HAVE_INDICATOR = True -except (ImportError, ValueError): - HAVE_INDICATOR = False - - -MAX_POINTS = 60 -UPDATE_INTERVAL = 1000 # ms - - try: from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from matplotlib.figure import Figure @@ -31,147 +15,28 @@ except ImportError: HAVE_MPL = False +MAX_POINTS = 60 +UPDATE_INTERVAL = 1000 # ms + + class Tracker: def __init__(self): self.cpu_data = [] self.ram_data = [] - self.disk_data = [] self._last_cpu = None - now = time.time() - self.time_data = [now] - - def _net_rate(self, curr, last, interval): - delta = curr - last - rate = max(delta / interval, 0) - return max(int(rate), 0) - - def update(self, dt): - cpu = psutil.cpu_percent(interval=None) - ram = psutil.virtual_memory().percent - disk = psutil.disk_usage('/').percent - self._last_cpu = cpu - t = time.time() - self.time_data.append(t) - - self.cpu_data.append(cpu) - self.ram_data.append(ram) - self.disk_data.append(disk) - - net = psutil.net_io_counters() - sent = net.bytes_sent - recv = net.bytes_recv - self._last_net_sent = sent - self._last_net_recv = recv - - def get_latest(self): - if self._last_cpu is None: - self.update(1) - return self._last_cpu, self.ram_data[-1] if self.ram_data else 0 - - def get_disk(self): - return self.disk_data[-1] if self.disk_data else 0 - - def get_net_rates(self): - return 0, 0 def cpu_percent(self): return psutil.cpu_percent(interval=None) -class SysTrayIndicator: - def __init__(self, monitor): - if not HAVE_INDICATOR: - return - - self.indicator = AyatanaAppIndicator3.Indicator.new( - "cpu-monitor", - "cpu-monitor", - AyatanaAppIndicator3.IndicatorCategory.SYSTEM_SERVICES - ) - self.indicator.set_menu(self._create_menu()) - self.monitor = monitor - self._update_icon() - - try: - import cairo - except ImportError: - return - - def _create_menu(self): - menu = Gtk.Menu() - - item = Gtk.MenuItem(label=f"CPU: {psutil.cpu_percent(interval=None)}%") - item.show() - menu.append(item) - - item2 = Gtk.MenuItem(label=f"RAM: {psutil.virtual_memory().percent}%") - item2.show() - menu.append(item2) - - sep = Gtk.SeparatorMenuItem() - sep.show() - menu.append(sep) - - open_item = Gtk.MenuItem(label="Open Monitor") - open_item.connect("activate", lambda w: subprocess.Popen(["cpu-monitor"])) - open_item.show() - menu.append(open_item) - - close_item = Gtk.MenuItem(label="Quit") - close_item.connect("activate", lambda w: Gtk.main_quit()) - close_item.show() - menu.append(close_item) - - return menu - - def _update_icon(self): - if not HAVE_INDICATOR: - return - try: - import cairo - except ImportError: - return - - cpu = psutil.cpu_percent() - if cpu > 80: - color = (0.93, 0.33, 0.31) - elif cpu > 50: - color = (1.0, 0.55, 0.0) - else: - color = (0.40, 0.76, 0.97) - - size = 24 - surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, size, size) - cr = cairo.Context(surface) - cr.set_source_rgba(*color, 1.0) - cr.paint() - - tmp = tempfile.NamedTemporaryFile(suffix='.png', delete=False, dir='/tmp') - tmp.close() - surface.write_to_png(tmp.name) - - try: - self.indicator.set_icon_full(tmp.name, "CPU Monitor") - except Exception: - pass - - GLib.timeout_add_seconds(2, self._update_icon) - - -def create_tray_icon(monitor): - if HAVE_INDICATOR: - return SysTrayIndicator(monitor) - return None - - class App: cpu_data = [] ram_data = [] - _last_cpu = None def __init__(self, root): self.root = root self.root.title("CPU / RAM Monitor") + self.root.geometry("1000x200") self.tracker = Tracker() @@ -199,14 +64,6 @@ class App: ) self.ram_label.pack(side=tk.LEFT, padx=20) - self.net_label = ttk.Label( - header_frame, - text=f"Net: ↓ --", - font=("Segoe UI", 20, "bold"), - foreground="#ffb74d", - ) - self.net_label.pack(side=tk.LEFT, padx=20) - self.disk_label = ttk.Label( header_frame, text=f"Disk: --%", @@ -299,10 +156,10 @@ class App: self.cpu_data.append(cpu) self.ram_data.append(ram) - if len(self.cpu_data) > MAX_POINTS: - self.cpu_data = self.cpu_data[-MAX_POINTS:] - if len(self.ram_data) > MAX_POINTS: - self.ram_data = self.ram_data[-MAX_POINTS:] + if len(App.cpu_data) > MAX_POINTS: + App.cpu_data = App.cpu_data[-MAX_POINTS:] + if len(App.ram_data) > MAX_POINTS: + App.ram_data = App.ram_data[-MAX_POINTS:] self.cpu_label.config(text=f"CPU: {cpu:5.1f}%") self.ram_label.config(text=f"RAM: {ram:5.1f}%") @@ -313,8 +170,8 @@ class App: ax_ram = self.fig.axes[1] ax_disk = self.fig.axes[2] - self.cpu_line.set_data(range(len(self.cpu_data)), self.cpu_data) - self.ram_line.set_data(range(len(self.ram_data)), self.ram_data) + self.cpu_line.set_data(range(len(App.cpu_data)), App.cpu_data) + self.ram_line.set_data(range(len(App.ram_data)), App.ram_data) ax_cpu.set_xlim(0, MAX_POINTS) ax_ram.set_xlim(0, MAX_POINTS) @@ -328,19 +185,11 @@ class App: self._running = False self.status_label.config(text="Stopped.") self.root.destroy() - if HAVE_INDICATOR: - GLib.idle_add(Gtk.main_quit) def main(): root = tk.Tk() app = App(root) - - _tray = None - if HAVE_INDICATOR: - _tray = SysTrayIndicator(app) - root.bind('', lambda e: GLib.idle_add(Gtk.main_quit)) - root.mainloop() diff --git a/debian/.debhelper/generated/cpu-monitor/dh_installchangelogs.dch.trimmed b/debian/.debhelper/generated/cpu-monitor/dh_installchangelogs.dch.trimmed index 8cf162d..32bc293 100644 --- a/debian/.debhelper/generated/cpu-monitor/dh_installchangelogs.dch.trimmed +++ b/debian/.debhelper/generated/cpu-monitor/dh_installchangelogs.dch.trimmed @@ -1,7 +1,6 @@ -cpu-monitor (1.1) noble; urgency=low +cpu-monitor (1.2) noble; urgency=low - * v2: Add GNOME AppIndicator systray icon in system tray bar - * v2: Autostart .desktop in /etc/xdg/autostart - * v2: System tray icon with CPU/RAM status menu + * Removed AppIndicator (Wayland incompatible) + * Simpler, more reliable autostart -- tmzf5455 Sun, 10 May 2026 00:00:00 +0000 diff --git a/debian/changelog b/debian/changelog index 8cf162d..32bc293 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,7 +1,6 @@ -cpu-monitor (1.1) noble; urgency=low +cpu-monitor (1.2) noble; urgency=low - * v2: Add GNOME AppIndicator systray icon in system tray bar - * v2: Autostart .desktop in /etc/xdg/autostart - * v2: System tray icon with CPU/RAM status menu + * Removed AppIndicator (Wayland incompatible) + * Simpler, more reliable autostart -- tmzf5455 Sun, 10 May 2026 00:00:00 +0000 diff --git a/debian/control b/debian/control index 8bc4ff1..7408072 100644 --- a/debian/control +++ b/debian/control @@ -8,7 +8,7 @@ Rules-Requires-Root: no Package: cpu-monitor Architecture: all -Depends: python3, python3-psutil, python3-matplotlib, python3-tk, gir1.2-ayatanaappindicator3-0.1, ${misc:Depends} +Depends: python3, python3-psutil, python3-matplotlib, python3-tk, ${misc:Depends} Description: CPU/RAM/Disk/Network monitor GUI A system monitor tool with real-time matplotlib charts and a tkinter GUI, showing CPU, RAM, disk and network usage. diff --git a/debian/cpu-monitor/DEBIAN/control b/debian/cpu-monitor/DEBIAN/control index 9d92cdf..268be7a 100644 --- a/debian/cpu-monitor/DEBIAN/control +++ b/debian/cpu-monitor/DEBIAN/control @@ -1,9 +1,9 @@ Package: cpu-monitor -Version: 1.1 +Version: 1.2 Architecture: all Maintainer: tmzf5455 -Installed-Size: 32 -Depends: python3, python3-psutil, python3-matplotlib, python3-tk, gir1.2-ayatanaappindicator3-0.1 +Installed-Size: 19 +Depends: python3, python3-psutil, python3-matplotlib, python3-tk Section: utils Priority: optional Description: CPU/RAM/Disk/Network monitor GUI diff --git a/debian/cpu-monitor/DEBIAN/md5sums b/debian/cpu-monitor/DEBIAN/md5sums index 0982e61..a8f4d85 100644 --- a/debian/cpu-monitor/DEBIAN/md5sums +++ b/debian/cpu-monitor/DEBIAN/md5sums @@ -1,3 +1,2 @@ -f0e9f6392ef8c8b1447d39da0622a0d7 usr/bin/cpu-monitor -c8cc9827601e0cc0b156979c4caa4980 usr/share/doc/cpu-monitor/changelog.gz -fd11337fda885b79dc49d83a15abcffd usr/share/icons/hicolor/48x48/apps/cpu-monitor.png +f2f2755049314fcc90af2529be7731e4 usr/bin/cpu-monitor +34f5fe29e2343c3c795082bbcb93bd0c usr/share/doc/cpu-monitor/changelog.gz diff --git a/debian/cpu-monitor/usr/bin/cpu-monitor b/debian/cpu-monitor/usr/bin/cpu-monitor index a2486d5..a333cd9 100755 --- a/debian/cpu-monitor/usr/bin/cpu-monitor +++ b/debian/cpu-monitor/usr/bin/cpu-monitor @@ -3,26 +3,10 @@ import tkinter as tk from tkinter import ttk -import subprocess -import tempfile -import os import time import psutil -import gi -try: - gi.require_version('AyatanaAppIndicator3', '0.1') - from gi.repository import AyatanaAppIndicator3, GLib, Gtk - HAVE_INDICATOR = True -except (ImportError, ValueError): - HAVE_INDICATOR = False - - -MAX_POINTS = 60 -UPDATE_INTERVAL = 1000 # ms - - try: from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from matplotlib.figure import Figure @@ -31,147 +15,28 @@ except ImportError: HAVE_MPL = False +MAX_POINTS = 60 +UPDATE_INTERVAL = 1000 # ms + + class Tracker: def __init__(self): self.cpu_data = [] self.ram_data = [] - self.disk_data = [] self._last_cpu = None - now = time.time() - self.time_data = [now] - - def _net_rate(self, curr, last, interval): - delta = curr - last - rate = max(delta / interval, 0) - return max(int(rate), 0) - - def update(self, dt): - cpu = psutil.cpu_percent(interval=None) - ram = psutil.virtual_memory().percent - disk = psutil.disk_usage('/').percent - self._last_cpu = cpu - t = time.time() - self.time_data.append(t) - - self.cpu_data.append(cpu) - self.ram_data.append(ram) - self.disk_data.append(disk) - - net = psutil.net_io_counters() - sent = net.bytes_sent - recv = net.bytes_recv - self._last_net_sent = sent - self._last_net_recv = recv - - def get_latest(self): - if self._last_cpu is None: - self.update(1) - return self._last_cpu, self.ram_data[-1] if self.ram_data else 0 - - def get_disk(self): - return self.disk_data[-1] if self.disk_data else 0 - - def get_net_rates(self): - return 0, 0 def cpu_percent(self): return psutil.cpu_percent(interval=None) -class SysTrayIndicator: - def __init__(self, monitor): - if not HAVE_INDICATOR: - return - - self.indicator = AyatanaAppIndicator3.Indicator.new( - "cpu-monitor", - "cpu-monitor", - AyatanaAppIndicator3.IndicatorCategory.SYSTEM_SERVICES - ) - self.indicator.set_menu(self._create_menu()) - self.monitor = monitor - self._update_icon() - - try: - import cairo - except ImportError: - return - - def _create_menu(self): - menu = Gtk.Menu() - - item = Gtk.MenuItem(label=f"CPU: {psutil.cpu_percent(interval=None)}%") - item.show() - menu.append(item) - - item2 = Gtk.MenuItem(label=f"RAM: {psutil.virtual_memory().percent}%") - item2.show() - menu.append(item2) - - sep = Gtk.SeparatorMenuItem() - sep.show() - menu.append(sep) - - open_item = Gtk.MenuItem(label="Open Monitor") - open_item.connect("activate", lambda w: subprocess.Popen(["cpu-monitor"])) - open_item.show() - menu.append(open_item) - - close_item = Gtk.MenuItem(label="Quit") - close_item.connect("activate", lambda w: Gtk.main_quit()) - close_item.show() - menu.append(close_item) - - return menu - - def _update_icon(self): - if not HAVE_INDICATOR: - return - try: - import cairo - except ImportError: - return - - cpu = psutil.cpu_percent() - if cpu > 80: - color = (0.93, 0.33, 0.31) - elif cpu > 50: - color = (1.0, 0.55, 0.0) - else: - color = (0.40, 0.76, 0.97) - - size = 24 - surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, size, size) - cr = cairo.Context(surface) - cr.set_source_rgba(*color, 1.0) - cr.paint() - - tmp = tempfile.NamedTemporaryFile(suffix='.png', delete=False, dir='/tmp') - tmp.close() - surface.write_to_png(tmp.name) - - try: - self.indicator.set_icon_full(tmp.name, "CPU Monitor") - except Exception: - pass - - GLib.timeout_add_seconds(2, self._update_icon) - - -def create_tray_icon(monitor): - if HAVE_INDICATOR: - return SysTrayIndicator(monitor) - return None - - class App: cpu_data = [] ram_data = [] - _last_cpu = None def __init__(self, root): self.root = root self.root.title("CPU / RAM Monitor") + self.root.geometry("1000x200") self.tracker = Tracker() @@ -199,14 +64,6 @@ class App: ) self.ram_label.pack(side=tk.LEFT, padx=20) - self.net_label = ttk.Label( - header_frame, - text=f"Net: ↓ --", - font=("Segoe UI", 20, "bold"), - foreground="#ffb74d", - ) - self.net_label.pack(side=tk.LEFT, padx=20) - self.disk_label = ttk.Label( header_frame, text=f"Disk: --%", @@ -299,10 +156,10 @@ class App: self.cpu_data.append(cpu) self.ram_data.append(ram) - if len(self.cpu_data) > MAX_POINTS: - self.cpu_data = self.cpu_data[-MAX_POINTS:] - if len(self.ram_data) > MAX_POINTS: - self.ram_data = self.ram_data[-MAX_POINTS:] + if len(App.cpu_data) > MAX_POINTS: + App.cpu_data = App.cpu_data[-MAX_POINTS:] + if len(App.ram_data) > MAX_POINTS: + App.ram_data = App.ram_data[-MAX_POINTS:] self.cpu_label.config(text=f"CPU: {cpu:5.1f}%") self.ram_label.config(text=f"RAM: {ram:5.1f}%") @@ -313,8 +170,8 @@ class App: ax_ram = self.fig.axes[1] ax_disk = self.fig.axes[2] - self.cpu_line.set_data(range(len(self.cpu_data)), self.cpu_data) - self.ram_line.set_data(range(len(self.ram_data)), self.ram_data) + self.cpu_line.set_data(range(len(App.cpu_data)), App.cpu_data) + self.ram_line.set_data(range(len(App.ram_data)), App.ram_data) ax_cpu.set_xlim(0, MAX_POINTS) ax_ram.set_xlim(0, MAX_POINTS) @@ -328,19 +185,11 @@ class App: self._running = False self.status_label.config(text="Stopped.") self.root.destroy() - if HAVE_INDICATOR: - GLib.idle_add(Gtk.main_quit) def main(): root = tk.Tk() app = App(root) - - _tray = None - if HAVE_INDICATOR: - _tray = SysTrayIndicator(app) - root.bind('', lambda e: GLib.idle_add(Gtk.main_quit)) - root.mainloop() diff --git a/debian/cpu-monitor/usr/share/doc/cpu-monitor/changelog.gz b/debian/cpu-monitor/usr/share/doc/cpu-monitor/changelog.gz index e53c908..a711c4c 100644 Binary files a/debian/cpu-monitor/usr/share/doc/cpu-monitor/changelog.gz and b/debian/cpu-monitor/usr/share/doc/cpu-monitor/changelog.gz differ diff --git a/debian/cpu-monitor/usr/share/icons/hicolor/48x48/apps/cpu-monitor.png b/debian/cpu-monitor/usr/share/icons/hicolor/48x48/apps/cpu-monitor.png deleted file mode 100644 index 8fef48a..0000000 Binary files a/debian/cpu-monitor/usr/share/icons/hicolor/48x48/apps/cpu-monitor.png and /dev/null differ diff --git a/debian/files b/debian/files index 1aabd31..ed6bd3c 100644 --- a/debian/files +++ b/debian/files @@ -1,2 +1,2 @@ -cpu-monitor_1.1_all.deb utils optional -cpu-monitor_1.1_arm64.buildinfo utils optional +cpu-monitor_1.2_all.deb utils optional +cpu-monitor_1.2_arm64.buildinfo utils optional diff --git a/debian/rules b/debian/rules index 12229d9..fd5558e 100755 --- a/debian/rules +++ b/debian/rules @@ -4,4 +4,3 @@ override_dh_auto_install: install -D -m 0755 cpu_monitor_gui.py $(CURDIR)/debian/cpu-monitor/usr/bin/cpu-monitor install -D -m 0644 cpu_monitor_gui.desktop $(CURDIR)/debian/cpu-monitor/etc/xdg/autostart/cpu-monitor.desktop - install -D -m 0644 cpu-monitor.png $(CURDIR)/debian/cpu-monitor/usr/share/icons/hicolor/48x48/apps/cpu-monitor.png