Gnome Notification Area Application in Python (English)
It’s nice how many of your preferred Gnome applications can fall back into a small icon on the notification area (also called tray), and conveniently sit there until something happens. Have you ever wondered how to do that in Python?
This is a not-so-quick and not-so-dirty demonstration of how to write a small Gnome Python application that will sit in the Gnome notification area (which we will also call “tray”), and react to some menu actions.
You can find the full code by downloading this file:
Below I will comment the most important parts of the code, so that you understand the basics, and create your own code from there.
First of all, bare with me, I decided to make the application fully object-oriented because it’s then easier to extend, and add more features later. Also, it’s a good exercise to write even the simplest applications using OOP, since the most complex ones will be easier to maintain if you do so, and practice takes you to perfection (well, at least to better practice). Also, notice I’m a free-time developer (my primary job is system administration), so many things here might be poorly explained or poorly coded, but the general guidance is what matters. Let’s move on.
I will explain how the code works by following the regular flow of the code, like how it would be executed in our test environment. Each number in the beginning of a line of code means the line number on the actual file (so that you can follow easily).
The code starts with a simple Python statement that will tell us which one is the main application object.
71: if __name__ == "__main__": 72: helloWord = HelloTray()
The class declaration starts on line 6. Notice that apart from what you expected, the class does not need to be a derivation of anything else. This happens because the application itself is not on the notification area, but rather it’s the interface which sits in there. So we need to create that interface.
31: def __init__(self): 32: self.statusIcon = gtk.StatusIcon() 33: self.statusIcon.set_from_stock(gtk.STOCK_ABOUT) 34: self.statusIcon.set_visible(True) 35: self.statusIcon.set_tooltip("Hello World")
The class initialization code starts by creating a gtk.StatusIcon widget. That’s the “magic” that creates the tray icon. This is just like if you were creating your main gtk.Window in a regular PyGTK application. Then we need to define some properties for that status icon. In this particular case we use the stock GTK icons, just to make our lives easier. Another advantage of using stock icons, is that your application will seamlesly fit into which ever theme is currently active. The tool tip property on line 35 sets the text that will show when we hover the mouse over the icon.
37: self.menu = gtk.Menu() 38: self.menuItem = gtk.ImageMenuItem(gtk.STOCK_EXECUTE) 39: self.menuItem.connect('activate', self.execute_cb, self.statusIcon) 40: self.menu.append(self.menuItem) 41: self.menuItem = gtk.ImageMenuItem(gtk.STOCK_QUIT) 42: self.menuItem.connect('activate', self.quit_cb, self.statusIcon) 43: self.menu.append(self.menuItem)
Now we need to create a pop up menu, that will be shown when we right-click over the status icon. We use the standard gtk.Menu widget. The gtk.ImageMenuItem widget creates a menu item with a small icon and a caption. In this case we’re also using stock items just to wrap up quickly. Notice that for each menu item, there is an associate call back method (self.execute_cb and self.quit_cb), which will be called whenever the user clicks that. Those are the real “actions” on our small application.
45: self.statusIcon.connect('popup-menu', self.popup_menu_cb, self.menu) 46: self.statusIcon.set_visible(1) 47: 48: gtk.main()
Now we need to connect the menu with the “pop-up” action from the status icon widget. This also triggers an associated call back method (self.popup_menu_cb) that will show the pop-up menu (line 41 on the code).
Line 48 on the code starts the main GTK iteration, that makes all the visible widgets to show. In this case, the icon now shows on the notification area. Right-click on the icon, and you will see the beautiful pop-up menu.
68: data.popup(None, None, gtk.status_icon_position_menu, 69: 3, time, self.statusIcon)
I would like to make a small comment on that part of the code. The gtk.status_icon_position_menu is a call back method associated with showing up the menu that works as a helper to verify where to position the pop-up menu itself. Without that call back, the pop-up will show exactly below the mouse cursor, exactly where the icon has been clicked. With this call back, the menu beautifully shows below the icon, out of the panel bar (if the panel that holds the notification area is on the top, or above the icon if it’s on the bottom). That looks much more professional.
The quit_cb method on line 61 simply shuts down the whole thing (closes the window, if open, and terminates the tray icon).
Well, I think that’s it! The intention here was just to show you how easy it is to place your application on the notification area, and point you our to the necessary widgets needed for the task. From here, you’re free to create your own applications.
By the way, feel free to comment below, and ask any questions. I’ll be very glad to help you.
See you around!😉