def __init__(self, mainwindow, parent, stats): super(CallHistoryList, self).__init__(parent, -1) self._main_window=mainwindow self._stats=stats self.nodes={} self.nodes_keys={} self._display_filter="All" vbs=wx.BoxSizer(wx.VERTICAL) hbs=wx.BoxSizer(wx.HORIZONTAL) static_bs=wx.StaticBoxSizer(wx.StaticBox(self, -1, 'Historical Data Status:'), wx.VERTICAL) self.historical_data_label=wx.StaticText(self, -1, 'Current Data') static_bs.Add(self.historical_data_label, 1, wx.EXPAND|wx.ALL, 5) hbs.Add(static_bs, 1, wx.EXPAND|wx.ALL, 5) vbs.Add(hbs, 0, wx.EXPAND|wx.ALL, 5) column_info=[] column_info.append(("Call Type", 80, False)) column_info.append(("Date", 120, False)) column_info.append(("Number", 100, False)) column_info.append(("Duration", 80, True)) column_info.append(("Name", 130, False)) self._item_list=guiwidgets.BitPimListCtrl(self, column_info) self._item_list.ResetView(self.nodes, self.nodes_keys) vbs.Add(self._item_list, 1, wx.EXPAND|wx.ALL, 5) vbs.Add(wx.StaticText(self, -1, ' Note: Click column headings to sort data'), 0, wx.ALIGN_CENTRE|wx.BOTTOM, 10) today.bind_notification_event(self.OnTodaySelectionIncoming, today.Today_Group_IncomingCalls) today.bind_notification_event(self.OnTodaySelectionMissed, today.Today_Group_MissedCalls) self.today_data=None self.SetSizer(vbs) self.SetAutoLayout(True) vbs.Fit(self)
def __init__(self, mainwindow, parent): global widgets_list super(TodoWidget, self).__init__(parent, -1) self._main_window=mainwindow self._data=self._data_map={} vbs=wx.BoxSizer(wx.VERTICAL) hbs=wx.BoxSizer(wx.HORIZONTAL) self._item_list=wx.ListBox(self, wx.NewId(), style=wx.LB_SINGLE|wx.LB_HSCROLL|wx.LB_NEEDED_SB) hbs.Add(self._item_list, 1, wx.EXPAND|wx.BOTTOM, border=5) scrolled_panel=scrolled.ScrolledPanel(self, -1) vbs1=wx.BoxSizer(wx.VERTICAL) self._items=( (GeneralEditor, 0, None), (cal_editor.CategoryEditor, 1, 'category'), (pb_editor.MemoEditor, 1, 'memo') ) self._w=[] for n in self._items: w=n[0](scrolled_panel, -1) vbs1.Add(w, n[1], wx.EXPAND|wx.ALL, 5) self._w.append(w) if n[2]: widgets_list.append((w.static_box, n[2])) scrolled_panel.SetSizer(vbs1) scrolled_panel.SetAutoLayout(True) vbs1.Fit(scrolled_panel) scrolled_panel.SetupScrolling() hbs.Add(scrolled_panel, 3, wx.EXPAND|wx.ALL, border=5) self._general_editor_w=self._w[0] self._cat_editor_w=self._w[1] self._memo_editor_w=self._w[2] hbs1=wx.BoxSizer(wx.HORIZONTAL) self._save_btn=wx.Button(self, wx.NewId(), "Save") self._revert_btn=wx.Button(self, wx.NewId(), "Revert") help_btn=wx.Button(self, wx.ID_HELP, "Help") hbs1.Add(self._save_btn, 0, wx.ALIGN_CENTRE|wx.ALL, 5) hbs1.Add(help_btn, 0, wx.ALIGN_CENTRE|wx.ALL, 5) hbs1.Add(self._revert_btn, 0, wx.ALIGN_CENTRE|wx.ALL, 5) vbs.Add(hbs, 1, wx.EXPAND|wx.ALL, 5) vbs.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5) vbs.Add(hbs1, 0, wx.ALIGN_CENTRE|wx.ALL, 5) self.SetSizer(vbs) self.SetAutoLayout(True) vbs.Fit(self) wx.EVT_LISTBOX(self, self._item_list.GetId(), self._OnListBoxItem) wx.EVT_BUTTON(self, self._save_btn.GetId(), self._OnSave) wx.EVT_BUTTON(self, self._revert_btn.GetId(), self._OnRevert) wx.EVT_BUTTON(self, wx.ID_HELP, lambda _: wx.GetApp().displayhelpid(helpids.ID_TAB_TODO)) for w in self._w: pb_editor.EVT_DIRTY_UI(self, w.GetId(), self.OnMakeDirty) self._populate() self.ignoredirty=False self.setdirty(False) today.bind_notification_event(self.OnTodaySelection, today.Today_Group_Todo) today.bind_request_event(self.OnTodayRequest) field_color.reload_color_info(self, widgets_list) pubsub.subscribe(self.OnPhoneChanged, pubsub.PHONE_MODEL_CHANGED)
def __init__(self, mainwindow, parent, stats): super(SMSList, self).__init__(parent, -1) self._main_window = mainwindow self._stats = stats self.nodes = {} self.nodes_keys = {} self._display_filter = "All" self._name_map = {} self._data_map = {} # main box sizer vbs = wx.BoxSizer(wx.VERTICAL) # data date adjuster hbs = wx.BoxSizer(wx.HORIZONTAL) static_bs = wx.StaticBoxSizer( wx.StaticBox(self, -1, 'Historical Data Status:'), wx.VERTICAL) self.historical_data_label = wx.StaticText(self, -1, 'Current Data') static_bs.Add(self.historical_data_label, 1, wx.EXPAND | wx.ALL, 5) hbs.Add(static_bs, 1, wx.EXPAND | wx.ALL, 5) vbs.Add(hbs, 0, wx.EXPAND | wx.ALL, 5) # main list hbmessage = wx.BoxSizer(wx.HORIZONTAL) column_info = [] column_info.append(("From", 105, False)) column_info.append(("To", 120, False)) column_info.append(("Date", 180, False)) self._item_list = guiwidgets.BitPimListCtrl(self, column_info) self._item_list.ResetView(self.nodes, self.nodes_keys) vbs0 = wx.BoxSizer(wx.VERTICAL) vbs0.Add(self._item_list, 1, wx.EXPAND | wx.ALL, 5) vbs0.Add( wx.StaticText(self, -1, ' Note: Click column headings to sort data'), 0, wx.ALIGN_CENTRE | wx.BOTTOM, 10) hbmessage.Add(vbs0, 1, wx.EXPAND | wx.ALL, 5) vbs1 = wx.BoxSizer(wx.VERTICAL) self._item_info = SMSInfo(self) vbs1.Add(self._item_info, 0, wx.EXPAND | wx.ALL, 5) self._item_text = pb_editor.MemoEditor(self, -1) vbs1.Add(self._item_text, 1, wx.EXPAND | wx.ALL, 5) hbmessage.Add(vbs1, 0, wx.EXPAND | wx.ALL, 5) hbmessage.SetItemMinSize(1, (350, 20)) vbs.Add(hbmessage, 1, wx.EXPAND | wx.ALL, 5) wx.EVT_LIST_ITEM_SELECTED(self, self._item_list.GetId(), self._OnSelChanged) pubsub.subscribe(self._OnPBLookup, pubsub.RESPONSE_PB_LOOKUP) # register for Today selection self.today_data = None today.bind_notification_event(self.OnTodaySelection, today.Today_Group_IncomingSMS) # all done self.SetSizer(vbs) self.SetAutoLayout(True) vbs.Fit(self)
def __init__(self, mainwindow, parent, stats): super(SMSList, self).__init__(parent, -1) self._main_window=mainwindow self._stats=stats self.nodes={} self.nodes_keys={} self._display_filter="All" self._name_map={} self._data_map={} # main box sizer vbs=wx.BoxSizer(wx.VERTICAL) # data date adjuster hbs=wx.BoxSizer(wx.HORIZONTAL) static_bs=wx.StaticBoxSizer(wx.StaticBox(self, -1, 'Historical Data Status:'), wx.VERTICAL) self.historical_data_label=wx.StaticText(self, -1, 'Current Data') static_bs.Add(self.historical_data_label, 1, wx.EXPAND|wx.ALL, 5) hbs.Add(static_bs, 1, wx.EXPAND|wx.ALL, 5) vbs.Add(hbs, 0, wx.EXPAND|wx.ALL, 5) # main list hbmessage=wx.BoxSizer(wx.HORIZONTAL) column_info=[] column_info.append(("From", 105, False)) column_info.append(("To", 120, False)) column_info.append(("Date", 180, False)) self._item_list=guiwidgets.BitPimListCtrl(self, column_info) self._item_list.ResetView(self.nodes, self.nodes_keys) vbs0=wx.BoxSizer(wx.VERTICAL) vbs0.Add(self._item_list, 1, wx.EXPAND|wx.ALL, 5) vbs0.Add(wx.StaticText(self, -1, ' Note: Click column headings to sort data'), 0, wx.ALIGN_CENTRE|wx.BOTTOM, 10) hbmessage.Add(vbs0, 1, wx.EXPAND|wx.ALL, 5) vbs1=wx.BoxSizer(wx.VERTICAL) self._item_info=SMSInfo(self) vbs1.Add(self._item_info, 0, wx.EXPAND|wx.ALL, 5) self._item_text=pb_editor.MemoEditor(self, -1) vbs1.Add(self._item_text, 1, wx.EXPAND|wx.ALL, 5) hbmessage.Add(vbs1, 0, wx.EXPAND|wx.ALL, 5) hbmessage.SetItemMinSize(1, (350, 20)) vbs.Add(hbmessage, 1, wx.EXPAND|wx.ALL, 5) wx.EVT_LIST_ITEM_SELECTED(self, self._item_list.GetId(), self._OnSelChanged) pubsub.subscribe(self._OnPBLookup, pubsub.RESPONSE_PB_LOOKUP) # register for Today selection self.today_data=None today.bind_notification_event(self.OnTodaySelection, today.Today_Group_IncomingSMS) # all done self.SetSizer(vbs) self.SetAutoLayout(True) vbs.Fit(self)
def __init__(self, mainwindow, parent, id=-1): """constructor @type mainwindow: gui.MainWindow @param mainwindow: Used to get configuration data (such as directory to save/load data. @param parent: Widget acting as parent for this one @param id: id """ self.mainwindow=mainwindow self.entrycache={} self.entries={} self.repeating=[] # nb this is stored unsorted self._data={} # the underlying data calendarcontrol.Calendar.__init__(self, parent, rows=5, id=id) self.dialog=calendarentryeditor.Editor(self) pubsub.subscribe(self.OnMediaNameChanged, pubsub.MEDIA_NAME_CHANGED) today.bind_notification_event(self.OnTodayItem, today.Today_Group_Calendar) today.bind_request_event(self.OnTodayRequest) pubsub.subscribe(self.OnTodayButton, pubsub.MIDNIGHT)
def __init__(self, mainwindow, parent, stats): super(CallHistoryList, self).__init__(parent, -1) self._main_window = mainwindow self._stats = stats self.nodes = {} self.nodes_keys = {} self._display_filter = "All" # main box sizer vbs = wx.BoxSizer(wx.VERTICAL) # data date adjuster hbs = wx.BoxSizer(wx.HORIZONTAL) static_bs = wx.StaticBoxSizer( wx.StaticBox(self, -1, 'Historical Data Status:'), wx.VERTICAL) self.historical_data_label = wx.StaticText(self, -1, 'Current Data') static_bs.Add(self.historical_data_label, 1, wx.EXPAND | wx.ALL, 5) hbs.Add(static_bs, 1, wx.EXPAND | wx.ALL, 5) vbs.Add(hbs, 0, wx.EXPAND | wx.ALL, 5) # main list column_info = [] column_info.append(("Call Type", 80, False)) column_info.append(("Date", 120, False)) column_info.append(("Number", 100, False)) column_info.append(("Duration", 80, False)) column_info.append(("Name", 130, False)) self._item_list = guiwidgets.BitPimListCtrl(self, column_info) self._item_list.ResetView(self.nodes, self.nodes_keys) vbs.Add(self._item_list, 1, wx.EXPAND | wx.ALL, 5) vbs.Add( wx.StaticText(self, -1, ' Note: Click column headings to sort data'), 0, wx.ALIGN_CENTRE | wx.BOTTOM, 10) # all done today.bind_notification_event(self.OnTodaySelectionIncoming, today.Today_Group_IncomingCalls) today.bind_notification_event(self.OnTodaySelectionMissed, today.Today_Group_MissedCalls) self.today_data = None self.SetSizer(vbs) self.SetAutoLayout(True) vbs.Fit(self)
def __init__(self, mainwindow, parent): super(SMSWidget, self).__init__(parent, -1) self._main_window=mainwindow self._data=self._canned_data={} vbs=wx.BoxSizer(wx.VERTICAL) hbs=wx.BoxSizer(wx.HORIZONTAL) self.read_only=False self.historical_date=None static_bs=wx.StaticBoxSizer(wx.StaticBox(self, -1, 'Historical Data Status:'), wx.VERTICAL) self.historical_data_label=wx.StaticText(self, -1, 'Current Data') static_bs.Add(self.historical_data_label, 1, wx.EXPAND|wx.ALL, 5) hbs.Add(static_bs, 1, wx.EXPAND|wx.ALL, 5) vbs.Add(hbs, 0, wx.EXPAND|wx.ALL, 5) self._sms=FolderPage(self) wx.EVT_BUTTON(self, self._sms.save_btn.GetId(), self.OnSaveCannedMsg) vbs.Add(self._sms, 1, wx.EXPAND|wx.ALL, 5) self.SetSizer(vbs) self.SetAutoLayout(True) vbs.Fit(self) today.bind_notification_event(self._sms.OnTodaySelection, today.Today_Group_IncomingSMS)
def __init__(self, mainwindow, parent): wx.Panel.__init__(self, parent, -1) self._main_window = mainwindow self._data = {} self._data_map = {} # main box sizer vbs = wx.BoxSizer(wx.VERTICAL) # horizontal sizer for the listbox and tabs hbs = wx.BoxSizer(wx.HORIZONTAL) # the list box self._item_list = wx.ListBox(self, wx.NewId(), style=wx.LB_SINGLE | wx.LB_HSCROLL | wx.LB_NEEDED_SB) hbs.Add(self._item_list, 1, wx.EXPAND | wx.BOTTOM, border=5) # the detailed info pane vbs1 = wx.BoxSizer(wx.VERTICAL) self._items = ((GeneralEditor, 0, None), (cal_editor.CategoryEditor, 1, 'category'), (pb_editor.MemoEditor, 1, 'memo')) self._w = [] for n in self._items: w = n[0](self, -1) vbs1.Add(w, n[1], wx.EXPAND | wx.ALL, 5) self._w.append(w) if n[2]: widgets_list.append((w.static_box, n[2])) hbs.Add(vbs1, 3, wx.EXPAND | wx.ALL, border=5) self._general_editor_w = self._w[0] self._cat_editor_w = self._w[1] self._memo_editor_w = self._w[2] # the bottom buttons hbs1 = wx.BoxSizer(wx.HORIZONTAL) self._save_btn = wx.Button(self, wx.ID_SAVE) self._revert_btn = wx.Button(self, wx.ID_REVERT_TO_SAVED) help_btn = wx.Button(self, wx.ID_HELP) hbs1.Add(self._save_btn, 0, wx.ALIGN_CENTRE | wx.ALL, 5) hbs1.Add(help_btn, 0, wx.ALIGN_CENTRE | wx.ALL, 5) hbs1.Add(self._revert_btn, 0, wx.ALIGN_CENTRE | wx.ALL, 5) # all done vbs.Add(hbs, 1, wx.EXPAND | wx.ALL, 5) vbs.Add(wx.StaticLine(self, -1), 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5) vbs.Add(hbs1, 0, wx.ALIGN_CENTRE | wx.ALL, 5) self.SetSizer(vbs) self.SetAutoLayout(True) vbs.Fit(self) # event handlers wx.EVT_LISTBOX(self, self._item_list.GetId(), self._OnListBoxItem) wx.EVT_BUTTON(self, self._save_btn.GetId(), self._OnSave) wx.EVT_BUTTON(self, self._revert_btn.GetId(), self._OnRevert) wx.EVT_BUTTON(self, wx.ID_HELP, lambda _: wx.GetApp().displayhelpid(helpids.ID_TAB_MEMO)) # DIRTY UI Event handlers for w in self._w: pb_editor.EVT_DIRTY_UI(self, w.GetId(), self.OnMakeDirty) # populate data self._populate() # turn on dirty flag self.ignoredirty = False self.setdirty(False) # register for Today selection today.bind_notification_event(self.OnTodaySelection, today.Today_Group_Memo) # color code editable labels field_color.reload_color_info(self, widgets_list) pubsub.subscribe(self.OnPhoneChanged, pubsub.PHONE_MODEL_CHANGED)
def Set(self, data): self.ignore_dirty=True if data is None: for n in self._fields: n[self._w_index].Enable(False) else: for n in self._fields: w=n[self._w_index] w.Enable(True) w.SetValue(getattr(data, n[self._dict_key_index])) self.ignore_dirty=self.dirty=False def Get(self, data): self.ignore_dirty=self.dirty=False if data is None: return for n in self._fields: w=n[self._w_index] v=w.GetValue() setattr(data, n[self._dict_key_index], v) class TodoWidget (wx.Panel) : color_field_name='todo' def __init__(self, mainwindow, parent): global widgets_list super(TodoWidget, self).__init__(parent, -1) self._main_window=mainwindow self._data=self._data_map={} vbs=wx.BoxSizer(wx.VERTICAL) hbs=wx.BoxSizer(wx.HORIZONTAL) self._item_list=wx.ListBox(self, wx.NewId(), style=wx.LB_SINGLE|wx.LB_HSCROLL|wx.LB_NEEDED_SB) hbs.Add(self._item_list, 1, wx.EXPAND|wx.BOTTOM, border=5) scrolled_panel=scrolled.ScrolledPanel(self, -1) vbs1=wx.BoxSizer(wx.VERTICAL) self._items=( (GeneralEditor, 0, None), (cal_editor.CategoryEditor, 1, 'category'), (pb_editor.MemoEditor, 1, 'memo') ) self._w=[] for n in self._items: w=n[0](scrolled_panel, -1) vbs1.Add(w, n[1], wx.EXPAND|wx.ALL, 5) self._w.append(w) if n[2]: widgets_list.append((w.static_box, n[2])) scrolled_panel.SetSizer(vbs1) scrolled_panel.SetAutoLayout(True) vbs1.Fit(scrolled_panel) scrolled_panel.SetupScrolling() hbs.Add(scrolled_panel, 3, wx.EXPAND|wx.ALL, border=5) self._general_editor_w=self._w[0] self._cat_editor_w=self._w[1] self._memo_editor_w=self._w[2] hbs1=wx.BoxSizer(wx.HORIZONTAL) self._save_btn=wx.Button(self, wx.NewId(), "Save") self._revert_btn=wx.Button(self, wx.NewId(), "Revert") help_btn=wx.Button(self, wx.ID_HELP, "Help") hbs1.Add(self._save_btn, 0, wx.ALIGN_CENTRE|wx.ALL, 5) hbs1.Add(help_btn, 0, wx.ALIGN_CENTRE|wx.ALL, 5) hbs1.Add(self._revert_btn, 0, wx.ALIGN_CENTRE|wx.ALL, 5) vbs.Add(hbs, 1, wx.EXPAND|wx.ALL, 5) vbs.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5) vbs.Add(hbs1, 0, wx.ALIGN_CENTRE|wx.ALL, 5) self.SetSizer(vbs) self.SetAutoLayout(True) vbs.Fit(self) wx.EVT_LISTBOX(self, self._item_list.GetId(), self._OnListBoxItem) wx.EVT_BUTTON(self, self._save_btn.GetId(), self._OnSave) wx.EVT_BUTTON(self, self._revert_btn.GetId(), self._OnRevert) wx.EVT_BUTTON(self, wx.ID_HELP, lambda _: wx.GetApp().displayhelpid(helpids.ID_TAB_TODO)) for w in self._w: pb_editor.EVT_DIRTY_UI(self, w.GetId(), self.OnMakeDirty) self._populate() self.ignoredirty=False self.setdirty(False) today.bind_notification_event(self.OnTodaySelection, today.Today_Group_Todo) today.bind_request_event(self.OnTodayRequest) field_color.reload_color_info(self, widgets_list) pubsub.subscribe(self.OnPhoneChanged, pubsub.PHONE_MODEL_CHANGED) def OnPhoneChanged(self, _): field_color.reload_color_info(self, widgets_list) self.Refresh() def _clear(self): self._item_list.Clear() self._clear_each() def _clear_each(self): for w in self._w: w.Set(None) w.Enable(False) self.Refresh() def _publish_today_events(self): now=datetime.datetime.now() _today='%04d%02d%02d'%(now.year, now.month, now.day) keys=self._data.keys() keys.sort() today_event=today.TodayTodoEvent() for k in keys: if self._data[k].is_active() and \ (not self._data[k].due_date or \ self._data[k].due_date<=_today): today_event.append(self._data[k].summary, { 'key': k, 'index': self._data_map[k] }) today_event.broadcast() def _publish_thisweek_events(self): now=datetime.datetime.now() _today='%04d%02d%02d'%(now.year, now.month, now.day) s=now+datetime.timedelta(7-now.isoweekday()%7) _sun='%04d%02d%02d'%(s.year, s.month, s.day) keys=self._data.keys() keys.sort() today_event=today.ThisWeekTodoEvent() dow_flg=[False]*7 for k in keys: due_date=self._data[k].due_date if due_date>_today and due_date<_sun: dt=datetime.datetime(int(due_date[:4]), int(due_date[4:6]), int(due_date[6:8])) _dow=dt.isoweekday()%7 if dow_flg[_dow]: _name=today.dow_initials[-1]+' '+self._data[k].summary else: dow_flg[_dow]=True _name=today.dow_initials[_dow]+' - '+self._data[k].summary today_event.append(_name, { 'key': k, 'index': self._data_map[k] }) today_event.broadcast() def OnTodayRequest(self, _): self._publish_today_events() self._publish_thisweek_events() def OnTodaySelection(self, evt): if evt.data: self._item_list.SetSelection(evt.data.get('index', wx.NOT_FOUND)) self._populate_each(evt.data.get('key', None)) def _populate(self): self._clear() self._data_map={} keys=self._data.keys() keys.sort() for k in keys: n=self._data[k] i=self._item_list.Append(n.summary) self._item_list.SetClientData(i, k) self._data_map[k]=i self._publish_today_events() self._publish_thisweek_events() def _populate_each(self, k): if k is None: self._clear_each() return self.ignoredirty=True for w in self._w: w.Enable(True) entry=self._data[k] self._general_editor_w.Set(entry) self._cat_editor_w.Set(entry.categories) self._memo_editor_w.Set({ 'memo': entry.note }) self.ignoredirty=False self.setdirty(False) def OnMakeDirty(self, _=None): """A public function you can call that will set the dirty flag""" if self.dirty or self.ignoredirty or not self.IsShown(): return self.setdirty(True) def setdirty(self, val): """Set the dirty flag""" if self.ignoredirty: return self.dirty=val self._item_list.Enable(not self.dirty) self._save_btn.Enable(self.dirty) self._revert_btn.Enable(self.dirty) def OnAdd(self, _): if self.dirty: return m=TodoEntry() m.summary='New Task' self._data[m.id]=m self._populate() self._save_to_db(self._data) self._item_list.Select(self._data_map[m.id]) self._populate_each(m.id) def OnDelete(self, _): sel_idx=self._item_list.GetSelection() if sel_idx is None or sel_idx==-1: return self.ignoredirty=True k=self._item_list.GetClientData(sel_idx) self._item_list.Delete(sel_idx) self._clear_each() del self._data[k] del self._data_map[k] self._save_to_db(self._data) self.ignoredirty=False self.setdirty(False) def getdata(self,dict,want=None): dict['todo']=copy.deepcopy(self._data) return dict def populate(self, dict): self._data=dict.get('todo', {}) self._populate() def _save_to_db(self, todo_dict): db_rr={} for k, e in todo_dict.items(): db_rr[k]=TodoDataObject(e) database.ensurerecordtype(db_rr, todoobjectfactory) self._main_window.database.savemajordict('todo', db_rr) self._publish_today_events() self._publish_thisweek_events() def populatefs(self, dict): self._save_to_db(dict.get('todo', {})) return dict def getfromfs(self, result): todo_dict=self._main_window.database.\ getmajordictvalues('todo',todoobjectfactory) r={} for k,e in todo_dict.items(): ce=TodoEntry() ce.set_db_dict(e) r[ce.id]=ce result.update({ 'todo': r }) return result def _OnListBoxItem(self, evt): self._populate_each(self._item_list.GetClientData(evt.GetInt())) self.Refresh() def _OnSave(self, evt): self.ignoredirty=True sel_idx=self._item_list.GetSelection() k=self._item_list.GetClientData(sel_idx) entry=self._data[k] self._general_editor_w.Get(entry) entry.note=self._memo_editor_w.Get().get('memo', None) entry.categories=self._cat_editor_w.Get() entry.check_completion() self._general_editor_w.Set(entry) self._item_list.SetString(sel_idx, entry.summary) self._save_to_db(self._data) self.ignoredirty=False self.setdirty(False) def _OnRevert(self, evt): self.ignoredirty=True sel_idx=self._item_list.GetSelection() k=self._item_list.GetClientData(sel_idx) self._populate_each(k) self.ignoredirty=False self.setdirty(False)
def set(self, data): self._data={} self._data.update(data) self._data['start']=bptime.BPTime(data['start']) self._data['end']=bptime.BPTime(data['end']) if self.repeat is not None: r=RepeatEntry() r.set(self.repeat) self.repeat=r for k, e in self._data.items(): if e is None or e=='' or e==[]: del self._data[k] def set_db_dict(self, data): self._data={} self._data.update(data) self.allday=len(data['start'])==8 self._data['start']=bptime.BPTime(data['start']) self._data['end']=bptime.BPTime(data['end']) if data.has_key('repeat'): rp=RepeatEntry() rp.set_db_dict(data) self.repeat=rp def is_active(self, y, m ,d): s=self._data['start'].date e=self._data['end'].date d=datetime.date(y, m, d) if d<s or d>e: return False if self.repeat is None: return True return self.repeat.is_active(s, d) def suppress_repeat_entry(self, y, m, d): if self.repeat is None: return self.repeat.add_suppressed(y, m, d) def _set_or_del(self, key, v, v_list=()): if v is None or v in v_list: if self._data.has_key(key): del self._data[key] else: self._data[key]=v def _get_description(self): return self._data.get('description', '') def _set_description(self, desc): self._set_or_del('description', desc, ('',)) description=property(fget=_get_description, fset=_set_description) def _get_location(self): return self._data.get('location', '') def _set_location(self, location): self._set_or_del('location', location, ('',)) location=property(fget=_get_location, fset=_set_location) def _get_desc_loc(self): if self.location: return self.description+'['+self.location+']' return self.description def _set_desc_loc(self, v): _idx1=v.find('[') _idx2=v.find(']') if _idx1!=-1 and _idx2!=-1 and _idx2>_idx1: self.location=v[_idx1+1:_idx2] self.description=v[:_idx1] else: self.description=v desc_loc=property(fget=_get_desc_loc, fset=_set_desc_loc) def _get_priority(self): return self._data.get('priority', None) def _set_priority(self, priority): self._set_or_del('priority', priority) priority=property(fget=_get_priority, fset=_set_priority) def _get_alarm(self): return self._data.get('alarm', -1) def _set_alarm(self, alarm): self._set_or_del('alarm', alarm) alarm=property(fget=_get_alarm, fset=_set_alarm) def _get_allday(self): return self._data.get('allday', False) def _set_allday(self, allday): self._data['allday']=allday allday=property(fget=_get_allday, fset=_set_allday) def _get_start(self): return self._data['start'].get() def _set_start(self, datetime): self._data['start'].set(datetime) start=property(fget=_get_start, fset=_set_start) def _get_start_str(self): return self._data['start'].date_str()+' '+\ self._data['start'].time_str(False, '00:00') start_str=property(fget=_get_start_str) def _get_end(self): return self._data['end'].get() def _set_end(self, datetime): self._data['end'].set(datetime) end=property(fget=_get_end, fset=_set_end) def _get_end_str(self): return self._data['end'].date_str()+' '+\ self._data['end'].time_str(False, '00:00') end_str=property(fget=_get_end_str) def _get_vibrate(self): return self._data.get('vibrate', 0) def _set_vibrate(self, v): self._set_or_del('vibrate', v, (None, 0, False)) vibrate=property(fget=_get_vibrate, fset=_set_vibrate) def _get_voice(self): return self._data.get('voice', None) def _set_voice(self, v): self._set_or_del('voice', v, (None,)) voice=property(fget=_get_voice, fset=_set_voice) def _get_serials(self): return self._data.get('serials', None) def _set_serials(self, serials): self._data['serials']=serials serials=property(fget=_get_serials, fset=_set_serials) def _get_repeat(self): return self._data.get('repeat', None) def _set_repeat(self, repeat): self._set_or_del('repeat', repeat) repeat=property(fget=_get_repeat, fset=_set_repeat) def _get_id(self): s=self._data.get('serials', []) for n in s: if n.get('sourcetype', None)=='bitpim': return n.get('id', None) return None def _set_id(self, id): s=self._data.get('serials', []) for n in s: if n.get('sourcetype', None)=='bitpim': n['id']=id return self._data['serials'].append({'sourcetype': 'bitpim', 'id': id } ) id=property(fget=_get_id, fset=_set_id) def _get_notes(self): return self._data.get('notes', '') def _set_notes(self, s): self._set_or_del('notes', s, ('',)) notes=property(fget=_get_notes, fset=_set_notes) def _get_categories(self): return self._data.get('categories', []) def _set_categories(self, s): self._set_or_del('categories', s,([],)) if s==[] and self._data.has_key('categories'): del self._data['categories'] categories=property(fget=_get_categories, fset=_set_categories) def _get_categories_str(self): c=self.categories if len(c): return ';'.join([x['category'] for x in c]) else: return '' categories_str=property(fget=_get_categories_str) def _get_ringtone(self): return self._data.get('ringtone', '') def _set_ringtone(self, rt): self._set_or_del('ringtone', rt, ('',)) ringtone=property(fget=_get_ringtone, fset=_set_ringtone) def _get_wallpaper(self): return self._data.get('wallpaper', '',) def _set_wallpaper(self, wp): self._set_or_del('wallpaper', wp, ('',)) wallpaper=property(fget=_get_wallpaper, fset=_set_wallpaper) _persistrandom=random.Random() def _create_id(self): "Create a BitPim serial for this entry" rand2=random.Random() num=sha.new() num.update(`self._persistrandom.random()`) num.update(`rand2.random()`) self._data["serials"].append({"sourcetype": "bitpim", "id": num.hexdigest()}) def _get_print_data(self): """ return a list of strings used for printing this event: [0]: start time, [1]: '', [2]: end time, [3]: Description [4]: Repeat Type, [5]: Alarm """ if self.allday: t0='All Day' t1='' else: t0=self._data['start'].time_str() t1=self._data['end'].time_str() rp=self.repeat if rp is None: rp_str='' else: rp_str=rp.repeat_type[0].upper() if self.alarm==-1: alarm_str='' else: alarm_str='%d:%02d'%(self.alarm/60, self.alarm%60) return [t0, '', t1, self.description, rp_str, alarm_str] print_data=property(fget=_get_print_data) def cmp_by_time(a, b): """ compare 2 objects by start times. -1 if a<b, 0 if a==b, and 1 if a>b allday is always less than having start times. Mainly used for sorting list of events """ if not isinstance(a, CalendarEntry) or \ not isinstance(b, CalendarEntry): raise TypeError, 'must be a CalendarEntry object' if a.allday and b.allday: return 0 if a.allday and not b.allday: return -1 if not a.allday and b.allday: return 1 t0=a.start[3:] t1=b.start[3:] if t0<t1: return -1 if t0==t1: return 0 if t0>t1: return 1 cmp_by_time=staticmethod(cmp_by_time) def _summary(self): if self.allday: str=self.description else: hr=self.start[3] ap="am" if hr>=12: ap="pm" hr-=12 if hr==0: hr=12 str="%2d:%02d %s" % (hr, self.start[4], ap) str+=" "+self.description return str summary=property(fget=_summary) class Calendar (calendarcontrol.Calendar) : """A class encapsulating the GUI and data of the calendar (all days). A seperate L{DayViewDialog} is used to edit the content of one particular day.""" CURRENTFILEVERSION=3 def __init__(self, mainwindow, parent, id=-1): """constructor @type mainwindow: gui.MainWindow @param mainwindow: Used to get configuration data (such as directory to save/load data. @param parent: Widget acting as parent for this one @param id: id """ self.mainwindow=mainwindow self.entrycache={} self.entries={} self.repeating=[] self._data={} calendarcontrol.Calendar.__init__(self, parent, rows=5, id=id) self.dialog=calendarentryeditor.Editor(self) pubsub.subscribe(self.OnMediaNameChanged, pubsub.MEDIA_NAME_CHANGED) today.bind_notification_event(self.OnTodayItem, today.Today_Group_Calendar) today.bind_request_event(self.OnTodayRequest) pubsub.subscribe(self.OnTodayButton, pubsub.MIDNIGHT) def OnPrintDialog(self, mainwindow, config): dlg=CalendarPrintDialog(self, mainwindow, config) dlg.ShowModal() dlg.Destroy() def OnMediaNameChanged(self, msg): d=msg.data _type=d.get(pubsub.media_change_type, None) _old_name=d.get(pubsub.media_old_name, None) _new_name=d.get(pubsub.media_new_name, None) if _type is None or _old_name is None or _new_name is None: return if _type!=pubsub.wallpaper_type and \ _type!=pubsub.ringtone_type: return _old_name=common.basename(_old_name) _new_name=common.basename(_new_name) if _type==pubsub.wallpaper_type: attr_name='wallpaper' else: attr_name='ringtone' modified=False for k,e in self._data.items(): if getattr(e, attr_name, None)==_old_name: setattr(e, attr_name, _new_name) modified=True if modified: self.updateonchange() def getdata(self, dict): """Return underlying calendar data in bitpim format @return: The modified dict updated with at least C{dict['calendar']}""" if dict.get('calendar_version', None)==2: dict['calendar']=self._convert3to2(self._data, dict.get('ringtone-index', None)) else: dict['calendar']=copy.deepcopy(self._data, _nil={}) return dict def updateonchange(self): """Called when our data has changed The disk, widget and display are all updated with the new data""" d={} d=self.getdata(d) self.populatefs(d) self.populate(d) self.RefreshAllEntries() def AddEntry(self, entry): """Adds and entry into the calendar data. The entries on disk are updated by this function. @type entry: a dict containing all the fields. @param entry: an entry. It must contain a C{pos} field. You should call L{newentryfactory} to make an entry that you then modify """ self._data[entry.id]=entry self.updateonchange() def DeleteEntry(self, entry): """Deletes an entry from the calendar data. The entries on disk are updated by this function. @type entry: a dict containing all the fields. @param entry: an entry. It must contain a C{pos} field corresponding to an existing entry """ del self._data[entry.id] self.updateonchange() def DeleteEntryRepeat(self, entry, year, month, day): """Deletes a specific repeat of an entry See L{DeleteEntry}""" self._data[entry.id].suppress_repeat_entry(year, month, day) self.updateonchange() def ChangeEntry(self, oldentry, newentry): """Changes an entry in the calendar data. The entries on disk are updated by this function. """ assert oldentry.id==newentry.id self._data[newentry.id]=newentry self.updateonchange() def getentrydata(self, year, month, day): """return the entry objects for corresponding date @rtype: list""" res=self.entrycache.get( (year,month,day), None) if res is not None: return res res=self.entries.get((year,month,day), []) for i in self.repeating: if i.is_active(year, month, day): res.append(i) self.entrycache[(year,month,day)] = res return res def newentryfactory(self, year, month, day): """Returns a new 'blank' entry with default fields @rtype: CalendarEntry """ res=CalendarEntry(year, month, day) now=time.localtime() event_start=(year, month, day, now.tm_hour, now.tm_min) event_end=[year, month, day, now.tm_hour, now.tm_min] if event_end[3]<23: event_end[3]+=1 event_end[4]=0 else: event_end[3]=23 event_end[4]=59 res.start=event_start res.end=event_end res.description='New Event' return res def getdaybitmap(self, start, repeat): if repeat!="weekly": return 0 dayofweek=calendar.weekday(*(start[:3])) dayofweek=(dayofweek+1)%7 return [2048,1024,512,256,128,64,32][dayofweek] def OnGetEntries(self, year, month, day): """return pretty printed sorted entries for date as required by the parent L{calendarcontrol.Calendar} for display in a cell""" entry_list=self.getentrydata(year, month, day) res=[ (i.start[3], i.start[4], i.description) \ for i in entry_list if not i.allday ] res += [ (None, None, i.description) \ for i in entry_list if i.allday ] res.sort() return res def OnEdit(self, year, month, day, entry=None): """Called when the user wants to edit entries for a particular day""" if self.dialog.dirty: wx.Bell() else: self.dialog.setdate(year, month, day, entry) self.dialog.Show(True) def OnTodayItem(self, evt): if evt.data: args=evt.data['datetime']+(evt.data['entry'],) self.OnEdit(*args) def OnTodayButton(self, evt): """ Called when the user goes to today cell""" super(Calendar, self).OnTodayButton(evt) if self.dialog.IsShown(): self.OnEdit(*self.selecteddate) def _publish_today_events(self): now=datetime.datetime.now() l=self.getentrydata(now.year, now.month, now.day) l.sort(CalendarEntry.cmp_by_time) today_event=today.TodayCalendarEvent() for e in l: today_event.append(e.summary, { 'datetime': (now.year, now.month, now.day), 'entry': e }) today_event.broadcast() def _publish_thisweek_events(self): now=datetime.datetime.now() one_day=datetime.timedelta(1) d1=now _days=6-(now.isoweekday()%7) res=[] today_event=today.ThisWeekCalendarEvent() for i in range(_days): d1+=one_day l=self.getentrydata(d1.year, d1.month, d1.day) if l: _dow=today.dow_initials[d1.isoweekday()%7] l.sort(CalendarEntry.cmp_by_time) for i,x in enumerate(l): if i: _name=today.dow_initials[-1]+' ' else: _name=_dow+' - ' _name+=x.summary today_event.append(_name, { 'datetime': (d1.year, d1.month, d1.day), 'entry': x }) today_event.broadcast() def OnTodayRequest(self, _): self._publish_today_events() self._publish_thisweek_events() def populate(self, dict): """Updates the internal data with the contents of C{dict['calendar']}""" if dict.get('calendar_version', None)==2: self._data=self._convert2to3(dict.get('calendar', {}), dict.get('ringtone-index', {})) else: self._data=dict.get('calendar', {}) self.entrycache={} self.entries={} self.repeating=[] for entry in self._data: entry=self._data[entry] y,m,d,h,min=entry.start if entry.repeat is None: self.entries.setdefault((y,m,d), []).append(entry) else: self.repeating.append(entry) self._publish_today_events() self._publish_thisweek_events() self.RefreshAllEntries() def populatefs(self, dict): """Saves the dict to disk""" if dict.get('calendar_version', None)==2: cal_dict=self._convert2to3(dict.get('calendar', {}), dict.get('ringtone-index', {})) else: cal_dict=dict.get('calendar', {}) db_rr={} for k, e in cal_dict.items(): db_rr[k]=CalendarDataObject(e) database.ensurerecordtype(db_rr, calendarobjectfactory) db_rr=database.extractbitpimserials(db_rr) self.mainwindow.database.savemajordict('calendar', db_rr) return dict def getfromfs(self, dict): """Updates dict with info from disk @Note: The dictionary passed in is modified, as well as returned @rtype: dict @param dict: the dictionary to update @return: the updated dictionary""" self.thedir=self.mainwindow.calendarpath if os.path.exists(os.path.join(self.thedir, "index.idx")): dct={'result': {}} common.readversionedindexfile(os.path.join(self.thedir, "index.idx"), dct, self.versionupgrade, self.CURRENTFILEVERSION) converted=dct['result'].has_key('converted') db_r={} for k,e in dct['result'].get('calendar', {}).items(): if converted: db_r[k]=CalendarDataObject(e) else: ce=CalendarEntry() ce.set(e) db_r[k]=CalendarDataObject(ce) database.ensurerecordtype(db_r, calendarobjectfactory) db_r=database.extractbitpimserials(db_r) self.mainwindow.database.savemajordict('calendar', db_r) os.rename(os.path.join(self.thedir, "index.idx"), os.path.join(self.thedir, "index-is-now-in-database.bak")) cal_dict=self.mainwindow.database.getmajordictvalues('calendar', calendarobjectfactory) r={} for k,e in cal_dict.items(): ce=CalendarEntry() ce.set_db_dict(e) r[ce.id]=ce dict.update({ 'calendar': r }) return dict def versionupgrade(self, dict, version): """Upgrade old data format read from disk @param dict: The dict that was read in @param version: version number of the data on disk """ if version==0: version=1 if version==1: version=2 for k in dict['result']['calendar']: entry=dict['result']['calendar'][k] entry['daybitmap']=self.getdaybitmap(entry['start'], entry['repeat']) del entry['?d'] if version==2: version=3 dict['result']['calendar']=self.convert_dict(dict['result'].get('calendar', {}), 2, 3) dict['result']['converted']=True def convert_dict(self, dict, from_version, to_version, ringtone_index={}): """ Convert the calendatr dict from one version to another. Currently only support conversion between version 2 and 3. """ if dict is None: return None if from_version==2 and to_version==3: return self._convert2to3(dict, ringtone_index) elif from_version==3 and to_version==2: return self._convert3to2(dict, ringtone_index) else: raise 'Invalid conversion' def _convert2to3(self, dict, ringtone_index): """ Convert calendar dict from version 2 to 3. """ r={} for k,e in dict.items(): ce=CalendarEntry() ce.start=e['start'] ce.end=e['end'] ce.description=e['description'] ce.alarm=e['alarm'] ce.ringtone=ringtone_index.get(e['ringtone'], {}).get('name', '') repeat=e['repeat'] if repeat is None: ce.repeat=None else: repeat_entry=RepeatEntry() if repeat=='daily': repeat_entry.repeat_type=repeat_entry.daily repeat_entry.interval=1 elif repeat=='monfri': repeat_entry.repeat_type=repeat_entry.daily repeat_entry.interval=0 elif repeat=='weekly': repeat_entry.repeat_type=repeat_entry.weekly repeat_entry.interval=1 dow=datetime.date(*e['start'][:3]).isoweekday()%7 repeat_entry.dow=1<<dow elif repeat=='monthly': repeat_entry.repeat_type=repeat_entry.monthly else: repeat_entry.repeat_type=repeat_entry.yearly s=[] for n in e.get('exceptions',[]): s.append(bptime.BPTime(n)) repeat_entry.suppressed=s ce.repeat=repeat_entry r[ce.id]=ce return r def _convert_daily_events(self, e, d): """ Conver a daily event from v3 to v2 """ rp=e.repeat if rp.interval==1: d['repeat']='daily' elif rp.interval==0: d['repeat']='monfri' else: d['repeat']='daily' t0=datetime.date(*e.start[:3]) t1=datetime.date(*e.end[:3]) delta_t=datetime.timedelta(1) while t0<=t1: if not e.is_active(t0.year, t0.month, t0.day): d['exceptions'].append((t0.year, t0.month, t0.day)) t0+=delta_t def _convert_weekly_events(self, e, d, idx): """ Convert a weekly event from v3 to v2 """ rp=e.repeat dow=rp.dow t0=datetime.date(*e.start[:3]) t1=t3=datetime.date(*e.end[:3]) delta_t=datetime.timedelta(1) delta_t7=datetime.timedelta(7) if (t1-t0).days>6: t1=t0+datetime.timedelta(6) d['repeat']='weekly' res={} while t0<=t1: dow_0=t0.isoweekday()%7 if (1<<dow_0)&dow: dd=copy.deepcopy(d) dd['start']=(t0.year, t0.month, t0.day, e.start[3], e.start[4]) dd['daybitmap']=self.getdaybitmap(dd['start'], dd['repeat']) t2=t0 while t2<=t3: if not e.is_active(t2.year, t2.month, t2.day): dd['exceptions'].append((t2.year, t2.month, t2.day)) t2+=delta_t7 dd['pos']=idx res[idx]=dd idx+=1 t0+=delta_t return idx, res def _convert3to2(self, dict, ringtone_index): """Convert calendar dict from version 3 to 2.""" r={} idx=0 for k,e in dict.items(): d={} d['start']=e.start d['end']=e.end d['description']=e.description d['alarm']=e.alarm d['changeserial']=1 d['snoozedelay']=0 d['ringtone']=0 try: d['ringtone']=[i for i,r in ringtone_index.items() \ if r.get('name', '')==e.ringtone][0] except: pass rp=e.repeat if rp is None: d['repeat']=None d['exceptions']=[] d['daybitmap']=0 else: s=[] for n in rp.suppressed: s.append(n.get()[:3]) d['exceptions']=s if rp.repeat_type==rp.daily: self._convert_daily_events(e, d) elif rp.repeat_type==rp.weekly: idx, rr=self._convert_weekly_events(e, d, idx) r.update(rr) continue elif rp.repeat_type==rp.monthly: d['repeat']='monthly' elif rp.repeat_type==rp.yearly: d['repeat']='yearly' d['daybitmap']=self.getdaybitmap(d['start'], d['repeat']) d['pos']=idx r[idx]=d idx+=1 if __debug__: print 'Calendar._convert3to2: V2 dict:' print r return r """A class encapsulating the GUI and data of the calendar (all days). A seperate dialog is used to edit the content of one particular day.""" class CalendarPrintDialog (wx.Dialog) : _regular_template='cal_regular.xy' _regular_style='cal_regular_style.xy' _monthly_template='cal_monthly.xy' _monthly_style='cal_monthly_style.xy' def __init__(self, calwidget, mainwindow, config): super(CalendarPrintDialog, self).__init__(mainwindow, -1, 'Print Calendar') self._cal_widget=calwidget self._xcp=self._html=self._dns=None self._dt_index=self._dt_start=self._dt_end=None self._date_changed=self._style_changed=False self._tmp_file=common.gettempfilename("htm") vbs=wx.BoxSizer(wx.VERTICAL) hbs=wx.BoxSizer(wx.HORIZONTAL) sbs=wx.StaticBoxSizer(wx.StaticBox(self, -1, 'Print Range'), wx.VERTICAL) gs=wx.FlexGridSizer(-1, 2, 5, 5) gs.AddGrowableCol(1) gs.Add(wx.StaticText(self, -1, 'Start:'), 0, wx.ALL, 0) self._start_date=wx.DatePickerCtrl(self, style=wx.DP_DROPDOWN | wx.DP_SHOWCENTURY) wx.EVT_DATE_CHANGED(self, self._start_date.GetId(), self.OnDateChanged) gs.Add(self._start_date, 0, wx.ALL, 0) gs.Add(wx.StaticText(self, -1, 'End:'), 0, wx.ALL, 0) self._end_date=wx.DatePickerCtrl(self, style=wx.DP_DROPDOWN | wx.DP_SHOWCENTURY) wx.EVT_DATE_CHANGED(self, self._end_date.GetId(), self.OnDateChanged) gs.Add(self._end_date, 0, wx.ALL, 0) sbs.Add(gs, 1, wx.EXPAND|wx.ALL, 5) hbs.Add(sbs, 0, wx.ALL, 5) self._print_style=wx.RadioBox(self, -1, 'Print Style', choices=['List View', 'Month View'], style=wx.RA_SPECIFY_ROWS) wx.EVT_RADIOBOX(self, self._print_style.GetId(), self.OnStyleChanged) hbs.Add(self._print_style, 0, wx.ALL, 5) vbs.Add(hbs, 0, wx.ALL, 5) vbs.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5) hbs=wx.BoxSizer(wx.HORIZONTAL) for b in (('Print', -1, self.OnPrint), ('Page Setup', -1, self.OnPageSetup), ('Print Preview', -1, self.OnPrintPreview), ('Close', wx.ID_CANCEL, self.OnClose)): btn=wx.Button(self, b[1], b[0]) hbs.Add(btn, 0, wx.ALIGN_CENTER|wx.ALL, 5) if b[2] is not None: wx.EVT_BUTTON(self, btn.GetId(), b[2]) vbs.Add(hbs, 0, wx.ALIGN_CENTRE|wx.EXPAND|wx.ALL, 5) self.SetSizer(vbs) self.SetAutoLayout(True) vbs.Fit(self) _one_day=wx.DateSpan(days=1) _empty_day=['', []] def _one_day_data(self): r=[str(self._dt_index.GetDay())] events=[] if self._dt_start<=self._dt_index<=self._dt_end: entries=self._cal_widget.getentrydata(self._dt_index.GetYear(), self._dt_index.GetMonth()+1, self._dt_index.GetDay()) else: entries=[] self._dt_index+=self._one_day if len(entries): entries.sort(CalendarEntry.cmp_by_time) for e in entries: print_data=e.print_data events.append('%s: %s'%(print_data[0], print_data[3])) r.append(events) return r def _one_week_data(self): dow=self._dt_index.GetWeekDay() if dow: r=[self._empty_day]*dow else: r=[] for d in range(dow, 7): r.append(self._one_day_data()) if self._dt_index.GetDay()==1: break return r def _one_month_data(self): m=self._dt_index.GetMonth() y=self._dt_index.GetYear() r=['%s %d'%(self._dt_index.GetMonthName(m), y)] while self._dt_index.GetMonth()==m: r.append(self._one_week_data()) return r def _get_monthly_data(self): """ generate a dict suitable to print monthly events """ res=[] self._dt_index=wx.DateTimeFromDMY(1, self._dt_start.GetMonth(), self._dt_start.GetYear()) while self._dt_index<=self._dt_end: res.append(self._one_month_data()) return res def _get_list_data(self): """ generate a dict suitable for printing""" self._dt_index=wx.DateTimeFromDMY(self._dt_start.GetDay(), self._dt_start.GetMonth(), self._dt_start.GetYear()) current_month=None res=a_month=month_events=[] while self._dt_index<=self._dt_end: y=self._dt_index.GetYear() m=self._dt_index.GetMonth() d=self._dt_index.GetDay() entries=self._cal_widget.getentrydata(y, m+1, d) self._dt_index+=self._one_day if not len(entries): continue entries.sort(CalendarEntry.cmp_by_time) if m!=current_month: if len(month_events): a_month.append(month_events) res.append(a_month) current_month=m a_month=['%s %d'%(self._dt_index.GetMonthName(m), y)] month_events=[] for i,e in enumerate(entries): if i: date_str=day_str='' else: date_str=str(d) day_str=self._dt_index.GetWeekDayName( self._dt_index.GetWeekDay()-1, wx.DateTime.Name_Abbr) month_events.append([date_str, day_str]+e.print_data) if len(month_events): a_month.append(month_events) res.append(a_month) return res def _gen_print_data(self): if not self._date_changed and \ not self._style_changed and \ self._html is not None: return self._dt_start=self._start_date.GetValue() self._dt_end=self._end_date.GetValue() if not self._dt_start.IsValid() or not self._dt_end.IsValid(): return print_data=( (self._regular_template, self._regular_style, self._get_list_data), (self._monthly_template, self._monthly_style, self._get_monthly_data)) print_style=self._print_style.GetSelection() print_dict=print_data[print_style][2]() if self._xcp is None: self._xcp=xyaptu.xcopier(None) tmpl=file(guihelper.getresourcefile(print_data[print_style][0]), 'rt').read() self._xcp.setupxcopy(tmpl) elif self._style_changed: tmpl=file(guihelper.getresourcefile(print_data[print_style][0]), 'rt').read() self._xcp.setupxcopy(tmpl) if self._dns is None: self._dns={ 'common': __import__('common') } self._dns['guihelper']=__import__('guihelper') self._dns['events']=[] self._dns['events']=print_dict self._dns['date_range']='%s - %s'%\ (self._dt_start.FormatDate(), self._dt_end.FormatDate()) html=self._xcp.xcopywithdns(self._dns.copy()) sd={'styles': {}, '__builtins__': __builtins__ } try: execfile(guihelper.getresourcefile(print_data[print_style][1]), sd, sd) except UnicodeError: common.unicode_execfile(guihelper.getresourcefile(print_data[print_style][1]), sd, sd) try: self._html=bphtml.applyhtmlstyles(html, sd['styles']) except: if __debug__: file('debug.html', 'wt').write(html) raise self._date_changed=self._style_change=False def OnDateChanged(self, _): self._date_changed=True def OnStyleChanged(self, _): self._style_changed=True def OnPrint(self, _): self._gen_print_data() wx.GetApp().htmlprinter.PrintText(self._html) def OnPageSetup(self, _): wx.GetApp().htmlprinter.PageSetup() def OnPrintPreview(self, _): self._gen_print_data() wx.GetApp().htmlprinter.PreviewText(self._html) def OnHelp(self, _): pass def OnClose(self, _): try: os.remove(self._tmp_file) except: pass self.EndModal(wx.ID_CANCEL)
def __init__(self, mainwindow, parent): global widgets_list super(TodoWidget, self).__init__(parent, -1) self._main_window=mainwindow self._data=self._data_map={} # main box sizer vbs=wx.BoxSizer(wx.VERTICAL) # horizontal sizer for the listbox and tabs hbs=wx.BoxSizer(wx.HORIZONTAL) # the list box self._item_list=wx.ListBox(self, wx.NewId(), style=wx.LB_SINGLE|wx.LB_HSCROLL|wx.LB_NEEDED_SB) hbs.Add(self._item_list, 1, wx.EXPAND|wx.BOTTOM, border=5) # the detailed info pane as a scrolled panel scrolled_panel=scrolled.ScrolledPanel(self, -1) vbs1=wx.BoxSizer(wx.VERTICAL) self._items=( (GeneralEditor, 0, None), (cal_editor.CategoryEditor, 1, 'category'), (pb_editor.MemoEditor, 1, 'memo') ) self._w=[] for n in self._items: w=n[0](scrolled_panel, -1) vbs1.Add(w, n[1], wx.EXPAND|wx.ALL, 5) self._w.append(w) if n[2]: widgets_list.append((w.static_box, n[2])) scrolled_panel.SetSizer(vbs1) scrolled_panel.SetAutoLayout(True) vbs1.Fit(scrolled_panel) scrolled_panel.SetupScrolling() hbs.Add(scrolled_panel, 3, wx.EXPAND|wx.ALL, border=5) # save references to the widgets self._general_editor_w=self._w[0] self._cat_editor_w=self._w[1] self._memo_editor_w=self._w[2] # the bottom buttons hbs1=wx.BoxSizer(wx.HORIZONTAL) self._save_btn=wx.Button(self, wx.ID_SAVE) self._revert_btn=wx.Button(self, wx.ID_REVERT_TO_SAVED) help_btn=wx.Button(self, wx.ID_HELP) hbs1.Add(self._save_btn, 0, wx.ALIGN_CENTRE|wx.ALL, 5) hbs1.Add(help_btn, 0, wx.ALIGN_CENTRE|wx.ALL, 5) hbs1.Add(self._revert_btn, 0, wx.ALIGN_CENTRE|wx.ALL, 5) # all done vbs.Add(hbs, 1, wx.EXPAND|wx.ALL, 5) vbs.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5) vbs.Add(hbs1, 0, wx.ALIGN_CENTRE|wx.ALL, 5) self.SetSizer(vbs) self.SetAutoLayout(True) vbs.Fit(self) # event handlers wx.EVT_LISTBOX(self, self._item_list.GetId(), self._OnListBoxItem) wx.EVT_BUTTON(self, self._save_btn.GetId(), self._OnSave) wx.EVT_BUTTON(self, self._revert_btn.GetId(), self._OnRevert) wx.EVT_BUTTON(self, wx.ID_HELP, lambda _: wx.GetApp().displayhelpid(helpids.ID_TAB_TODO)) # DIRTY UI Event handlers for w in self._w: pb_editor.EVT_DIRTY_UI(self, w.GetId(), self.OnMakeDirty) # populate data self._populate() # turn on dirty flag self.ignoredirty=False self.setdirty(False) # register for Today selection today.bind_notification_event(self.OnTodaySelection, today.Today_Group_Todo) today.bind_request_event(self.OnTodayRequest) # color coded labels field_color.reload_color_info(self, widgets_list) pubsub.subscribe(self.OnPhoneChanged, pubsub.PHONE_MODEL_CHANGED)
def OnTodaySelection(self, evt): if evt.data: self._item_list.SelectItem(evt.data['id']) def get_sel_data(self): res={} for sel_idx in self._item_list.GetSelections(): k=self._item_list.GetPyData(sel_idx) if k: res[k]=self._data[k] return res class SMSWidget (wx.Panel) : _data_key='sms' _canned_data_key='canned_msg' def __init__(self, mainwindow, parent): super(SMSWidget, self).__init__(parent, -1) self._main_window=mainwindow self._data=self._canned_data={} vbs=wx.BoxSizer(wx.VERTICAL) hbs=wx.BoxSizer(wx.HORIZONTAL) self.read_only=False self.historical_date=None static_bs=wx.StaticBoxSizer(wx.StaticBox(self, -1, 'Historical Data Status:'), wx.VERTICAL) self.historical_data_label=wx.StaticText(self, -1, 'Current Data') static_bs.Add(self.historical_data_label, 1, wx.EXPAND|wx.ALL, 5) hbs.Add(static_bs, 1, wx.EXPAND|wx.ALL, 5) vbs.Add(hbs, 0, wx.EXPAND|wx.ALL, 5) self._sms=FolderPage(self) wx.EVT_BUTTON(self, self._sms.save_btn.GetId(), self.OnSaveCannedMsg) vbs.Add(self._sms, 1, wx.EXPAND|wx.ALL, 5) self.SetSizer(vbs) self.SetAutoLayout(True) vbs.Fit(self) today.bind_notification_event(self._sms.OnTodaySelection, today.Today_Group_IncomingSMS) def _populate(self): self._sms.Set(self._data, self._canned_data) self._sms.publish_today_data() def OnSaveCannedMsg(self, _): if self.read_only: wx.MessageBox('You are viewing historical data which cannot be changed or saved', 'Cannot Save SMS Data', style=wx.OK|wx.ICON_ERROR) return self._data, self._canned_data=self._sms.Get() self._save_to_db(canned_msg_dict=self._canned_data) def OnDelete(self, _): if self.read_only: return if self._sms.delete_selection(self._data): self._save_to_db(sms_dict=self._data) def getdata(self,dict,want=None): dict[self._data_key]=copy.deepcopy(self._data, {}) dict[self._canned_data_key]=self._canned_data.get().get( self._canned_data_key, {}) def get_selected_data(self): return self._sms.get_sel_data() def get_data(self): return self._data def populate(self, dict, force=False): if self.read_only and not force: return if not self.read_only: self._canned_data=sms.CannedMsgEntry() self._canned_data.set({ self._canned_data_key: dict.get(self._canned_data_key, [])}) self._data=dict.get(self._data_key, {}) self._populate() def _save_to_db(self, sms_dict=None, canned_msg_dict=None): if self.read_only: return if sms_dict is not None: db_rr={} for k, e in sms_dict.items(): db_rr[k]=sms.SMSDataObject(e) database.ensurerecordtype(db_rr, sms.smsobjectfactory) self._main_window.database.savemajordict(self._data_key, db_rr) if canned_msg_dict is not None: db_rr={} db_rr[self._canned_data_key]=sms.CannedMsgDataObject( canned_msg_dict) database.ensurerecordtype(db_rr, sms.cannedmsgobjectfactory) self._main_window.database.savemajordict(self._canned_data_key, db_rr) def populatefs(self, dict): if self.read_only: wx.MessageBox('You are viewing historical data which cannot be changed or saved', 'Cannot Save SMS Data', style=wx.OK|wx.ICON_ERROR) return canned_msg=sms.CannedMsgEntry() canned_msg.set({ self._canned_data_key: dict.get(self._canned_data_key, [])}) self._save_to_db(sms_dict=dict.get(self._data_key, []), canned_msg_dict=canned_msg) return dict def getfromfs(self, result, timestamp=None): sms_dict=self._main_window.database.\ getmajordictvalues(self._data_key, sms.smsobjectfactory, at_time=timestamp) r={} for k,e in sms_dict.items(): ce=sms.SMSEntry() ce.set_db_dict(e) r[ce.id]=ce result.update({ self._data_key: r }) canned_msg_dict=self._main_window.database.\ getmajordictvalues(self._canned_data_key, sms.cannedmsgobjectfactory) for k,e in canned_msg_dict.items(): ce=sms.CannedMsgEntry() ce.set_db_dict(e) result.update(ce.get()) return result def merge(self, dict): if self.read_only: wx.MessageBox('You are viewing historical data which cannot be changed or saved', 'Cannot Save SMS Data', style=wx.OK|wx.ICON_ERROR) return existing_id=[e.msg_id for k,e in self._data.items()] d=dict.get(self._data_key, {}) for k,e in d.items(): if e.msg_id not in existing_id: self._data[e.id]=e self._canned_data=sms.CannedMsgEntry() self._canned_data.set({ self._canned_data_key: dict.get(self._canned_data_key, []) } ) self._populate() self._save_to_db(sms_dict=self._data, canned_msg_dict=self._canned_data) def OnHistoricalData(self): """Display current or historical data""" if self.read_only: current_choice=guiwidgets.HistoricalDataDialog.Historical_Data else: current_choice=guiwidgets.HistoricalDataDialog.Current_Data dlg=guiwidgets.HistoricalDataDialog(self, current_choice=current_choice, historical_date=self.historical_date, historical_events=\ self._main_window.database.getchangescount(self._data_key)) if dlg.ShowModal()==wx.ID_OK: self._main_window.OnBusyStart() current_choice, self.historical_date=dlg.GetValue() r={} if current_choice==guiwidgets.HistoricalDataDialog.Current_Data: self.read_only=False msg_str='Current Data' self.getfromfs(r) else: self.read_only=True msg_str='Historical Data as of %s'%\ str(wx.DateTimeFromTimeT(self.historical_date)) self.getfromfs(r, self.historical_date) self.populate(r, True) self.historical_data_label.SetLabel(msg_str) self._main_window.OnBusyEnd() dlg.Destroy()