Module outlook_calendar
[hide private]
[frames] | no frames]

Source Code for Module outlook_calendar

  1  ### BITPIM 
  2  ### 
  3  ### Copyright (C) 2004 Joe Pham <djpham@netzero.com> 
  4  ### 
  5  ### This program is free software; you can redistribute it and/or modify 
  6  ### it under the terms of the BitPim license as detailed in the LICENSE file. 
  7  ### 
  8  ### $Id: outlook_calendar.py 4405 2007-09-24 21:49:06Z djpham $ 
  9   
 10  "Deals with Outlook calendar import stuff" 
 11   
 12  # System modules 
 13  from __future__ import with_statement 
 14  import datetime 
 15  import pywintypes 
 16  import sys 
 17  import time 
 18   
 19  # wxPython modules 
 20  import wx 
 21  import wx.calendar 
 22  import wx.lib.mixins.listctrl as listmix 
 23   
 24  # Others 
 25   
 26  # My modules 
 27  import bpcalendar 
 28  import common 
 29  import common_calendar 
 30  import guihelper 
 31  import guiwidgets 
 32  import helpids 
 33  import native.outlook 
34 35 # common convertor functions 36 -def to_bp_date(dict, v, oc):
37 # convert a pyTime to (y, m, d, h, m) 38 if not isinstance(v, pywintypes.TimeType): 39 raise TypeError, 'illegal type' 40 if v.year>common_calendar.no_end_date[0]: 41 return common_calendar.no_end_date 42 return (v.year, v.month, v.day, v.hour, v.minute)
43
44 -def bp_repeat_str(dict, v):
45 if v is None: 46 return '' 47 elif v==OutlookCalendarImportData.olRecursDaily: 48 return 'Daily' 49 elif v==OutlookCalendarImportData.olRecursWeekly: 50 return 'Weekly' 51 elif v==OutlookCalendarImportData.olRecursMonthly or \ 52 v==OutlookCalendarImportData.olRecursMonthNth: 53 return 'Monthly' 54 elif v==OutlookCalendarImportData.olRecursYearly: 55 return 'Yearly' 56 else: 57 return '<Unknown Value>'
58
59 -def convert_categories(dict, v, oc):
60 return [x.strip() for x in v.split(",") if len(x)]
61
62 -def set_recurrence(item, dict, oc):
63 oc.update_display() 64 if not dict['repeat']: 65 # no reccurrence, ignore 66 dict['repeat']=None 67 return True 68 # get the recurrence pattern and map it to BP Calendar 69 return oc.process_repeat(item, dict)
70
71 #------------------------------------------------------------------------------- 72 -class ImportDataSource(common_calendar.ImportDataSource):
73 # how to define, and retrieve calendar import data source 74
75 - def browse(self, parent=None):
76 # how to select a source 77 self._source=native.outlook.pickfolder()
78
79 - def name(self):
80 # return a string name for the source 81 if self._source: 82 return native.outlook.getfoldername(self._source) 83 return ''
84
85 - def _get_id(self):
86 if self._source: 87 return native.outlook.getfolderid(self._source) 88 return None
89 - def _set_id(self, id):
90 self._source=None 91 if id: 92 self._source=native.outlook.getfolderfromid(id, False, 'calendar')
93 id=property(fget=_get_id, fset=_set_id)
94
95 #------------------------------------------------------------------------------- 96 -class OutlookCalendarImportData:
97 _non_auto_sync_calendar_keys=[ 98 # (Outlook field, BP Calendar field, convertor function) 99 ('Subject', 'description', None), 100 ('Location', 'location', None), 101 ('Start', 'start', to_bp_date), 102 ('End', 'end', to_bp_date), 103 ('Categories', 'categories', convert_categories), 104 ('IsRecurring', 'repeat', None), 105 ('ReminderSet', 'alarm', None), 106 ('ReminderMinutesBeforeStart', 'alarm_value', None), 107 ('Importance', 'priority', None), 108 ('Body', 'notes', None), 109 ('AllDayEvent', 'allday', None) 110 ] 111 # the auto_sync calender fields do not support the "body" of the appointment 112 # accessing this field causes an outlook warning to appear which prevents automation 113 _auto_sync_calendar_keys=[ 114 # (Outlook field, BP Calendar field, convertor function) 115 ('Subject', 'description', None), 116 ('Location', 'location', None), 117 ('Start', 'start', to_bp_date), 118 ('End', 'end', to_bp_date), 119 ('Categories', 'categories', convert_categories), 120 ('IsRecurring', 'repeat', None), 121 ('ReminderSet', 'alarm', None), 122 ('ReminderMinutesBeforeStart', 'alarm_value', None), 123 ('Importance', 'priority', None), 124 ('AllDayEvent', 'allday', None) 125 ] 126 _recurrence_keys=[ 127 # (Outlook field, BP Calendar field, convertor function) 128 ('NoEndDate', 'NoEndDate', None), 129 ('PatternStartDate', 'PatternStartDate', to_bp_date), 130 ('PatternEndDate', 'PatternEndDate', to_bp_date), 131 ('Instance', 'Instance', None), 132 ('DayOfWeekMask', 'DayOfWeekMask', None), 133 ('Interval', 'Interval', None), 134 ('Occurrences', 'Occurrences', None), 135 ('RecurrenceType', 'RecurrenceType', None) 136 ] 137 _exception_keys=[ 138 # (Outlook field, BP Calendar field, convertor function) 139 ('OriginalDate', 'exception_date', to_bp_date), 140 ('Deleted', 'deleted', None) 141 ] 142 _default_filter={ 143 'start': None, 144 'end': None, 145 'categories': None, 146 'rpt_events': False, 147 'no_alarm': False, 148 'ringtone': None, 149 'alarm_override':False, 150 'vibrate':False, 151 'alarm_value':0 152 } 153 154 # Outlook constants 155 olRecursDaily = native.outlook.outlook_com.constants.olRecursDaily 156 olRecursMonthNth = native.outlook.outlook_com.constants.olRecursMonthNth 157 olRecursMonthly = native.outlook.outlook_com.constants.olRecursMonthly 158 olRecursWeekly = native.outlook.outlook_com.constants.olRecursWeekly 159 olRecursYearNth = native.outlook.outlook_com.constants.olRecursYearNth 160 olRecursYearly = native.outlook.outlook_com.constants.olRecursYearly 161 olImportanceHigh = native.outlook.outlook_com.constants.olImportanceHigh 162 olImportanceLow = native.outlook.outlook_com.constants.olImportanceLow 163 olImportanceNormal = native.outlook.outlook_com.constants.olImportanceNormal 164
165 - def __init__(self, outlook=native.outlook, auto_sync_only=0):
166 self._outlook=outlook 167 self._data=[] 168 self._error_list=[] 169 self._single_data=[] 170 self._folder=None 171 self._filter=self._default_filter 172 self._total_count=0 173 self._current_count=0 174 self._update_dlg=None 175 self._exception_list=[] 176 if auto_sync_only: 177 self._calendar_keys=self._auto_sync_calendar_keys 178 else: 179 self._calendar_keys=self._non_auto_sync_calendar_keys
180
181 - def _accept(self, entry):
182 s_date=entry['start'][:3] 183 e_date=entry['end'][:3] 184 if entry.get('repeat', False): 185 # repeat event, must not fall outside the range 186 if self._filter['start'] is not None and \ 187 e_date<self._filter['start'][:3]: 188 return False 189 if self._filter['end'] is not None and \ 190 s_date>self._filter['end'][:3]: 191 return False 192 else: 193 # non-repeat event, must fall within the range 194 if self._filter['start'] is not None and \ 195 e_date<self._filter['start'][:3]: 196 return False 197 if self._filter['end'] is not None and \ 198 e_date>self._filter['end'][:3]: 199 return False 200 # check the catefory 201 c=self._filter.get('categories', None) 202 if c is None or not len(c): 203 # no categories specified => all catefories allowed. 204 return True 205 if len([x for x in entry['categories'] if x in c]): 206 return True 207 return False
208
209 - def _populate_entry(self, e, ce):
210 # populate an calendar entry with outlook data 211 ce.description=e.get('description', None) 212 ce.location=e.get('location', None) 213 v=e.get('priority', None) 214 if v is not None: 215 if v==self.olImportanceNormal: 216 ce.priority=ce.priority_normal 217 elif v==self.olImportanceLow: 218 ce.priority=ce.priority_low 219 elif v==self.olImportanceHigh: 220 ce.priority=ce.priority_high 221 if not self._filter.get('no_alarm', False) and \ 222 not self._filter.get('alarm_override', False) and \ 223 e.get('alarm', False): 224 ce.alarm=e.get('alarm_value', 0) 225 ce.ringtone=self._filter.get('ringtone', "") 226 ce.vibrate=self._filter.get('vibrate', False) 227 elif not self._filter.get('no_alarm', False) and \ 228 self._filter.get('alarm_override', False): 229 ce.alarm=self._filter.get('alarm_value', 0) 230 ce.ringtone=self._filter.get('ringtone', "") 231 ce.vibrate=self._filter.get('vibrate', False) 232 ce.allday=e.get('allday', False) 233 if ce.allday: 234 if not e.get('repeat', False): 235 ce.start=e['start'][:3]+(0,0) 236 # for non-recurrent allday events, Outlook always set the 237 # end date to 1-extra day. 238 _dt=datetime.datetime(*e['end'])-datetime.timedelta(1) 239 ce.end=(_dt.year, _dt.month, _dt.day, 23, 59) 240 else: 241 # unless it is a repeating all day event! 242 # we can now handle allday events that span more than one day! 243 ce.start=e['start'][:3]+(0,0) 244 ce.end=e['end'][:3]+(23,59) 245 else: 246 ce.start=e['start'] 247 ce.end=e['end'] 248 ce.notes=e.get('notes', None) 249 v=[] 250 for k in e.get('categories', []): 251 v.append({ 'category': k }) 252 ce.categories=v 253 # look at repeat events 254 if not e.get('repeat', False): 255 # not a repeat event, just return 256 return 257 rp=bpcalendar.RepeatEntry() 258 rt=e['repeat_type'] 259 r_interval=e.get('repeat_interval', 0) 260 r_interval2=e.get('repeat_interval2', 1) 261 r_dow=e.get('repeat_dow', 0) 262 if rt==self.olRecursDaily: 263 rp.repeat_type=rp.daily 264 elif rt==self.olRecursWeekly: 265 if r_interval: 266 # weekly event 267 rp.repeat_type=rp.weekly 268 else: 269 # mon-fri event 270 rp.repeat_type=rp.daily 271 elif rt==self.olRecursMonthly or rt==self.olRecursMonthNth: 272 rp.repeat_type=rp.monthly 273 else: 274 rp.repeat_type=rp.yearly 275 if rp.repeat_type==rp.daily: 276 rp.interval=r_interval 277 elif rp.repeat_type==rp.weekly or rp.repeat_type==rp.monthly: 278 rp.interval=r_interval 279 rp.interval2=r_interval2 280 rp.dow=r_dow 281 # check for invalid monthly type 282 if rp.repeat_type==rp.monthly and \ 283 rp.dow in (rp.dow_weekday, rp.dow_weekend): 284 rp.dow=0 285 # add the list of exceptions 286 for k in e.get('exceptions', []): 287 rp.add_suppressed(*k[:3]) 288 ce.repeat=rp
289
290 - def _generate_repeat_events(self, e):
291 # generate multiple single events from this repeat event 292 ce=bpcalendar.CalendarEntry() 293 self._populate_entry(e, ce) 294 l=[] 295 new_e=e.copy() 296 new_e['repeat']=False 297 for k in ('repeat_type', 'repeat_interval', 'repeat_dow'): 298 if new_e.has_key(k): 299 del new_e[k] 300 s_date=datetime.datetime(*self._filter['start']) 301 e_date=datetime.datetime(*self._filter['end']) 302 one_day=datetime.timedelta(1) 303 this_date=s_date 304 while this_date<=e_date: 305 date_l=(this_date.year, this_date.month, this_date.day) 306 if ce.is_active(*date_l): 307 new_e['start']=date_l+new_e['start'][3:] 308 new_e['end']=date_l+new_e['end'][3:] 309 l.append(new_e.copy()) 310 this_date+=one_day 311 return l
312
313 - def get(self):
314 res={} 315 single_rpt=self._filter.get('rpt_events', False) 316 for k in self._data: 317 if self._accept(k): 318 if k.get('repeat', False) and single_rpt: 319 d=self._generate_repeat_events(k) 320 else: 321 d=[k] 322 for n in d: 323 ce=bpcalendar.CalendarEntry() 324 self._populate_entry(n, ce) 325 res[ce.id]=ce 326 return res
327
328 - def get_display_data(self):
329 cnt=0 330 res={} 331 single_rpt=self._filter.get('rpt_events', False) 332 no_alarm=self._filter.get('no_alarm', False) 333 for k in self._data: 334 if self._accept(k): 335 if k.get('repeat', False) and single_rpt: 336 d=self._generate_repeat_events(k) 337 else: 338 d=[k.copy()] 339 for n in d: 340 if no_alarm: 341 n['alarm']=False 342 res[cnt]=n 343 cnt+=1 344 return res
345
346 - def get_category_list(self):
347 l=[] 348 for e in self._data: 349 l+=[x for x in e.get('categories', []) if x not in l] 350 return l
351
352 - def pick_folder(self):
353 return self._outlook.pickfolder()
354
355 - def set_folder(self, f):
356 if f is None: 357 # default folder 358 self._folder=self._outlook.getfolderfromid('', True, 'calendar') 359 else: 360 self._folder=f
361
362 - def get_folder_id(self):
363 return self._outlook.getfolderid(self._folder)
364
365 - def set_folder_id(self, id):
366 if id is None or id=="": 367 self.set_folder(None) 368 else: 369 self._folder=self._outlook.getfolderfromid(id)
370
371 - def set_filter(self, filter):
372 self._filter=filter
373
374 - def get_filter(self):
375 return self._filter
376
377 - def get_folder_name(self):
378 if self._folder is None: 379 return '' 380 return self._outlook.getfoldername(self._folder)
381
382 - def read(self, folder=None, update_dlg=None):
383 # folder from which to read 384 if folder is not None: 385 self._folder=folder 386 if self._folder is None: 387 self._folder=self._outlook.getfolderfromid('', True, 'calendar') 388 self._update_dlg=update_dlg 389 self._total_count=self._folder.Items.Count 390 self._current_count=0 391 self._exception_list=[] 392 self._data, self._error_list=self._outlook.getdata(self._folder, 393 self._calendar_keys, 394 {}, self, 395 set_recurrence) 396 # add in the exception list, .. or shoule we keep it separate ?? 397 self._data+=self._exception_list
398
399 - def _set_repeat_dates(self, dict, r):
400 dict['start']=r['PatternStartDate'][:3]+dict['start'][3:] 401 dict['end']=r['PatternEndDate'][:3]+dict['end'][3:] 402 dict['repeat_type']=r['RecurrenceType']
403
404 - def _is_daily_or_weekly(self, dict, r):
405 if r['RecurrenceType']==self.olRecursDaily or \ 406 r['RecurrenceType']==self.olRecursWeekly: 407 self._set_repeat_dates(dict, r) 408 dict['repeat_interval']=r['Interval'] 409 dict['repeat_dow']=r['DayOfWeekMask'] 410 return True 411 return False
412
413 - def _is_monthly(self, dict, r):
414 if r['RecurrenceType']==self.olRecursMonthly or \ 415 r['RecurrenceType']==self.olRecursMonthNth: 416 self._set_repeat_dates(dict, r) 417 dict['repeat_interval2']=r['Interval'] 418 if r['RecurrenceType']==self.olRecursMonthNth: 419 dict['repeat_interval']=r['Instance'] 420 dict['repeat_dow']=r['DayOfWeekMask'] 421 return True 422 return False
423
424 - def _is_yearly(self, dict, r):
425 if r['RecurrenceType']==self.olRecursYearly and \ 426 r['Interval']==12: 427 self._set_repeat_dates(dict, r) 428 return True 429 return False
430
431 - def _process_exceptions(self, dict, r):
432 # check for and process exceptions for this event 433 r_ex=r.Exceptions 434 if not r_ex.Count: 435 # no exception, bail 436 return 437 for i in range(1, r_ex.Count+1): 438 ex=self._outlook.getitemdata(r_ex.Item(i), {}, 439 self._exception_keys, self) 440 dict.setdefault('exceptions', []).append(ex['exception_date']) 441 if not ex['deleted']: 442 # if this instance has been changed, then need to get it 443 appt=self._outlook.getitemdata(r_ex.Item(i).AppointmentItem, 444 {}, self._calendar_keys, self) 445 # by definition, this instance cannot be a repeat event 446 appt['repeat']=False 447 appt['end']=appt['start'][:3]+appt['end'][3:] 448 # and add it to the exception list 449 self._exception_list.append(appt)
450
451 - def process_repeat(self, item, dict):
452 # get the recurrence info that we need. 453 rec_pat=item.GetRecurrencePattern() 454 r=self._outlook.getitemdata(rec_pat, {}, 455 self._recurrence_keys, self) 456 if self._is_daily_or_weekly(dict, r) or \ 457 self._is_monthly(dict, r) or \ 458 self._is_yearly(dict, r): 459 self._process_exceptions(dict, rec_pat) 460 return True 461 # invalide repeat type, turn this event into a regular event 462 dict['repeat']=False 463 dict['end']=dict['start'][:3]+dict['end'][3:] 464 dict['notes']+=' [BITPIM: Unrecognized repeat event, repeat event discarded]' 465 return True
466
467 - def update_display(self):
468 # update the progress dialog if specified 469 self._current_count += 1 470 if self._update_dlg is not None: 471 self._update_dlg.Update(100*self._current_count/self._total_count)
472
473 - def has_errors(self):
474 return bool(self._error_list)
475 - def get_error_list(self):
476 # return a list of strings of failed items 477 res=[] 478 for d in self._error_list: 479 # the format is 'YY-MM-DD hh:mm Description' if available 480 _start=d.get('start', None) 481 s='' 482 if _start: 483 if len(_start)>4: 484 s='%02d-%02d-%02d %02d:%02d '%_start[:5] 485 elif len(_start)>2: 486 s='%02d-%02d-%02d '%_start[:3] 487 _desc=d.get('description', None) 488 if _desc: 489 s+=_desc 490 if not s: 491 s='<Unknown>' 492 res.append(s) 493 return res
494
495 #------------------------------------------------------------------------------- 496 -class OutlookImportCalDialog(common_calendar.PreviewDialog):
497 _column_labels=[ 498 ('description', 'Description', 400, None), 499 ('start', 'Start', 150, common_calendar.bp_date_str), 500 ('end', 'End', 150, common_calendar.bp_date_str), 501 ('repeat_type', 'Repeat', 80, bp_repeat_str), 502 ('alarm', 'Alarm', 80, common_calendar.bp_alarm_str), 503 ('categories', 'Category', 150, common_calendar.category_str) 504 ] 505 506 _config_name='import/calendar/outlookdialog' 507 _browse_label='Outlook Calendar Folder:' 508 _progress_dlg_title='Outlook Calendar Import' 509 _error_dlg_title='Outlook Calendar Import Error' 510 _error_dlg_text='Outlook Calendar Items that failed to import:' 511 _data_class=OutlookCalendarImportData 512 _filter_dlg_class=common_calendar.FilterDialog 513
514 - def __init__(self, parent, id, title):
515 self._oc=self._data_class(native.outlook) 516 self._oc.set_folder(None) 517 common_calendar.PreviewDialog.__init__(self, parent, id, title, 518 self._column_labels, 519 self._oc.get_display_data(), 520 config_name=self._config_name)
521
522 - def getcontrols(self, main_bs):
523 hbs=wx.BoxSizer(wx.HORIZONTAL) 524 # label 525 hbs.Add(wx.StaticText(self, -1, self._browse_label), 0, wx.ALL|wx.ALIGN_CENTRE, 2) 526 # where the folder name goes 527 self.folderctrl=wx.TextCtrl(self, -1, "", style=wx.TE_READONLY) 528 self.folderctrl.SetValue(self._oc.get_folder_name()) 529 hbs.Add(self.folderctrl, 1, wx.EXPAND|wx.ALL, 2) 530 # browse button 531 id_browse=wx.NewId() 532 hbs.Add(wx.Button(self, id_browse, 'Browse ...'), 0, wx.EXPAND|wx.ALL, 2) 533 main_bs.Add(hbs, 0, wx.EXPAND|wx.ALL, 5) 534 main_bs.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5) 535 wx.EVT_BUTTON(self, id_browse, self.OnBrowseFolder)
536
537 - def getpostcontrols(self, main_bs):
538 main_bs.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5) 539 hbs=wx.BoxSizer(wx.HORIZONTAL) 540 id_import=wx.NewId() 541 hbs.Add(wx.Button(self, id_import, 'Import'), 0, wx.ALIGN_CENTRE|wx.ALL, 5) 542 hbs.Add(wx.Button(self, wx.ID_OK, 'Replace All'), 0, wx.ALIGN_CENTRE|wx.ALL, 5) 543 hbs.Add(wx.Button(self, self.ID_ADD, 'Add'), 0, wx.ALIGN_CENTRE|wx.ALL, 5) 544 hbs.Add(wx.Button(self, self.ID_MERGE, 'Merge'), 0, wx.ALIGN_CENTRE|wx.ALL, 5) 545 hbs.Add(wx.Button(self, wx.ID_CANCEL, 'Cancel'), 0, wx.ALIGN_CENTRE|wx.ALL, 5) 546 id_filter=wx.NewId() 547 hbs.Add(wx.Button(self, id_filter, 'Filter'), 0, wx.ALIGN_CENTRE|wx.ALL, 5) 548 hbs.Add(wx.Button(self, wx.ID_HELP, 'Help'), 0, wx.ALIGN_CENTRE|wx.ALL, 5) 549 main_bs.Add(hbs, 0, wx.ALIGN_CENTRE|wx.ALL, 5) 550 wx.EVT_BUTTON(self, id_import, self.OnImport) 551 wx.EVT_BUTTON(self, id_filter, self.OnFilter) 552 wx.EVT_BUTTON(self, self.ID_ADD, self.OnEndModal) 553 wx.EVT_BUTTON(self, self.ID_MERGE, self.OnEndModal) 554 wx.EVT_BUTTON(self, wx.ID_HELP, lambda *_: wx.GetApp().displayhelpid(helpids.ID_DLG_CALENDAR_IMPORT))
555 556 @guihelper.BusyWrapper
557 - def OnImport(self, evt):
558 with guihelper.WXDialogWrapper(wx.ProgressDialog(self._progress_dlg_title, 559 'Importing Outlook Data, please wait ...\n(Please also watch out for the Outlook Permission Request dialog)', 560 parent=self)) as dlg: 561 self._oc.read(None, dlg) 562 self.populate(self._oc.get_display_data()) 563 if self._oc.has_errors(): 564 # display the list of failed items 565 with guihelper.WXDialogWrapper(wx.SingleChoiceDialog(self, 566 self._error_dlg_text, 567 self._error_dlg_title, 568 self._oc.get_error_list()), 569 True): 570 pass
571
572 - def OnBrowseFolder(self, evt):
573 f=self._oc.pick_folder() 574 if f is None: 575 return # user hit cancel 576 self._oc.set_folder(f) 577 self.folderctrl.SetValue(self._oc.get_folder_name())
578
579 - def OnFilter(self, evt):
580 cat_list=self._oc.get_category_list() 581 with guihelper.WXDialogWrapper(self._filter_dlg_class(self, -1, 'Filtering Parameters', cat_list), 582 True) as (dlg, retcode): 583 if retcode==wx.ID_OK: 584 self._oc.set_filter(dlg.get()) 585 self.populate(self._oc.get_display_data())
586
587 - def OnEndModal(self, evt):
588 self.EndModal(evt.GetId())
589
590 - def get(self):
591 return self._oc.get()
592
593 - def get_categories(self):
594 return self._oc.get_category_list()
595
596 #------------------------------------------------------------------------------- 597 -def ImportCal(folder, filters):
598 _oc=OutlookCalendarImportData(native.outlook, auto_sync_only=1) 599 _oc.set_folder_id(folder) 600 _oc.set_filter(filters) 601 _oc.read() 602 res={ 'calendar':_oc.get() } 603 return res
604
605 #------------------------------------------------------------------------------- 606 -class OutlookAutoConfCalDialog(wx.Dialog):
607 - def __init__(self, parent, id, title, folder, filters, 608 style=wx.CAPTION|wx.MAXIMIZE_BOX| \ 609 wx.SYSTEM_MENU|wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER):
610 self._oc=OutlookCalendarImportData(native.outlook, auto_sync_only=1) 611 self._oc.set_folder_id(folder) 612 self._oc.set_filter(filters) 613 self.__read=False 614 wx.Dialog.__init__(self, parent, id=id, title=title, style=style) 615 main_bs=wx.BoxSizer(wx.VERTICAL) 616 hbs=wx.BoxSizer(wx.HORIZONTAL) 617 # label 618 hbs.Add(wx.StaticText(self, -1, "Outlook Calendar Folder:"), 0, wx.ALL|wx.ALIGN_CENTRE, 2) 619 # where the folder name goes 620 self.folderctrl=wx.TextCtrl(self, -1, "", style=wx.TE_READONLY) 621 self.folderctrl.SetValue(self._oc.get_folder_name()) 622 hbs.Add(self.folderctrl, 1, wx.EXPAND|wx.ALL, 2) 623 # browse button 624 id_browse=wx.NewId() 625 hbs.Add(wx.Button(self, id_browse, 'Browse ...'), 0, wx.EXPAND|wx.ALL, 2) 626 main_bs.Add(hbs, 0, wx.EXPAND|wx.ALL, 5) 627 main_bs.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5) 628 wx.EVT_BUTTON(self, id_browse, self.OnBrowseFolder) 629 hbs=wx.BoxSizer(wx.HORIZONTAL) 630 hbs.Add(wx.Button(self, wx.ID_OK, 'OK'), 0, wx.ALIGN_CENTRE|wx.ALL, 5) 631 hbs.Add(wx.Button(self, wx.ID_CANCEL, 'Cancel'), 0, wx.ALIGN_CENTRE|wx.ALL, 5) 632 id_filter=wx.NewId() 633 hbs.Add(wx.Button(self, id_filter, 'Filter'), 0, wx.ALIGN_CENTRE|wx.ALL, 5) 634 hbs.Add(wx.Button(self, wx.ID_HELP, 'Help'), 0, wx.ALIGN_CENTRE|wx.ALL, 5) 635 main_bs.Add(hbs, 0, wx.ALIGN_CENTRE|wx.ALL, 5) 636 wx.EVT_BUTTON(self, id_filter, self.OnFilter) 637 wx.EVT_BUTTON(self, wx.ID_HELP, lambda *_: wx.GetApp().displayhelpid(helpids.ID_DLG_CALENDAR_IMPORT)) 638 self.SetSizer(main_bs) 639 self.SetAutoLayout(True) 640 main_bs.Fit(self)
641
642 - def OnBrowseFolder(self, evt):
643 f=self._oc.pick_folder() 644 if f is None: 645 return # user hit cancel 646 self._oc.set_folder(f) 647 self.folderctrl.SetValue(self._oc.get_folder_name()) 648 self.__read=False
649
650 - def OnFilter(self, evt):
651 # read the calender to get the category list 652 if not self.__read: 653 self._oc.read() 654 self.__read=True 655 cat_list=self._oc.get_category_list() 656 with guihelper.WXDialogWrapper(common_calendar.AutoSyncFilterDialog(self, -1, 'Filtering Parameters', cat_list)) as dlg: 657 dlg.set(self._oc.get_filter()) 658 if dlg.ShowModal()==wx.ID_OK: 659 self._oc.set_filter(dlg.get())
660
661 - def GetFolder(self):
662 return self._oc.get_folder_id()
663
664 - def GetFilter(self):
665 return self._oc.get_filter()
666