Module t9editor
[hide private]
[frames] | no frames]

Source Code for Module t9editor

  1  ### BITPIM 
  2  ### 
  3  ### Copyright (C) 2006 Joe Pham <djpham@bitpim.org> 
  4  ### 
  5  ### This program is free software; you can redistribute it and/or modify 
  6  ### it under the terms of the BitPim license as detailed in the LICENSE file. 
  7  ### 
  8  ### $Id: t9editor.py 4379 2007-08-28 03:06:58Z djpham $ 
  9  """ 
 10  Code to handle T9 Editor 
 11   
 12  The format of the T9 Words data is standardized.  It is a list of dict that 
 13  has the following standard fields: 
 14   
 15  "words": an ordered list of dicts, each dict has the following fields: 
 16           "word": string value of the actual T9 Word. 
 17   
 18  To implement T9 Editor feature for your phone, do the following: 
 19   
 20  1. Add 2 entries into Profile._supportedsyncs: 
 21          ... 
 22          ('t9_udb', 'read', 'OVERWRITE'), 
 23          ('t9_udb', 'write', 'OVERWRITE'), 
 24   
 25  2. Implement the following 2 methods in your Phone class: 
 26      def gett9db(self, result) 
 27      def savet9db(self, result, _merge) 
 28   
 29      The result dict should contain: 
 30      result[t9editor.dict_key]=<instance of t9editor.T9WordsList()> 
 31   
 32      See module phones.com_lgxv8500 for an example implementation. 
 33   
 34  """ 
 35   
 36  # wx Modules 
 37  from __future__ import with_statement 
 38  import wx 
 39  import wx.gizmos as gizmos 
 40   
 41  # BitPim modules 
 42  import database 
 43  import guihelper 
 44  import helpids 
 45  import widgets 
 46   
 47  # module constants-------------------------------------------------------------- 
 48  dict_key='T9 Data' 
 49   
 50  #------------------------------------------------------------------------------- 
51 -class T9WordsDataObject(database.basedataobject):
52 _knownproperties=[] 53 _knownlistproperties=database.basedataobject._knownlistproperties.copy() 54 _knownlistproperties.update( { 'words': ['word'] })
55 - def __init__(self, data=None):
56 if data and isinstance(data, dict): 57 self.update(data)
58 t9wordsdataobjectfactory=database.dataobjectfactory(T9WordsDataObject) 59 60 #-------------------------------------------------------------------------------
61 -class T9WordsList(object):
62 _t9_dict={'0': '0', '1': '1', 63 'a': '2', 'b': '2', 'c': '2', '2': '2', 64 'd': '3', 'e': '3', 'f': '3', '3': '3', 65 'g': '4', 'h': '4', 'i': '4', '4': '4', 66 'j': '5', 'k': '5', 'l': '5', '5': '5', 67 'm': '6', 'n': '6', 'o': '6', '6': '6', 68 'p': '7', 'q': '7', 'r': '7', 's': '7', '7': '7', 69 't': '8', 'u': '8', 'v': '8', '8': '8', 70 'w': '9', 'x': '9', 'y': '9', 'z': '9', '9': '9', 71 }
72 - def __init__(self):
73 self._data={}
74
75 - def get(self):
76 return copy.deepcopy(self._data, {})
77 - def set(self, d):
78 self._data={} 79 self._data.update(d)
80
81 - def _set_or_del(self, key, v, v_list=[]):
82 if v is None or v in v_list: 83 if self._data.has_key(key): 84 del self._data[key] 85 else: 86 self._data[key]=v
87
88 - def _get_keys(self):
89 # return a list of available keys in this list 90 _keys=[x for x,y in self._data.items() if y] 91 _keys.sort() 92 return _keys
93 keys=property(fget=_get_keys) 94
95 - def _keyof(self, word):
96 # return the T9 key of this word 97 return ''.join([self._t9_dict.get(x.lower(), '1') for x in word])
98
99 - def get_words(self, key=None):
100 # return a list of words of group 'key', 101 # if key is None, return the whole list 102 _res=[] 103 if key is None: 104 _keys=self.keys 105 _keys.sort() 106 for _k in _keys: 107 _res+=self.get_words(_k) 108 else: 109 return self._data.get(key, [])
110
111 - def del_word(self, word):
112 # delete the specified word from the list 113 _key=self._keyof(word) 114 if self._data.has_key(_key): 115 for _idx,_word in enumerate(self._data[_key]): 116 if _word==word: 117 del self._data[_key][_idx] 118 if not self._data[_key]: 119 # empty list 120 del self._data[_key] 121 return
122
123 - def append_word(self, word):
124 # Append this word to our existing list 125 self._data.setdefault(self._keyof(word), []).append(word)
126
127 - def set_words(self, words, key=None):
128 # set the list of words for group 'key' 129 # if key is None, set the whole database 130 if key is None: 131 # set the whole list 132 self._data={} 133 for _word in words: 134 self.append_word(_word) 135 else: 136 _l=[] 137 for _word in words: 138 if self._keyof(_word)==key: 139 _l.append(_word) 140 self._data[key]=_l
141
142 - def clear(self):
143 self._data={}
144
145 - def save(self, db):
146 # save the current list to the database db 147 global dict_key 148 _rec=[] 149 for _,_list in self._data.items(): 150 _rec+=[ { 'word': x } for x in _list ] 151 _dict={ dict_key: { 'words': _rec } } 152 database.ensurerecordtype(_dict, t9wordsdataobjectfactory) 153 db.savemajordict(dict_key, _dict)
154 - def load(self, db):
155 # load from database db into the current list 156 global dict_key 157 _dict=db.getmajordictvalues(dict_key, t9wordsdataobjectfactory) 158 self.clear() 159 for _word in _dict.get(dict_key, {}).get('words', []): 160 if _word.get('word', None): 161 self.append_word(_word['word'])
162 163 #-------------------------------------------------------------------------------
164 -class T9EditorWidget(wx.Panel, widgets.BitPimWidget):
165 help_id=helpids.ID_TAB_T9EDITOR
166 - def __init__(self, mainwindow, parent):
167 super(T9EditorWidget, self).__init__(parent, -1) 168 self._mw=mainwindow 169 self._t9list=T9WordsList() 170 self.ignoredirty=False 171 self.dirty=False 172 # main box sizer 173 vbs=wx.BoxSizer(wx.VERTICAL) 174 # horizontal sizer for the main contents 175 hbs=wx.BoxSizer(wx.HORIZONTAL) 176 _svbs=wx.StaticBoxSizer(wx.StaticBox(self, -1, 'T9 Keys'), 177 wx.VERTICAL) 178 self._keys_lb=wx.ListBox(self, -1, 179 style=wx.LB_SINGLE|wx.LB_HSCROLL|wx.LB_NEEDED_SB) 180 wx.EVT_LISTBOX(self, self._keys_lb.GetId(), self._OnSelectKey) 181 _svbs.Add(self._keys_lb, 1, wx.EXPAND|wx.ALL, 5) 182 hbs.Add(_svbs, 1, wx.EXPAND|wx.ALL, 5) 183 self._words_w=gizmos.EditableListBox(self, -1, 'T9 Words:', style=0) 184 self._words_lb=self._words_w.GetListCtrl() 185 wx.EVT_BUTTON(self._words_w, self._words_w.GetUpButton().GetId(), 186 self._OnUpDown) 187 wx.EVT_BUTTON(self._words_w, self._words_w.GetDownButton().GetId(), 188 self._OnUpDown) 189 hbs.Add(self._words_w, 3, wx.EXPAND|wx.ALL, 5) 190 vbs.Add(hbs, 1, wx.EXPAND|wx.ALL, 5) 191 vbs.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5) 192 hbs=wx.BoxSizer(wx.HORIZONTAL) 193 self._save_btn=wx.Button(self, wx.ID_SAVE) 194 hbs.Add(self._save_btn, 0, 195 wx.ALIGN_CENTRE|wx.ALL, 5) 196 hbs.Add(wx.Button(self, wx.ID_HELP), 0, 197 wx.ALIGN_CENTRE|wx.ALL, 5) 198 self._revert_btn=wx.Button(self, wx.ID_REVERT_TO_SAVED) 199 hbs.Add(self._revert_btn, 0, 200 wx.ALIGN_CENTRE|wx.ALL, 5) 201 wx.EVT_BUTTON(self, wx.ID_SAVE, self._OnSave) 202 wx.EVT_BUTTON(self, wx.ID_REVERT_TO_SAVED, self._OnRevert) 203 wx.EVT_BUTTON(self, wx.ID_HELP, 204 lambda _: wx.GetApp().displayhelpid(self.help_id)) 205 vbs.Add(hbs, 0, wx.ALIGN_CENTRE|wx.ALL, 5) 206 self.SetSizer(vbs) 207 self.SetAutoLayout(True) 208 vbs.Fit(self) 209 # populate data 210 self._populate() 211 # turn on dirty flag 212 self.setdirty(False)
213
214 - def setdirty(self, val):
215 if self.ignoredirty: 216 return 217 self.dirty=val 218 self._save_btn.Enable(self.dirty) 219 self._revert_btn.Enable(self.dirty)
220
221 - def _populate_each(self):
222 # populate the word list based on the selected key 223 _sel=self._keys_lb.GetStringSelection() 224 self._words_lb.DeleteAllItems() 225 if _sel: 226 self._words_w.SetStrings(self._t9list.get_words(_sel))
227 - def _populate(self):
228 # clear both lists 229 self._keys_lb.Clear() 230 self._words_lb.DeleteAllItems() 231 # populate the keys list 232 for _key in self._t9list.keys: 233 self._keys_lb.Append(_key)
234 - def populate(self, dict):
235 global dict_key 236 self._t9list=dict.get(dict_key, T9WordsList()) 237 self._populate()
238 - def populatefs(self, dict):
239 global dict_key 240 self._t9list=dict.get(dict_key, T9WordsList()) 241 self._t9list.save(self._mw.database) 242 self._populate() 243 return dict
244 - def getfromfs(self, result):
245 self._t9list.load(self._mw.database) 246 global dict_key 247 result[dict_key]=self._t9list 248 return result
249 # called from various widget update callbacks
250 - def _re_order(self):
251 # update the order of the list 252 self._t9list.set_words(self._words_w.GetStrings(), 253 self._keys_lb.GetStringSelection())
254 - def _OnUpDown(self, evt):
255 wx.CallAfter(self._re_order) 256 self.OnMakeDirty() 257 evt.Skip()
258 - def OnMakeDirty(self, _=None):
259 """A public function you can call that will set the dirty flag""" 260 if self.dirty or self.ignoredirty: 261 # already dirty, no need to make it worse 262 return 263 self.setdirty(True)
264 - def OnDirty(self, _):
265 self.setdirty(True)
266
267 - def _OnSave(self, _):
268 self._t9list.save(self._mw.database) 269 self.setdirty(False)
270 - def _OnRevert(self, _):
271 self._t9list.load(self._mw.database) 272 self._populate() 273 self.setdirty(False)
274 - def _OnSelectKey(self, _):
275 self._populate_each()
276 - def CanAdd(self):
277 return True
278 - def OnAdd(self, _):
279 with guihelper.WXDialogWrapper(wx.TextEntryDialog(self, 'Enter a new word:', 280 'T9 User Word'), 281 True) as (_dlg, _retcode): 282 if _retcode==wx.ID_OK: 283 if _dlg.GetValue(): 284 self.OnMakeDirty() 285 self._t9list.append_word(_dlg.GetValue()) 286 self._populate()
287
288 - def CanDelete(self):
289 return self._words_lb.GetSelectedItemCount()
290 - def OnDelete(self, _):
291 _idx=self._words_lb.GetNextItem(-1, state=wx.LIST_STATE_SELECTED) 292 if _idx==-1: 293 return 294 self._t9list.del_word(self._words_w.GetStrings()[_idx]) 295 self._words_lb.DeleteItem(_idx) 296 # Check if this key is empty, if it is, delete it from the keys LB 297 if self._words_lb.GetItemCount()<2: 298 # this key is empty, delete it as well 299 _idx=self._keys_lb.GetSelection() 300 if _idx!=wx.NOT_FOUND: 301 self._keys_lb.Delete(_idx) 302 self.OnMakeDirty() 303 wx.CallAfter(self._re_order)
304 - def getdata(self, result):
305 global dict_key 306 result[dict_key]=self._t9list 307 return result
308