Merge lp:~frederik-elwert/lens-cooking/chefkoch-scope into lp:lens-cooking

Proposed by Frederik Elwert
Status: Merged
Approved by: Eduard Gotwig
Approved revision: 44
Merge reported by: Eduard Gotwig
Merged at revision: not available
Proposed branch: lp:~frederik-elwert/lens-cooking/chefkoch-scope
Merge into: lp:lens-cooking
Diff against target: 331 lines (+233/-13)
8 files modified
chefkoch.scope (+3/-0)
chefkoch.svg (+71/-0)
debian/unity-lens-cooking.install (+7/-4)
setup.py (+9/-2)
unity-lens-cooking (+7/-5)
unity-scope-chefkoch (+131/-0)
unity-scope-chefkoch.service (+3/-0)
unity-scope-gourmet (+2/-2)
To merge this branch: bzr merge lp:~frederik-elwert/lens-cooking/chefkoch-scope
Reviewer Review Type Date Requested Status
Eduard Gotwig Approve
Review via email: mp+106897@code.launchpad.net

Description of the change

Added scope for chefkoch.de and added this as a new category to the lens.

To post a comment you must log in.
Revision history for this message
Eduard Gotwig (gotwig) wrote :

Approved, thank you for your big help :-)!

review: Approve
Revision history for this message
Eduard Gotwig (gotwig) wrote :

I am going to merge this in 5 hours.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'chefkoch.scope'
2--- chefkoch.scope 1970-01-01 00:00:00 +0000
3+++ chefkoch.scope 2012-05-22 20:35:21 +0000
4@@ -0,0 +1,3 @@
5+[Scope]
6+DBusName=net.launchpad.scope.cooking.chefkoch
7+DBusPath=/net/launchpad/scope/cooking/chefkoch
8
9=== added file 'chefkoch.svg'
10--- chefkoch.svg 1970-01-01 00:00:00 +0000
11+++ chefkoch.svg 2012-05-22 20:35:21 +0000
12@@ -0,0 +1,71 @@
13+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
14+<!-- Created with Inkscape (http://www.inkscape.org/) -->
15+
16+<svg
17+ xmlns:dc="http://purl.org/dc/elements/1.1/"
18+ xmlns:cc="http://creativecommons.org/ns#"
19+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
20+ xmlns:svg="http://www.w3.org/2000/svg"
21+ xmlns="http://www.w3.org/2000/svg"
22+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
23+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
24+ width="32.625004"
25+ height="28.500004"
26+ id="svg3018"
27+ version="1.1"
28+ inkscape:version="0.48.3.1 r9886"
29+ sodipodi:docname="chefkoch.svg">
30+ <defs
31+ id="defs3020" />
32+ <sodipodi:namedview
33+ id="base"
34+ pagecolor="#ffffff"
35+ bordercolor="#666666"
36+ borderopacity="1.0"
37+ inkscape:pageopacity="0.0"
38+ inkscape:pageshadow="2"
39+ inkscape:zoom="2.8"
40+ inkscape:cx="0.096507634"
41+ inkscape:cy="4.5050419"
42+ inkscape:document-units="px"
43+ inkscape:current-layer="layer1"
44+ showgrid="false"
45+ fit-margin-top="0"
46+ fit-margin-left="0"
47+ fit-margin-right="0"
48+ fit-margin-bottom="0"
49+ inkscape:window-width="1301"
50+ inkscape:window-height="744"
51+ inkscape:window-x="65"
52+ inkscape:window-y="24"
53+ inkscape:window-maximized="1" />
54+ <metadata
55+ id="metadata3023">
56+ <rdf:RDF>
57+ <cc:Work
58+ rdf:about="">
59+ <dc:format>image/svg+xml</dc:format>
60+ <dc:type
61+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
62+ <dc:title></dc:title>
63+ </cc:Work>
64+ </rdf:RDF>
65+ </metadata>
66+ <g
67+ inkscape:label="Ebene 1"
68+ inkscape:groupmode="layer"
69+ id="layer1"
70+ transform="translate(-335.3125,-518.46875)">
71+ <path
72+ inkscape:connector-curvature="0"
73+ id="path3219"
74+ d="m 342.15481,519.26909 c -3.31663,-0.003 -6.00944,2.58203 -6.01217,5.77118 -0.002,2.7707 2.02629,5.09149 4.7339,5.65418 l -0.0132,15.43625 21.50651,0.0183 0.0132,-15.43622 c 2.70857,-0.55807 4.74117,-2.8754 4.74353,-5.64609 0.003,-3.18916 -2.68563,-5.77862 -6.00229,-5.78146 -1.9333,-0.002 -3.65477,0.87481 -4.75521,2.23917 -1.09836,-1.36232 -2.80673,-2.24563 -4.73683,-2.24728 -1.92681,-0.002 -3.63969,0.86865 -4.74061,2.22516 -1.09859,-1.35838 -2.80999,-2.23161 -4.73683,-2.23325 z"
75+ style="fill:#eef4f3;fill-opacity:1;fill-rule:evenodd;stroke:#4c6f0f;stroke-width:1.62983214999999992;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
76+ <path
77+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#4c6f0f;stroke-width:1.62999999999999967;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
78+ d="m 340.73707,540.8274 21.38024,0.0183"
79+ id="path4436"
80+ inkscape:connector-curvature="0"
81+ sodipodi:nodetypes="cc" />
82+ </g>
83+</svg>
84
85=== modified file 'debian/unity-lens-cooking.install'
86--- debian/unity-lens-cooking.install 2012-04-06 14:37:30 +0000
87+++ debian/unity-lens-cooking.install 2012-05-22 20:35:21 +0000
88@@ -1,15 +1,18 @@
89 build/share/unity/lenses/cooking/cooking.lens /usr/share/unity/lenses/cooking
90 cooking.svg /usr/share/unity/lenses/cooking
91 recipefy.png /usr/share/unity/lenses/cooking/icons
92+chefkoch.svg /usr/share/unity/lenses/cooking/icons
93 gourmet.png /usr/share/unity/lenses/cooking/icons
94 cuisine.png /usr/share/unity/lenses/cooking/icons
95+unity-lens-cooking /usr/share/unity/lenses/cooking
96+unity-lens-cooking.service /usr/share/dbus-1/services
97 recipefy.scope /usr/share/unity/lenses/cooking
98-unity-lens-cooking /usr/share/unity/lenses/cooking
99 unity-scope-recipefy /usr/share/unity/lenses/cooking
100-unity-lens-cooking.service /usr/share/dbus-1/services
101 unity-scope-recipefy.service /usr/share/dbus-1/services
102+chefkoch.scope /usr/share/unity/lenses/cooking
103+unity-scope-chefkoch /usr/share/unity/lenses/cooking
104+unity-scope-chefkoch.service /usr/share/dbus-1/services
105+gourmet.scope /usr/share/unity/lenses/cooking
106 unity-scope-gourmet /usr/share/unity/lenses/cooking
107 unity-scope-gourmet.service /usr/share/dbus-1/services
108-gourmet.scope /usr/share/unity/lenses/cooking
109 build/mo/* /usr/share/locale
110-
111
112=== modified file 'setup.py'
113--- setup.py 2012-04-04 20:42:32 +0000
114+++ setup.py 2012-05-22 20:35:21 +0000
115@@ -14,10 +14,17 @@
116 ['unity-lens-cooking',
117 'unity-scope-gourmet',
118 'unity-scope-recipefy',
119- 'cooking.svg',]),
120+ 'unity-scope-chefkoch',
121+ 'chefkoch.svg',
122+ 'cooking.svg',
123+ 'cuisine.png',
124+ 'gourmet.png',
125+ ]),
126 ('share/dbus-1/services',
127 ['unity-lens-cooking.service',
128 'unity-scope-gourmet.service',
129- 'unity-scope-recipefy.service',]),
130+ 'unity-scope-recipefy.service',
131+ 'unity-scope-chefkoch.service',
132+ ]),
133 ], cmdclass={"build": build_extra.build_extra,
134 "build_i18n": build_i18n.build_i18n,})
135
136=== modified file 'unity-lens-cooking'
137--- unity-lens-cooking 2012-04-05 14:39:09 +0000
138+++ unity-lens-cooking 2012-05-22 20:35:21 +0000
139@@ -1,6 +1,6 @@
140 #! /usr/bin/python
141 # -*- coding: utf-8 -*-
142-# Copyright 2012 Eduard Gotwig
143+# Copyright 2012 Eduard Gotwig, Frederik Elwert <frederik.elwert@web.de>
144 # License: GPLv3
145
146 from gi.repository import GLib, GObject, Gio
147@@ -23,8 +23,9 @@
148 # Translatable strings
149
150
151-ONLINE = _("Recipefy Recipes")
152-LOCAL = _("Gourmet Recipes")
153+RECIPEFY = _("Recipefy Recipes")
154+CHEFKOCH = _("Chefkoch Recipes")
155+GOURMET = _("Gourmet Recipes")
156
157 LIKES = _("Likes")
158 TIME = _("Time")
159@@ -60,8 +61,9 @@
160 ### Then, we populate the categories
161 cats = []
162 # A category is a display name, an icon and a renderer
163- cats.append (Unity.Category.new (ONLINE,Gio.ThemedIcon.new("/usr/share/unity/lenses/cooking/icons/recipefy.png"),Unity.CategoryRenderer.HORIZONTAL_TILE))
164- cats.append (Unity.Category.new (LOCAL,Gio.ThemedIcon.new("/usr/share/unity/lenses/cooking/icons/gourmet.png"),Unity.CategoryRenderer.HORIZONTAL_TILE))
165+ cats.append (Unity.Category.new (RECIPEFY,Gio.ThemedIcon.new("/usr/share/unity/lenses/cooking/icons/recipefy.png"),Unity.CategoryRenderer.HORIZONTAL_TILE))
166+ cats.append (Unity.Category.new (CHEFKOCH,Gio.ThemedIcon.new("/usr/share/unity/lenses/cooking/icons/chefkoch.svg"),Unity.CategoryRenderer.HORIZONTAL_TILE))
167+ cats.append (Unity.Category.new (GOURMET,Gio.ThemedIcon.new("/usr/share/unity/lenses/cooking/icons/gourmet.png"),Unity.CategoryRenderer.HORIZONTAL_TILE))
168 self._lens.props.categories = cats
169 ### Populate filters NOT IN USE FOR NOW
170 """filters = []
171
172=== added file 'unity-scope-chefkoch'
173--- unity-scope-chefkoch 1970-01-01 00:00:00 +0000
174+++ unity-scope-chefkoch 2012-05-22 20:35:21 +0000
175@@ -0,0 +1,131 @@
176+#! /usr/bin/python
177+# -*- coding: utf-8 -*-
178+# Copyright 2012 Eduard Gotwig, Frederik Elwert <frederik.elwert@web.de>
179+# License: GPLv3
180+
181+from gi.repository import GLib, GObject, Gio
182+from gi.repository import Dee
183+from gi.repository import Unity
184+import lxml.html
185+import os
186+import re
187+import gettext
188+import locale
189+import sys
190+
191+APP_NAME="unity-lens-cooking"
192+LOCAL_PATH="/usr/share/locale"
193+
194+gettext.bindtextdomain(APP_NAME, LOCAL_PATH)
195+gettext.textdomain(APP_NAME)
196+_ = gettext.gettext
197+
198+RUNNING = _("Failed to own name %s. Bailing out. An other instance is already running!")
199+
200+FULLSTAR_RE = re.compile(r'suche-scrore-(\d).gif')
201+HALFSTAR_RE = re.compile(r'suche-scrore-(\d)_(\d).gif')
202+
203+# The scope dbus id
204+BUS_NAME = "net.launchpad.scope.cooking.chefkoch"
205+
206+class Daemon:
207+ def __init__ (self):
208+ # Create the scope (this matches the path defined in the .scope file)
209+ self.scope = Unity.Scope.new ("/net/launchpad/scope/cooking/chefkoch")
210+ # Is the scope searchable from the home dash?
211+ self.scope.search_in_global = False
212+ # Connect to the search changed signal (it is fired when the lens is opened for the first time, then for each search change)
213+ self.scope.connect ("search-changed", self.on_search_changed)
214+ # Listen to the lens filters
215+ self.scope.connect ("filters-changed", lambda scope : scope.queue_search_changed(Unity.SearchType.DEFAULT))
216+ # The scope is ready
217+ self.scope.export()
218+ # On each search change, this method is called
219+ def on_search_changed (self, scope, search, search_type, cancellable):
220+ # Get the search string
221+ search_string = search.props.search_string.strip()
222+ print "Search changed to \"%s\"" % search_string
223+ # Get the Dee model (the database used by the lens to store and display search results)
224+ model = search.props.results_model
225+ # Empty the model
226+ model.clear()
227+ # Update the model
228+ self.update_results_model (search_string, model)
229+ # Signal to the lens that the search is finished (the spinning search icon stops)
230+ search.finished()
231+
232+ # Update the model
233+ def update_results_model(self, search, model):
234+ self.chefkoch(search, model)
235+
236+ # This method sends the search string to chefkoch and brings back results
237+ def chefkoch_search(self,search):
238+ # Search for recipes over GET
239+ url = ("http://www.chefkoch.de/rs/s0/%s/Rezepte.html" % (search))
240+ print "Searching for Recipes at %s" % url
241+ tree = lxml.html.parse(url)
242+ tree.getroot().make_links_absolute()
243+ items = tree.xpath("//table[@class='result']//tr[@bgcolor]")
244+ print 'Got %d results' % len(items)
245+ return items
246+ # This method parses the results and adds them to the model
247+ def chefkoch(self, search, model):
248+ # Skip empty search
249+ if not search:
250+ print 'Empty search, skipping.'
251+ return
252+ # We iterate through each of the returned results
253+ for i, item in enumerate(self.chefkoch_search(search)):
254+ title = item.xpath("string(td[2]/a)")
255+ icon = item.xpath("td[1]/img/@src")[0]
256+ if icon == 'http://cdn.chefkoch.de/img/no-image-rsmain.gif':
257+ icon = '/usr/share/unity/lenses/cooking/icons/cuisine.png'
258+ uri = item.xpath("td[2]/a/@href")[0]
259+ stars = {0: '☆☆☆☆☆', 1: '✮☆☆☆☆', 2: '★☆☆☆☆', 3: '★✮☆☆☆', 4: '★★☆☆☆', 5: '★★✮☆☆', 6: '★★★☆☆', 7: '★★★✮☆', 8: '★★★★☆', 9: '★★★★✮', 10: '★★★★★'}
260+ likes = 0
261+ stars_img = item.xpath("td[3]/img/@src")[0]
262+ result = FULLSTAR_RE.search(stars_img)
263+ if result:
264+ likes = int(result.group(1)) * 2
265+ else:
266+ result = HALFSTAR_RE.search(stars_img)
267+ if result:
268+ likes = int(result.group(1)) * 2 + 1
269+ time = item[3].text
270+ difficulty = item[3].find('br').tail
271+ comments = [stars[likes], time + ' ⌚ ', difficulty]
272+ comment = ' | '.join(comments)
273+
274+ # If the uri seems valid, we add the results to the Dee model
275+ if (uri.startswith("http://")):
276+ # uri, icon, category (matching the order of the categories in the lens), mimetype, title, comment, drag and drop uri
277+ model.append(uri, icon, 1, "text/html", title, comment, uri)
278+ # We can append the same result to multiple models, just by changing the category
279+
280+if __name__ == "__main__":
281+ # Check if we are running in a German locale. Otherwise, the results are
282+ # rather useless, so don't create the daemon.
283+ lang = locale.getdefaultlocale()[0]
284+ if '_' in lang:
285+ lang = lang.split('_', 1)[0]
286+ if not lang == 'de':
287+ raise SystemExit('No German locale, exiting chefkoch scope')
288+ # The following lines take care of the Bus connexion.
289+ session_bus_connection = Gio.bus_get_sync (Gio.BusType.SESSION, None)
290+ session_bus = Gio.DBusProxy.new_sync (session_bus_connection, 0, None,
291+ 'org.freedesktop.DBus',
292+ '/org/freedesktop/DBus',
293+ 'org.freedesktop.DBus', None)
294+ result = session_bus.call_sync('RequestName',
295+ GLib.Variant ("(su)", (BUS_NAME, 0x4)),
296+ 0, -1, None)
297+
298+ # Unpack variant response with signature "(u)". 1 means we got it.
299+ result = result.unpack()[0]
300+
301+ if result != 1 :
302+ print >> sys.stderr, RUNNING % BUS_NAME
303+ raise SystemExit (1)
304+
305+ daemon = Daemon()
306+ GObject.MainLoop().run()
307
308=== added file 'unity-scope-chefkoch.service'
309--- unity-scope-chefkoch.service 1970-01-01 00:00:00 +0000
310+++ unity-scope-chefkoch.service 2012-05-22 20:35:21 +0000
311@@ -0,0 +1,3 @@
312+[D-BUS Service]
313+Name=net.launchpad.scope.cooking.chefkoch
314+Exec=/usr/share/unity/lenses/cooking/unity-scope-chefkoch
315
316=== modified file 'unity-scope-gourmet'
317--- unity-scope-gourmet 2012-04-07 23:41:13 +0000
318+++ unity-scope-gourmet 2012-05-22 20:35:21 +0000
319@@ -128,10 +128,10 @@
320 # uri, icon, category (matching the order of the categories in the lens), mimetype, title, comment, drag and drop uri
321 if row[14]:
322 open('/tmp/unity-scope-gourmet/icon' + str(i), 'wb').write(row[14])
323- model.append(uri, '/tmp/unity-scope-gourmet/icon' + str(i), 1, "text/html", title, comment, uri)
324+ model.append(uri, '/tmp/unity-scope-gourmet/icon' + str(i), 2, "text/html", title, comment, uri)
325 else:
326 if os.path.exists('/tmp/unity-scope-gourmet/icon' + str(i)): os.remove('/tmp/unity-scope-gourmet/icon' + str(i))
327- model.append(uri, '/usr/share/unity/lenses/cooking/icons/cuisine.png', 1, "text/html", title, comment, uri)
328+ model.append(uri, '/usr/share/unity/lenses/cooking/icons/cuisine.png', 2, "text/html", title, comment, uri)
329 # We can append the same result to multiple models, just by changing the category
330
331 # The following lines take care of the Bus connexion.

Subscribers

People subscribed via source and target branches

to all changes: