One of the most interesting features about the Ubuntu's Unity desktop is that it takes the focus away from just applications and files and moves it towards discovering content. It does this through an interface (called the Dash) that is largely driven by a search window. To enable this system to focus on different content (e.g. to primarily look for music files instead of applications) different tabs appear on the Dash called Lenses. These can aggregate in to a general lens that allow searching across local and remote items in one go. What if this idea could be extended slightly to enable the discovery of Open Educational Resources (OERs)? The user might not have even heard about OERs, so might not think to go looking for them, but having OER discovery built into the operating system gets around this issue and makes every search a chance to learn. So I had a go at building such a Lens.
OERs are in the educational world the rough equivalent of open source software. These are materials that are free to use and to adapt. With the increasing cost of traditional courses, OERs could be the answer to providing people with the level of education that they desire without the financial worry. A great site for searching these is OER Commons where links to courses on all sorts of subject areas can be found.
On the OER Commons site is a search box where you can starting looking for materials. When I tried this I noticed that an RSS feed was also available, and even more usefully it was possible to generate an RSS feed for different subject areas just by manipulating the URL. On the Ubuntu Developer site there is a simple tutorial for creating an Unity Lens to search Wikipedia. So I used this as the basis for a lens that would take the search from Unity and plug it directly into OER Commons, parse the returning RSS feed and display it directly on the desktop. Hopefully this would make it easier to discover OERs. No need to look for a web site about it, Ubuntu will put the search right in front of you. It also could increase the chance to find OERs completely by accident. The Lens I ended up with is shown in the screenshot below, with a search for "history" being performed.
The tutorial on the Ubuntu Developer site uses Quickly to make development of the Lens much easier. Quickly is a rapid application development toolkit for Ubuntu. This hides much of the complexity of developing the lens and leaves us mainly just with the task of building the URL for the search, parsing the results and returning the results to Unity in the right format. Before starting on the application I installed the following packages: quickly, quickly-unity-lens-template and to parse the RSS feed in Python: python-feedparser. Then it was time to open up the terminal and get to work. The command: quickly create unity-lens unity-lens-oercommons creates the basis for our project, entering quickly edit opens up a text editor with all of the project files that we might need to change.
Following the guidance of the tutorial I changed the Meta class to be like this:
class Meta:
name = 'oercommons'
description = 'OER Commons Lens'
search_hint = 'Search OER Commons'
icon = 'oercommons.svg'
search_on_blank=True
Don't worry about the “oercommons.svg” file, a default one is created automatically (although a more appropriate file would look much better). The “search_on_blank” entry is set to true, this is a chance to show some OERs to the user before they even enter a search term. More on this later. Next we need to add a couple of import statements at the top for feedparser and urllib (note not urllib2 as in the Ubuntu tutorial as we will be using it to help build a URL rather that retrieve a web resource).
The results in a Unity search are shown in categories. This is particularly important when it comes to the global search on the first tab. I set up a single category with this line:
oer_category = ListViewCategory("Open Educational Resources", "dialog-information-symbolic")
In the generated code for the lens you will see that a search method has been set up. In the Ubuntu tutorial this calls another search method that returns results. I am going to follow the same pattern here and add a method (below) which constructs the URL to query, then calls the very useful feedparser library with that URL and returns the items for the feed.
def oercommons_search(self, search):
try:
if search=="":
url = "http://www.oercommons.org/courses/material_types/full-course?feed=yes"
else:
url = "http://www.oercommons.org/search?f.search=%s&feed=yes" % (urllib.quote_plus(search))
print url
print "Searching OER Commons for '%s'" % (search)
results = feedparser.parse(url)
return results["items"]
except (IOError, KeyError):
print "Error : Unable to search OER Commons"
return []
You will notice too that a different URL is used when the search term is blank. This currently shows the latest full course items to be added, but could be changed to any RSS feed which shows results which change over time that might be interesting to the user. In the search method we now need to map each result on to a result object that Unity will be expecting.
def search(self, search, results):
for oer in self.oercommons_search(search):
results.append(oer["link"],
"http://www.oercommons.org/media/images/logo.png",
self.oer_category,
"text/html",
oer["title"],
', '.join([ tag["term"] for tag in oer["tags"] ]),
oer["link"])
pass
Here we are saying that the link opened for the resource should be the URL for the item from the feed, the icon used for each result should be the logo from the OER Commons site, that the heading they should appear under is the Open Educational Resources category that we set up earlier, that the content is text/html, a web page which means clicking on the resource will open it in a browser, the title for the resource is the item title from the feed, the description will be the subjects (defined in tags) attached to that resource and lastly the link and lastly that the drag and drop link is the same as the link for the item.
Bizarrely the lens is nearly complete. We just need to define a method for the global lens to call.
def global_search(self, search, results):
print "Searching globally for %s" % (search)
self.search(search, results)
This maps global search onto our existing search, but could be enhanced, e.g. you might want to return more detailed results on the tab for the lens but a summary on the global lens.
To run the lens use the command: sudo quickly install which puts the files in the right places and restarts Unity, then quickly run to use it and see your debug output.
Problems, problems
This exercise did not go as smootly as I would have hoped. When I created the project with Quickly I got this message:
WARNING: Your project is out of date. Newly created projects use
GTK+ 3, PyGI, and GSettings. See https://wiki.ubuntu.com/Quickly/GTK3 for
porting information and when you have finished porting your code, run
'quickly upgrade' to get rid of this message.
If anyone knows how to fix this message please leave a comment! This didn't seem to cause a problem though. Additionally I found that when I ran the project for some reason Unity started complaining that it could not convert the image files for use as icons, but it could after a reboot which was strange. I am not sure if this is because I am not using a fresh install of Ubuntu but one that has been through lots of distribution upgrades. In the end though everything worked so it seems ok.
Sharing
Quickly can create a standard Debian format installer file for you. It even picks up dependencies (e.g. in this case the need to install the python-feedparser package) automatically. This is done with the quickly package command, you can then share your work through a Personal Package Archive on Launchpad. For more details see: http://blog.didrocks.fr/index.php/post/Build-your-application-quickly-with-Quickly%3A-Inside-Quickly-part-9.
Once you install the newly created package, the lens will actually autostart so you do not need to run the script manually. You will however have to log out and then back in again.
There are many ways in which this app could be improved. Different approaches could be taken to discovering OERs through Unity. Maybe even a different approach could be taken entirely! Hopefully though shows though how a user interface on an operating system could be used to bring OERs to the attention of the user. The idea here is to bring the resources to the place where the user currently is rather than trying to get them to go to a destination site in order to discover them.
You can find the complete code for this lens on Launchpad at: https://code.launchpad.net/unity-lens-oercommons, Feel free to check it out and experiment!