Merge lp:~frederik-elwert/askubuntu-lens/add_texdoc_scope into lp:askubuntu-lens

Proposed by Frederik Elwert
Status: Merged
Merge reported by: Mark Tully
Merged at revision: not available
Proposed branch: lp:~frederik-elwert/askubuntu-lens/add_texdoc_scope
Merge into: lp:askubuntu-lens
Diff against target: 311 lines (+249/-0)
7 files modified
.bzrignore (+2/-0)
debian/control (+21/-0)
debian/unity-scope-texdoc.install (+3/-0)
scopes/texdoc/unity-scope-texdoc.scope (+5/-0)
scopes/texdoc/unity-scope-texdoc.service (+3/-0)
scopes/texdoc/unity-texdoc-daemon (+212/-0)
setup.py (+3/-0)
To merge this branch: bzr merge lp:~frederik-elwert/askubuntu-lens/add_texdoc_scope
Reviewer Review Type Date Requested Status
Mark Tully Approve
Review via email: mp+114981@code.launchpad.net

Description of the change

I added a scope for searching texdoc. This is packaged as a separate package unity-scope-texdoc.

I did not yet add apparmor support, as I am not very familiar with it. I could need some advice as if this should be added to the scope and how.

To post a comment you must log in.
57. By Frederik Elwert

Handle additional exception when retrieving PDF titles.

Revision history for this message
Mark Tully (markjtully) wrote :

Apologies for the really long delay. I've finally got around to doing something about this.

I've created a new source package called unity-lens-help-extras (https://code.launchpad.net/~markjtully/askubuntu-lens/extras) to contain scopes not included in quantal's universe repositories and added this scope and a devhelp scope to it (so far). These are now available either for installation via my PPA or the askubuntu-tools PPA (https://code.launchpad.net/~askubuntu-tools/+archive/ppa).

I've removed all the apparmor stuff from all these scopes for now as it was really only required for submission to the software centre.

Setting this to merged (even though it has been merged to a different branch than specified)

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2012-06-21 23:43:09 +0000
3+++ .bzrignore 2012-07-20 23:01:30 +0000
4@@ -19,3 +19,5 @@
5 ./debian/unity-scope-asklibreoffice
6 ./debian/unity-scope-asklibreoffice.debhelper.log
7 ./debian/unity-scope-manpages.debhelper.log
8+./debian/unity-scope-texdoc
9+./debian/unity-scope-texdoc.debhelper.log
10
11=== modified file 'debian/control'
12--- debian/control 2012-07-11 20:15:00 +0000
13+++ debian/control 2012-07-20 23:01:30 +0000
14@@ -67,6 +67,27 @@
15 computer. After installing this scope,
16 you will need to log out and log back in again in order to use it.
17
18+Package: unity-scope-texdoc
19+Enhances: unity-lens-help
20+Architecture: all
21+Depends: ${misc:Depends},
22+ python2.7 | python2.6,
23+ python (>= 2.6),
24+ python (<< 2.8),
25+ gir1.2-unity-5.0,
26+ gir1.2-dee-1.0,
27+ unity-lens-help,
28+ texlive-base
29+Suggests: apparmor (>= 2.3), python-pypdf
30+XB-AppName: TexDoc Scope
31+XB-Icon: icons/help-lens-logo.png
32+XB-Screenshot-Url: http://software-center.ubuntu.com/site_media/screenshots/2012/01/usc-screenshot.png
33+XB-Category: Accessories;
34+Description: TeXDoc scope for Help Lens
35+ A scope for the Unity Help Lens to search TeX documentation on your
36+ computer. After installing this scope,
37+ you will need to log out and log back in again in order to use it.
38+
39 Package: unity-scope-sumo
40 Enhances: unity-lens-help
41 Architecture: all
42
43=== added file 'debian/unity-scope-texdoc.install'
44--- debian/unity-scope-texdoc.install 1970-01-01 00:00:00 +0000
45+++ debian/unity-scope-texdoc.install 2012-07-20 23:01:30 +0000
46@@ -0,0 +1,3 @@
47+usr/lib/unity-lens-help/unity-texdoc-daemon
48+usr/share/dbus-1/services/unity-scope-texdoc.service
49+usr/share/unity/lenses/help/unity-scope-texdoc.scope
50
51=== added directory 'scopes/texdoc'
52=== added file 'scopes/texdoc/unity-scope-texdoc.scope'
53--- scopes/texdoc/unity-scope-texdoc.scope 1970-01-01 00:00:00 +0000
54+++ scopes/texdoc/unity-scope-texdoc.scope 2012-07-20 23:01:30 +0000
55@@ -0,0 +1,5 @@
56+[Scope]
57+DBusName=net.launchpad.scope.help.texdoc
58+DBusPath=/net/launchpad/scope/help/texdoc
59+ScopeIdentifier=texdoc
60+ScopeName=TeXDoc
61
62=== added file 'scopes/texdoc/unity-scope-texdoc.service'
63--- scopes/texdoc/unity-scope-texdoc.service 1970-01-01 00:00:00 +0000
64+++ scopes/texdoc/unity-scope-texdoc.service 2012-07-20 23:01:30 +0000
65@@ -0,0 +1,3 @@
66+[D-BUS Service]
67+Name=net.launchpad.scope.help.texdoc
68+Exec=/usr/lib/unity-lens-help/unity-texdoc-daemon
69
70=== added file 'scopes/texdoc/unity-texdoc-daemon'
71--- scopes/texdoc/unity-texdoc-daemon 1970-01-01 00:00:00 +0000
72+++ scopes/texdoc/unity-texdoc-daemon 2012-07-20 23:01:30 +0000
73@@ -0,0 +1,212 @@
74+#!/usr/bin/python
75+# -*- coding: utf-8 -*-
76+
77+"""
78+# Copyright (C) 2012 Frederik Elwert <frederik.elwert@web.de>
79+# 2012 Pawel Stolowski <stolowski@gmail.com>
80+# 2012 Mark Tully <markjtully@gmail.com>
81+
82+# This program is free software: you can redistribute it and/or modify
83+# it under the terms of the GNU General Public License as published by
84+# the Free Software Foundation, either version 3 of the License, or
85+# (at your option) any later version.
86+
87+# This program is distributed in the hope that it will be useful,
88+# but WITHOUT ANY WARRANTY; without even the implied warranty of
89+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
90+# GNU General Public License for more details.
91+
92+# You should have received a copy of the GNU General Public License
93+# along with this program. If not, see <http://www.gnu.org/licenses/>.
94+"""
95+
96+import sys
97+import re
98+import os.path
99+from subprocess import Popen, PIPE
100+from mimetypes import guess_type
101+from HTMLParser import HTMLParser
102+
103+try:
104+ from pyPdf import PdfFileReader
105+ from pyPdf.utils import PdfReadError
106+ pdf_available = True
107+except ImportError:
108+ pdf_available = False
109+
110+# Unity imports
111+from gi.repository import GLib
112+from gi.repository import GObject
113+from gi.repository import Gio
114+from gi.repository import Gtk
115+from gi.repository import Unity
116+
117+BUS_NAME = "net.launchpad.scope.help.texdoc"
118+
119+EVERYTHING = 0
120+OFFICIAL = 1
121+COMMUNITY = 2
122+TECHNICAL = 3
123+TAGS = 4
124+
125+TEXDOC_RE = re.compile('^\s*(\d+)\s+(.+?)$')
126+
127+
128+class Daemon (object):
129+ """ Manpages Daemon searches manpages for results matching query
130+ """
131+ def __init__(self):
132+ """ Sets up the texdoc scope
133+ """
134+ self.scope = Unity.Scope.new("/net/launchpad/scope/help/texdoc")
135+
136+ # Listen for changes and requests
137+ self.scope.props.search_in_global = False
138+ self.scope.connect("search-changed", self.on_search_changed)
139+ self.scope.connect("filters-changed", self.on_filters_changed)
140+ self.scope.connect("notify::active", self.on_lens_active)
141+ self.scope.export()
142+
143+ def on_filters_changed(self, *_):
144+ """ Called when a filter is clicked. Queue's a new search
145+ """
146+ self.scope.queue_search_changed(Unity.SearchType.DEFAULT)
147+
148+ def on_lens_active(self, *_):
149+ """ Called when the lens is activated. Queue's a new search
150+ """
151+ if self.scope.props.active:
152+ self.scope.queue_search_changed(Unity.SearchType.DEFAULT)
153+
154+ def on_search_changed(self, scope, search=None, search_type=0, cancellable=None):
155+ """ Called when the search is changed. Gets the search string and search
156+ type and passes it to update_results_model()
157+ Args:
158+ scope: a scope object
159+ search: the search string
160+ search_type: the search type (global or local)
161+ cancellable: cancellable object
162+ """
163+ if hasattr(search, "props"):
164+ search_string = search.props.search_string
165+ else:
166+ search_string = ""
167+
168+ if search_type == Unity.SearchType.DEFAULT:
169+ results = scope.props.results_model
170+ else:
171+ results = scope.props.global_results_model
172+
173+ print "Search changed to: '%s'" % search_string
174+ self.update_results_model(search_string, results)
175+ if hasattr(search, "finished"):
176+ search.finished()
177+
178+ def update_results_model(self, search, model, _global=False):
179+ """ Takes the search string and runs apropos <search string>
180+ Parses its results and adds them to the model
181+ Args:
182+ search: the search string
183+ model: the model object that results are added to
184+ """
185+ model.clear()
186+
187+ scope_active = False
188+ e = self.scope.get_filter("sources")
189+ if not e.props.filtering:
190+ scope_active = True
191+ for source in e.options:
192+ if source.props.id == "texdoc":
193+ if source.props.active:
194+ scope_active = True
195+
196+ if scope_active:
197+ result = []
198+ if len(search) > 2: # don't run texdoc for strings shorter than 3 chars
199+ proc = Popen(["texdoc", "--list", "--nointeract", search],
200+ stdout=PIPE)
201+ os.waitpid(proc.pid, 0)
202+ out = proc.communicate()[0]
203+ for line in out.splitlines():
204+ m = TEXDOC_RE.match(line)
205+ if m:
206+ result.append(m.group(2))
207+ for res in result:
208+ info = self.get_file_info(res)
209+ if info['mimetype']:
210+ # Only handle known file types, otherwise we might get
211+ # Makefiles and things like that.
212+ model.append(info['uri'], info['icon'].to_string(),
213+ TECHNICAL, info['mimetype'], info['filename'],
214+ info['title'], info['uri'])
215+
216+ def get_file_info(self, filepath):
217+ info = {}
218+ info['uri'] = 'file://' + filepath
219+ info['filename'] = os.path.basename(filepath)
220+ info['mimetype'] = guess_type(info['uri'])[0] or ''
221+ if info['mimetype']:
222+ info['icon'] = Gio.content_type_get_icon(info['mimetype'])
223+ if info['mimetype'] == 'application/pdf' and pdf_available:
224+ info['title'] = self.get_pdf_title(filepath)
225+ elif info['mimetype'] == 'text/html':
226+ info['title'] = self.get_html_title(filepath)
227+ else:
228+ info['title'] = ''
229+ else:
230+ info['icon'] = Gio.ThemedIcon.new('text-x-generic')
231+ info['title'] = ''
232+ return info
233+
234+ def get_pdf_title(self, filepath):
235+ with open(filepath, 'rb') as pdffile:
236+ reader = PdfFileReader(pdffile)
237+ try:
238+ return reader.documentInfo.title or ''
239+ except (PdfReadError, AttributeError):
240+ return ''
241+
242+ def get_html_title(self, filepath):
243+
244+ class HTMLTitleParser(HTMLParser):
245+ def __init__(self):
246+ HTMLParser.__init__(self)
247+ self.is_title = False
248+ self.title_complete = False
249+ self.title = ''
250+ def handle_starttag(self, tag, attrs):
251+ if tag == 'title':
252+ self.is_title = True
253+ def handle_data(self, data):
254+ if self.is_title:
255+ self.title += data
256+ def handle_endtag(self, tag):
257+ if tag == 'title':
258+ self.title_complete = True
259+ self.is_title = False
260+
261+ with open(filepath, 'r') as htmlfile:
262+ parser = HTMLTitleParser()
263+ for line in htmlfile:
264+ parser.feed(line)
265+ if parser.title_complete:
266+ return parser.title
267+ return ''
268+
269+
270+if __name__ == "__main__":
271+ session_bus_connection = Gio.bus_get_sync(Gio.BusType.SESSION, None)
272+ session_bus = Gio.DBusProxy.new_sync(session_bus_connection, 0, None,
273+ 'org.freedesktop.DBus', '/org/freedesktop/DBus',
274+ 'org.freedesktop.DBus', None)
275+ result = session_bus.call_sync('RequestName',
276+ GLib.Variant("(su)", (BUS_NAME, 0x4)), 0, -1, None)
277+ result = result.unpack()[0]
278+ # We could try to do some automated rescue when this happens:
279+ if result != 1:
280+ print >> sys.stderr, "Failed to own name %s. Bailing out." % BUS_NAME
281+ print >> sys.stderr, "Do you have another instance running?"
282+ raise SystemExit(1)
283+ daemon = Daemon()
284+ print "entering the main loop"
285+ GObject.MainLoop().run()
286
287=== modified file 'setup.py'
288--- setup.py 2012-07-11 20:23:45 +0000
289+++ setup.py 2012-07-20 23:01:30 +0000
290@@ -18,6 +18,7 @@
291 'scopes/yelp/unity-lens-help-daemon',
292 'scopes/askubuntu/unity-askubuntu-daemon',
293 'scopes/manpages/unity-manpages-daemon',
294+ 'scopes/texdoc/unity-texdoc-daemon',
295 'scopes/sumo/unity-sumo-daemon',
296 'scopes/asklibreoffice/unity-asklibreoffice-daemon',
297 ],
298@@ -25,11 +26,13 @@
299 ('/usr/share/unity/lenses/help', ['scopes/yelp/help.lens',
300 'scopes/askubuntu/unity-scope-askubuntu.scope',
301 'scopes/manpages/unity-scope-manpages.scope',
302+ 'scopes/texdoc/unity-scope-texdoc.scope',
303 'scopes/sumo/unity-scope-sumo.scope',
304 'scopes/asklibreoffice/unity-scope-asklibreoffice.scope']),
305 ('/usr/share/dbus-1/services', ['scopes/yelp/unity-lens-help.service',
306 'scopes/askubuntu/unity-scope-askubuntu.service',
307 'scopes/manpages/unity-scope-manpages.service',
308+ 'scopes/texdoc/unity-scope-texdoc.service',
309 'scopes/sumo/unity-scope-sumo.service',
310 'scopes/asklibreoffice/unity-scope-asklibreoffice.service']),
311 ('/etc/apparmor.d', ['scopes/yelp/usr.lib.unity-lens-help.unity-lens-help-daemon',

Subscribers

People subscribed via source and target branches

to all changes: