Ubuntu – Using Gtk.Widgets in App Indicators with Python

application-developmentindicatorpython

In 2010 Stefano Palazzo , asked a related question, Putting an arbitrary gtk.Widget into an appindicator.Indicator, and similar one was asked on StackOverflow. In both cases the consensus is that Ubuntu's App Indicators are limited. As Michael Ekstrand put it:

The Application Indicator menu support is based on D-Bus menus, which
are limited in what they support – they only support basic menu
functionality, not more exotic things such as arbitrary widgets.

However, it contradicts what we see in Bluetooth indicator today, in 2016: it uses toggle switches.

enter image description here

Same could be observed with Ubuntu One indicator from 13.04:

enter image description here

So obviously there is a way. I've studied indicator-bluetooth source code, but it's written in Vala. I,however, work primarily in python, and learning Vala just to rewrite all of my already existing indicators is a bit too much work.

So the core of the question : How can one use Gtk.Widgets, or at the very minimum a toggle switch just like in the Bluetooth indicator, using Python ?

NOTE: I am willing to put bounty on this question to reward an answer which will provide a working example in python. Other languages are not accepted.

Best Answer

This problem exists because while AppIndicators make it easy to create an indicator menu, they do get in the way of making one. Let's look at the differences between example python code using AppIndicator and one using GLib Menus the way the Bluetooth code does.

Firstly you're instructed to make a gtk.Menu, these are old style Gtk menu objects that use Gtk.Action that are now deprecated. AppIndicator takes the gtk.Menu object from you during the set_menu(...) process and parses it, pushing each of the menus it finds onto the indicator service created using libdbusmenu. This process of parsing means that anything not supported by AppIndicator is filtered out, no matter what you do.

Next let's look at the Bluetooth menu. That's created using Gio.Menu objects, these are new style Gnome menus using the GAction system. It then registered it's own service without using AppIndicator or libdbusmenu and set's it's up using a custom x-canonical-type property to create the switch widget which is passed to libido for parsing.

This whole exercise is pretty bad, since it's all Canonical's own Unity customisations. So as soon as unity goes, there's no appindicators anyway.