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)
Exemplo n.º 3
0
    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)
Exemplo n.º 4
0
    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)
Exemplo n.º 6
0
 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)
Exemplo n.º 8
0
 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)
Exemplo n.º 11
0
    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()