How to create Ubuntu indicator with Python

Default featured post

For a long period of time, I wanted to make a simple Ubuntu unity indicator just to learn how they work. Finally in Christmas holidays I got a chance to search on the internet and came up with a simple idea of having a weather indicator. The result was great and I have ended up with a new project called Ubuntu Indicator Weather.

To begin with, I recommend to have some background about Python because it turns the entire process to having piece of cake. I am a Java programmer, though learned basic Python programming a year ago and that time I considered my time wasted. Now, the usefulness of having basic knowledge of Python revealed in this project.
Apart from Python, different languages such as C++ (QT), C# (Mono) are available.
Now, let’s get started. First step is to import GTK and appindicator libraries to your Python code like below.

import gtk
import appindicator
view raw test.py hosted with ❤ by GitHub

Then need to initialize the indicator and set icon for it which can be either default Ubuntu ones or your desired icon.
Basically, the code looks like this,

def __init__(self): #1
self.ind = appindicator.Indicator("weather-indicator", "weather-clear", appindicator.CATEGORY_APPLICATION_STATUS) #2
self.ind.set_status(appindicator.STATUS_ACTIVE) #3
self.menu_setup() #4
self.ind.set_menu(self.menu) #5
view raw test.py hosted with ❤ by GitHub

Line 1 is basically constructor of the class which has nothing especially. Line 2 is initializing indicator, the first parameter is your indicator name, second is icon name (in the above code default Ubuntu is used), the third is a fixed variable for now. To get list of default Ubuntu icons, refer to this path in Ubuntu systems.

/usr/share/icons/
view raw test.sh hosted with ❤ by GitHub

Line number 3 and 4 are setting status of the indicator and calling creating menu function respectively, which is covered later. Lastly, line 5 add created menu by menu_setup to indicator variable.
Let’s have a look how menu is created,

def menu_setup(self): #1
self.menu = gtk.Menu() #2
self.quit_item = gtk.MenuItem("Quit") #3
self.quit_item.connect("activate", self.quit) #4
self.quit_item.show() #5
self.menu.append(self.quit_item) #6
self.temp_item = gtk.MenuItem("") #7
self.temp_item.show() #8
self.menu.append(self.temp_item) #9
view raw test.py hosted with ❤ by GitHub

Line 1 is function declaration apparently. Line 2 is loading gtk menu function. Line 3 is creating a menu item with a label Quit. Line 4 which is very important is setting action for quit_item when is clicked. In the code function quit is called. Line 5 and 6 is showing item menu and append it to main menu which will be assigned to indicator as demonstrated in above. Line 7 is creating a new item menu with empty label and line 8 and 9 have basically identical functionalities with line 5 and 6.
Almost everything is done, just need to have a function to start gtk main function. This is done in a function called main. The code looks like following,

def main(self):
self.get_weather()
gtk.timeout_add(PING_FREQUENCY * 60000, self.get_weather) #3
gtk.main()
view raw test.py hosted with ❤ by GitHub

The only important part is line 3 which defines how often a certain function (get_weather) should be called to update indicator value.
The entire code entire indicator code looks like this,

#! /bin/sh
""":"
exec python $0 ${1+"$@"}
"""
import sys
import gtk
import appindicator
import urllib
import json
PING_FREQUENCY = 10 # minutes
class GetWeather:
def __init__(self):
self.ind = appindicator.Indicator("weather-indicator",
"weather-clear", appindicator.CATEGORY_APPLICATION_STATUS)
self.ind.set_status(appindicator.STATUS_ACTIVE)
self.menu_setup()
self.ind.set_menu(self.menu)
def menu_setup(self):
self.menu = gtk.Menu()
self.quit_item = gtk.MenuItem("Quit")
self.quit_item.connect("activate", self.quit)
self.quit_item.show()
self.menu.append(self.quit_item)
self.temp_item = gtk.MenuItem("")
#self.temp_item.connect("activate")
self.temp_item.show()
self.menu.append(self.temp_item)
def main(self):
self.get_weather()
gtk.timeout_add(PING_FREQUENCY * 60000, self.get_weather)
gtk.main()
def quit(self, widget):
sys.exit(0)
def get_weather(self):
country,city = self.get_location()
url = 'http://api.openweathermap.org/data/2.5/weather?appid=c15e2598880e57fad011a64061948fac&q=' + country + ',' + city + '&units=metric'
u = urllib.urlopen(url)
data = u.read()
#print data
j = json.loads(data)
temp = j['main']['temp']
print temp
degree = u"\u2103"
rtn_val = str(temp) + degree + ' ' + city
self.ind.set_label(rtn_val)
self.temp_item.get_child().set_text(rtn_val)
return True
def get_location(self):
try:
url = 'http://ipinfo.io/json/'
u = urllib.urlopen(url)
data = u.read()
j = json.loads(data)
country = j['country']
city = j['city']
return (country,city)
except:
return False,0
if __name__ == "__main__":
indicator = GetWeather()
indicator.main()
view raw test.py hosted with ❤ by GitHub

In the above code two web services are called. For this case, urlib and JSON libraries are utilized to call web services and parsing returned JSON values.
Keep in mind to not copy the above code directly to your editor as it might not work due to indentation. You can get working code from GitHub on this link


For making Python code executable, you have few options which I highly recommend you to look at this link and if you don’t like reading and preferring video tutorials have a look at this video. The code of the video is also available here and YouTube channel which I quite like it.

Last but not least, if you are interested to make your indicator be auto start up, you need to create a file like this,

[Desktop Entry]
Type=Application
Name=Indicator Weather
Exec=/usr/bin/indicator-weather
NoDisplay=true
StartupNotify=false
Terminal=false
OnlyShowIn=Unity;GNOME;
AutostartCondition=GNOME3 unless-session gnome
X-Ubuntu-Gettext-Domain=indicator-weather
view raw test.py hosted with ❤ by GitHub

Important parameters are Name which is indicator name, Exec where script is located.

After that you need to copy this file and paste it in /etc/xdg/autostart. Have a look at this link for better understanding.