Merge lp:~minakov/calendar-indicator/all-calendars into lp:calendar-indicator/precise

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
Reviewer Review Type Date Requested Status
atareao-team Pending
Review via email: mp+95446@code.launchpad.net

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)

Subscribers

People subscribed via source and target branches

to all changes: