0001 ### BITPIM 0002 ### 0003 ### Copyright (C) 2005 Joe Pham <djpham@bitpim.org> 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: today.py 4601 2008-03-04 22:37:48Z djpham $ 0009 0010 """ 0011 Code to handle BitPim Today tab. 0012 0013 """ 0014 0015 # standard modules 0016 0017 # wx modules 0018 import wx 0019 import wx.lib.scrolledpanel as scrolled 0020 import wx.lib.hyperlink as hl 0021 0022 # BitPim modules 0023 import aggregatedisplay as aggr 0024 import pubsub 0025 import widgets 0026 0027 0028 # Today REQUEST_TAB_CHANGED keys, types, and constants 0029 Tab_Today=0 0030 Tab_PhoneBook=1 0031 Tab_Wallpaper=2 0032 Tab_Ringers=3 0033 Tab_Calendar=4 0034 Tab_Memo=5 0035 Tab_Todo=6 0036 Tab_SMS=7 0037 Tab_CallHistory=8 0038 # TODAY_DATA keys, types, and constants 0039 Today_Section='section' 0040 Today_Groups='groups' 0041 Today_Group_Tab='tab_index' 0042 Today_Items='items' 0043 Today_Item_Name='name' 0044 Today_Item_Data='item_data' 0045 # Sections 0046 Today_Section_Today='Today' 0047 Today_Section_ThisWeek='This Week' 0048 # Groups 0049 Today_Group_Calendar='Calendar:' 0050 Today_Group_Todo='Todo List:' 0051 Today_Group_Memo='Memo:' 0052 Today_Group_IncomingSMS='SMS Inbox:' 0053 Today_Group_IncomingCalls='Incoming Calls:' 0054 Today_Group_MissedCalls='Missed Calls:' 0055 0056 dow_initials=('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', ' ') 0057 0058 EVT_TODAY_ITEM_SELECTED=wx.NewEventType() 0059 0060 #------------------------------------------------------------------------------- 0061 class NotificationEvent(object): 0062 def __init__(self, evt_handler, client_data=None): 0063 self._evt_handler=evt_handler 0064 self.client_data=client_data 0065 self.data=None 0066 def send(self): 0067 self._evt_handler(self) 0068 0069 #------------------------------------------------------------------------------- 0070 class NotificationEventHandler(object): 0071 def __init__(self): 0072 self._evt_table={} 0073 0074 def append(self, evt_handler, group, client_data=None): 0075 evt=NotificationEvent(evt_handler, client_data) 0076 self._evt_table.setdefault(group, []).append(evt) 0077 0078 def process(self, group, evt): 0079 for e in self._evt_table.get(group, []): 0080 e.data=evt 0081 e.send() 0082 0083 #------------------------------------------------------------------------------- 0084 evt_handler=None 0085 def bind_notification_event(_evt_handler, group, client_data=None): 0086 global evt_handler 0087 if evt_handler is None: 0088 evt_handler=NotificationEventHandler() 0089 evt_handler.append(_evt_handler, group, client_data) 0090 0091 #------------------------------------------------------------------------------- 0092 class BaseEvent(object): 0093 def __init__(self, section, group): 0094 self.section=section 0095 self.group=group 0096 self._items=[] 0097 0098 def append(self, item_name, item_data=None): 0099 # append a data item to this event 0100 self._items.append({ Today_Item_Name: item_name, 0101 Today_Item_Data: item_data }) 0102 0103 def _set_names(self, names): 0104 self._items=[{ Today_Item_Name: x, Today_Item_Data: None } \ 0105 for x in names] 0106 def _get_names(self): 0107 return [x[Today_Item_Name] for x in self._items] 0108 names=property(fget=_get_names, fset=_set_names) 0109 0110 def _get_items(self): 0111 return self._items 0112 items=property(fget=_get_items) 0113 0114 def broadcast(self): 0115 # broadcast this event 0116 pubsub.publish(pubsub.NEW_DATA_AVAILABLE, data=self) 0117 @classmethod 0118 def bind(_, func): 0119 pubsub.subscribe(func, pubsub.NEW_DATA_AVAILABLE) 0120 0121 #------------------------------------------------------------------------------- 0122 class TodayCalendarEvent(BaseEvent): 0123 def __init__(self): 0124 super(TodayCalendarEvent, self).__init__(Today_Section_Today, 0125 Today_Group_Calendar) 0126 class ThisWeekCalendarEvent(BaseEvent): 0127 def __init__(self): 0128 super(ThisWeekCalendarEvent, self).__init__(Today_Section_ThisWeek, 0129 Today_Group_Calendar) 0130 class TodayTodoEvent(BaseEvent): 0131 def __init__(self): 0132 super(TodayTodoEvent, self).__init__(Today_Section_Today, 0133 Today_Group_Todo) 0134 class ThisWeekTodoEvent(BaseEvent): 0135 def __init__(self): 0136 super(ThisWeekTodoEvent, self).__init__(Today_Section_ThisWeek, 0137 Today_Group_Todo) 0138 class TodayMemoEvent(BaseEvent): 0139 def __init__(self): 0140 super(TodayMemoEvent, self).__init__(Today_Section_Today, 0141 Today_Group_Memo) 0142 class TodaySMSEvent(BaseEvent): 0143 def __init__(self): 0144 super(TodaySMSEvent, self).__init__(Today_Section_Today, 0145 Today_Group_IncomingSMS) 0146 class TodayIncomingCallsEvent(BaseEvent): 0147 def __init__(self): 0148 super(TodayIncomingCallsEvent, self).__init__(Today_Section_Today, 0149 Today_Group_IncomingCalls) 0150 class TodayMissedCallsEvent(BaseEvent): 0151 def __init__(self): 0152 super(TodayMissedCallsEvent, self).__init__(Today_Section_Today, 0153 Today_Group_MissedCalls) 0154 0155 # Request Today Event----------------------------------------------------------- 0156 def bind_request_event(evt_handler): 0157 pubsub.subscribe(evt_handler, pubsub.REQUEST_TODAY_DATA) 0158 def send_request_event(): 0159 pubsub.publish(pubsub.REQUEST_TODAY_DATA) 0160 0161 #------------------------------------------------------------------------------- 0162 EVT_HYPERLINK_LEFT=hl.EVT_HYPERLINK_LEFT 0163 class HyperLinkCtrl(hl.HyperLinkCtrl): 0164 def __init__(self, *args, **kargs): 0165 super(HyperLinkCtrl, self).__init__(*args, **kargs) 0166 self.AutoBrowse(False) 0167 self.DoPopup(False) 0168 self.client_data=None 0169 0170 def SetToolTip(self, tip): 0171 if isinstance(tip, (str, unicode)): 0172 super(HyperLinkCtrl, self).SetToolTip(wx.ToolTip(tip)) 0173 else: 0174 super(HyperLinkCtrl, self).SetToolTip(tip) 0175 0176 def SetLabel(self, label): 0177 super(HyperLinkCtrl, self).SetLabel(label) 0178 self.SetToolTip(label) 0179 0180 #------------------------------------------------------------------------------- 0181 class StaticText(wx.StaticText): 0182 _max_item_len=30 0183 _postfix='...' 0184 _max_client_len=_max_item_len-len(_postfix) 0185 def __init__(self, *args, **kargs): 0186 super(StaticText, self).__init__(*args, **kargs) 0187 def SetLabel(self, label): 0188 if len(label)>self._max_item_len: 0189 label=label[:self._max_client_len]+self._postfix 0190 super(StaticText, self).SetLabel(label) 0191 0192 #------------------------------------------------------------------------------- 0193 class ItemHyperLink(HyperLinkCtrl): 0194 _max_item_len=30 0195 _postfix='...' 0196 _max_client_len=_max_item_len-len(_postfix) 0197 def __init__(self, *args, **kargs): 0198 super(ItemHyperLink, self).__init__(*args, **kargs) 0199 self.client_data=None 0200 def SetLabel(self, label, client_data=None): 0201 # if label contains linefeed truncate 0202 if label.find('\n')>-1: 0203 label=label.split('\n')[0]+self._postfix 0204 if len(label)>self._max_item_len: 0205 label=label[:self._max_client_len]+self._postfix 0206 super(ItemHyperLink, self).SetLabel(label) 0207 self.client_data=client_data 0208 0209 #------------------------------------------------------------------------------- 0210 class GroupWidget(wx.Panel, widgets.BitPimWidget): 0211 max_total_items=10 0212 max_items=9 0213 _title_font=None 0214 _item_font=None 0215 _last_item={ Today_Item_Name: '... more ...', 0216 Today_Item_Data: None } 0217 def __init__(self, parent, _name): 0218 super(GroupWidget, self).__init__(parent, wx.NewId()) 0219 self.name=_name.get('name', '') 0220 self.tab_index=_name.get('tab_index', None) 0221 self._data=[] 0222 self._widgets=[] 0223 if not self._title_font: 0224 self._title_font=wx.Font(12, wx.FONTFAMILY_DEFAULT, 0225 wx.FONTSTYLE_NORMAL, 0226 wx.FONTWEIGHT_BOLD) 0227 self._item_font=wx.Font(10, wx.FONTFAMILY_MODERN, 0228 wx.FONTSTYLE_NORMAL, 0229 wx.FONTWEIGHT_NORMAL) 0230 bs=wx.StaticBoxSizer(wx.StaticBox(self, -1, ''), wx.VERTICAL) 0231 title=HyperLinkCtrl(self, -1, self.name) 0232 if self._title_font.Ok(): 0233 title.SetFont(self._title_font) 0234 hl.EVT_HYPERLINK_LEFT(self, title.GetId(), self.OnItemSelected) 0235 bs.Add(title, 0, wx.ALL, 5) 0236 vbs=wx.BoxSizer(wx.VERTICAL) 0237 for i in range(self.max_total_items): 0238 w=ItemHyperLink(self, -1, '') 0239 if self._item_font.Ok(): 0240 w.SetFont(self._item_font) 0241 hl.EVT_HYPERLINK_LEFT(self, w.GetId(), self.OnItemSelected) 0242 vbs.Add(w, 0, wx.RIGHT|wx.LEFT, 5) 0243 vbs.Hide(i) 0244 self._widgets.append(w) 0245 bs.Add(vbs, 1, wx.LEFT, 10) 0246 self._vbs=vbs 0247 bs.Fit(self) 0248 self.SetSizer(bs) 0249 self.SetAutoLayout(True) 0250 0251 def Draw(self, dc, width, height, selected): 0252 x=dc.pos[0]-dc.view_start[0] 0253 y=dc.pos[1]-dc.view_start[1] 0254 self.SetDimensions(x, y, width, height) 0255 0256 def OnHyperlinkLeft(self, evt): 0257 if self.tab_index: 0258 pubsub.publish(pubsub.REQUEST_TAB_CHANGED, 0259 data=self.tab_index) 0260 0261 def OnItemSelected(self, evt): 0262 if evt_handler: 0263 self.OnHyperlinkLeft(evt) 0264 evt_handler.process(self.name, evt.GetEventObject().client_data) 0265 0266 def Set(self, data): 0267 data_len=len(data) 0268 if data_len>self.max_total_items: 0269 self._data=data[:self.max_items] 0270 self._data.append(self._last_item) 0271 data_len=self.max_total_items 0272 else: 0273 self._data=data 0274 for i in range(data_len): 0275 self._widgets[i].SetLabel(self._data[i].get(Today_Item_Name, ''), 0276 self._data[i].get(Today_Item_Data, None)) 0277 self._vbs.Show(i) 0278 for i in range(data_len, self.max_total_items): 0279 self._vbs.Hide(i) 0280 self._vbs.Layout() 0281 self.Fit() 0282 self.Refresh() 0283 0284 def not_empty(self): 0285 return self._data 0286 0287 #------------------------------------------------------------------------------- 0288 class SectionHeader(aggr.SectionHeader): 0289 default_width=10 0290 default_height=10 0291 def __init__(self, label): 0292 super(SectionHeader, self).__init__(label) 0293 self._items=[] 0294 def Add(self, item): 0295 self._items.append(item) 0296 def GetAllItems(self): 0297 return self._items 0298 def GetItems(self): 0299 l=[] 0300 for x in self._items: 0301 if x.not_empty(): 0302 l.append(x) 0303 x.Show() 0304 else: 0305 x.Hide() 0306 return l 0307 def GetItemSize(self): 0308 w=self.default_width 0309 h=self.default_height 0310 for e in self._items: 0311 w1,h1=e.GetSizeTuple() 0312 w=max(w, w1) 0313 h=max(h,h1) 0314 return (w,h) 0315 0316 def not_empty(self): 0317 return self.GetItems() 0318 0319 0320 #------------------------------------------------------------------------------- 0321 class TodayWidget(aggr.Display, widgets.BitPimWidget): 0322 _section_names=('Today','This Week') 0323 _item_names=(({ 'name': Today_Group_Calendar, 'tab_index': Tab_Calendar }, 0324 { 'name': Today_Group_Todo, 'tab_index': Tab_Todo }, 0325 { 'name': Today_Group_Memo, 'tab_index': Tab_Memo }, 0326 { 'name': Today_Group_IncomingSMS, 'tab_index': Tab_SMS }, 0327 { 'name': Today_Group_IncomingCalls, 'tab_index': Tab_CallHistory }, 0328 { 'name': Today_Group_MissedCalls, 'tab_index': Tab_CallHistory }), 0329 ({ 'name': Today_Group_Calendar, 'tab_index': Tab_Calendar }, 0330 { 'name': Today_Group_Todo, 'tab_index': Tab_Todo } )) 0331 0332 def __init__(self, mainwindow, parent): 0333 self._sections=[] 0334 super(TodayWidget, self).__init__(parent, self) 0335 self._main_window=mainwindow 0336 # sections & items info 0337 self._sections=[SectionHeader(s) for s in self._section_names] 0338 for i,group in enumerate(self._item_names): 0339 for name in group: 0340 w=GroupWidget(self, name) 0341 self._sections[i].Add(w) 0342 # all done 0343 # populate data 0344 self.UpdateItems() 0345 # register for pubsub events 0346 BaseEvent.bind(self.OnNewData) 0347 pubsub.subscribe(self._OnMidnight, pubsub.MIDNIGHT) 0348 0349 def GetSections(self): 0350 "Return a list of section headers" 0351 return [x for x in self._sections if x.not_empty()] 0352 0353 def GetItemSize(self, sectionnumber, sectionheader): 0354 "Return (width, height of each item)" 0355 return sectionheader.GetItemSize() 0356 0357 def GetItemsFromSection(self,sectionnumber,sectionheader): 0358 return sectionheader.GetItems() 0359 0360 def _populate(self, data): 0361 section_name=data.section 0362 group_name=data.group 0363 for s in self._sections: 0364 if s.label!=section_name: 0365 continue 0366 for group in s.GetAllItems(): 0367 if group.name==group_name: 0368 group.Set(data.items) 0369 break 0370 break 0371 self.UpdateItems() 0372 self.Refresh() 0373 0374 def OnNewData(self, msg=None): 0375 if msg is None: 0376 return 0377 self._populate(msg.data) 0378 0379 def _OnMidnight(self, _): 0380 send_request_event() 0381
Generated by PyXR 0.9.4