PyXR

c:\projects\bitpim\src \ common_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: common_calendar.py 4675 2008-08-12 21:52:12Z djpham $
0009 
0010 "Common stuff for the Calendar Import functions"
0011 
0012 # system modules
0013 from __future__ import with_statement
0014 import calendar
0015 import copy
0016 import datetime
0017 import sys
0018 
0019 # wxPython modules
0020 import wx
0021 import wx.calendar
0022 import wx.lib.mixins.listctrl as listmix
0023 
0024 # local modules
0025 import database
0026 import guihelper
0027 import guiwidgets
0028 import pubsub
0029 
0030 no_end_date=(4000, 1, 1, 0, 0)
0031 
0032 def bp_repeat_str(dict, v):
0033     if v is None:
0034         return ''
0035     return v
0036 
0037 def bp_date_str(dict, v):
0038     try:
0039         if v[0]>=no_end_date[0]:
0040             # no-end date, don't display it
0041             if dict.get('allday', False):
0042                 return ''
0043             else:
0044                 return '%02d:%02d'%v[3:]
0045 
0046         if dict.get('allday', False):
0047             return '%04d-%02d-%02d'%v[:3]
0048         else:
0049             return '%04d-%02d-%02d  %02d:%02d'% v
0050     except (ValueError, TypeError):
0051         return ''
0052     except:
0053         if __debug__: raise
0054         return ''
0055 
0056 def bp_alarm_str(dict, v):
0057     try:
0058         if dict.get('alarm', False):
0059             v=dict.get('alarm_value', 0)
0060             if v:
0061                 return '-%d min'%v
0062             else:
0063                 return 'Ontime'
0064         else:
0065             return ''
0066     except (ValueError, TypeError):
0067         return ''
0068     except:
0069         if __debug__: raise
0070         return ''
0071 
0072 def category_str(dict, v):
0073     try:
0074         s=''
0075         for d in v:
0076             if len(d):
0077                 if len(s):
0078                     s+=', '+d
0079                 else:
0080                     s=d
0081         return s
0082     except (ValueError, TypeError):
0083         return ''
0084     except:
0085         if __debug__: raise
0086         return ''
0087 
0088 #-------------------------------------------------------------------------------
0089 class ImportDataSource(object):
0090     # how to define, and retrieve calendar import data source
0091 
0092     # subclass might want to set these
0093     message_str='Select the source'
0094     wildcard='*.*'
0095 
0096     def __init__(self):
0097         self._source=None
0098 
0099     def browse(self, parent=None):
0100         # how to select a source, default to select a file
0101         with guihelper.WXDialogWrapper(wx.FileDialog(parent, self.message_str, wildcard=self.wildcard),
0102                                        True) as (dlg, retcode):
0103             if retcode==wx.ID_OK:
0104                 self._source=dlg.GetPath()
0105 
0106     def get(self):
0107         # return a source suitable for importing data
0108         return self._source
0109 
0110     def name(self):
0111         # return a string name for the source, default is the source itself
0112         return self._source or ''
0113 
0114     def _get_id(self):
0115         # return the ID string of this source (mainly for Outlook),
0116         # by default, just return the name
0117         return self.name()
0118     def _set_id(self, id):
0119         # set the ID of this source (mainly for Outlook),
0120         # by default, just set the source to it
0121         self._source=id
0122     id=property(fget=_get_id, fset=_set_id)
0123 
0124 #-------------------------------------------------------------------------------
0125 class PreviewDialog(wx.Dialog, listmix.ColumnSorterMixin):
0126     ID_ADD=wx.NewId()
0127     ID_MERGE=wx.NewId()
0128 
0129     def __init__(self, parent, id, title, col_labels, data={},
0130                  config_name=None,
0131                  style=wx.CAPTION|wx.MAXIMIZE_BOX| \
0132                  wx.SYSTEM_MENU|wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER):
0133 
0134         wx.Dialog.__init__(self, parent, id=id, title=title, style=style)
0135         
0136         self.__col_labels=col_labels
0137         self.__config_name=config_name
0138         self.itemDataMap={}
0139         # main boxsizer
0140         main_bs=wx.BoxSizer(wx.VERTICAL)
0141         # add custom controls here
0142         self.getcontrols(main_bs)
0143         # create a data preview list with supplied column labels
0144         self.__list=wx.ListView(self, wx.NewId())
0145         self.__image_list=wx.ImageList(16, 16)
0146         self.__ig_up=self.__image_list.Add(wx.ArtProvider_GetBitmap(wx.ART_GO_UP,
0147                                                              wx.ART_OTHER,
0148                                                              (16, 16)))
0149         self.__ig_dn=self.__image_list.Add(wx.ArtProvider_GetBitmap(wx.ART_GO_DOWN,
0150                                                              wx.ART_OTHER,
0151                                                              (16, 16)))
0152         self.__list.SetImageList(self.__image_list, wx.IMAGE_LIST_SMALL)
0153         li=wx.ListItem()
0154         li.m_mask=wx.LIST_MASK_TEXT | wx.LIST_MASK_IMAGE
0155         li.m_image=-1
0156         for i, d in enumerate(self.__col_labels):
0157             # insert a column with specified name and width
0158             li.m_text=d[1]
0159             self.__list.InsertColumnInfo(i, li)
0160             self.__list.SetColumnWidth(i, d[2])
0161         main_bs.Add(self.__list, 1, wx.EXPAND, 0)
0162         self.populate(data)
0163         # the Mixin sorter
0164         listmix.ColumnSorterMixin.__init__(self, len(col_labels))
0165         # now the buttons
0166         self.getpostcontrols(main_bs)
0167         # handle events
0168         # all done
0169         self.SetSizer(main_bs)
0170         self.SetAutoLayout(True)
0171         main_bs.Fit(self)
0172         # save my own size, if specified
0173         if config_name is not None:
0174             guiwidgets.set_size(config_name, self)
0175             wx.EVT_SIZE(self, self.__save_size)
0176 
0177     def getcontrols(self, main_bs):
0178         # controls to be placed above the preview pane
0179         # by default, put nothing.
0180         pass
0181 
0182     def getpostcontrols(self, main_bs):
0183         # control to be placed below the preview pane
0184         # by default, just add the OK & CANCEL button
0185         main_bs.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5)
0186         main_bs.Add(self.CreateButtonSizer(wx.OK|wx.CANCEL), 0, wx.ALIGN_CENTRE|wx.ALL, 5)
0187         
0188     def populate(self, data):
0189         self.__list.DeleteAllItems()
0190         m={}
0191         m_count=0
0192         for k in data:
0193             try:
0194                 d=data[k]
0195                 col_idx=None
0196                 mm={}
0197                 for i, l in enumerate(self.__col_labels):
0198                     entry=d.get(l[0], None)
0199                     s=''
0200                     if l[3] is None:
0201                         s=str(entry)
0202                     else:
0203                         s=l[3](d, entry)
0204                     mm[i]=s
0205                     if i:
0206                         self.__list.SetStringItem(col_idx, i, s)
0207                     else:
0208                         col_idx=self.__list.InsertImageStringItem(sys.maxint, s, -1)
0209                 self.__list.SetItemData(col_idx, m_count)
0210                 m[m_count]=mm
0211                 m_count += 1
0212             except:
0213                 # something wrong happened, drop this event
0214                 if __debug__: raise
0215         self.itemDataMap=m
0216 
0217     def GetListCtrl(self):
0218         return self.__list
0219 
0220     def GetSortImages(self):
0221         return (self.__ig_dn, self.__ig_up)
0222 
0223     def __save_size(self, evt):
0224         if self.__config_name is not None:
0225             guiwidgets.save_size(self.__config_name, self.GetRect())
0226         evt.Skip()
0227 
0228 #-------------------------------------------------------------------------------
0229 class FilterDataObject(database.basedataobject):
0230     _knownproperties=['rpt_events', 'no_alarm', 'alarm_override',
0231                       'ringtone', 'vibrate', 'alarm_value',
0232                       'preset_date' ]
0233     _knownlistproperties=database.basedataobject._knownlistproperties.copy()
0234     _knownlistproperties.update( {'categories': ['category'],
0235                                   'start': ['year', 'month', 'day'],
0236                                   'end': ['year', 'month', 'day'] })
0237     def __init__(self, data=None):
0238         if data:
0239             self.update(data)
0240 
0241 filterobjectfactory=database.dataobjectfactory(FilterDataObject)
0242 #-------------------------------------------------------------------------------
0243 class FilterDialogBase(wx.Dialog):
0244     unnamed="Select:"
0245     def __init__(self, parent, id, caption, categories, style=wx.DEFAULT_DIALOG_STYLE):
0246         wx.Dialog.__init__(self, parent, id,
0247                            title=caption, style=style)
0248         # the main box sizer
0249         bs=wx.BoxSizer(wx.VERTICAL)
0250         # the flex grid sizers for the editable items
0251         main_fgs=wx.FlexGridSizer(0, 1, 0, 0)
0252         fgs=wx.FlexGridSizer(3, 2, 0, 5)
0253         fgs1=wx.FlexGridSizer(0, 1, 0, 0)
0254         fgs2=wx.FlexGridSizer(0, 2, 0, 5)
0255         # set the date options
0256         self.SetDateControls(fgs, fgs1)
0257         # new repeat to single events option
0258         self._rpt_chkbox=wx.CheckBox(self, id=wx.NewId(), label='Repeat Events:',
0259                                       style=wx.ALIGN_RIGHT)
0260         self._rpt_chkbox.Disable()
0261         fgs.Add(self._rpt_chkbox, 0, wx.ALIGN_RIGHT|wx.TOP|wx.BOTTOM, 5)
0262         self._rpt_chkbox_text=wx.StaticText(self, -1, 'Import as multi-single events.')
0263         fgs.Add(self._rpt_chkbox_text, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTRE, 0)
0264         self._rpt_chkbox_text.Disable()
0265         # alarm option
0266         choices=('Disable All Alarms', 'Use Alarm Settings From Calender', 
0267                  'Set Alarm On All Events') 
0268         self.__alarm_setting = wx.RadioBox(self, id=wx.NewId(),
0269                                            label="Select Alarm Settings For Imported Events",
0270                                            choices=choices,
0271                                            majorDimension=1,
0272                                            size=(280,-1))
0273         fgs1.Add(self.__alarm_setting, 0, wx.ALIGN_CENTRE|wx.TOP|wx.BOTTOM, 5)
0274         #alarm vibrate
0275         self.__vibrate=wx.CheckBox(self, id=wx.NewId(), label='Alarm Vibrate:',
0276                                    style=wx.ALIGN_RIGHT)
0277         fgs2.Add(self.__vibrate, 0, wx.ALIGN_RIGHT|wx.TOP|wx.BOTTOM, 5)
0278         self.__vibrate_text=wx.StaticText(self, -1, 'Enable vibrate for alarms.')
0279         fgs2.Add(self.__vibrate_text, 0, wx.ALIGN_LEFT|wx.TOP|wx.BOTTOM, 5)
0280         # alarm settings
0281         self.__ringtone_text=wx.StaticText(self, -1, 'Alarm Ringtone:')
0282         fgs2.Add(self.__ringtone_text, 0, wx.ALIGN_RIGHT|wx.TOP|wx.BOTTOM, 5)
0283         self.__ringtone=wx.ComboBox(self, id=wx.NewId(),
0284                                     style=wx.CB_DROPDOWN|wx.CB_READONLY,
0285                                     choices=[self.unnamed], size=(160,-1))
0286         fgs2.Add(self.__ringtone, 0, wx.ALIGN_LEFT|wx.TOP|wx.BOTTOM, 2)
0287         # alarm value
0288         self.__alarm_value_text=wx.StaticText(self, -1, 'Alert before (mins):')
0289         fgs2.Add(self.__alarm_value_text, 0, wx.ALIGN_RIGHT|wx.TOP|wx.BOTTOM, 5)
0290         self.__alarm_value=wx.lib.intctrl.IntCtrl(self, id=wx.NewId(), size=(50,-1), 
0291                                                value=0, min=0, max=1000)
0292         fgs2.Add( self.__alarm_value, 0, wx.ALIGN_LEFT|wx.TOP|wx.BOTTOM, 2)
0293         # category option
0294         self.__cat_chkbox=wx.CheckBox(self, id=wx.NewId(), label='Categories:',
0295                                       style=wx.ALIGN_RIGHT)
0296         fgs2.Add(self.__cat_chkbox, 0, wx.ALIGN_RIGHT|wx.TOP|wx.BOTTOM, 5)
0297         for i,c in enumerate(categories):
0298             if not len(c):
0299                 categories[i]='<None>'
0300         self.__cats=wx.CheckListBox(self, choices=categories, size=(160, 50))
0301         self.__cats.Disable()
0302         fgs2.Add(self.__cats, 0, wx.ALIGN_LEFT, 0)
0303         main_fgs.Add(fgs, 1, wx.EXPAND|wx.ALL, 0)
0304         main_fgs.Add(fgs1, 1, wx.EXPAND|wx.ALL, 0)
0305         main_fgs.Add(fgs2, 1, wx.EXPAND|wx.ALL, 0)
0306         bs.Add(main_fgs, 1, wx.EXPAND|wx.ALL, 5)
0307         # the buttons
0308         bs.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5)
0309         bs.Add(self.CreateButtonSizer(wx.OK|wx.CANCEL), 0, wx.ALIGN_CENTRE|wx.ALL, 5)
0310         # event handles
0311         wx.EVT_CHECKBOX(self, self._start_date_chkbox.GetId(), self.OnCheckBox)
0312         wx.EVT_CHECKBOX(self, self._end_date_chkbox.GetId(), self.OnCheckBox)
0313         wx.EVT_CHECKBOX(self, self.__cat_chkbox.GetId(), self.OnCheckBox)
0314         wx.EVT_RADIOBOX(self, self.__alarm_setting.GetId(), self.OnAlarmSetting)
0315         # Listen to changes in ringtones list
0316         pubsub.subscribe(self.OnRingtoneUpdates, pubsub.ALL_RINGTONES)
0317         # all done
0318         self.SetSizer(bs)
0319         self.SetAutoLayout(True)
0320         bs.Fit(self)
0321 
0322     def __del__(self):
0323         pubsub.unsubscribe(self.OnRingtoneUpdates)
0324 
0325     def ShowModal(self):
0326         # request ringtones from 
0327         wx.CallAfter(pubsub.publish, pubsub.REQUEST_RINGTONES) # make the call once we are onscreen
0328         return wx.Dialog.ShowModal(self)
0329 
0330     def OnRingtoneUpdates(self, msg):
0331         "Receives pubsub message with ringtone list"
0332         tones=msg.data[:]
0333         #cur=self.Get()
0334         try:
0335             self.__ringtone.Clear()
0336             self.__ringtone.Append(self.unnamed)
0337             for p in tones:
0338                 self.__ringtone.Append(p)
0339             rt=self.__ringtone.SetStringSelection(self.ringtone)
0340         except:
0341             self.ringtone=self.unnamed
0342 
0343     def __set_cats(self, chk_box, c, data):
0344         if data is None:
0345             chk_box.SetValue(False)
0346             c.Disable()
0347         else:
0348             chk_box.SetValue(True)
0349             c.Enable()
0350             for i,d in enumerate(data):
0351                 if not len(d):
0352                     data[i]='<None>'
0353             for i in range(c.GetCount()):
0354                 c.Check(i, c.GetString(i) in data)
0355 
0356     def __set_rpt(self, data):
0357         if self._start_date_chkbox.GetValue() and\
0358            self._end_date_chkbox.GetValue():
0359             self._rpt_chkbox.Enable()
0360             self._rpt_chkbox_text.Enable()
0361             self._rpt_chkbox.SetValue(data)
0362         else:
0363             self._rpt_chkbox.SetValue(False)
0364             self._rpt_chkbox.Disable()
0365             self._rpt_chkbox_text.Disable()
0366 
0367     def __set_alarm_fields(self, value):
0368         if value==0:
0369             self.__vibrate.Disable()
0370             self.__alarm_value.Disable()
0371             self.__ringtone.Disable()
0372             self.__vibrate_text.Disable()
0373             self.__alarm_value_text.Disable()
0374             self.__ringtone_text.Disable()
0375         elif value==1:
0376             self.__vibrate.Enable()
0377             self.__alarm_value.Disable()
0378             self.__ringtone.Enable()
0379             self.__vibrate_text.Enable()
0380             self.__alarm_value_text.Disable()
0381             self.__ringtone_text.Enable()
0382         else:
0383             self.__vibrate.Enable()
0384             self.__alarm_value.Enable()
0385             self.__ringtone.Enable()
0386             self.__vibrate_text.Enable()
0387             self.__alarm_value_text.Enable()
0388             self.__ringtone_text.Enable()
0389 
0390     def set_base(self, data):
0391         self.__set_rpt(data.get('rpt_events', False))
0392         no_alarm=data.get('no_alarm', False)
0393         alarm_override=data.get('alarm_override', False)
0394         if no_alarm:
0395             value=0
0396         elif alarm_override:
0397             value=2
0398         else:
0399             value=1
0400         self.__set_alarm_fields(value)
0401         self.__alarm_setting.SetSelection(value)
0402         self.ringtone=data.get('ringtone', self.unnamed)
0403         try:
0404             self.__ringtone.SetStringSelection(ringtone)
0405         except:
0406             self.__ringtone.SetStringSelection(self.unnamed)
0407         value=data.get('vibrate', False);
0408         self.__vibrate.SetValue(value)
0409         self.__alarm_value.SetValue(data.get('alarm_value', 0))
0410         self.__set_cats(self.__cat_chkbox, self.__cats, data.get('categories', None))
0411 
0412     def get_base(self, r):
0413         r['rpt_events']=self._rpt_chkbox.GetValue()
0414         value=self.__alarm_setting.GetSelection()
0415         if value==0:
0416             r['no_alarm']=True
0417             r['alarm_override']=False
0418         elif value==1:
0419             r['no_alarm']=False
0420             r['alarm_override']=False
0421         else:
0422             r['no_alarm']=False
0423             r['alarm_override']=True
0424         r['ringtone']=self.__ringtone.GetStringSelection()
0425         r['vibrate']=self.__vibrate.GetValue()
0426         r['alarm_value']=self.__alarm_value.GetValue()
0427         if self.__cat_chkbox.GetValue():
0428             c=[]
0429             for i in range(self.__cats.GetCount()):
0430                 if self.__cats.IsChecked(i):
0431                     s=self.__cats.GetString(i)
0432                     if s=='<None>':
0433                         c.append('')
0434                     else:
0435                         c.append(s)
0436             r['categories']=c
0437         else:
0438             r['categories']=None
0439         return
0440     
0441     def OnAlarmSetting(self, _):
0442         self.__set_alarm_fields(self.__alarm_setting.GetSelection())
0443 
0444     def _repeat_option(self, on=True):
0445         if on:
0446             self._rpt_chkbox.Enable()
0447             self._rpt_chkbox_text.Enable()
0448         else:
0449             self._rpt_chkbox.SetValue(False)
0450             self._rpt_chkbox.Disable()
0451             self._rpt_chkbox_text.Disable()
0452 
0453     def OnCheckBox(self, evt):
0454         evt_id=evt.GetId()
0455         if evt_id==self._start_date_chkbox.GetId():
0456             w1,w2=self._start_date_chkbox, self._start_date
0457         elif evt_id==self._end_date_chkbox.GetId():
0458             w1,w2=self._end_date_chkbox, self._end_date
0459         else:
0460             w1,w2=self.__cat_chkbox, self.__cats
0461         if w1.GetValue():
0462             w2.Enable()
0463         else:
0464             w2.Disable()
0465         # turn on the repeat event option of both start date and end date
0466         # are specified.
0467         self._repeat_option(self._start_date_chkbox.GetValue() and \
0468                             self._end_date_chkbox.GetValue())
0469 
0470 #-------------------------------------------------------------------------------
0471 class FilterDialog(FilterDialogBase):
0472     def __init__(self, parent, id, caption, categories, style=wx.DEFAULT_DIALOG_STYLE):
0473         FilterDialogBase.__init__(self, parent, id, caption, categories, style)
0474         self._get_from_fs()
0475 
0476     def _get_from_fs(self):
0477         _db_data=self.GetParent().GetParent().GetActiveDatabase().getmajordictvalues('calendar_filter',
0478                                                            filterobjectfactory)
0479         _data={}
0480         _data.update(_db_data.get('filter', {}))
0481         if _data.has_key('categories'):
0482             _cat=[x['category'] for x in _data['categories']]
0483             del _data['categories']
0484             _data['categories']=_cat
0485         if _data.has_key('start'):
0486             _d0=_data['start'][0]
0487             _date=(_d0['year'], _d0['month'], _d0['day'])
0488             del _data['start']
0489             _data['start']=_date
0490         if _data.has_key('end'):
0491             _d0=_data['end'][0]
0492             _date=(_d0['year'], _d0['month'], _d0['day'])
0493             del _data['end']
0494             _data['end']=_date
0495         self.set(_data)
0496 
0497     def _save_to_fs(self, data):
0498         _data=copy.deepcopy(data, {})
0499         del _data['categories']
0500         if data.has_key('categories') and data['categories']:
0501             _cat=[{'category': x} for x in data['categories'] ]
0502             _data['categories']=_cat
0503         del _data['start']
0504         if data.has_key('start') and data['start']:
0505             _date=[{'year': data['start'][0], 'month': data['start'][1],
0506                     'day': data['start'][2] }]
0507             _data['start']=_date
0508         del _data['end']
0509         if data.has_key('end') and data['end']:
0510             _date=[{'year': data['end'][0], 'month': data['end'][1],
0511                     'day': data['end'][2] }]
0512             _data['end']=_date
0513         _dict={ 'filter': _data }
0514         database.ensurerecordtype(_dict, filterobjectfactory)
0515         self.GetParent().GetParent().GetActiveDatabase().savemajordict('calendar_filter',
0516                                                             _dict)
0517 
0518     def SetDateControls(self, fgs, fgs1):
0519         self._start_date_chkbox=wx.CheckBox(self, id=wx.NewId(), 
0520                                              label='Start Date:',
0521                                              style=wx.ALIGN_RIGHT)
0522         fgs.Add(self._start_date_chkbox, 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTRE_VERTICAL, 0)
0523         self._start_date=wx.calendar.CalendarCtrl(self, -1, wx.DateTime_Now(),
0524                                           style = wx.calendar.CAL_SUNDAY_FIRST
0525                                           | wx.calendar.CAL_SEQUENTIAL_MONTH_SELECTION)
0526         self._start_date.Disable()
0527         fgs.Add(self._start_date, 1, wx.ALIGN_LEFT, 5)
0528         self._end_date_chkbox=wx.CheckBox(self, id=wx.NewId(),
0529                                            label='End Date:',
0530                                            style=wx.ALIGN_RIGHT)
0531         fgs.Add(self._end_date_chkbox, 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTRE_VERTICAL, 0)
0532         self._end_date=wx.calendar.CalendarCtrl(self, -1, wx.DateTime_Now(),
0533                                           style = wx.calendar.CAL_SUNDAY_FIRST
0534                                           | wx.calendar.CAL_SEQUENTIAL_MONTH_SELECTION)
0535         self._end_date.Disable()
0536         fgs.Add(self._end_date, 1, wx.ALIGN_LEFT, 5)
0537         self._preset_date_chkbox=wx.CheckBox(self, -1, label='Preset Duration',
0538                                              style=wx.ALIGN_RIGHT)
0539         fgs.Add(self._preset_date_chkbox, 0,
0540                 wx.ALIGN_RIGHT|wx.ALIGN_CENTRE_VERTICAL, 0)
0541         self._preset_date=wx.Choice(self, -1, choices=('This Week',
0542                                                        'This Month',
0543                                                        'This Year',
0544                                                        'Next 7 Days',))
0545         self._preset_date.SetSelection(1)
0546         self._preset_date.Disable()
0547         fgs.Add(self._preset_date, 0, wx.ALIGN_LEFT, 5)
0548         wx.EVT_CHECKBOX(self, self._preset_date_chkbox.GetId(),
0549                         self.OnCheckBox)
0550 
0551     def OnCheckBox(self, evt):
0552         super(FilterDialog, self).OnCheckBox(evt)
0553         self._repeat_option(self._start_date_chkbox.GetValue() and \
0554                             self._end_date_chkbox.GetValue() or \
0555                             self._preset_date_chkbox.GetValue())
0556         if evt.GetId()==self._preset_date_chkbox.GetId():
0557             if self._preset_date_chkbox.GetValue():
0558                 self._preset_date.Enable()
0559             else:
0560                 self._preset_date.Disable()
0561 
0562     def __set_date(self, chk_box, cal, d):
0563         if d is None:
0564             chk_box.SetValue(False)
0565             cal.Disable()
0566         else:
0567             chk_box.SetValue(True)
0568             cal.Enable()
0569             dt=wx.DateTime()
0570             dt.Set(d[2], year=d[0], month=d[1]-1)
0571             cal.SetDate(dt)
0572 
0573     def set_base(self, data):
0574         super(FilterDialog, self).set_base(data)
0575         self._rpt_chkbox.SetValue(data.get('rpt_events', False))
0576 
0577     def set(self, data):
0578         self.__set_date(self._start_date_chkbox, self._start_date,
0579                         data.get('start', None))
0580         self.__set_date(self._end_date_chkbox, self._end_date,
0581                         data.get('end', None))
0582         self.set_base(data)
0583         if data.get('preset_date', None) is not None:
0584             self._preset_date_chkbox.SetValue(True)
0585             self._preset_date.Enable()
0586             self._preset_date.SetSelection(data['preset_date'])
0587             self._repeat_option(True)
0588         else:
0589             self._preset_date_chkbox.SetValue(False)
0590             self._preset_date.Disable()
0591 
0592     def _get_preset_thisweek(self):
0593         # return the dates of (today, Sat)
0594         _today=datetime.date.today()
0595         _dow=_today.isoweekday()%7  #Sun=0, Sat=6
0596         _end=_today+datetime.timedelta(6-_dow)
0597         return ((_today.year, _today.month, _today.day),
0598                 (_end.year, _end.month, _end.day))
0599 
0600     def _get_preset_thismonth(self):
0601         # return the dates of (today, end-of-month)
0602         _today=datetime.date.today()
0603         _end=_today.replace(day=calendar.monthrange(_today.year,_today.month)[1])
0604         return ((_today.year, _today.month, _today.day),
0605                 (_end.year, _end.month, _end.day))
0606 
0607     def _get_preset_thisyear(self):
0608         # return the dates of (today, end-of-year)
0609         _today=datetime.date.today()
0610         _end=_today.replace(month=12, day=31)
0611         return ((_today.year, _today.month, _today.day),
0612                 (_end.year, _end.month, _end.day))
0613 
0614     def _get_preset_next7(self):
0615         # return the dates of (today, today+6)
0616         _today=datetime.date.today()
0617         _end=_today+datetime.timedelta(days=6)
0618         return ((_today.year, _today.month, _today.day),
0619                 (_end.year, _end.month, _end.day))
0620 
0621     def _get_preset_date(self):
0622         _choice=self._preset_date.GetSelection()
0623         if _choice==wx.NOT_FOUND:
0624             return None, None
0625         if _choice==0:
0626             return self._get_preset_thisweek()
0627         elif _choice==1:
0628             return self._get_preset_thismonth()
0629         elif _choice==2:
0630             return self._get_preset_thisyear()
0631         else:
0632             return self._get_preset_next7()
0633 
0634     def get(self):
0635         r={}
0636         if self._preset_date_chkbox.GetValue():
0637             r['start'],r['end']=self._get_preset_date()
0638             r['preset_date']=self._preset_date.GetSelection()
0639         else:
0640             r['preset_date']=None
0641             if self._start_date_chkbox.GetValue():
0642                 dt=self._start_date.GetDate()
0643                 r['start']=(dt.GetYear(), dt.GetMonth()+1, dt.GetDay())
0644             else:
0645                 r['start']=None
0646             if self._end_date_chkbox.GetValue():
0647                 dt=self._end_date.GetDate()
0648                 r['end']=(dt.GetYear(), dt.GetMonth()+1, dt.GetDay())
0649             else:
0650                 r['end']=None
0651         self.get_base(r)
0652         self._save_to_fs(r)
0653         return r
0654     
0655 #-------------------------------------------------------------------------------
0656 class AutoSyncFilterDialog(FilterDialogBase):
0657     def __init__(self, parent, id, caption, categories, style=wx.DEFAULT_DIALOG_STYLE):
0658         FilterDialogBase.__init__(self, parent, id, caption, categories, style)
0659 
0660     def SetDateControls(self, fgs, fgs1):
0661         #start_offset
0662         self._start_date_chkbox=wx.CheckBox(self, id=wx.NewId(), 
0663                                              label='Start Offset (days):',
0664                                              style=wx.ALIGN_RIGHT)
0665         fgs.Add(self._start_date_chkbox, 0, wx.ALIGN_RIGHT|wx.TOP|wx.BOTTOM, 5)
0666         self._start_date=wx.lib.intctrl.IntCtrl(self, id=wx.NewId(), size=(50,-1), 
0667                                                  value=0, min=0, max=1000)
0668         self._start_date.Disable()
0669         fgs.Add( self._start_date, 0, wx.ALIGN_LEFT|wx.TOP|wx.BOTTOM, 2)
0670         #end_offset
0671         self._end_date_chkbox=wx.CheckBox(self, id=wx.NewId(),
0672                                            label='End Offset (days):',
0673                                            style=wx.ALIGN_RIGHT)
0674         fgs.Add(self._end_date_chkbox, 0, wx.ALIGN_RIGHT|wx.TOP|wx.BOTTOM, 5)
0675         self._end_date=wx.lib.intctrl.IntCtrl(self, id=wx.NewId(), size=(50,-1), 
0676                                                value=0, min=0, max=1000)
0677         self._end_date.Disable()
0678         fgs.Add( self._end_date, 0, wx.ALIGN_LEFT|wx.TOP|wx.BOTTOM, 2)
0679         fgs1.Add(wx.StaticText(self, -1, 'Note: The start offset is the number of days' + 
0680                                ' in the past, and the end offset is the number of days' +
0681                                ' in the future imported from the calender into your phone. If' +
0682                                ' disabled, all past and/or future events are imported.',
0683                                size=(270,55)),
0684                                0, wx.ALIGN_LEFT|wx.TOP|wx.BOTTOM, 5)
0685 
0686 
0687     def __set_start_date(self, d):
0688         if d is None:
0689             self._start_date_chkbox.SetValue(False)
0690             self._start_date.Disable()
0691         else:
0692             self._start_date_chkbox.SetValue(True)
0693             self._start_date.Enable()
0694             self._start_date.SetValue(d)
0695 
0696     def __set_end_date(self, d):
0697         if d is None:
0698             self._end_date_chkbox.SetValue(False)
0699             self._end_date.Disable()
0700         else:
0701             self._end_date_chkbox.SetValue(True)
0702             self._end_date.Enable()
0703             self._end_date.SetValue(d)
0704 
0705     def set(self, data):
0706         self.__set_start_date(data.get('start_offset', None))
0707         self.__set_end_date(data.get('end_offset', None))
0708         self.set_base(data)
0709 
0710     def get(self):
0711         r={}
0712         if self._start_date_chkbox.GetValue():
0713             r['start_offset']=self._start_date.GetValue()
0714         else:
0715             r['start_offset']=None
0716         if self._end_date_chkbox.GetValue():
0717             r['end_offset']=self._end_date.GetValue()
0718         else:
0719             r['end_offset']=None
0720         self.get_base(r)
0721         return r
0722 
0723 #-------------------------------------------------------------------------------
0724 class ExportCalendarDialog(wx.Dialog):
0725     # subclass should override these
0726     _default_file_name=""
0727     _wildcards="All files|*.*"
0728     
0729     def __init__(self, parent, title):
0730         super(ExportCalendarDialog, self).__init__(parent, -1, title)
0731         # make the ui
0732         vbs=wx.BoxSizer(wx.VERTICAL)
0733         hbs=wx.BoxSizer(wx.HORIZONTAL)
0734         hbs.Add(wx.StaticText(self, -1, "File"), 0, wx.ALL|wx.ALIGN_CENTRE, 5)
0735         self.filenamectrl=wx.TextCtrl(self, -1, self._default_file_name)
0736         hbs.Add(self.filenamectrl, 1, wx.ALL|wx.EXPAND, 5)
0737         self.browsectrl=wx.Button(self, wx.NewId(), "Browse...")
0738         hbs.Add(self.browsectrl, 0, wx.ALL|wx.EXPAND, 5)
0739         vbs.Add(hbs, 0, wx.EXPAND|wx.ALL, 5)
0740         # selection GUI
0741         vbs.Add(self.GetSelectionGui(self), 5, wx.EXPAND|wx.ALL, 5)
0742         # the buttons
0743         vbs.Add(wx.StaticLine(self, -1, style=wx.LI_HORIZONTAL), 0, wx.EXPAND|wx.ALL,5)
0744         vbs.Add(self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.HELP), 0, wx.ALIGN_CENTER|wx.ALL, 5)
0745         # event handlers
0746         wx.EVT_BUTTON(self, self.browsectrl.GetId(), self.OnBrowse)
0747         wx.EVT_BUTTON(self, wx.ID_OK, self.OnOk)
0748         # all done
0749         self.SetSizer(vbs)
0750         self.SetAutoLayout(True)
0751         vbs.Fit(self)
0752 
0753     def GetSelectionGui(self, parent):
0754         hbs=wx.BoxSizer(wx.HORIZONTAL)
0755         self._selection=wx.RadioBox(parent, wx.NewId(), 'Events Selection',
0756                                     choices=['All', 'Date Range'],
0757                                     style=wx.RA_SPECIFY_ROWS)
0758         hbs.Add(self._selection, 0, wx.EXPAND|wx.ALL, 5)
0759         sbs=wx.StaticBoxSizer(wx.StaticBox(parent, -1, 'Date Range'), wx.VERTICAL)
0760         gs=wx.FlexGridSizer(-1, 2, 5, 5)
0761         gs.AddGrowableCol(1)
0762         gs.Add(wx.StaticText(self, -1, 'Start:'), 0, wx.ALL, 0)
0763         self._start_date=wx.DatePickerCtrl(self, style=wx.DP_DROPDOWN | wx.DP_SHOWCENTURY)
0764         gs.Add(self._start_date, 0, wx.ALL, 0)
0765         gs.Add(wx.StaticText(self, -1, 'End:'), 0, wx.ALL, 0)
0766         self._end_date=wx.DatePickerCtrl(self, style=wx.DP_DROPDOWN | wx.DP_SHOWCENTURY)
0767         gs.Add(self._end_date, 0, wx.ALL, 0)
0768         sbs.Add(gs, 1, wx.EXPAND|wx.ALL, 5)
0769         hbs.Add(sbs, 0, wx.EXPAND|wx.ALL, 5)
0770         return hbs
0771 
0772     def OnBrowse(self, _):
0773         with guihelper.WXDialogWrapper(wx.FileDialog(self, defaultFile=self.filenamectrl.GetValue(),
0774                                                      wildcard=self._wildcards, style=wx.SAVE|wx.CHANGE_DIR),
0775                                        True) as (dlg, retcode):
0776             if retcode==wx.ID_OK:
0777                 self.filenamectrl.SetValue(dlg.GetPath())
0778 
0779     def _export(self):
0780         # perform the actual caledar data import, subclass MUST override
0781         raise NotImplementedError
0782 
0783     def OnOk(self, _):
0784         # do export
0785         self._export()
0786         self.EndModal(wx.ID_OK)
0787 

Generated by PyXR 0.9.4