v1.4: Add working AppIndicator systray with GTK3
This commit is contained in:
@@ -3,10 +3,24 @@
|
|||||||
|
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from tkinter import ttk
|
from tkinter import ttk
|
||||||
|
import subprocess
|
||||||
|
import tempfile
|
||||||
|
import os
|
||||||
import time
|
import time
|
||||||
|
import sys
|
||||||
|
import gi
|
||||||
|
|
||||||
import psutil
|
import psutil
|
||||||
|
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
gi.require_version('AyatanaAppIndicator3', '0.1')
|
||||||
|
from gi.repository import AyatanaAppIndicator3, GLib, Gtk
|
||||||
|
|
||||||
|
|
||||||
|
MAX_POINTS = 60
|
||||||
|
UPDATE_INTERVAL = 1000 # ms
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
|
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
|
||||||
from matplotlib.figure import Figure
|
from matplotlib.figure import Figure
|
||||||
@@ -15,10 +29,6 @@ except ImportError:
|
|||||||
HAVE_MPL = False
|
HAVE_MPL = False
|
||||||
|
|
||||||
|
|
||||||
MAX_POINTS = 60
|
|
||||||
UPDATE_INTERVAL = 1000 # ms
|
|
||||||
|
|
||||||
|
|
||||||
class Tracker:
|
class Tracker:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.cpu_data = []
|
self.cpu_data = []
|
||||||
@@ -29,6 +39,99 @@ class Tracker:
|
|||||||
return psutil.cpu_percent(interval=None)
|
return psutil.cpu_percent(interval=None)
|
||||||
|
|
||||||
|
|
||||||
|
class SysTrayIndicator:
|
||||||
|
def __init__(self, monitor):
|
||||||
|
self.indicator = AyatanaAppIndicator3.Indicator.new(
|
||||||
|
"cpu-monitor",
|
||||||
|
"utilities-system-monitor",
|
||||||
|
AyatanaAppIndicator3.IndicatorCategory.SYSTEM_SERVICES
|
||||||
|
)
|
||||||
|
self.indicator.set_status(AyatanaAppIndicator3.IndicatorStatus.ACTIVE)
|
||||||
|
self.indicator.set_menu(self._create_menu())
|
||||||
|
self.monitor = monitor
|
||||||
|
self._update_icon()
|
||||||
|
|
||||||
|
def _create_menu(self):
|
||||||
|
menu = Gtk.Menu()
|
||||||
|
cpu = psutil.cpu_percent(interval=None)
|
||||||
|
ram = psutil.virtual_memory().percent
|
||||||
|
disk = psutil.disk_usage('/').percent
|
||||||
|
|
||||||
|
item1 = Gtk.MenuItem(label=f"CPU: {cpu:.1f}%")
|
||||||
|
item1.show()
|
||||||
|
menu.append(item1)
|
||||||
|
|
||||||
|
item2 = Gtk.MenuItem(label=f"RAM: {ram:.1f}%")
|
||||||
|
item2.show()
|
||||||
|
menu.append(item2)
|
||||||
|
|
||||||
|
item3 = Gtk.MenuItem(label=f"Disk: {disk:.1f}%")
|
||||||
|
item3.show()
|
||||||
|
menu.append(item3)
|
||||||
|
|
||||||
|
sep = Gtk.SeparatorMenuItem()
|
||||||
|
sep.show()
|
||||||
|
menu.append(sep)
|
||||||
|
|
||||||
|
hide = Gtk.MenuItem(label="Hide Window")
|
||||||
|
hide.connect("activate", lambda w: self.monitor.root.withdraw())
|
||||||
|
hide.show()
|
||||||
|
menu.append(hide)
|
||||||
|
|
||||||
|
show = Gtk.MenuItem(label="Show Window")
|
||||||
|
show.connect("activate", lambda w: self.monitor.root.deiconify())
|
||||||
|
show.show()
|
||||||
|
menu.append(show)
|
||||||
|
|
||||||
|
sep2 = Gtk.SeparatorMenuItem()
|
||||||
|
sep2.show()
|
||||||
|
menu.append(sep2)
|
||||||
|
|
||||||
|
quit_item = Gtk.MenuItem(label="Quit")
|
||||||
|
quit_item.connect("activate", lambda w: self._quit())
|
||||||
|
quit_item.show()
|
||||||
|
menu.append(quit_item)
|
||||||
|
|
||||||
|
menu.show()
|
||||||
|
return menu
|
||||||
|
|
||||||
|
def _quit(self):
|
||||||
|
GLib.idle_add(Gtk.main_quit)
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
def _update_icon(self):
|
||||||
|
try:
|
||||||
|
import cairo
|
||||||
|
except ImportError:
|
||||||
|
GLib.timeout_add_seconds(1, self._update_icon)
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
||||||
class App:
|
class App:
|
||||||
cpu_data = []
|
cpu_data = []
|
||||||
ram_data = []
|
ram_data = []
|
||||||
@@ -184,12 +287,15 @@ class App:
|
|||||||
def _stop(self):
|
def _stop(self):
|
||||||
self._running = False
|
self._running = False
|
||||||
self.status_label.config(text="Stopped.")
|
self.status_label.config(text="Stopped.")
|
||||||
self.root.destroy()
|
self.root.withdraw()
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
root = tk.Tk()
|
root = tk.Tk()
|
||||||
app = App(root)
|
app = App(root)
|
||||||
|
|
||||||
|
_tray = SysTrayIndicator(app)
|
||||||
|
|
||||||
root.mainloop()
|
root.mainloop()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
7
debian/changelog
vendored
Normal file → Executable file
7
debian/changelog
vendored
Normal file → Executable file
@@ -1,6 +1,7 @@
|
|||||||
cpu-monitor (1.2) noble; urgency=low
|
cpu-monitor (1.4) noble; urgency=low
|
||||||
|
|
||||||
* Removed AppIndicator (Wayland incompatible)
|
* v1.4: Add working AppIndicator systray with GTK3
|
||||||
* Simpler, more reliable autostart
|
* v1.4: System tray icon with CPU/RAM/Disk status menu
|
||||||
|
* v1.4: Hide/Show window from systray menu
|
||||||
|
|
||||||
-- tmzf5455 <tmzf5455> Sun, 10 May 2026 00:00:00 +0000
|
-- tmzf5455 <tmzf5455> Sun, 10 May 2026 00:00:00 +0000
|
||||||
|
|||||||
2
debian/control
vendored
Normal file → Executable file
2
debian/control
vendored
Normal file → Executable file
@@ -8,7 +8,7 @@ Rules-Requires-Root: no
|
|||||||
|
|
||||||
Package: cpu-monitor
|
Package: cpu-monitor
|
||||||
Architecture: all
|
Architecture: all
|
||||||
Depends: python3, python3-psutil, python3-matplotlib, python3-tk, ${misc:Depends}
|
Depends: python3, python3-psutil, python3-matplotlib, python3-tk, gir1.2-ayatanaappindicator3-0.1, gir1.2-gtk-3.0, ${misc:Depends}
|
||||||
Description: CPU/RAM/Disk/Network monitor GUI
|
Description: CPU/RAM/Disk/Network monitor GUI
|
||||||
A system monitor tool with real-time matplotlib charts
|
A system monitor tool with real-time matplotlib charts
|
||||||
and a tkinter GUI, showing CPU, RAM, disk and network usage.
|
and a tkinter GUI, showing CPU, RAM, disk and network usage.
|
||||||
|
|||||||
0
debian/source/format
vendored
Normal file → Executable file
0
debian/source/format
vendored
Normal file → Executable file
Reference in New Issue
Block a user