0001 ### BITPIM 0002 ### 0003 ### Copyright (C) 2004 Joe Pham <djpham@netzero.com> 0004 ### 0005 ### This program is free software; you can redistribute it and/or modify 0006 ### it under the terms of the BitPim license as detailed in the LICENSE file. 0007 ### 0008 ### $Id: outlook_calendar.py 4405 2007-09-24 21:49:06Z djpham $ 0009 0010 "Deals with Outlook calendar import stuff" 0011 0012 # System modules 0013 from __future__ import with_statement 0014 import datetime 0015 import pywintypes 0016 import sys 0017 import time 0018 0019 # wxPython modules 0020 import wx 0021 import wx.calendar 0022 import wx.lib.mixins.listctrl as listmix 0023 0024 # Others 0025 0026 # My modules 0027 import bpcalendar 0028 import common 0029 import common_calendar 0030 import guihelper 0031 import guiwidgets 0032 import helpids 0033 import native.outlook 0034 0035 # common convertor functions 0036 def to_bp_date(dict, v, oc): 0037 # convert a pyTime to (y, m, d, h, m) 0038 if not isinstance(v, pywintypes.TimeType): 0039 raise TypeError, 'illegal type' 0040 if v.year>common_calendar.no_end_date[0]: 0041 return common_calendar.no_end_date 0042 return (v.year, v.month, v.day, v.hour, v.minute) 0043 0044 def bp_repeat_str(dict, v): 0045 if v is None: 0046 return '' 0047 elif v==OutlookCalendarImportData.olRecursDaily: 0048 return 'Daily' 0049 elif v==OutlookCalendarImportData.olRecursWeekly: 0050 return 'Weekly' 0051 elif v==OutlookCalendarImportData.olRecursMonthly or \ 0052 v==OutlookCalendarImportData.olRecursMonthNth: 0053 return 'Monthly' 0054 elif v==OutlookCalendarImportData.olRecursYearly: 0055 return 'Yearly' 0056 else: 0057 return '<Unknown Value>' 0058 0059 def convert_categories(dict, v, oc): 0060 return [x.strip() for x in v.split(",") if len(x)] 0061 0062 def set_recurrence(item, dict, oc): 0063 oc.update_display() 0064 if not dict['repeat']: 0065 # no reccurrence, ignore 0066 dict['repeat']=None 0067 return True 0068 # get the recurrence pattern and map it to BP Calendar 0069 return oc.process_repeat(item, dict) 0070 0071 #------------------------------------------------------------------------------- 0072 class ImportDataSource(common_calendar.ImportDataSource): 0073 # how to define, and retrieve calendar import data source 0074 0075 def browse(self, parent=None): 0076 # how to select a source 0077 self._source=native.outlook.pickfolder() 0078 0079 def name(self): 0080 # return a string name for the source 0081 if self._source: 0082 return native.outlook.getfoldername(self._source) 0083 return '' 0084 0085 def _get_id(self): 0086 if self._source: 0087 return native.outlook.getfolderid(self._source) 0088 return None 0089 def _set_id(self, id): 0090 self._source=None 0091 if id: 0092 self._source=native.outlook.getfolderfromid(id, False, 'calendar') 0093 id=property(fget=_get_id, fset=_set_id) 0094 0095 #------------------------------------------------------------------------------- 0096 class OutlookCalendarImportData: 0097 _non_auto_sync_calendar_keys=[ 0098 # (Outlook field, BP Calendar field, convertor function) 0099 ('Subject', 'description', None), 0100 ('Location', 'location', None), 0101 ('Start', 'start', to_bp_date), 0102 ('End', 'end', to_bp_date), 0103 ('Categories', 'categories', convert_categories), 0104 ('IsRecurring', 'repeat', None), 0105 ('ReminderSet', 'alarm', None), 0106 ('ReminderMinutesBeforeStart', 'alarm_value', None), 0107 ('Importance', 'priority', None), 0108 ('Body', 'notes', None), 0109 ('AllDayEvent', 'allday', None) 0110 ] 0111 # the auto_sync calender fields do not support the "body" of the appointment 0112 # accessing this field causes an outlook warning to appear which prevents automation 0113 _auto_sync_calendar_keys=[ 0114 # (Outlook field, BP Calendar field, convertor function) 0115 ('Subject', 'description', None), 0116 ('Location', 'location', None), 0117 ('Start', 'start', to_bp_date), 0118 ('End', 'end', to_bp_date), 0119 ('Categories', 'categories', convert_categories), 0120 ('IsRecurring', 'repeat', None), 0121 ('ReminderSet', 'alarm', None), 0122 ('ReminderMinutesBeforeStart', 'alarm_value', None), 0123 ('Importance', 'priority', None), 0124 ('AllDayEvent', 'allday', None) 0125 ] 0126 _recurrence_keys=[ 0127 # (Outlook field, BP Calendar field, convertor function) 0128 ('NoEndDate', 'NoEndDate', None), 0129 ('PatternStartDate', 'PatternStartDate', to_bp_date), 0130 ('PatternEndDate', 'PatternEndDate', to_bp_date), 0131 ('Instance', 'Instance', None), 0132 ('DayOfWeekMask', 'DayOfWeekMask', None), 0133 ('Interval', 'Interval', None), 0134 ('Occurrences', 'Occurrences', None), 0135 ('RecurrenceType', 'RecurrenceType', None) 0136 ] 0137 _exception_keys=[ 0138 # (Outlook field, BP Calendar field, convertor function) 0139 ('OriginalDate', 'exception_date', to_bp_date), 0140 ('Deleted', 'deleted', None) 0141 ] 0142 _default_filter={ 0143 'start': None, 0144 'end': None, 0145 'categories': None, 0146 'rpt_events': False, 0147 'no_alarm': False, 0148 'ringtone': None, 0149 'alarm_override':False, 0150 'vibrate':False, 0151 'alarm_value':0 0152 } 0153 0154 # Outlook constants 0155 olRecursDaily = native.outlook.outlook_com.constants.olRecursDaily 0156 olRecursMonthNth = native.outlook.outlook_com.constants.olRecursMonthNth 0157 olRecursMonthly = native.outlook.outlook_com.constants.olRecursMonthly 0158 olRecursWeekly = native.outlook.outlook_com.constants.olRecursWeekly 0159 olRecursYearNth = native.outlook.outlook_com.constants.olRecursYearNth 0160 olRecursYearly = native.outlook.outlook_com.constants.olRecursYearly 0161 olImportanceHigh = native.outlook.outlook_com.constants.olImportanceHigh 0162 olImportanceLow = native.outlook.outlook_com.constants.olImportanceLow 0163 olImportanceNormal = native.outlook.outlook_com.constants.olImportanceNormal 0164 0165 def __init__(self, outlook=native.outlook, auto_sync_only=0): 0166 self._outlook=outlook 0167 self._data=[] 0168 self._error_list=[] 0169 self._single_data=[] 0170 self._folder=None 0171 self._filter=self._default_filter 0172 self._total_count=0 0173 self._current_count=0 0174 self._update_dlg=None 0175 self._exception_list=[] 0176 if auto_sync_only: 0177 self._calendar_keys=self._auto_sync_calendar_keys 0178 else: 0179 self._calendar_keys=self._non_auto_sync_calendar_keys 0180 0181 def _accept(self, entry): 0182 s_date=entry['start'][:3] 0183 e_date=entry['end'][:3] 0184 if entry.get('repeat', False): 0185 # repeat event, must not fall outside the range 0186 if self._filter['start'] is not None and \ 0187 e_date<self._filter['start'][:3]: 0188 return False 0189 if self._filter['end'] is not None and \ 0190 s_date>self._filter['end'][:3]: 0191 return False 0192 else: 0193 # non-repeat event, must fall within the range 0194 if self._filter['start'] is not None and \ 0195 e_date<self._filter['start'][:3]: 0196 return False 0197 if self._filter['end'] is not None and \ 0198 e_date>self._filter['end'][:3]: 0199 return False 0200 # check the catefory 0201 c=self._filter.get('categories', None) 0202 if c is None or not len(c): 0203 # no categories specified => all catefories allowed. 0204 return True 0205 if len([x for x in entry['categories'] if x in c]): 0206 return True 0207 return False 0208 0209 def _populate_entry(self, e, ce): 0210 # populate an calendar entry with outlook data 0211 ce.description=e.get('description', None) 0212 ce.location=e.get('location', None) 0213 v=e.get('priority', None) 0214 if v is not None: 0215 if v==self.olImportanceNormal: 0216 ce.priority=ce.priority_normal 0217 elif v==self.olImportanceLow: 0218 ce.priority=ce.priority_low 0219 elif v==self.olImportanceHigh: 0220 ce.priority=ce.priority_high 0221 if not self._filter.get('no_alarm', False) and \ 0222 not self._filter.get('alarm_override', False) and \ 0223 e.get('alarm', False): 0224 ce.alarm=e.get('alarm_value', 0) 0225 ce.ringtone=self._filter.get('ringtone', "") 0226 ce.vibrate=self._filter.get('vibrate', False) 0227 elif not self._filter.get('no_alarm', False) and \ 0228 self._filter.get('alarm_override', False): 0229 ce.alarm=self._filter.get('alarm_value', 0) 0230 ce.ringtone=self._filter.get('ringtone', "") 0231 ce.vibrate=self._filter.get('vibrate', False) 0232 ce.allday=e.get('allday', False) 0233 if ce.allday: 0234 if not e.get('repeat', False): 0235 ce.start=e['start'][:3]+(0,0) 0236 # for non-recurrent allday events, Outlook always set the 0237 # end date to 1-extra day. 0238 _dt=datetime.datetime(*e['end'])-datetime.timedelta(1) 0239 ce.end=(_dt.year, _dt.month, _dt.day, 23, 59) 0240 else: 0241 # unless it is a repeating all day event! 0242 # we can now handle allday events that span more than one day! 0243 ce.start=e['start'][:3]+(0,0) 0244 ce.end=e['end'][:3]+(23,59) 0245 else: 0246 ce.start=e['start'] 0247 ce.end=e['end'] 0248 ce.notes=e.get('notes', None) 0249 v=[] 0250 for k in e.get('categories', []): 0251 v.append({ 'category': k }) 0252 ce.categories=v 0253 # look at repeat events 0254 if not e.get('repeat', False): 0255 # not a repeat event, just return 0256 return 0257 rp=bpcalendar.RepeatEntry() 0258 rt=e['repeat_type'] 0259 r_interval=e.get('repeat_interval', 0) 0260 r_interval2=e.get('repeat_interval2', 1) 0261 r_dow=e.get('repeat_dow', 0) 0262 if rt==self.olRecursDaily: 0263 rp.repeat_type=rp.daily 0264 elif rt==self.olRecursWeekly: 0265 if r_interval: 0266 # weekly event 0267 rp.repeat_type=rp.weekly 0268 else: 0269 # mon-fri event 0270 rp.repeat_type=rp.daily 0271 elif rt==self.olRecursMonthly or rt==self.olRecursMonthNth: 0272 rp.repeat_type=rp.monthly 0273 else: 0274 rp.repeat_type=rp.yearly 0275 if rp.repeat_type==rp.daily: 0276 rp.interval=r_interval 0277 elif rp.repeat_type==rp.weekly or rp.repeat_type==rp.monthly: 0278 rp.interval=r_interval 0279 rp.interval2=r_interval2 0280 rp.dow=r_dow 0281 # check for invalid monthly type 0282 if rp.repeat_type==rp.monthly and \ 0283 rp.dow in (rp.dow_weekday, rp.dow_weekend): 0284 rp.dow=0 0285 # add the list of exceptions 0286 for k in e.get('exceptions', []): 0287 rp.add_suppressed(*k[:3]) 0288 ce.repeat=rp 0289 0290 def _generate_repeat_events(self, e): 0291 # generate multiple single events from this repeat event 0292 ce=bpcalendar.CalendarEntry() 0293 self._populate_entry(e, ce) 0294 l=[] 0295 new_e=e.copy() 0296 new_e['repeat']=False 0297 for k in ('repeat_type', 'repeat_interval', 'repeat_dow'): 0298 if new_e.has_key(k): 0299 del new_e[k] 0300 s_date=datetime.datetime(*self._filter['start']) 0301 e_date=datetime.datetime(*self._filter['end']) 0302 one_day=datetime.timedelta(1) 0303 this_date=s_date 0304 while this_date<=e_date: 0305 date_l=(this_date.year, this_date.month, this_date.day) 0306 if ce.is_active(*date_l): 0307 new_e['start']=date_l+new_e['start'][3:] 0308 new_e['end']=date_l+new_e['end'][3:] 0309 l.append(new_e.copy()) 0310 this_date+=one_day 0311 return l 0312 0313 def get(self): 0314 res={} 0315 single_rpt=self._filter.get('rpt_events', False) 0316 for k in self._data: 0317 if self._accept(k): 0318 if k.get('repeat', False) and single_rpt: 0319 d=self._generate_repeat_events(k) 0320 else: 0321 d=[k] 0322 for n in d: 0323 ce=bpcalendar.CalendarEntry() 0324 self._populate_entry(n, ce) 0325 res[ce.id]=ce 0326 return res 0327 0328 def get_display_data(self): 0329 cnt=0 0330 res={} 0331 single_rpt=self._filter.get('rpt_events', False) 0332 no_alarm=self._filter.get('no_alarm', False) 0333 for k in self._data: 0334 if self._accept(k): 0335 if k.get('repeat', False) and single_rpt: 0336 d=self._generate_repeat_events(k) 0337 else: 0338 d=[k.copy()] 0339 for n in d: 0340 if no_alarm: 0341 n['alarm']=False 0342 res[cnt]=n 0343 cnt+=1 0344 return res 0345 0346 def get_category_list(self): 0347 l=[] 0348 for e in self._data: 0349 l+=[x for x in e.get('categories', []) if x not in l] 0350 return l 0351 0352 def pick_folder(self): 0353 return self._outlook.pickfolder() 0354 0355 def set_folder(self, f): 0356 if f is None: 0357 # default folder 0358 self._folder=self._outlook.getfolderfromid('', True, 'calendar') 0359 else: 0360 self._folder=f 0361 0362 def get_folder_id(self): 0363 return self._outlook.getfolderid(self._folder) 0364 0365 def set_folder_id(self, id): 0366 if id is None or id=="": 0367 self.set_folder(None) 0368 else: 0369 self._folder=self._outlook.getfolderfromid(id) 0370 0371 def set_filter(self, filter): 0372 self._filter=filter 0373 0374 def get_filter(self): 0375 return self._filter 0376 0377 def get_folder_name(self): 0378 if self._folder is None: 0379 return '' 0380 return self._outlook.getfoldername(self._folder) 0381 0382 def read(self, folder=None, update_dlg=None): 0383 # folder from which to read 0384 if folder is not None: 0385 self._folder=folder 0386 if self._folder is None: 0387 self._folder=self._outlook.getfolderfromid('', True, 'calendar') 0388 self._update_dlg=update_dlg 0389 self._total_count=self._folder.Items.Count 0390 self._current_count=0 0391 self._exception_list=[] 0392 self._data, self._error_list=self._outlook.getdata(self._folder, 0393 self._calendar_keys, 0394 {}, self, 0395 set_recurrence) 0396 # add in the exception list, .. or shoule we keep it separate ?? 0397 self._data+=self._exception_list 0398 0399 def _set_repeat_dates(self, dict, r): 0400 dict['start']=r['PatternStartDate'][:3]+dict['start'][3:] 0401 dict['end']=r['PatternEndDate'][:3]+dict['end'][3:] 0402 dict['repeat_type']=r['RecurrenceType'] 0403 0404 def _is_daily_or_weekly(self, dict, r): 0405 if r['RecurrenceType']==self.olRecursDaily or \ 0406 r['RecurrenceType']==self.olRecursWeekly: 0407 self._set_repeat_dates(dict, r) 0408 dict['repeat_interval']=r['Interval'] 0409 dict['repeat_dow']=r['DayOfWeekMask'] 0410 return True 0411 return False 0412 0413 def _is_monthly(self, dict, r): 0414 if r['RecurrenceType']==self.olRecursMonthly or \ 0415 r['RecurrenceType']==self.olRecursMonthNth: 0416 self._set_repeat_dates(dict, r) 0417 dict['repeat_interval2']=r['Interval'] 0418 if r['RecurrenceType']==self.olRecursMonthNth: 0419 dict['repeat_interval']=r['Instance'] 0420 dict['repeat_dow']=r['DayOfWeekMask'] 0421 return True 0422 return False 0423 0424 def _is_yearly(self, dict, r): 0425 if r['RecurrenceType']==self.olRecursYearly and \ 0426 r['Interval']==12: 0427 self._set_repeat_dates(dict, r) 0428 return True 0429 return False 0430 0431 def _process_exceptions(self, dict, r): 0432 # check for and process exceptions for this event 0433 r_ex=r.Exceptions 0434 if not r_ex.Count: 0435 # no exception, bail 0436 return 0437 for i in range(1, r_ex.Count+1): 0438 ex=self._outlook.getitemdata(r_ex.Item(i), {}, 0439 self._exception_keys, self) 0440 dict.setdefault('exceptions', []).append(ex['exception_date']) 0441 if not ex['deleted']: 0442 # if this instance has been changed, then need to get it 0443 appt=self._outlook.getitemdata(r_ex.Item(i).AppointmentItem, 0444 {}, self._calendar_keys, self) 0445 # by definition, this instance cannot be a repeat event 0446 appt['repeat']=False 0447 appt['end']=appt['start'][:3]+appt['end'][3:] 0448 # and add it to the exception list 0449 self._exception_list.append(appt) 0450 0451 def process_repeat(self, item, dict): 0452 # get the recurrence info that we need. 0453 rec_pat=item.GetRecurrencePattern() 0454 r=self._outlook.getitemdata(rec_pat, {}, 0455 self._recurrence_keys, self) 0456 if self._is_daily_or_weekly(dict, r) or \ 0457 self._is_monthly(dict, r) or \ 0458 self._is_yearly(dict, r): 0459 self._process_exceptions(dict, rec_pat) 0460 return True 0461 # invalide repeat type, turn this event into a regular event 0462 dict['repeat']=False 0463 dict['end']=dict['start'][:3]+dict['end'][3:] 0464 dict['notes']+=' [BITPIM: Unrecognized repeat event, repeat event discarded]' 0465 return True 0466 0467 def update_display(self): 0468 # update the progress dialog if specified 0469 self._current_count += 1 0470 if self._update_dlg is not None: 0471 self._update_dlg.Update(100*self._current_count/self._total_count) 0472 0473 def has_errors(self): 0474 return bool(self._error_list) 0475 def get_error_list(self): 0476 # return a list of strings of failed items 0477 res=[] 0478 for d in self._error_list: 0479 # the format is 'YY-MM-DD hh:mm Description' if available 0480 _start=d.get('start', None) 0481 s='' 0482 if _start: 0483 if len(_start)>4: 0484 s='%02d-%02d-%02d %02d:%02d '%_start[:5] 0485 elif len(_start)>2: 0486 s='%02d-%02d-%02d '%_start[:3] 0487 _desc=d.get('description', None) 0488 if _desc: 0489 s+=_desc 0490 if not s: 0491 s='<Unknown>' 0492 res.append(s) 0493 return res 0494 0495 #------------------------------------------------------------------------------- 0496 class OutlookImportCalDialog(common_calendar.PreviewDialog): 0497 _column_labels=[ 0498 ('description', 'Description', 400, None), 0499 ('start', 'Start', 150, common_calendar.bp_date_str), 0500 ('end', 'End', 150, common_calendar.bp_date_str), 0501 ('repeat_type', 'Repeat', 80, bp_repeat_str), 0502 ('alarm', 'Alarm', 80, common_calendar.bp_alarm_str), 0503 ('categories', 'Category', 150, common_calendar.category_str) 0504 ] 0505 0506 _config_name='import/calendar/outlookdialog' 0507 _browse_label='Outlook Calendar Folder:' 0508 _progress_dlg_title='Outlook Calendar Import' 0509 _error_dlg_title='Outlook Calendar Import Error' 0510 _error_dlg_text='Outlook Calendar Items that failed to import:' 0511 _data_class=OutlookCalendarImportData 0512 _filter_dlg_class=common_calendar.FilterDialog 0513 0514 def __init__(self, parent, id, title): 0515 self._oc=self._data_class(native.outlook) 0516 self._oc.set_folder(None) 0517 common_calendar.PreviewDialog.__init__(self, parent, id, title, 0518 self._column_labels, 0519 self._oc.get_display_data(), 0520 config_name=self._config_name) 0521 0522 def getcontrols(self, main_bs): 0523 hbs=wx.BoxSizer(wx.HORIZONTAL) 0524 # label 0525 hbs.Add(wx.StaticText(self, -1, self._browse_label), 0, wx.ALL|wx.ALIGN_CENTRE, 2) 0526 # where the folder name goes 0527 self.folderctrl=wx.TextCtrl(self, -1, "", style=wx.TE_READONLY) 0528 self.folderctrl.SetValue(self._oc.get_folder_name()) 0529 hbs.Add(self.folderctrl, 1, wx.EXPAND|wx.ALL, 2) 0530 # browse button 0531 id_browse=wx.NewId() 0532 hbs.Add(wx.Button(self, id_browse, 'Browse ...'), 0, wx.EXPAND|wx.ALL, 2) 0533 main_bs.Add(hbs, 0, wx.EXPAND|wx.ALL, 5) 0534 main_bs.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5) 0535 wx.EVT_BUTTON(self, id_browse, self.OnBrowseFolder) 0536 0537 def getpostcontrols(self, main_bs): 0538 main_bs.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5) 0539 hbs=wx.BoxSizer(wx.HORIZONTAL) 0540 id_import=wx.NewId() 0541 hbs.Add(wx.Button(self, id_import, 'Import'), 0, wx.ALIGN_CENTRE|wx.ALL, 5) 0542 hbs.Add(wx.Button(self, wx.ID_OK, 'Replace All'), 0, wx.ALIGN_CENTRE|wx.ALL, 5) 0543 hbs.Add(wx.Button(self, self.ID_ADD, 'Add'), 0, wx.ALIGN_CENTRE|wx.ALL, 5) 0544 hbs.Add(wx.Button(self, self.ID_MERGE, 'Merge'), 0, wx.ALIGN_CENTRE|wx.ALL, 5) 0545 hbs.Add(wx.Button(self, wx.ID_CANCEL, 'Cancel'), 0, wx.ALIGN_CENTRE|wx.ALL, 5) 0546 id_filter=wx.NewId() 0547 hbs.Add(wx.Button(self, id_filter, 'Filter'), 0, wx.ALIGN_CENTRE|wx.ALL, 5) 0548 hbs.Add(wx.Button(self, wx.ID_HELP, 'Help'), 0, wx.ALIGN_CENTRE|wx.ALL, 5) 0549 main_bs.Add(hbs, 0, wx.ALIGN_CENTRE|wx.ALL, 5) 0550 wx.EVT_BUTTON(self, id_import, self.OnImport) 0551 wx.EVT_BUTTON(self, id_filter, self.OnFilter) 0552 wx.EVT_BUTTON(self, self.ID_ADD, self.OnEndModal) 0553 wx.EVT_BUTTON(self, self.ID_MERGE, self.OnEndModal) 0554 wx.EVT_BUTTON(self, wx.ID_HELP, lambda *_: wx.GetApp().displayhelpid(helpids.ID_DLG_CALENDAR_IMPORT)) 0555 0556 @guihelper.BusyWrapper 0557 def OnImport(self, evt): 0558 with guihelper.WXDialogWrapper(wx.ProgressDialog(self._progress_dlg_title, 0559 'Importing Outlook Data, please wait ...\n(Please also watch out for the Outlook Permission Request dialog)', 0560 parent=self)) as dlg: 0561 self._oc.read(None, dlg) 0562 self.populate(self._oc.get_display_data()) 0563 if self._oc.has_errors(): 0564 # display the list of failed items 0565 with guihelper.WXDialogWrapper(wx.SingleChoiceDialog(self, 0566 self._error_dlg_text, 0567 self._error_dlg_title, 0568 self._oc.get_error_list()), 0569 True): 0570 pass 0571 0572 def OnBrowseFolder(self, evt): 0573 f=self._oc.pick_folder() 0574 if f is None: 0575 return # user hit cancel 0576 self._oc.set_folder(f) 0577 self.folderctrl.SetValue(self._oc.get_folder_name()) 0578 0579 def OnFilter(self, evt): 0580 cat_list=self._oc.get_category_list() 0581 with guihelper.WXDialogWrapper(self._filter_dlg_class(self, -1, 'Filtering Parameters', cat_list), 0582 True) as (dlg, retcode): 0583 if retcode==wx.ID_OK: 0584 self._oc.set_filter(dlg.get()) 0585 self.populate(self._oc.get_display_data()) 0586 0587 def OnEndModal(self, evt): 0588 self.EndModal(evt.GetId()) 0589 0590 def get(self): 0591 return self._oc.get() 0592 0593 def get_categories(self): 0594 return self._oc.get_category_list() 0595 0596 #------------------------------------------------------------------------------- 0597 def ImportCal(folder, filters): 0598 _oc=OutlookCalendarImportData(native.outlook, auto_sync_only=1) 0599 _oc.set_folder_id(folder) 0600 _oc.set_filter(filters) 0601 _oc.read() 0602 res={ 'calendar':_oc.get() } 0603 return res 0604 0605 #------------------------------------------------------------------------------- 0606 class OutlookAutoConfCalDialog(wx.Dialog): 0607 def __init__(self, parent, id, title, folder, filters, 0608 style=wx.CAPTION|wx.MAXIMIZE_BOX| \ 0609 wx.SYSTEM_MENU|wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER): 0610 self._oc=OutlookCalendarImportData(native.outlook, auto_sync_only=1) 0611 self._oc.set_folder_id(folder) 0612 self._oc.set_filter(filters) 0613 self.__read=False 0614 wx.Dialog.__init__(self, parent, id=id, title=title, style=style) 0615 main_bs=wx.BoxSizer(wx.VERTICAL) 0616 hbs=wx.BoxSizer(wx.HORIZONTAL) 0617 # label 0618 hbs.Add(wx.StaticText(self, -1, "Outlook Calendar Folder:"), 0, wx.ALL|wx.ALIGN_CENTRE, 2) 0619 # where the folder name goes 0620 self.folderctrl=wx.TextCtrl(self, -1, "", style=wx.TE_READONLY) 0621 self.folderctrl.SetValue(self._oc.get_folder_name()) 0622 hbs.Add(self.folderctrl, 1, wx.EXPAND|wx.ALL, 2) 0623 # browse button 0624 id_browse=wx.NewId() 0625 hbs.Add(wx.Button(self, id_browse, 'Browse ...'), 0, wx.EXPAND|wx.ALL, 2) 0626 main_bs.Add(hbs, 0, wx.EXPAND|wx.ALL, 5) 0627 main_bs.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5) 0628 wx.EVT_BUTTON(self, id_browse, self.OnBrowseFolder) 0629 hbs=wx.BoxSizer(wx.HORIZONTAL) 0630 hbs.Add(wx.Button(self, wx.ID_OK, 'OK'), 0, wx.ALIGN_CENTRE|wx.ALL, 5) 0631 hbs.Add(wx.Button(self, wx.ID_CANCEL, 'Cancel'), 0, wx.ALIGN_CENTRE|wx.ALL, 5) 0632 id_filter=wx.NewId() 0633 hbs.Add(wx.Button(self, id_filter, 'Filter'), 0, wx.ALIGN_CENTRE|wx.ALL, 5) 0634 hbs.Add(wx.Button(self, wx.ID_HELP, 'Help'), 0, wx.ALIGN_CENTRE|wx.ALL, 5) 0635 main_bs.Add(hbs, 0, wx.ALIGN_CENTRE|wx.ALL, 5) 0636 wx.EVT_BUTTON(self, id_filter, self.OnFilter) 0637 wx.EVT_BUTTON(self, wx.ID_HELP, lambda *_: wx.GetApp().displayhelpid(helpids.ID_DLG_CALENDAR_IMPORT)) 0638 self.SetSizer(main_bs) 0639 self.SetAutoLayout(True) 0640 main_bs.Fit(self) 0641 0642 def OnBrowseFolder(self, evt): 0643 f=self._oc.pick_folder() 0644 if f is None: 0645 return # user hit cancel 0646 self._oc.set_folder(f) 0647 self.folderctrl.SetValue(self._oc.get_folder_name()) 0648 self.__read=False 0649 0650 def OnFilter(self, evt): 0651 # read the calender to get the category list 0652 if not self.__read: 0653 self._oc.read() 0654 self.__read=True 0655 cat_list=self._oc.get_category_list() 0656 with guihelper.WXDialogWrapper(common_calendar.AutoSyncFilterDialog(self, -1, 'Filtering Parameters', cat_list)) as dlg: 0657 dlg.set(self._oc.get_filter()) 0658 if dlg.ShowModal()==wx.ID_OK: 0659 self._oc.set_filter(dlg.get()) 0660 0661 def GetFolder(self): 0662 return self._oc.get_folder_id() 0663 0664 def GetFilter(self): 0665 return self._oc.get_filter() 0666
Generated by PyXR 0.9.4