1
2
3
4
5
6
7
8
9 """
10 Auto synchronization of calender
11 This module provides functionality to automatically sync the calender on your PC (outlook etc.)
12 with your phone. It will do so at a regular interval if the phone is connected and BitPim is running
13 This feature works with all BitPim calender types and phones that support the writing of calenders
14
15 """
16
17
18 import copy
19 import sha
20 import time
21 import re
22
23
24 import wx
25
26
27 import database
28 import guiwidgets
29 import common_calendar
30 import guiwidgets
31 import gui
32
33 _data_key='auto_sync_settings'
34 _filter_keys=['start_offset', 'end_offset', 'no_alarm', 'rpt_events', "alarm_value",
35 'ringtone', 'vibrate', 'categories', 'alarm_override']
36
43
47
50
51 self.__log=log
52 self.__data={}
53
54 - def log(self, log_str):
55 if self.__log is None:
56 print log_str
57 else:
58 self.__log.log(log_str)
59 - def logdata(self, log_str, log_data):
60 if self.__log is None:
61 print log_str,log_data
62 else:
63 self.__log.logdata(log_str, log_data)
64
66 res=0
67 for entry in self.mw.calenders:
68 if entry[0]==self.settings.caltype:
69 filter={}
70 for setting in _filter_keys:
71 if self.settings._data.has_key(setting) and self.settings._data[setting]!=None:
72
73 if setting=='start_offset':
74 tm=time.gmtime(time.time()-(self.settings._data[setting]*24*60*60))
75 date=(tm.tm_year, tm.tm_mon, tm.tm_mday)
76 filter['start']=date
77 elif setting=='end_offset':
78 tm=time.gmtime(time.time()+(self.settings._data[setting]*24*60*60))
79 date=(tm.tm_year, tm.tm_mon, tm.tm_mday)
80 filter['end']=date
81 elif setting=="categories":
82
83 filter[setting]=self.settings._data[setting].split("||")
84 else:
85 filter[setting]=self.settings._data[setting]
86 else:
87 if setting=='start_offset':
88 filter['start']=None
89 if setting=='end_offset':
90 filter['end']=None
91 res=entry[2](self.mw.tree.GetActivePhone(), self.settings.calender_id, filter)
92 if res==1:
93
94 self.log("Auto Sync: Imported calender OK")
95 if not res:
96 self.log("Auto Sync: Failed to import calender")
97 return res
98
110
123
125 if exception!=None:
126 if not self.silent:
127 self.mw.HandleException(exception)
128 self.log("Auto Sync: Failed, Exception writing calender to phone")
129 self.mw.OnBusyEnd()
130 return
131 if self.silent==0:
132 wx.MessageBox('Phone Synchronized OK',
133 'Synchronize Complete', wx.OK)
134 self.log("Auto Sync: Synchronize Completed OK")
135 self.mw.OnBusyEnd()
136
137 - def sync(self, mw, silent, profile="Default Autosync"):
138 self.silent=silent
139
140
141 self.mw=mw
142 if mw.config.ReadInt("SafeMode", False):
143 self.log("Auto Sync: Disabled, BitPim in safe mode")
144 return 0
145 if wx.IsBusy():
146 self.log("Auto Sync: Failed, BitPim busy")
147 return 0
148 self.log("Auto Sync: Starting (silent mode=%d)..." % (silent))
149 self.mw.OnBusyStart()
150 self.mw.GetStatusBar().progressminor(0, 100, 'Auto Calendar Import in progress ...')
151
152 self.settings=_getsettings(mw, profile)
153
154 res=self.importcalenderdata()
155 if res==1:
156
157 res=self.sendcalendertophone()
158 else:
159 self.mw.OnBusyEnd()
160 if silent==0:
161 wx.MessageBox('Unable to Auto-Import Calendar Data',
162 'Auto Calendar Import failed', wx.OK)
163 self.log("Auto Sync: Failed, Unable to synchronize phone schedule")
164 return res
165
166
168 _knownproperties=['caltype', 'calender_id', 'sync_on_connect', 'sync_frequency', \
169 'start_offset', 'end_offset', 'no_alarm', 'rpt_events', 'categories', \
170 'ringtone', 'vibrate', 'alarm_override', 'alarm_value']
171 _knownlistproperties=database.basedataobject._knownlistproperties.copy()
176 autosyncsettingsobjectfactory=database.dataobjectfactory(AutoSyncSettingsobject)
177
178
180 _caltype_key='caltype'
181 _calender_id_key='calender_id'
182 _sync_on_connect_key='sync_on_connect'
183 _sync_frequency_key='sync_frequency'
184
185
186
187
188
189
190 - def __init__(self):
191 self._data={ 'serials': [] }
192
193
194 - def __eq__(self, rhs):
197 - def __ne__(self, rhs):
198 return (not __eq__(rhs))
200 return copy.deepcopy(self._data, {})
202 self._data={}
203 self._data.update(d)
204
205 - def get_db_dict(self):
207 - def set_db_dict(self, d):
209
211 s=self._data.get('serials', [])
212 for n in s:
213 if n.get('sourcetype', None)=='bitpim':
214 return n.get('id', None)
215 return None
216 - def _set_id(self, id):
217 s=self._data.get('serials', [])
218 for n in s:
219 if n.get('sourcetype', None)=='bitpim':
220 n['id']=id
221 return
222 self._data['serials'].append({'sourcetype': 'bitpim', 'id': id } )
223 id=property(fget=_get_id, fset=_set_id)
224
225 - def _set_or_del(self, key, v, v_list=[]):
226 if v is None or v in v_list:
227 if self._data.has_key(key):
228 del self._data[key]
229 else:
230 self._data[key]=v
231
232 - def _get_caltype(self):
233 return self._data.get(self._caltype_key, 'None')
234 - def _set_caltype(self, v):
235 self._set_or_del(self._caltype_key, v, [''])
236 caltype=property(fget=_get_caltype, fset=_set_caltype)
237
239 return self._data.get(self._calender_id_key, '')
240 - def _set_calender_id(self, v):
242 calender_id=property(fget=_get_calender_id, fset=_set_calender_id)
243
245 return self._data.get(self._sync_on_connect_key, False)
248 sync_on_connect=property(fget=_get_sync_on_connect, fset=_set_sync_on_connect)
249
251 return self._data.get(self._sync_frequency_key, 0)
254 sync_frequency=property(fget=_get_sync_frequency, fset=_set_sync_frequency)
255
256
257
258
259
261 ID_CALSETTINGS=wx.NewId()
262 - def __init__(self, mainwindow, frame, title="Auto Calendar Import Settings", profile="Default Autosync", id=-1):
263 t=title+" - "+profile
264 wx.Dialog.__init__(self, frame, id, t,
265 style=wx.CAPTION|wx.SYSTEM_MENU|wx.DEFAULT_DIALOG_STYLE)
266 self.mw=mainwindow
267 self.profile=profile
268
269 gs=wx.GridBagSizer(10, 10)
270 gs.AddGrowableCol(1)
271
272
273 gs.Add( wx.StaticText(self, -1, "Calender Type"), pos=(0,0), flag=wx.ALIGN_CENTER_VERTICAL)
274
275 calendertype=('None',)
276
277 for entry in self.mw.calenders:
278 calendertype+=(entry[0], )
279
280 self.caltype=wx.ComboBox(self, -1, calendertype[0], style=wx.CB_DROPDOWN|wx.CB_READONLY,choices=calendertype)
281 gs.Add( self.caltype, pos=(0,1), flag=wx.ALIGN_CENTER_VERTICAL)
282 gs.Add( wx.Button(self, self.ID_CALSETTINGS, "Calender Settings..."), pos=(0,2), flag=wx.ALIGN_CENTER_VERTICAL)
283
284
285 gs.Add( wx.StaticText(self, -1, "Update when phone re-connected"), pos=(1,0), flag=wx.ALIGN_CENTER_VERTICAL)
286 self.sync_on_connect=wx.CheckBox(self, wx.NewId(), "")
287 gs.Add( self.sync_on_connect, pos=(1,1), flag=wx.ALIGN_CENTER_VERTICAL)
288
289
290 gs.Add( wx.StaticText(self, -1, "Update Frequency (mins) 0=never"), pos=(2,0), flag=wx.ALIGN_CENTER_VERTICAL)
291 self.sync_frequency=wx.lib.intctrl.IntCtrl(self, -1, value=0, min=0, max=1440)
292 gs.Add( self.sync_frequency, pos=(2,1), flag=wx.ALIGN_CENTER_VERTICAL)
293
294
295 bs=wx.BoxSizer(wx.VERTICAL)
296 bs.Add(gs, 0, wx.EXPAND|wx.ALL, 10)
297 bs.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 7)
298
299 but=self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.HELP)
300 bs.Add(but, 0, wx.CENTER|wx.ALL, 10)
301
302 wx.EVT_BUTTON(self, wx.ID_HELP, self.OnHelp)
303 wx.EVT_BUTTON(self, wx.ID_CANCEL, self.OnCancel)
304 wx.EVT_BUTTON(self, wx.ID_OK, self.OnOK)
305 wx.EVT_BUTTON(self, self.ID_CALSETTINGS, self.OnConfigCalender)
306 wx.EVT_COMBOBOX(self, self.caltype.GetId(), self.OnCaltypeChange)
307
308 self.settings=AutoSyncSettingsEntry()
309
310 self.SetSizer(bs)
311 self.SetAutoLayout(True)
312 bs.Fit(self)
313
314 self.getfromfs()
315 self.auto_sync_timer_id = wx.NewId()
316 self.auto_sync_timer = wx.Timer(self, self.auto_sync_timer_id)
317
318 self.SetAutoSyncTimer()
319
320
321 guiwidgets.set_size("AutoSyncSettingsDialog", self, screenpct=-1, aspect=3.5)
322
323 wx.EVT_CLOSE(self, self.OnClose)
324
330
332 old_folder=self.settings.calender_id
333 for entry in self.mw.calenders:
334 if entry[0]==self.caltype.GetValue():
335
336 if self.settings.caltype!=self.caltype.GetValue():
337 self.settings.calender_id=''
338 filter={}
339 for setting in _filter_keys:
340 if self.settings._data.has_key(setting) and self.settings._data[setting]!=None:
341 if setting=="categories":
342
343 filter[setting]=self.settings._data[setting].split("||")
344 else:
345 filter[setting]=self.settings._data[setting]
346 res, temp=entry[1](self.mw, self.settings.calender_id, filter)
347 if res==wx.ID_OK and res != None:
348
349 self.settings.calender_id=temp[0]
350 for setting in _filter_keys:
351 if(temp[1].has_key(setting) and temp[1][setting]!=None):
352 if setting=="categories":
353
354 cat_str=""
355 for cat in temp[1][setting]:
356
357 if len(cat_str):
358 cat_str=cat_str+"||"+cat
359 else:
360 cat_str=cat
361 self.settings._data[setting]=cat_str
362 else:
363 self.settings._data[setting]=temp[1][setting]
364 else:
365 if self.settings._data.has_key(setting):
366 del self.settings._data[setting]
367 self.settings.caltype=self.caltype.GetValue()
368 else:
369
370 self.caltype.SetValue(self.settings.caltype)
371 self.settings.calender_id=old_folder
372 return
373 return
374
379
381 self.saveSize()
382 self.EndModal(wx.ID_OK)
383 return
384
388
394
404
411
414
416 self.mw.auto_save_dict=self.settings
417
426
429
431
432 self.auto_sync_timer.Stop()
433 oneShot = True
434 timeout=self.settings.sync_frequency*60000
435 if timeout:
436 self.auto_sync_timer.Start(timeout, oneShot)
437 self.Bind(wx.EVT_TIMER, self.OnTimer, self.auto_sync_timer)
438
443