Package modules :: Module contacts_dbussim
[hide private]
[frames] | no frames]

Source Code for Module modules.contacts_dbussim

  1  """ 
  2  Synchronize with SIM card via DBUS (currently used as default contacts storage in SHR) 
  3   
  4  This file is part of Pisi. 
  5   
  6  Check these links for background information: 
  7  - U{http://git.freesmartphone.org/?p=specs.git;a=blob_plain;f=html/org.freesmartphone.GSM.SIM.html;hb=HEAD} 
  8  - U{http://dbus.freedesktop.org/doc/dbus-python/doc/tutorial.html#data-types} 
  9  - U{http://wiki.openmoko.org/wiki/Dbus} 
 10   
 11  Pisi is free software: you can redistribute it and/or modify 
 12  it under the terms of the GNU General Public License as published by 
 13  the Free Software Foundation, either version 3 of the License, or 
 14  (at your option) any later version. 
 15   
 16  Pisi is distributed in the hope that it will be useful, 
 17  but WITHOUT ANY WARRANTY; without even the implied warranty of 
 18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 19  GNU General Public License for more details. 
 20   
 21  You should have received a copy of the GNU General Public License 
 22  along with Pisi.  If not, see <http://www.gnu.org/licenses/>. 
 23  """ 
 24   
 25  from contacts import contacts 
 26  from pisiconstants import * 
 27  import pisiprogress 
 28  import pisitools 
 29   
 30  import dbus 
 31   
 32  DBUS_GSM_DEVICE = ["org.freesmartphone.ogsmd", "/org/freesmartphone/GSM/Device"] 
 33  """Addressing information in DBUS""" 
 34  DBUS_SIM = 'org.freesmartphone.GSM.SIM' 
 35  """Addressing information in DBUS""" 
 36  DBUS_CONTACTS = 'contacts' 
 37  """Addressing information in DBUS""" 
 38  DBUS_NAME_MOBILEPHONE_SUFFIX = '*' 
 39  """String to be appended to an entry when phone number is of type 'mobile'""" 
 40  DBUS_NAME_WORKPHONE_SUFFIX = '-' 
 41  """String to be appended to an entry when phone number is of type 'work'""" 
 42  DBUS_NAME_HOMEPHONE_SUFFIX = '+' 
 43  """String to be appended to an entry when phone number is of type 'home'""" 
 44   
 45  PHONE_TYPE_MOBILE = 0 
 46  PHONE_TYPE_HOME = 1 
 47  PHONE_TYPE_WORK = 2 
 48   
49 -class SynchronizationModule(contacts.AbstractContactSynchronizationModule):
50 """ 51 The implementation of the interface L{contacts.AbstractContactSynchronizationModule} for SIM Card backend accesed via DBUS 52 """
53 - def __init__( self, modulesString, config, configsection, folder, verbose=False, soft=False):
54 """ 55 Constructor 56 57 Super class constructor (L{contacts.AbstractContactSynchronizationModule.__init__}) is called. 58 Local variables are initialized. 59 The settings from the configuration file are loaded. 60 61 @param modulesString: is a small string to help you make a unique id. It is the two modules configuration-names concatinated. 62 @param config: is the configuration from ~/.pisi/conf. Use like config.get(configsection,'user') 63 @param configsection: is the configuration from ~/.pisi/conf. Use like config.get(configsection,'user') 64 @param folder: is a string with the location for where your module can save its own files if necessary 65 @param verbose: should make your module "talk" more 66 @param soft: should tell you if you should make changes (ie. save) 67 """ 68 contacts.AbstractContactSynchronizationModule.__init__(self, verbose, soft, modulesString, config, configsection, "Contacts DBUS SIM") 69 self.verbose = verbose 70 self._determineSimLimitations() 71 self._availableIds = {} 72 for i in range (1, self._max_simentries + 1): 73 self._availableIds[i] = 1 74 self._idMappings = {} 75 pisiprogress.getCallback().verbose("DBUS_SIM module loaded")
76
77 - def _determineSimLimitations(self):
78 """ 79 Supporting function in order to auto-determine limitation of SIM card (max number of entries and max length of name) 80 """ 81 bus = dbus.SystemBus() 82 gsm_device_obj = bus.get_object(DBUS_GSM_DEVICE[0], DBUS_GSM_DEVICE[1]) 83 sim = dbus.Interface(gsm_device_obj,DBUS_SIM) 84 infos = sim.GetPhonebookInfo(DBUS_CONTACTS) 85 self._max_simentries = infos["max_index"] 86 self._name_maxlength = infos["name_length"]
87
88 - def load(self):
89 """ 90 Load all data from backend 91 """ 92 pisiprogress.getCallback().verbose ("DBUS_SIM: Loading") 93 pisiprogress.getCallback().progress.push(0, 100) 94 pisiprogress.getCallback().verbose (" >SIM Card Limitations: %d entries maximum; no more than %d characters per name" %(self._max_simentries, self._name_maxlength)) 95 bus = dbus.SystemBus() 96 gsm_device_obj = bus.get_object(DBUS_GSM_DEVICE[0], DBUS_GSM_DEVICE[1]) 97 sim = dbus.Interface(gsm_device_obj,DBUS_SIM) 98 dbusContacts = sim.RetrievePhonebook(DBUS_CONTACTS, 1, self._max_simentries) 99 pisiprogress.getCallback().progress.setProgress(20) 100 pisiprogress.getCallback().update("Loading") 101 i = 0 102 for c in dbusContacts: 103 dbus_id = c[0] 104 name = c[1] 105 number = c[2] 106 107 del self._availableIds[dbus_id] 108 109 type = PHONE_TYPE_MOBILE 110 if name.endswith(DBUS_NAME_MOBILEPHONE_SUFFIX): 111 name = name[:len(name) - len(DBUS_NAME_MOBILEPHONE_SUFFIX)] 112 if name.endswith(DBUS_NAME_WORKPHONE_SUFFIX): 113 type = PHONE_TYPE_WORK 114 name = name[:len(name) - len(DBUS_NAME_WORKPHONE_SUFFIX)] 115 elif name.endswith(DBUS_NAME_HOMEPHONE_SUFFIX): 116 type = PHONE_TYPE_HOME 117 name = name[:len(name) - len(DBUS_NAME_HOMEPHONE_SUFFIX)] 118 119 atts = {} 120 title, first, last, middle = pisitools.parseFullName(name) 121 atts['title'] = title 122 atts['firstname'] = first 123 atts['lastname'] = last 124 atts['middlename'] = middle 125 126 id = contacts.assembleID(atts) 127 if self._allContacts.has_key(id): 128 c = self._allContacts[id] 129 if type == PHONE_TYPE_MOBILE: 130 c.attributes['mobile'] = number.strip() 131 elif type == PHONE_TYPE_WORK: 132 c.attributes['officePhone'] = number.strip() 133 elif type == PHONE_TYPE_HOME: 134 c.attributes['phone'] = number.strip() 135 136 else: 137 if type == PHONE_TYPE_MOBILE: 138 atts['mobile'] = number.strip() 139 elif type == PHONE_TYPE_WORK: 140 atts['officePhone'] = number.strip() 141 elif type == PHONE_TYPE_HOME: 142 atts['phone'] = number.strip() 143 c = contacts.Contact(id, atts) 144 self._allContacts[id] = c 145 self._idMappings[id] = [] 146 self._idMappings[id].append(dbus_id) 147 i+=1 148 pisiprogress.getCallback().progress.setProgress(20 + ((i*80) / len(dbusContacts))) 149 pisiprogress.getCallback().update('Loading') 150 pisiprogress.getCallback().progress.drop()
151
152 - def _saveOperationAdd(self, sim, id):
153 """ 154 Writing through: Adds a single value to the SIM Card 155 """ 156 c = self.getContact(id) 157 fullName = pisitools.assembleFullName(c) 158 if len(fullName) > self._name_maxlength - len(DBUS_NAME_MOBILEPHONE_SUFFIX): # let's assume, all suffixes are of same length 159 fullName = fullName[:self._name_maxlength - len(DBUS_NAME_MOBILEPHONE_SUFFIX)] 160 # 1st - mobile 161 if len(self._availableIds) == 0: 162 return 163 try: 164 number = c.attributes['mobile'] 165 if number and number != '': 166 myid = self._availableIds.keys()[0] 167 sim.StoreEntry(DBUS_CONTACTS, myid, fullName + DBUS_NAME_MOBILEPHONE_SUFFIX, number) 168 del self._availableIds[myid] 169 except KeyError: 170 pass # fine - no mobile; no entry! 171 172 #2nd - home phone 173 if len(self._availableIds) == 0: 174 return 175 try: 176 number = c.attributes['phone'] 177 if number and number != '': 178 myid = self._availableIds.keys()[0] 179 sim.StoreEntry(DBUS_CONTACTS, myid, fullName + DBUS_NAME_HOMEPHONE_SUFFIX, number) 180 del self._availableIds[myid] 181 except KeyError: 182 pass # fine - no home phone; no entry! 183 184 #3rd - office phone 185 if len(self._availableIds) == 0: 186 return 187 try: 188 number = c.attributes['officePhone'] 189 if number and number != '': 190 myid = self._availableIds.keys()[0] 191 sim.StoreEntry(DBUS_CONTACTS, myid, fullName + DBUS_NAME_WORKPHONE_SUFFIX, number) 192 del self._availableIds[myid] 193 except KeyError: 194 pass # fine - no work phone; no entry!
195
196 - def _saveOperationDelete(self, sim, id):
197 """ 198 Writing through: Removes a single value from the SIM card 199 """ 200 for dbus_id in self._idMappings[id]: 201 sim.DeleteEntry(DBUS_CONTACTS, dbus_id) 202 self._availableIds[dbus_id] = 1
203
204 - def saveModifications( self ):
205 """ 206 Save whatever changes have come by 207 """ 208 pisiprogress.getCallback().verbose("DBUS_SIM module: I apply %d changes now" %(len(self._history))) 209 bus = dbus.SystemBus() 210 gsm_device_obj = bus.get_object(DBUS_GSM_DEVICE[0], DBUS_GSM_DEVICE[1]) 211 sim = dbus.Interface(gsm_device_obj, DBUS_SIM) 212 213 i = 0 214 for listItem in self._history: 215 action = listItem[0] 216 id = listItem[1] 217 if action == ACTIONID_ADD: 218 pisiprogress.getCallback().verbose("\t\t<DBUS_SIM> adding %s" %(id)) 219 self._saveOperationAdd(sim, id) 220 elif action == ACTIONID_DELETE: 221 pisiprogress.getCallback().verbose("\t\t<DBUS_SIM> deleting %s" %(id)) 222 self._saveOperationDelete(sim, id) 223 elif action == ACTIONID_MODIFY: 224 pisiprogress.getCallback().verbose("\t\t<DBUS_SIM> replacing %s" %(id)) 225 self._saveOperationDelete(sim, id) 226 self._saveOperationAdd(sim, id) 227 i += 1 228 pisiprogress.getCallback().progress.setProgress(i * 100 / len(self._history)) 229 pisiprogress.getCallback().update('Storing') 230 231 pisiprogress.getCallback().progress.setProgress(100) 232 pisiprogress.getCallback().update('Storing') 233 if len(self._availableIds.keys()) == 0: 234 pisiprogress.getCallback().message("Applying changes to SIM card:\nMaximum number of entries on SIM card (%d) reached.\nSome entries were possibly dopped." %(self._max_simentries))
235