|
1 # Database example application: a sports diary. |
|
2 |
|
3 # Copyright (c) 2005 Nokia Corporation |
|
4 # |
|
5 # Licensed under the Apache License, Version 2.0 (the "License"); |
|
6 # you may not use this file except in compliance with the License. |
|
7 # You may obtain a copy of the License at |
|
8 # |
|
9 # http://www.apache.org/licenses/LICENSE-2.0 |
|
10 # |
|
11 # Unless required by applicable law or agreed to in writing, software |
|
12 # distributed under the License is distributed on an "AS IS" BASIS, |
|
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
14 # See the License for the specific language governing permissions and |
|
15 # limitations under the License. |
|
16 |
|
17 |
|
18 import time |
|
19 |
|
20 import e32 |
|
21 import e32db |
|
22 import appuifw |
|
23 |
|
24 class SportsDiary: |
|
25 def __init__(self, db_name): |
|
26 try: |
|
27 self.native_db = e32db.Dbms() |
|
28 self.native_db.open(db_name) |
|
29 except: |
|
30 self.native_db.create(db_name) |
|
31 self.native_db.open(db_name) |
|
32 self.native_db.execute(SportsDiaryEntry.sql_create) |
|
33 |
|
34 def get_all_entries(self): |
|
35 dbv = e32db.Db_view() |
|
36 dbv.prepare(self.native_db, |
|
37 u"SELECT * from events ORDER BY date DESC") |
|
38 dbv.first_line() |
|
39 results = [] |
|
40 for i in range(dbv.count_line()): |
|
41 dbv.get_line() |
|
42 e = SportsDiaryEntry(dbv) |
|
43 results.append(e) |
|
44 dbv.next_line() |
|
45 return results |
|
46 |
|
47 def add(self, e): |
|
48 self.native_db.execute(e.sql_add()) |
|
49 |
|
50 def delete(self, e): |
|
51 self.native_db.execute(e.sql_delete()) |
|
52 |
|
53 def close(self): |
|
54 self.native_db.close() |
|
55 |
|
56 class SportsDiaryEntry: |
|
57 sports = [u"Running", u"Skating", u"Biking", u"Skiing", u"Swimming"] |
|
58 sql_create = u"CREATE TABLE events (date TIMESTAMP, duration FLOAT, distance FLOAT, sport INTEGER, comment VARCHAR)" |
|
59 |
|
60 # Initialize with a row from Sport_diary_db |
|
61 def __init__(self, r=None): |
|
62 if r: |
|
63 self.timestamp = r.col(1) |
|
64 self.duration = r.col(2) |
|
65 self.distance = r.col(3) |
|
66 self.sport = r.col(4) |
|
67 self.comment = r.col(5) |
|
68 else: |
|
69 self.timestamp = time.time() |
|
70 self.duration = 0.0 |
|
71 self.distance = 0.0 |
|
72 self.sport = None |
|
73 self.comment = u"" |
|
74 |
|
75 def sql_add(self): |
|
76 sql = "INSERT INTO events (date, duration, distance, sport, comment) VALUES (#%s#,%d,%d,%d,'%s')"%( |
|
77 e32db.format_time(self.timestamp), |
|
78 self.duration, |
|
79 self.distance, |
|
80 self.sport, |
|
81 self.comment) |
|
82 return unicode(sql) |
|
83 |
|
84 def sql_delete(self): |
|
85 sql = "DELETE FROM events WHERE date=#%s#"%\ |
|
86 e32db.format_time(self.timestamp) |
|
87 return unicode(sql) |
|
88 |
|
89 def unixtime(self): |
|
90 return self.timestamp |
|
91 |
|
92 def get_sport_text(self): |
|
93 return self.sports[self.sport] |
|
94 |
|
95 def get_form(self): |
|
96 # Convert Unix timestamp into the form the form accepts. |
|
97 (yr, mo, da, h, m, s, wd, jd, ds) = \ |
|
98 time.localtime(self.timestamp) |
|
99 m += 60*h # 60 minutes per hour |
|
100 s += 60*m # 60 seconds per minute |
|
101 result = [(u"Date", 'date', float(self.timestamp-s)), |
|
102 (u"Time", 'time', float(s)), |
|
103 (u"Duration", 'time', float(self.duration)), |
|
104 (u"Distance", 'number', int(self.distance))] |
|
105 if self.sport == None: |
|
106 result.append((u"Sport", 'combo', (self.sports, 0))) |
|
107 else: |
|
108 result.append((u"Sport", 'combo', (self.sports, self.sport))) |
|
109 result.append((u"Comment", 'text', self.comment)) |
|
110 return result |
|
111 |
|
112 def set_from_form(self, form): |
|
113 self.timestamp = form[0][2]+form[1][2] |
|
114 self.duration = form[2][2] |
|
115 self.distance = form[3][2] |
|
116 self.sport = form[4][2][1] |
|
117 self.comment = form[5][2] |
|
118 |
|
119 |
|
120 class SportsDiaryApp: |
|
121 def __init__(self): |
|
122 self.lock = e32.Ao_lock() |
|
123 self.exit_flag = False |
|
124 appuifw.app.exit_key_handler = self.abort |
|
125 self.main_view = appuifw.Listbox([(u"Loading...", u"")], |
|
126 self.handle_view_entry) |
|
127 appuifw.app.body = self.main_view |
|
128 self.entry_list = [] |
|
129 self.menu_add = (u"Add", self.handle_add) |
|
130 self.menu_summary = (u"Summary", self.handle_summary) |
|
131 self.menu_delete = (u"Delete", self.handle_delete) |
|
132 appuifw.app.menu = [] |
|
133 |
|
134 def initialize_db(self, db_name): |
|
135 self.sports_diary = SportsDiary(db_name) |
|
136 |
|
137 def run(self): |
|
138 while not self.exit_flag: |
|
139 self.show_main_view() |
|
140 self.lock.wait() |
|
141 self.close() |
|
142 |
|
143 def close(self): |
|
144 appuifw.app.menu = [] |
|
145 appuifw.app.body = None |
|
146 appuifw.app.exit_key_handler = None |
|
147 self.sports_diary.close() |
|
148 |
|
149 def abort(self): |
|
150 self.exit_flag = True |
|
151 self.lock.signal() |
|
152 |
|
153 def update_entry_list(self): |
|
154 self.entry_list = self.sports_diary.get_all_entries() |
|
155 |
|
156 def show_main_view(self): |
|
157 self.update_entry_list() |
|
158 if not self.entry_list: |
|
159 content = [(u"(Empty)", u"")] |
|
160 else: |
|
161 content = [(unicode(time.ctime(item.unixtime())), |
|
162 item.get_sport_text()) for item in self.entry_list] |
|
163 |
|
164 self.main_view.set_list(content) |
|
165 |
|
166 if not self.entry_list: |
|
167 appuifw.app.menu = [self.menu_add] |
|
168 else: |
|
169 appuifw.app.menu = [self.menu_add, |
|
170 self.menu_delete, |
|
171 self.menu_summary] |
|
172 |
|
173 def handle_add(self): |
|
174 new_entry = SportsDiaryEntry() |
|
175 data = new_entry.get_form() |
|
176 flags = appuifw.FFormEditModeOnly |
|
177 f = appuifw.Form(data, flags) |
|
178 f.execute() |
|
179 new_entry.set_from_form(f) |
|
180 self.sports_diary.add(new_entry) |
|
181 self.lock.signal() |
|
182 |
|
183 def handle_delete(self): |
|
184 if self.entry_list: |
|
185 index = self.main_view.current() |
|
186 if appuifw.query(u"Delete entry?", 'query'): |
|
187 self.sports_diary.delete(self.entry_list[index]) |
|
188 self.lock.signal() |
|
189 |
|
190 def handle_summary(self): |
|
191 sum = 0 |
|
192 for e in self.entry_list: |
|
193 sum += e.distance |
|
194 appuifw.note(u"Total distance is "+str(sum), 'info') |
|
195 |
|
196 def handle_view_entry(self): |
|
197 if self.entry_list: |
|
198 index = self.main_view.current() |
|
199 self.show_entry(self.entry_list[index]) |
|
200 self.lock.signal() |
|
201 |
|
202 def show_entry(self, entry): |
|
203 data = entry.get_form() |
|
204 flags = appuifw.FFormViewModeOnly |
|
205 f = appuifw.Form(data, flags) |
|
206 f.execute() |
|
207 |
|
208 def main(): |
|
209 app = SportsDiaryApp() |
|
210 app.initialize_db(u"c:\\SportsDiary.db") |
|
211 app.run() |
|
212 |
|
213 if __name__ == '__main__': |
|
214 old_title = appuifw.app.title |
|
215 try: |
|
216 appuifw.app.title = u"Sports diary" |
|
217 e32.ao_yield() |
|
218 main() |
|
219 finally: |
|
220 appuifw.app.title = old_title |