23

The application in question does some action (here connecting audio to network streams) and runs minimized if these actions were successful. Therefore a status icon is needed to display the state of the connection (e.g. CONNECTED/DISCONNECTED). Only when clicking the icon the application window will open to give access to further options.

Using Python 2.6 and pyGtk I conveniently realised this by using gtk_status_icon. I deliberately wrote the application to run on as many distributions as possible including the various Ubuntu versions. I took care to use possible dependencies only after the user had installed them.

However now I hear that gtk_status_icon will no longer be supported in future Ubuntu releases. Developers are asked to use Application Indicators instead. What is then best practise to make sure that:

  1. The application's local icons are displayed properly
  2. The application will still run and display it's icons in future Ubuntu releases.
  3. The application will also run and display it's icons in other environments where indicator-applet, libappindicator, and python-appindicator are not provided.

Application Indicator fallback mechanisms to gtk_status_icon won't work if indicator-applet is not running. Python interpreters will not run if there was no appindicator module to import from. Do I need to develop different versions for different distributions or is there a better way to come around this.

Where do I find a documentation on how to use ApplicationIndicator other than in the example given in Ubuntu Wiki? What commands are provided to check if indicator-applet is running to avoid programming different source codes for Ubuntu vs. non-Ubuntu distributions?

Jorge Castro
  • 71,754
Takkat
  • 142,284

4 Answers4

16

I think that the need here is actually more determining of the python-appindicator library is present. If it is present, it will support all the fallback cases that you need. It will handle XFCE, KDE and older GNOME appropriately. Good example of how to do it in this answer.

The appindicator library will use DBus to check if the application indicator rendering process is available. This will be the case on Unity, or if the indicator-applet is running. If it is available it will use that, if not, it will fallback to using a GtkStatusIcon with the same menu.

Unfortunately, I believe you'd have to keep both code paths if you want to handle the case of the library not being available. Though, we'd be happy to help get the library in other distros :)

Ted Gould
  • 3,425
  • Thank you for this very clear answer. This points to the path I will have to go if I want my app running in 11.04. I do have a working path for GtkStatusIcon but will need to develop the whole thing again for indicator-applet. If I understood your comment to bug #668375 I can possibly use my local icons without having to create a whole icon theme, can I? – Takkat Nov 15 '10 at 17:00
  • Having had the time to dive into AppIndicator programming I found that using jgoguen's suggestion to check for appindicator module does not really help, because custom Icons won't render in 10.04 LTS. See my comments to bug #668375. – Takkat Dec 29 '10 at 10:20
  • My answer includes a very easy way to solve this problem. It's worked very well for my app and has even made it painless to port an app that uses AppIndicators to Windows! – Nathan Osman May 11 '11 at 00:07
10

I have an excellent solution that has worked well in StackApplet - I created a functionally-equivalent version of the appindicator module that uses gtk.StatusIcon internally to provide identical functionality when the real module does not exist.

Using it is as simple as:

  1. Downloading the following file and call it appindicator_replacement.py
  2. Adding the following to your application:

    try:
        import appindicator
    except ImportError:
        import appindicator_replacement as appindicator
    

That's it! Now your application will run perfectly with or without support for AppIndicators. It will even run on Windows, assuming you don't have any other platform-specific code.


Note: the file is released under the MIT license - so you can use it pretty much for anything.

Nathan Osman
  • 32,155
9

You will need to write code for both. You can detect the presence of appindicator in your Python code using something similar to:

have_appindicator = True
try:
    import appindicator
except:
    have_appindicator = False

From there, use have_appindicator to decide whether you should use appindicator code or gtk_status_icon code.

Unfortunately, this also means you will need to have both an Ubuntu and another environment to test with.

jgoguen
  • 99
  • 1
    Still, there may be environments where python-appindicator is installed but indicator applet is not running. The application would need to handle this too. – Takkat Nov 14 '10 at 14:27
  • For that case see https://wiki.ubuntu.com/DesktopExperienceTeam/ApplicationIndicators > Custom Fallbacks. Per default, you'll get a gtk.StatusIcon for the application indicator if there's no indicator applet present. – htorque Nov 14 '10 at 15:14
  • I am aware of the fallback option. What I don't understand is, if indicator-applet is not running how can indicator-applet provide a fallback? – Takkat Nov 14 '10 at 15:51
  • I imagine that it simply checks for indicator-applet and provides gtk_status_icon functionality behind the scenes. – jgoguen Nov 14 '10 at 22:42
  • 1
    @jgoguen: what is "it"? I understand that from 11.04 Ubuntu/Unity will not support gtk_status_icon any more. Other distributions may not have "it". I'm really worried about this. – Takkat Nov 15 '10 at 07:56
  • @user3940 "it" refers to appindicator, the Python library that handles Application Indicators. I don't think you'll need to consider much else for Ubuntu 11.04 onward - indicator-applet is mandatory and so will be running, and the "alternate scenario" code I gave already can be used to work with other platforms that don't have Application Indicators at all. – jgoguen Nov 15 '10 at 20:25
  • @jgoguen: unfortunately won't work with 10.04 LTS :( – Takkat Dec 29 '10 at 10:21
3
for line in os.popen("ps xa"): 
fields = line.split() 
pid = fields[0] 
process = fields[4]

applet_is_running = ( process.find('indicator-applet') > 0 )

This way you can detect if indicator applet is running. You don't need to worry about Ubuntu 11.04 because this won't be the case. There are no fallback scenario because indicator-applet is a mandatory component, running by default.

OpenNingia
  • 3,303
  • Thank you for your pointing to getting the PID of indicator-applet (I do this already for other possible dependencies by using pidof), this would be an admittedly less elegant way if nothing better was available. As far as I can see indicator-applet is reliably running with unity only if hardware requirements are met. Users will be able to boot into 2D GNOME and could decide not to run indicator-applet. However this may not by my problem then. – Takkat Nov 15 '10 at 10:15
  • I agree with you that it may not be 'elegant' ( but you can add all the cosmetic you want :D ) however it should work. Personally I prefer solutions that works well and elegance comes second :) – OpenNingia Nov 15 '10 at 11:09
  • This task does not seem to be running on my 14.04 system. Has the approach been superceded? There are a lot of /usr/lib/x86_64-linux-gnu/indicator-messages/indicator-messages-service tasks instead. – halfer Nov 22 '15 at 00:43