The Unity Dash provides a lightweight, instant and easy means to browse and retrieve interesting content. Through the use of lenses, it enables the user to search for information both locally and remotely. In this article you’ll learn how to easily write a lens to comfortably search the Wikipedia right from your desktop.

Requirements

To follow this tutorial, you’ll need the following:

Writing a Wikipedia Unity Lens

Making a lens begins with a simple step to set up the project. Fire up a terminal by pressing the Ctrl+Alt+T key combo, where you can type the commands below.

Create the project

quickly create unity-lens wikipedia
cd wikipedia

Now, let’s code!

quickly edit

This command will open three files in your favourite editor, the one we are going to edit is  __init__.py

The first interesting thing you can see here, is the Meta class. It defines the behaviour of the lens :

class Meta:
    name = 'Wikipedia'
    description = 'Wikipedia Lens'
    search_hint = 'Search Wikipedia'
    icon = 'wikipedia.svg'
    search_on_blank=True

Most of the time, when you make a simple lens, you don’t need to change anything here and in our case, we won’t.

A lens needs categories, which are used to visually separate different types of results. For Wikipedia, we only need one category, and we are going to name it “Articles”.

Below the Meta class, we see this line of code:

example_category = ListViewCategory("Examples", 'help')

We are going to modify it to suit our needs

  • First, we rename the variable to articles_category, for the sake of clarity
  • Then, we have to choose between ListView and IconView, which are different ways of presenting the results inside a category. Let’s keep the default:  ListView
  • We also need to give our category a display name: Articles
  • Finally, we need a decent icon for the category header, and we will choose a stock item from the system: dialog-information-symbolic
articles_category = ListViewCategory("Articles", "dialog-information-symbolic")

Now that we have the architecture of our lens ready, we are going to add what a lens is supposed to do: searching. The default code illustrates how to add results to a lens…

def search(self, search, results):
    # TODO: Add your search results
    results.append('https://wiki.ubuntu.com/Unity/Lenses/Singlet',
                'ubuntu-logo',
                self.example_category,
                "text/html",
                'Learn More',
                'Find out how to write your Unity Lens',
                'https://wiki.ubuntu.com/Unity/Lenses/Singlet')
    pass

…but what we want is to ask results to Wikipedia.

Searching on Wikipedia

Let’s create a new function to search Wikipedia, that we will plug into this one.

We name it wikipedia_query, which sounds appropriate. It will take the string typed by the user in the search bar as an argument. We are also going to need a few Python modules to do the search: urllib2 to do the HTTP call and simplejson to parse the data delivered by Wikipedia.

At the top of the file, with all the other import, we import the modules we need:

import urllib2
import simplejson

Then, inside the WikipediaLens(SingleScopeLens) class, our main class, we add a wiki variable, which will help to simplify the code:

wiki = "http://en.wikipedia.org"

And we create our function :

def wikipedia_query(self, search):

search, is the string typed by the user in the search bar. We need to change it a little before sending it to Wikipedia, by replacing blank spaces with | , as it’s the way Wikipedia understands queries.

search = search.replace(" ", "|")

We now create our query url, using the Wikipedia opensearch API

url = ("%s/w/api.php?action=opensearch&limit=25&format=json&search=%s" % (self.wiki, search))

And we store our returned results in a results variable, they are in json, so we use the simplejson module to turn them into a list.

results = simplejson.loads(urllib2.urlopen(url).read())

We also add a debug line, to show what we are doing.

print "Searching Wikipedia for %s" % (search)

And we finish our work on this function by making it return something.

return results[1]

Our wikipedia_query function should look like this, or almost, as I’ve added a try and an except, to catch eventual errors (network error, results error, etc.). If there is one, it will print an informative debug message and return an empty list of results.

def wikipedia_query(self,search):
    try:
        search = search.replace(" ", "|")
        url = ("%s/w/api.php?action=opensearch&limit=25&format=json&search=%s" % (self.wiki, search))
        results = simplejson.loads(urllib2.urlopen(url).read())
        print "Searching Wikipedia"
        return results[1]
    except (IOError, KeyError, urllib2.URLError, urllib2.HTTPError, simplejson.JSONDecodeError):
        print "Error : Unable to search Wikipedia"
        return []

Next, all we need to do is plugging this new function into our existing search function

def search(self, search, results):
    for article in self.wikipedia_query(search):
        results.append("%s/wiki/%s" % (self.wiki, article),
                    "http://upload.wikimedia.org/wikipedia/commons/6/63/Wikipedia-logo.png",
                    self.articles_category,
                    "text/html",
                    article,
                    "Wikipedia Article",
                    "%s/wiki/%s" % (self.wiki, article))
    pass

Which can be translated as: for each result returned by wikipedia_query, add an article to the lens.
What happens in results.append is really important to understand what we can display in a lens. Here is what we need to pass to Unity for each result:

results.append (url,
            icon,
            category,
            mime-type,
            text,
            comment,
            drag and drop url)

That’s it, your lens is done.

Using the Wikipedia Lens

You can now make it visible in the Dash by typing the following command on the terminal:

sudo quickly install

and run it with

quickly run

It does what it’s supposed to, which is great, but we are going to make it a bit nicer…

Making it nicer

First, the way of displaying results is not appropriate for Wiki results, we don’t need to see “Wikipedia Article” on each one. Let’s change the category to use the IconView:

articles_category = IconViewCategory("Articles", "dialog-information-symbolic")

Then, you may have noticed that it only returns English results, which is fine… if you assume that all your users will speak English. Let’s try to improve this by finding out the user’s session language and ask Wikipedia for this language only.

At the top of our file we need to add a new import : the locale module.

import locale

Then, inside our main class, above the wiki variable, we need to find the user’s locale :

locale.setlocale(locale.LC_MESSAGES, '')
loc = locale.getlocale(locale.LC_MESSAGES)[0].split("_")[0]

loc is now a variable containing a string like  “en”, “fr”, “de”, etc.

We modify our wiki variable to use loc.

wiki = "http://%s.wikipedia.org" % (loc)

And if we run our lens again…

Localized results in your language, as expected from an OS for human beings

Conclusion

This tutorial demonstrated how to easily create lens for the Unity dash to enrich the Ubuntu user experience and provide the ability to search on the wikipedia right from the desktop.

Learn more

Questions?

If you’ve got any questions on this tutorial, or on the technologies that it uses, just ask on Askubuntu!

Oh, and don’t forget to leave your feedback in the comments!

Follow Ubuntu App Development on:

 

Social Media Icons by Paul Robert Lloyd

  • http://abarcarodriguez.com kinduff

    Amazing! This is just amazing!

  • prakash

    never thought i could make lenses myself.
    Very nice.

  • http://muyiscoi.com muyiscoi

    Wow! It’s so easy!! Thanks!

  • http://andrusk.com Justin Andrusk

    Really? Using a browser is too much work for people to look up Wikipedia articles? Bet I could get to the article faster using a browser than the time it takes lens to find it and spawn it ;)

  • KTP

    I agree with above. This will just clutter the search and is rather pointless. Not that I care, i can’t handle Unity. In gnome shell you can add buttons easily in the overview, that will open the browser and do the search for you.. Much better way.

  • XFCE

    What’s unity?

  • A

    I can not get this to work at all without getting indentation errors. Each time I try and format the code, I keep getting a new error. How can I fix this? Any chance to see the completed code?

  • https://login.ubuntu.com/+id/8McftMw Michael Hall

    Justin: This is a demonstration lens, you can make lenses and scopes that search local files or other non-googlable sources.

    A: Python is whitespace sensitive, so if you change the indentation at all it’ll cause an error.

  • aqib

    I want to create this for my website is there anyway to distribute it as a software or something after creating???

  • Mathieu Cossette

    Answer to No. 7 Comments or question I would say .. hihi

    http://paste.ubuntu.com/907519/ … me too I was having difficulties trying to get this code in order but hey… nothing better than copy and paste a finalized code !!!!

    Here you go !!!!!!

  • Mathieu Cossette

    Ohh…. in the end no results with my query …. it is weird

  • http://danilo.segan.org/ Danilo

    Heya David, nice work :)

    You can replace those two locale fetching lines with one:

    loc = locale.setlocale(locale.LC_MESSAGES, ”).split(‘_’)[0]

    (setlocale also returns the locale it has just set, no need to use getlocale, which is probably internally implemented in terms of setlocale(cat, None) anyway)

  • Jeycoff

    No tts no good!

  • Pingback: How to create a Wikipedia lens (official tutorial) | Dark-Code

  • A

    Solved the whitespace issue but now this lens only works while the terminal remains open after running “quickly install”. Stops working when the terminal is closed. How is this solved?

  • Pingback: Como crear nuestro propio Wikipedia Unity Lens en Ubuntu | Ayuda Linux

  • http://gotwig.tk Eduard Gotwig

    A:

    the lens (and scope part) works only while your terminal is open, becouse its a deamon. or it should be.

    So you have to add it to the daemon list of startup applications.

    (see your task manager for other unity lenses & scopes that run in the background)

  • SuperEngineer

    Having done all of the steps – yes – it is a good lens.
    BUT…

    it is of absolutely ZERO use if not able to run automatically at start up….
    without that last bit of the info it has put me back off off of coding/hacking rather than getting back into it.

    Sorry – fail.

  • Pingback: Realizando buscas na Wikipdia diretamente no Dash do Unity | Blog Seja Livre

  • Jo-Erlend Schinstad

    This is awesome stuff! The one question I have, is what does “quickly install” do? Because that’s not something Quickly normally does. What I would expect from a Quickly template is to be able to use “quickly package”, “quickly share”, etc. Then the user would install the deb as usual. But that can be fixed! :)

    It would be nice if the article could be updated to explain that point.

  • Jo-Erlend Schinstad

    I just wanted to add that Lenses, like everything else in Unity, is specifically designed not to depend on the Unity shell. I will expect to see Dash implementations in the form of plugins and applets for LXDE, Xfce, KDE, and all the other desktops. Then all lenses will automatically work, regardless of your environment. Of course, these technologies are brand new, so it’ll take a little time.

    In other words; even if you don’t like the Unity implementation, that’s no reason not to use Indicators, Lenses, etc.

  • http://www.mhall119.com Michael Hall

    Unity will only pick up a lens if it’s .lens file is in /usr/share/unity/lenses//, so before you can even run your lens locally we need to copy that file there. Furthermore, Unity only scans these at startup, so we need to restart Unity after adding or removing a lens before those changes will take affect. “quickly install” does both of those things for you, so that “quickly run” will actually work.

  • Pingback: Ubuntu Weekly Newsletter Issue 261 | Ubuntu Linux FAQs

  • Jo-Erlend Schinstad

    In an updated 12.04 system, I did a quick test, simply running quickly create unity-lens wikipedia, then sudo quickly install and then quickly run. The lens shows up, but when I try to search, I get a warning about missing dbus .service files, and there’s no results:

    WARN 2012-04-17 00:25:50 unity.glib.dbusproxy GLibDBusProxy.cpp:283 Calling method “Search” on object path: “/unity/singlet/lens/wikipedia” failed: GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown: The name unity.singlet.lens.wikipedia was not provided by any .service files

  • ihashacks

    unity.glib.dbusproxy GLibDBusProxy.cpp:283 Calling method “SetViewType” on object path: “/unity/singlet/lens/wikipedia” failed: GDBus.Error:org.freedesktop.DBus.Error.UnknownMethod: No such interface `com.canonical.Unity.Lens’ on object at path /unity/singlet/lens/wikipedia

    AND

    unity.iconloader IconLoader.cpp:536 Unable to load icon http://upload.wikimedia.org/wikipedia/commons/6/63/Wikipedia-logo.png at size 64: Operation not supported

  • Pingback: How do I compile a Wikipedia lens and install? | MoVn - Linux Ubuntu Center

  • Pingback: moeblog » Lente Unity para SSH

  • http://www.mhall119.com Michael Hall

    Jo-Erland, did you leave “quickly run” running? If there isn’t an active process using the dbus name specified in the .lens file, Unity will try to find a .service file in /usr/share/dbus-1/services/ for it. But if you leave “quickly run” running, Unity will use that for searching.

  • Jo-Erlend Schinstad

    I did leave it running, yes.

  • Jo-Erlend Schinstad

    Disregard my previous comments. It was my mistake exclusively. The software works as intended! :)

  • Pingback: Ubuntu News Watch | How to create a Wikipedia Unity lens for Ubuntu

  • ConfusedUser

    No offense, but this is COMPLETELY useless. It is not able to run automatically unless you do “quickly run”.

  • Carles Oriol

    Is there any way to define a process for the service? or it has to be done manually?

  • T_W

    I also am getting the error:

    WARN 2012-05-09 22:12:05 unity.glib.dbusproxy GLibDBusProxy.cpp:283 Calling method “Search” on object path: “/unity/singlet/lens/wikipedia” failed: GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown: The name unity.singlet.lens.wikipedia was not provided by any .service files

    ‘quickly run’ is still running. Jo-Erlend how did you resolve this?

  • Hitesh

    This doesnt works for me.

  • Pingback: Unity fails to load external icons in lens | PHP Developer Resource

  • Pingback: Unity fails to load external icons in lens | MoVn - Linux Ubuntu Center

  • Vishnu V

    hi,
    how to execute a command when we select an entry from unity-lens
    results.append(url,icon,
    category,
    mime-type,
    text,
    comment,
    drag and drop url)
    i tried to set file://, but it opens the file with text editor (if it is not readable with text editor it do nothing)
    Please help

    Thank you
    Vishnu V

  • thediex

    We want an app that makes it automatically!

  • Pingback: Wikipedia lens example broken | MoVn - Linux Ubuntu Center

  • Michal

    Please add the app for software center.

  • Kevin

    Thanks for this great tutorial. Is it possible to make a lens auto refresh the data when search term is empty (ie “”). Currently, I have to type spacebar and backspace (any key would work) to see the changes but I want to see new data as long as I click on the lens.

    I have tried if (search == “”) or (search != “”): in the scope but still no affect when I click on the lens.