Merge lp:~minakov/calendar-indicator/all-calendars into lp:calendar-indicator/precise
- all-calendars
- Merge into trunk
Proposed by
Vladimir Minakov
Status: | Needs review |
---|---|
Proposed branch: | lp:~minakov/calendar-indicator/all-calendars |
Merge into: | lp:calendar-indicator/precise |
Diff against target: |
405 lines (+243/-75) 3 files modified
src/calendar-indicator.py (+51/-73) src/comun.py (+2/-2) src/googlecalendar.py (+190/-0) |
To merge this branch: | bzr merge lp:~minakov/calendar-indicator/all-calendars |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
atareao-team | Pending | ||
Review via email: mp+95446@code.launchpad.net |
Commit message
Description of the change
support all calendars
To post a comment you must log in.
- 19. By Vladimir Minakov
-
Fix bugs
Unmerged revisions
- 19. By Vladimir Minakov
-
Fix bugs
- 18. By Vladimir Minakov
-
All calendars
- 17. By Vladimir Minakov
-
All calendars
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'src/calendar-indicator.py' |
2 | --- src/calendar-indicator.py 2012-02-19 20:33:42 +0000 |
3 | +++ src/calendar-indicator.py 2012-03-01 20:44:18 +0000 |
4 | @@ -44,7 +44,7 @@ |
5 | # |
6 | import comun |
7 | from configurator import Configuration |
8 | -from gcal import GCal |
9 | +from googlecalendar import GoogleCalendar |
10 | from preferences_dialog import Preferences |
11 | # |
12 | locale.setlocale(locale.LC_ALL, '') |
13 | @@ -52,29 +52,9 @@ |
14 | gettext.textdomain(comun.APP) |
15 | _ = gettext.gettext |
16 | |
17 | -def internet_on(): |
18 | - try: |
19 | - response=urllib2.urlopen('http://google.com',timeout=1) |
20 | - return True |
21 | - except: |
22 | - pass |
23 | - return False |
24 | - |
25 | - |
26 | -def getTimeAndDate(cadena): |
27 | - if cadena.find('T')==-1: |
28 | - date = cadena.split('-') |
29 | - time = datetime.time(0,0,0) |
30 | - else: |
31 | - date = cadena.split('T')[0].split('-') |
32 | - time = cadena.split('T')[1].split(':') |
33 | - time = datetime.time(int(time[0]),int(time[1]),int(time[2][0:2])) |
34 | - date = datetime.date(int(date[0]),int(date[1]),int(date[2])) |
35 | - return date.strftime('%d/%m/%Y')+' - '+time.strftime('%H:%M') |
36 | - |
37 | def check_events(event1,event2): |
38 | - if event1.when[0].start == event2.when[0].start: |
39 | - if event1.when[0].end == event2.when[0].end: |
40 | + if event1.when[0].start_time == event2.when[0].start_time: |
41 | + if event1.when[0].end_time == event2.when[0].end_time: |
42 | if event1.title.text == event2.title.text: |
43 | return True |
44 | return False |
45 | @@ -119,6 +99,8 @@ |
46 | self.read_preferences() |
47 | # |
48 | self.events = [] |
49 | + self.load_events() |
50 | + self.set_icon() |
51 | self.set_menu() |
52 | GObject.timeout_add_seconds(60, self.work) |
53 | |
54 | @@ -127,7 +109,7 @@ |
55 | while error: |
56 | try: |
57 | configuration = Configuration() |
58 | - self.gcal=GCal(configuration.get('user'), configuration.get('password')) |
59 | + self.gcal = GoogleCalendar(configuration.get('user'), configuration.get('password')) |
60 | self.time = configuration.get('time') |
61 | self.theme = configuration.get('theme') |
62 | error = False |
63 | @@ -153,45 +135,53 @@ |
64 | |
65 | def work(self): |
66 | if (time.time()-self.actualization_time) > self.time*60: |
67 | - while internet_on() == False: |
68 | - time.sleep(1) |
69 | - self.actualization_time = time.time() |
70 | - self.set_menu(check=True) |
71 | + try: |
72 | + self.load_events(True) |
73 | + except Exception, e: |
74 | + print e |
75 | + return True |
76 | + self.set_icon() |
77 | + self.set_menu() |
78 | return True |
79 | |
80 | - def set_menu(self,check=False): |
81 | - # |
82 | + def load_events(self,check=False): |
83 | + new_events = self.gcal.AgendaQuery() |
84 | + |
85 | + if check: |
86 | + for event in new_events: |
87 | + if not is_event_in_events(event, self.events): |
88 | + msg = event.s.strftime('%d/%m/%Y - %H:%M') + ' - ' + event.title.text |
89 | + self.notification = Notify.Notification.new(_('New event:'), msg, comun.ICON_NEW_EVENT) |
90 | + self.notification.show() |
91 | + for event in self.events: |
92 | + if not is_event_in_events(event, new_events): |
93 | + msg = event.s.strftime('%d/%m/%Y - %H:%M') + ' - ' + event.title.text |
94 | + self.notification = Notify.Notification.new(_('Event finished:'), msg, comun.ICON_FINISHED_EVENT) |
95 | + self.notification.show() |
96 | + |
97 | + self.events = new_events |
98 | + self.actualization_time = time.time() |
99 | + |
100 | + def set_icon(self): |
101 | now = datetime.datetime.now() |
102 | - normal_icon = os.path.join(comun.ICONDIR,'%s-%s-normal.svg'%(now.day,self.theme)) |
103 | - starred_icon = os.path.join(comun.ICONDIR,'%s-%s-starred.svg'%(now.day,self.theme)) |
104 | + normal_icon = os.path.join(comun.ICONDIR, '%s-%s-normal.svg' % (now.day, self.theme)) |
105 | + starred_icon = os.path.join(comun.ICONDIR, '%s-%s-starred.svg' % (now.day, self.theme)) |
106 | # |
107 | self.indicator.set_icon(normal_icon) |
108 | self.indicator.set_attention_icon(starred_icon) |
109 | #self.indicator.set_icon(comun.ICON_ENABLED) |
110 | - #self.indicator.set_attention_icon(comun.ICON_DISABLED) |
111 | - # |
112 | + #self.indicator.set_attention_icon(comun.ICON_DISABLED) |
113 | + |
114 | + if self._has_today(now): |
115 | + self.indicator.set_status(appindicator.IndicatorStatus.ATTENTION) |
116 | + else: |
117 | + self.indicator.set_status(appindicator.IndicatorStatus.ACTIVE) |
118 | + |
119 | + def set_menu(self): |
120 | self.menu = Gtk.Menu() |
121 | # |
122 | - events2 = self.gcal.getFirstTenEventsOnDefaultCalendar() |
123 | - if check and len(self.events)>0: |
124 | - for event in events2: |
125 | - if not is_event_in_events(event,self.events): |
126 | - msg = _('New event:')+'\n' |
127 | - msg += getTimeAndDate(event.when[0].start)+' - '+event.title.text |
128 | - print msg |
129 | - self.notification = Notify.Notification ('Calendar Indicator',msg,comun.ICON_NEW_EVENT) |
130 | - self.notification.show() |
131 | - for event in self.events: |
132 | - if not is_event_in_events(event,events2): |
133 | - msg = _('Event finished:')+'\n' |
134 | - msg += getTimeAndDate(event.when[0].start)+' - '+event.title.text |
135 | - print msg |
136 | - self.notification = Notify.Notification ('Calendar Indicator',msg,comun.ICON_FINISHED_EVENT) |
137 | - self.notification.show() |
138 | - |
139 | - self.events = events2 |
140 | for event in self.events: |
141 | - add2menu(self.menu, text = (getTimeAndDate(event.when[0].start)+' - '+event.title.text)) |
142 | + add2menu(self.menu, text = (event.s.strftime('%d/%m/%Y - %H:%M') + ' - ' + event.title.text)) |
143 | # |
144 | add2menu(self.menu) |
145 | self.menu_show_calendar = add2menu(self.menu, text = _('Show Calendar'), conector_event = 'activate',conector_action = self.menu_show_calendar_response) |
146 | @@ -202,29 +192,11 @@ |
147 | add2menu(self.menu) |
148 | add2menu(self.menu, text = _('Exit'), conector_event = 'activate',conector_action = self.menu_exit_response) |
149 | # |
150 | - now = datetime.datetime.now() |
151 | - if self.events[0].when[0].start.find('T') != -1: |
152 | - print self.events[0].when[0].start |
153 | - if self.events[0].when[0].start.find('.') != -1: |
154 | - com = datetime.datetime.strptime(self.events[0].when[0].start.split('.')[0],'%Y-%m-%dT%H:%M:%S') |
155 | - else: |
156 | - com = datetime.datetime.strptime(self.events[0].when[0].start,'%Y-%m-%dT%H:%M:%S') |
157 | - |
158 | - else: |
159 | - com = datetime.datetime.strptime(self.events[0].when[0].start,'%Y-%m-%d') |
160 | - if now.year == com.year and now.month == com.month and now.day == com.day and now.hour == com.hour: |
161 | - self.indicator.set_status (appindicator.IndicatorStatus.ATTENTION) |
162 | - else: |
163 | - print now.hour |
164 | - print com.hour |
165 | - print self.events[0].when[0].start |
166 | - self.indicator.set_status (appindicator.IndicatorStatus.ACTIVE) |
167 | - # |
168 | self.menu.show() |
169 | self.indicator.set_menu(self.menu) |
170 | + # |
171 | while Gtk.events_pending(): |
172 | Gtk.main_iteration() |
173 | - |
174 | |
175 | def get_help_menu(self): |
176 | help_menu =Gtk.Menu() |
177 | @@ -250,7 +222,7 @@ |
178 | while error: |
179 | try: |
180 | configuration = Configuration() |
181 | - self.gcal=GCal(configuration.get('user'), configuration.get('password')) |
182 | + self.gcal=GoogleCalendar(configuration.get('user'), configuration.get('password')) |
183 | self.time = configuration.get('time') |
184 | self.theme = configuration.get('theme') |
185 | error = False |
186 | @@ -311,6 +283,12 @@ |
187 | ad.run() |
188 | ad.destroy() |
189 | self.menu_about.set_sensitive(True) |
190 | + |
191 | + def _has_today(self, today): |
192 | + for event in self.events: |
193 | + if today.year == event.s.year and today.month == event.s.month and today.day == event.s.day and today.hour == event.s.hour: |
194 | + return True |
195 | + return False |
196 | |
197 | if __name__ == "__main__": |
198 | Notify.init("calendar-indicator") |
199 | |
200 | === modified file 'src/comun.py' |
201 | --- src/comun.py 2012-02-19 20:33:42 +0000 |
202 | +++ src/comun.py 2012-03-01 20:44:18 +0000 |
203 | @@ -60,5 +60,5 @@ |
204 | APPDIR = os.path.join(ROOTDIR, APP) |
205 | ICONDIR = os.path.join(ROOTDIR, 'data/icons') |
206 | |
207 | -ICON_NEW_EVENT = 'event-new' |
208 | -ICON_FINISHED_EVENT = 'event-finished' |
209 | +ICON_NEW_EVENT = os.path.join(ICONDIR, 'event-new.svg') |
210 | +ICON_FINISHED_EVENT = os.path.join(ICONDIR, 'event-finished.svg') |
211 | |
212 | === added file 'src/googlecalendar.py' |
213 | --- src/googlecalendar.py 1970-01-01 00:00:00 +0000 |
214 | +++ src/googlecalendar.py 2012-03-01 20:44:18 +0000 |
215 | @@ -0,0 +1,190 @@ |
216 | +#! /usr/bin/python |
217 | +# -*- coding: iso-8859-15 -*- |
218 | +# |
219 | +__author__='atareao' |
220 | +__date__ ='$30/10/2010' |
221 | +# |
222 | +# Copyright (C) 2010 Lorenzo Carbonell |
223 | +# lorenzo.carbonell.cerezo@gmail.com |
224 | +# |
225 | +# This program is free software: you can redistribute it and/or modify |
226 | +# it under the terms of the GNU General Public License as published by |
227 | +# the Free Software Foundation, either version 3 of the License, or |
228 | +# (at your option) any later version. |
229 | +# |
230 | +# This program is distributed in the hope that it will be useful, |
231 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
232 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
233 | +# GNU General Public License for more details. |
234 | +# |
235 | +# You should have received a copy of the GNU General Public License |
236 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
237 | +# |
238 | +import sys, re, urllib, getopt |
239 | +import threading, getpass |
240 | +from Queue import Queue |
241 | +from gdata.calendar.service import * |
242 | +from datetime import * |
243 | +from dateutil.tz import * |
244 | +from dateutil.parser import * |
245 | + |
246 | +class GoogleCalendar(object): |
247 | + allCals = None |
248 | + cals = [] |
249 | + now = datetime.now(tzlocal()) |
250 | + agendaLength = 30 |
251 | + |
252 | + def __init__(self,email,password): |
253 | + self.email = email |
254 | + self.password = password |
255 | + self.client = CalendarService() |
256 | + self.client.ClientLogin(self.email,self.password, 'calendar-indicator') |
257 | + |
258 | + # get the list of calendars |
259 | + self.allCals = self.client.GetAllCalendarsFeed() |
260 | + for cal in self.allCals.entry: |
261 | + cal.gcalcli_altLink = cal.GetAlternateLink().href |
262 | + match = re.match('^https?://www.google.com/calendar/feeds/(.*?)/(.*?)/(.*)$', cal.gcalcli_altLink) |
263 | + cal.gcalcli_username = urllib.unquote(match.group(1)) |
264 | + cal.gcalcli_visibility = urllib.unquote(match.group(2)) |
265 | + cal.gcalcli_projection = urllib.unquote(match.group(3)) |
266 | + self.cals.append(cal) |
267 | + |
268 | + def AgendaQuery(self): |
269 | + start = self.now |
270 | + end = (start + timedelta(days=self.agendaLength)) |
271 | + return self._SearchForCalEvents(start, end, None) |
272 | + |
273 | + def _SearchForCalEvents(self, start, end, searchText): |
274 | + eventList = [] |
275 | + queue = Queue() |
276 | + threads = [] |
277 | + |
278 | + def worker(cal, query): |
279 | + feed = self.client.CalendarQuery(query) |
280 | + queue.put((cal, feed)) |
281 | + |
282 | + for cal in self.cals: |
283 | + # see http://code.google.com/apis/calendar/reference.html |
284 | + if not searchText: |
285 | + query = CalendarEventQuery(cal.gcalcli_username, cal.gcalcli_visibility, cal.gcalcli_projection) |
286 | + query.start_min = start.isoformat() |
287 | + query.start_max = end.isoformat() |
288 | + else: |
289 | + query = CalendarEventQuery(cal.gcalcli_username, cal.gcalcli_visibility, cal.gcalcli_projection, searchText) |
290 | + if start: # flagged by --ignore-started |
291 | + # weeds out old but still pulls in started events |
292 | + query.futureevents = 'true' |
293 | + |
294 | + query.singleevents = 'true' |
295 | + |
296 | + # we sort later after getting events from all calendars |
297 | + #query.orderby = 'starttime' |
298 | + #query.sortorder = 'ascending' |
299 | + |
300 | + th = threading.Thread(target=worker, args=(cal, query)) |
301 | + threads.append(th) |
302 | + th.start() |
303 | + |
304 | + for th in threads: |
305 | + th.join() |
306 | + |
307 | + while not queue.empty(): |
308 | + cal, feed = queue.get() |
309 | + eventList.extend(self._GetAllEvents(cal, feed, end)) |
310 | + |
311 | + eventList.sort(lambda x, y: cmp(x.s, y.s)) |
312 | + |
313 | + return eventList |
314 | + |
315 | + def _GetAllEvents(self, cal, feed, end): |
316 | + eventList = [] |
317 | + |
318 | + while 1: |
319 | + next = feed.GetNextLink() |
320 | + |
321 | + for event in feed.entry: |
322 | + event.gcalcli_cal = cal |
323 | + |
324 | + event.s = parse(event.when[0].start_time) |
325 | + if event.s.tzinfo == None: |
326 | + event.s = event.s.replace(tzinfo=tzlocal()) |
327 | + |
328 | + event.e = parse(event.when[0].end_time) |
329 | + if event.e.tzinfo == None: |
330 | + event.e = event.e.replace(tzinfo=tzlocal()) |
331 | + |
332 | + # For all-day events, Google seems to assume that the event time |
333 | + # is based in the UTC instead of the local timezone. Here we |
334 | + # filter out those events start beyond a specified end time. |
335 | + if end and (event.s >= end): |
336 | + continue |
337 | + |
338 | + # http://en.wikipedia.org/wiki/Year_2038_problem |
339 | + # Catch the year 2038 problem here as the python dateutil module |
340 | + # can choke throwing a ValueError exception. If either the start |
341 | + # or end time for an event has a year '>= 2038' dump it. |
342 | + if event.s.year >= 2038 or event.e.year >= 2039: |
343 | + continue |
344 | + |
345 | + eventList.append(event) |
346 | + |
347 | + if not next: |
348 | + break |
349 | + |
350 | + feed = self.client.GetCalendarEventFeed(next.href) |
351 | + |
352 | + return eventList |
353 | + |
354 | + def _ValidTitle(self, title): |
355 | + if title == None: |
356 | + return "(No title)" |
357 | + else: |
358 | + return title |
359 | + |
360 | + def _CalendarColor(self, cal): |
361 | + if cal != None and hasattr(cal, 'colorSpec') and cal.colorSpec != None: |
362 | + return cal.colorSpec |
363 | + else: |
364 | + return None |
365 | + |
366 | +if __name__ == '__main__': |
367 | + try: |
368 | + opts, args = getopt.getopt(sys.argv[1:], "", [ "user=","pw=" ]) |
369 | + except getopt.error: |
370 | + sys.exit(1) |
371 | + |
372 | + usr = None |
373 | + pwd = None |
374 | + |
375 | + for opt, arg in opts: |
376 | + if opt == "--user": |
377 | + usr = arg |
378 | + elif opt == "--pw": |
379 | + pwd = arg |
380 | + |
381 | + if usr == None: |
382 | + sys.stdout.write('Error: must specify a username\n') |
383 | + sys.exit(1) |
384 | + |
385 | + try: |
386 | + if pwd == None: |
387 | + pwd = getpass.getpass("Password: ") |
388 | + except Exception, e: |
389 | + sys.stdout.write("Error: " + str(e) + "!\n") |
390 | + sys.exit(1) |
391 | + |
392 | + if pwd == None or pwd == '': |
393 | + sys.stdout.write('Error: must specify a password\n') |
394 | + sys.exit(1) |
395 | + |
396 | + try: |
397 | + gcal = GoogleCalendar(usr, pwd) |
398 | + except Exception, e: |
399 | + sys.stdout.write("Error: " + str(e) + "!\n") |
400 | + sys.exit(1) |
401 | + |
402 | + for event in gcal.AgendaQuery(): |
403 | + print event.title.text |
404 | + |
405 | + sys.exit(0) |