Quantcast
Channel: Planet Ubuntu
Viewing all articles
Browse latest Browse all 17727

Ubuntu App Developer Blog: How to create a Wikipedia Unity lens for Ubuntu

$
0
0

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


Viewing all articles
Browse latest Browse all 17727

Trending Articles