PyXR

c:\projects\bitpim\src \ outlook_calendar.py



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