Links
GitHub - furas/mate-python-applets: Examples which shows how to create MATE panel applet with Python.
My first panel applet
Create an Ubuntu Application Indicator in Python: step-by-step guide
Environment
- Ubuntu Mate 22.04.5 LTS
- Mate DE 1.26.0
- Python 3.10.12
Boilerplate: files and code
/usr/share/mate-panel/applets/org.mate.panel.TST00Applet.mate-panel-applet
[Applet Factory]
Id=TST00AppletFactory
InProcess=false
Location=/usr/lib/mate-applets/mate-ugn/
Name=TST00 Applet Factory
Description=Boilerplate code for a Mate Applet
[TST00Applet]
Name=TST00
Description=Boilerplate code for a Mate Applet
Icon=mate-desktop
/usr/share/dbus-1/services/org.mate.panel.applet.TST00AppletFactory.service
[D-BUS Service]
Name=org.mate.panel.applet.TST00AppletFactory
Exec=/usr/bin/env python3 /usr/lib/mate-applets/mate-ugn/tst00_applet.py
Notes:
TST00Applet
is applet'siid
- Pay your attention to files' and names' naming conventions
Location
directorymate-ugn
has been created to hold ugn's appletsName
and (optional)Icon
andDescription
are shown inAdd to panel...
dialogue
/usr/lib/mate-applets/mate-dock-applet/dock_applet.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('MatePanelApplet', '4.0')
from gi.repository import Gtk
from gi.repository import MatePanelApplet
# Your functions go here
def build_applet(applet):
# Your GTK code goes here
def applet_factory(applet, iid, data):
if iid != "TST00Applet":
return False
build_applet(applet)
return True
MatePanelApplet.Applet.factory_main("TST00AppletFactory", True,
MatePanelApplet.Applet.__gtype__,
applet_factory, None)
Development and debugging tips
It is expected that an applet is shown as a text, an icon or both on the panel. Besides that, it is expected that
- text/icon dynamically represent current status of an object/process;
- text/icon is a button to invoke a GUI dialogue window;
- text/icon is a top-level menu entry
I would recommend to develop and debug applet's code as a standalone GTK application and convert it to applet when finished. The point is that you can run it from terminal and see as your "print'ed" messages, as interpreter's exceptions information. The conversion procedure is simple and straightforward given that main window for GTK application is created manually and the parent window for an applet is provided as parameter of build_applet
function automagically.
The converted applet functionality can be verified by adding it to panel or with mate-panel-test-applets
utility. The latter provides applet selection menu and starts chosen applet in separate dialogue window, not in the panel.
You can print your diagnostic messages into file like this:
with open('/<path to log file>/tst00.log', 'a') as f:
print('tst00 - building', file=f)
Otherwise, you can use logging
module to log exceptions and messages. See the following link for recipe: mate-python-applets/example-X-debug/testapplet.py at master · furas/mate-python-applets · GitHub
If you want your applet to react to <ctrl>-<c>
key combination then add the following lines to the boilerplate code:
import signal
signal.signal(signal.SIGINT, signal.SIG_DFL)
- Running applet in terminal helps to catch syntax errors and is useless otherwise.
- While debugging, it is convenient to set
Location
andExec
keys in applet and service files to your project directory. killall mate-panel
command resets panel.Mate System Monitor
utility can be used to find and kill applet's process.- Command line can be used for the same purpose like this:
$ ps -ef | grep -i tst
ugn 61733 20699 0 13:52 pts/3 00:00:00 python3 tst00_applet.py
ugn 61833 61823 0 13:54 pts/1 00:00:00 grep --color=auto -i tst
$ kill 61733
Example: Dynamic text
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Mate panel applet to alter its text label
# ugnvs 4 Ubuntu Mate forum
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('MatePanelApplet', '4.0')
from gi.repository import Gtk
from gi.repository import GLib
from gi.repository import MatePanelApplet
status = None
tick = True
def update_status():
global status
global tick
if tick:
status.set_label('TST00-TICK')
else:
status.set_label('TST00-TOCK')
tick = not tick
GLib.timeout_add(4000, update_status)
def build_applet(applet):
global status
status = Gtk.Label("")
applet.add(status)
update_status()
applet.show_all()
def applet_factory(applet, iid, data):
result = (iid == "TST00Applet")
if result:
build_applet(applet)
return result
MatePanelApplet.Applet.factory_main("TST00AppletFactory", True,
MatePanelApplet.Applet.__gtype__,
applet_factory, None)
#EOF
Example: CPU usage
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Mate panel applet to measure CPU usage
# ugnvs 4 Ubuntu Mate forum
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('MatePanelApplet', '4.0')
from gi.repository import Gtk
from gi.repository import GLib
from gi.repository import MatePanelApplet
import time
status = None
# Refer to https://www.kernel.org/doc/Documentation/filesystems/proc.txt
# for /proc/stat fields explanation
def update_status():
global status
with open('/proc/stat', 'r') as f:
s=f.readline()
# name, user, nice, system, idle, iowait, irq, sofirq, steal, guest, guest_nice
s = s.split()
idle1 = int(s[4])
total1 = idle1 + int(s[1]) + int(s[2]) + int(s[3]) + int(s[6]) + int(s[7])
time.sleep(1)
with open('/proc/stat', 'r') as f:
s=f.readline()
s = s.split()
idle2 = int(s[4])
total2 = idle2 + int(s[1]) + int(s[2]) + int(s[3]) + int(s[6]) + int(s[7])
busy = 1.0-(idle2-idle1)/(total2 - total1)
txt = f'CPU: {busy:.0%}'
status.set_label(txt)
GLib.timeout_add(4000, update_status)
def build_applet(applet):
global status
status = Gtk.Label("")
applet.add(status)
update_status()
applet.show_all()
def applet_factory(applet, iid, data):
result = (iid == "TST00Applet")
if result:
build_applet(applet)
return result
MatePanelApplet.Applet.factory_main("TST00AppletFactory", True,
MatePanelApplet.Applet.__gtype__,
applet_factory, None)
#EOF
Example: Internet host availability and notification
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ping Google DNS host 8.8.4.4 and notify
# ugnvs 4 Ubuntu Mate forum
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('MatePanelApplet', '4.0')
from gi.repository import Gtk
from gi.repository import GLib
from gi.repository import MatePanelApplet
import subprocess
status = None
lastprobe = False
ping_command='ping -4nq -c 1 8.8.4.4'
def update_status():
global status
global lastprobe
res = subprocess.run(ping_command.split(' '), stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL, capture_output=False)
result = (res.returncode == 0)
if result != lastprobe:
lastprobe = result
if result:
txt = 'Ping OK'
subprocess.run(['notify-send', 'Internet connection available'], stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL, capture_output=False)
else:
txt = 'NO ping'
subprocess.run(['notify-send', 'Internet connection degraded'], stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL, capture_output=False)
status.set_label(txt)
GLib.timeout_add(4000, update_status)
def build_applet(applet):
global status
status = Gtk.Label("")
applet.add(status)
update_status()
applet.show_all()
def applet_factory(applet, iid, data):
result = (iid == "TST00Applet")
if result:
build_applet(applet)
return result
MatePanelApplet.Applet.factory_main("TST00AppletFactory", True,
MatePanelApplet.Applet.__gtype__,
applet_factory, None)
#EOF