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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright 2012 Eduard Gotwig
# License: GPLv3
from gi.repository import GLib, GObject, Gio
from gi.repository import Dee
from gi.repository import Unity
from datetime import timedelta
import os
import sqlite3
import sys
import gettext
import locale
APP_NAME="unity-lens-cooking"
LOCAL_PATH="/usr/share/locale"
gettext.bindtextdomain(APP_NAME, LOCAL_PATH)
gettext.textdomain(APP_NAME)
_ = gettext.gettext
RUNNING = _("Failed to own name %s. Bailing out. An other instance is already running!")
NOTFOUND = _("Can't find gourmet recipe managers database in ~/.gourmet/recipes.db. Is it installed?")
SECONDS = _("seconds")
MINUTES = _("min.")
HOURS = _("hours")
DAYS = _("days")
WEEKS = _("weeks")
# The scope dbus id
BUS_NAME = "net.launchpad.scope.cooking.gourmet"
def duration(s):
# Make a nice string representation of a number of seconds.
m, s = divmod(s, 60)
h, m = divmod(m, 60)
d, h = divmod(h, 24)
w, d = divmod(d, 7)
dur = []
if w:
dur.append(str(w) + " " + WEEKS)
if d:
dur.append(str(d) + " "+ DAYS)
if h:
dur.append(str(h) + " "+ HOURS)
if m:
dur.append(str(m) + " " + MINUTES)
if s:
if int(s) == s:
dur.append(str(s) + " " + SECONDS)
else:
dur.append("%.2f " % s + SECONDS)
if dur:
return " ".join(dur)
else:
return "0"
class Daemon:
def __init__ (self):
# Look if Gourmet Recipe Manager or the database exists
# Create temporary directory for icons
if not os.path.exists(os.getenv("HOME") + '/.gourmet/recipes.db'):
exit(NOTFOUND)
sys.exit()
# Create temporary directory for icons
if not os.path.exists('/tmp/unity-scope-gourmet'): os.makedirs('/tmp/unity-scope-gourmet')
# Create the scope (this matches the path defined in the .scope file)
self.scope = Unity.Scope.new ("/net/launchpad/scope/cooking/gourmet")
# 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.gourmet(search, model)
# This method sends queries and brings back results
def gourmet_search(self,search):
# Search for recipes over SQL
conn = sqlite3.connect(os.getenv("HOME") + '/.gourmet/recipes.db')
self.cursor = conn.cursor()
print("Searching for Gourmet recipes")
return self.cursor.execute('select * from recipe where title like ?', ('%'+search+'%',))
# This method parses the results and adds them to the model
def gourmet(self, search, model):
# We iterate through each of the returned results
for row in self.gourmet_search(search):
# Give each cached image file the unique ID of its reciipe
if not (row[15]):
i = row[0]
title = row[1]
uri = row[18]
likes = row[5]
stars = {0: '☆☆☆☆☆', 1: '✮☆☆☆☆', 2: '★☆☆☆☆', 3: '★✮☆☆☆', 4: '★★☆☆☆', 5: '★★✮☆☆', 6: '★★★☆☆', 7: '★★★✮☆', 8: '★★★★☆', 9: '★★★★✮', 10: '★★★★★'}
likes = stars[likes]
comments = row[3]
time = row[8] + row[9]
if (time):
time = str(duration(time))
comment = likes + ' | ' + time + ' \n' + str(comments)
else: comment = likes + '\n' + str(comments)
# add http:// if necessary
if not (uri.startswith("http://")) and not (uri==''): uri = 'http://' + uri
# uri, icon, category (matching the order of the categories in the lens), mimetype, title, comment, drag and drop uri
if row[14]:
open('/tmp/unity-scope-gourmet/icon' + str(i), 'wb').write(row[14])
model.append(uri, '/tmp/unity-scope-gourmet/icon' + str(i), 3, "text/html", title, comment, uri)
else:
if os.path.exists('/tmp/unity-scope-gourmet/icon' + str(i)): os.remove('/tmp/unity-scope-gourmet/icon' + str(i))
model.append(uri, '/usr/share/unity/lenses/cooking/icons/cuisine.png', 3, "text/html", title, comment, uri)
# We can append the same result to multiple models, just by changing the category
# 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(RUNNING % BUS_NAME, file=sys.stderr)
raise SystemExit (1)
daemon = Daemon()
GObject.MainLoop().run()
|