1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
#! /usr/bin/python
from gi.repository import GLib, GObject, Gio
from gi.repository import Dee
from gi.repository import Unity
import urllib2, simplejson, socket
#Set the timeout (in seconds) for http calls. By design, lenses shouldn't take more than 4 seconds to give results or indicate they have failed.
socket.setdefaulttimeout(3)
# The scope dbus id
BUS_NAME = "net.launchpad.scope.information.wikipedia"
class Daemon:
def __init__ (self):
# Create the scope (this matches the path defined in the .scope file)
self.scope = Unity.Scope.new ("/net/launchpad/scope/information/wikipedia")
# Is the scope searchable from the home dash?
self.scope.search_in_global = False
# Connect to the search changed signal (it is fired when the lens is opened for the first time, then for each search change)
self.scope.connect ("search-changed", self.on_search_changed)
# Listen to the lens filters
self.scope.connect ("filters-changed", lambda scope : scope.queue_search_changed(Unity.SearchType.DEFAULT))
# The scope is ready
self.scope.export()
# On each search change, this method is called
def on_search_changed (self, scope, search, search_type, cancellable):
# Get the search string
search_string = search.props.search_string.strip()
print "Search changed to \"%s\"" % search_string
# Get the Dee model (the database used by the lens to store and display search results)
model = search.props.results_model
# Empty the model
model.clear()
# Update the model
self.update_results_model (search_string, model)
# Signal to the lens that the search is finished (the spinning search icon stops)
search.finished()
# Update the model
def update_results_model(self, search, model):
self.wikipedia(search, model)
# This method sends the search string to Wikipedia and brings back results
def wikipedia_search(self,search):
try:
# Replace spaces by | to match the Wikipedia query format
search = search.replace(" ", "|")
# The Wikipedia "opensearch" API ( http://www.mediawiki.org/wiki/API:Opensearch )
url = ("http://en.wikipedia.org/w/api.php?action=opensearch&limit=25&format=json&search=%s" % (search))
# urllib2.urlopen(url) : send the query
# read() : read the results
# simplejson.loads() : we have asked Wikipedia to return the results in json format, we use simplejson to parse them
results = simplejson.loads(urllib2.urlopen(url).read())
print "Searching Wikipedia"
# We return the results list (the use of [1] is specific to Wikipedia json results)
return results[1]
except (IOError, KeyError, urllib2.URLError, urllib2.HTTPError, simplejson.JSONDecodeError):
print "Error : Unable to search Wikipedia"
return []
# This method parses the results and adds them to the model
def wikipedia(self, search, model):
# We iterate through each of the returned results
for i in self.wikipedia_search(search):
# Lens results are made of several things :
# An uri
uri = "http://en.wikipedia.org/wiki/%s" % i
# A title
title = i
# An icon
icon = 'http://upload.wikimedia.org/wikipedia/commons/6/63/Wikipedia-logo.png'
# A comment (optional)
comment = 'Wikipedia article'
# If the uri seems valid, we add the results to the Dee model
if (uri.startswith("http://")):
# uri, icon, category (matching the order of the categories in the lens), mimetype, title, comment, drag and drop uri
model.append(uri, icon, 0, "text/html", title, comment, uri)
# We can append the same result to multiple models, just by changing the category
model.append(uri, icon, 1, "text/html", title, comment, uri)
# The following lines take care of the Bus connexion.
if __name__ == "__main__":
session_bus_connection = Gio.bus_get_sync (Gio.BusType.SESSION, None)
session_bus = Gio.DBusProxy.new_sync (session_bus_connection, 0, None,
'org.freedesktop.DBus',
'/org/freedesktop/DBus',
'org.freedesktop.DBus', None)
result = session_bus.call_sync('RequestName',
GLib.Variant ("(su)", (BUS_NAME, 0x4)),
0, -1, None)
# Unpack variant response with signature "(u)". 1 means we got it.
result = result.unpack()[0]
if result != 1 :
print >> sys.stderr, "Failed to own name %s. Bailing out." % BUS_NAME
raise SystemExit (1)
daemon = Daemon()
GObject.MainLoop().run()
|