📄 contacts.py
字号:
#
# contacts.py
#
# Copyright (c) 2006-2008 Nokia Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import _contacts
def revdict(d):
return dict([(d[k],k) for k in d.keys()])
#This dictionary is created by calling create_api_mappings() from contactsmodule.cpp
_api_mappings = {((268440333,), 268451878): (13, 0), ((268440334, 268451441, 268450266), 268451882): (6, 2), ((268441486, 268450267), 268451872): (9, 1), ((268455417,), 268455407): (29, 0), ((268455412, 268450267), 268455402): (23, 1), ((268440332, 268450267), 268451869): (25, 1), ((270551984, 270553033), 270553033): (38, 0), ((268455415,), 268455405): (28, 0), ((268455414,), 268455404): (27, 0), ((268440334, 268451441), 268451882): (6, 0), ((270551984, 270553034, 268450266), 270551985): (36, 2), ((270522711,), 270522807): (31, 0), ((268440444,), 268451886): (2, 0), ((268440334, 268450269, 268450266), 268451882): (5, 2), ((268451893, 268450267), 268451885): (11, 1), ((270551984, 270553034), 270551985): (36, 0), ((268451868,), 268451877): (17, 0), ((268441489, 268450270, 268450266), 268451882): (7, 2), ((268455413, 268450267), 268455403): (24, 1), ((268441486, 268450266), 268451872): (9, 2), ((268473240,), 268451884): (12, 0), ((268455415, 268450266), 268455405): (28, 2), ((270487538,), 268451890): (35, 0), ((270551984, 270553034, 268450267), 270553034): (36, 1), ((268455416,), 268455406): (26, 0), ((268455417, 268450267), 268455407): (29, 1), ((268455416, 268450267), 268455406): (26, 1), ((270551984, 270553034), 270553034): (36, 0), ((268441483,), 268451886): (49, 0), ((268451893,), 268451885): (11, 0), ((270551984, 270553032), 270553032): (37, 0), ((268455413,), 268455403): (24, 0), ((268440332, 268450266), 268451869): (25, 2), ((268440332, 268450267), 268451874): (10, 1), ((268440334, 268450265, 268450266), 268451882): (32, 2), ((268461336,), 268451890): (15, 0), ((270551984, 270551985), 270551985): (39, 0), ((268441489, 268450270), 268451882): (7, 0), ((268459473,), 268451890): (18, 0), ((268451892,), 268451871): (16, 0), ((268440334, 268451441, 268450267), 268451882): (6, 1), ((268455412, 268450266), 268455402): (23, 2), ((268440332,), 268451874): (10, 0), ((268441484,), 268451886): (48, 0), ((268455415, 268450267), 268455405): (28, 1), ((270551984, 270553032), 270551985): (37, 0), ((268441486,), 268451872): (9, 0), ((268455414, 268450266), 268455404): (27, 2), ((270551984, 270553034, 268450267), 270551985): (36, 1), ((268459473,), 268451879): (19, 0), ((268440334, 268451442), 268451882): (8, 0), ((268440445,), 268451886): (1, 0), ((268451893, 268450266), 268451885): (11, 2), ((268455413, 268450266), 268455403): (24, 2), ((268440334, 268450269, 268450267), 268451882): (4, 1), ((268455417, 268450266), 268455407): (29, 2), ((268441489, 268450270, 268450267), 268451882): (7, 1), ((268440334, 268450269), 268451882): (3, 0), ((268461335,), 268451890): (22, 0), ((268440334, 268450265), 268451882): (32, 0), ((268455416, 268450266), 268455406): (26, 2), ((270551984, 270553034, 268450266), 270553034): (36, 2), ((268455414, 268450267), 268455404): (27, 1), ((270551984, 270553033), 270551985): (38, 0), ((268440332, 268450266), 268451874): (10, 2), ((268455412,), 268455402): (23, 0), ((268440332,), 268451869): (25, 0), ((268440334, 268450265, 268450267), 268451882): (32, 1)}
_api_mappings_reverse_map = revdict(_api_mappings)
fieldtype_names=["none",
"last_name",
"first_name",
"phone_number_general",
#"phone_number_home",
#"phone_number_work",
"phone_number_mobile",
"fax_number",
"pager_number",
"email_address",
"postal_address",
"url",
"job_title",
"company_name",
# "company_address", # same as postal_address
"dtmf_string",
"date",
"note",
"po_box",
"extended_address",
"street_address",
"postal_code",
"city",
"state",
"country",
"wvid",
"prefix",
"suffix",
"job_title",
"second_name",
"voip",
"push_to_talk",
"share_view",
"sip_id"]
fieldtypemap=dict([(k,getattr(_contacts,k)) for k in fieldtype_names])
unknown_field = 'unknown'
fieldtypemap.update({'video_number': 32,
'picture': 0x12,
'thumbnail_image': 0x13,
'voice_tag': 0x14,
'speed_dial': 0x15,
'personal_ringtone': 0x16,
'second_name': 0x1f,
'last_name_reading': 0x21,
'first_name_reading': 0x22,
'locationid_indication': 0x23,
unknown_field:-1})
fieldtypemap['mobile_number']=fieldtypemap['phone_number_mobile']
del fieldtypemap['phone_number_mobile']
fieldtypemap['phone_number']=fieldtypemap['phone_number_general']
del fieldtypemap['phone_number_general']
fieldtypereversemap=revdict(fieldtypemap)
unknown_location = 'unknown'
locationmap={None: _contacts.location_none,
'none': _contacts.location_none,
'home': _contacts.location_home,
'work': _contacts.location_work,
unknown_location:-1}
locationreversemap=revdict(locationmap)
locationreversemap[_contacts.location_none]='none'
_phonenumber_location_map={
None: _contacts.phone_number_general,
'none': _contacts.phone_number_general,
'home': _contacts.phone_number_home,
'work': _contacts.phone_number_work
}
_phonenumber_location_reversemap=revdict(_phonenumber_location_map)
storagetypemap={"text":_contacts.storage_type_text,
"binary":_contacts.storage_type_store,
"item_id":_contacts.storage_type_contact_item_id,
"datetime":_contacts.storage_type_datetime}
_storagetypereversemap=revdict(storagetypemap)
def pb_values_from_py_type_and_location(type,location=None):
if type=='phone_number':
return (_phonenumber_location_map[location],locationmap[location])
return (fieldtypemap[type],locationmap[location])
class ContactsDb(object):
def __init__(self,dbfile=None,mode=None):
if dbfile is None:
self._db=_contacts.open()
else:
dbfile = unicode(dbfile)
if (len(dbfile)<2) or dbfile[1]!=':':
dbfile = u"c:" + dbfile
if dbfile.find("\\") >= 0 or dbfile.find('/')>=0:
raise ValueError("database name cannot have path")
if mode is None:
self._db=_contacts.open(dbfile)
else:
self._db=_contacts.open(dbfile,mode)
if mode=='n':
for id in self._db:
del self._db[id]
self._have_field_types = 0
# create several lists and dictionaries to speed up the field type data handling.
data = self._db.field_types()
self._raw_field_types= data[0] # list of id values of each template field [[new_id_1, .., new_id_n], ..]
self._vcard_mappings = data[1] # vcard mappings for each template field [mapping_1, ..]
self._simple_field_types = [] # list of self._raw_field_types[index][0] for all values of index.
self._field_types=[] # [{"name":"field_default_label_1", "storagetype":"text", "type":"last_name", "location":"none"}, ..]
self._template_field_schema = {} # {template_field_index:{"name":"field_default_label_1", "storagetype":"text", "type":"last_name", "location":"none"}..}
self._schema_index_map = {} # ((new_id_1, .., new_id_n), vcard_mapping):schema_index_1, ..)
self._nr_of_field_types = len(self._raw_field_types)
for index in range(self._nr_of_field_types):
self._schema_index_map[(tuple(self._raw_field_types[index]), self._vcard_mappings[index])]=index
self._simple_field_types.append(self._raw_field_types[index][0])
def _field_type_pb_to_symbian(self,field_type,location):
key = ()
if (location is None) or (location == locationmap['none']) or (location == locationmap[unknown_location]):
key = (field_type,locationmap['none'])
else:
key = (field_type,location)
if _api_mappings_reverse_map.has_key(key):
return _api_mappings_reverse_map[key]
raise TypeError("field type " + str(key) + " was not recognized. _api_mappings update needed?")
def _field_type_symbian_to_pb(self,new_field_type,vcard_mapping,storage_type='text'):
key = (tuple(new_field_type),vcard_mapping)
if _api_mappings.has_key(key):
if _api_mappings[key][0] == _contacts.phone_number_home:
return (fieldtypemap['phone_number'],locationmap['home'])
if _api_mappings[key][0] == _contacts.phone_number_work:
return (fieldtypemap['phone_number'],locationmap['work'])
return _api_mappings[key]
import warnings
warnings.warn("new fieldtype " + str(key) + " not recognized. _api_mappings update needed?", RuntimeWarning)
return (fieldtypemap[unknown_field],locationmap[None])
def _field_schema(self,schemaid):
schema=self._db.field_type_info(schemaid)
schema['storagetype']=_storagetypereversemap[schema['storagetype']]
old_field_type = self._field_type_symbian_to_pb(self._raw_field_types[schemaid],schema['vcard_mapping'],schema['storagetype'])
del schema['vcard_mapping']
schema['location']=locationreversemap[old_field_type[1]]
if fieldtypereversemap.has_key(old_field_type[0]):
schema['type']=fieldtypereversemap[old_field_type[0]]
else:
schema['type']=unknown_field
return schema
def field_types(self):
if self._have_field_types==0:
for index in range(self._nr_of_field_types):
self._field_types.append(self._field_schema(index))
self._have_field_types=1
return list(self._field_types)
def _search_field_uids(self,vcard_match,field_uids):
#go through match list and check
longest_match=0
found_index=-1
for item in vcard_match:
match_count=0
for template_uid in self._raw_field_types[item]:
if template_uid in field_uids:
match_count+=1
if match_count==len(field_uids):break
if longest_match<match_count:
longest_match=match_count
found_index=item
if longest_match==len(field_uids):break
if found_index>=0:
return found_index
else: return None
def _search_vcard_mapping(self,vcard_id):
vcard_match=[]
for i in xrange (len(self._vcard_mappings)):
if self._vcard_mappings[i]==vcard_id:
vcard_match.append(i)
return vcard_match
def _determine_field_type(self,storage_type,field_uids,vcard_id,find_uids=None):
key = (tuple(field_uids),vcard_id)
if self._schema_index_map.has_key(key):
return self._schema_index_map[key]
#try to match to ids in find_uids list
if find_uids!=None:
matching=1
for uid in field_uids:
if uid not in find_uids:
matching=0
break
if matching==1:
return self._raw_field_types.index(find_uids)
vcard_match=self._search_vcard_mapping(vcard_id)
if len(vcard_match)>0:
found_index=self._search_field_uids(vcard_match,field_uids)
if found_index==-1:
#really broken field, map to one of templates with same vcard_id
return vcard_match[0]
else:
return found_index
else:
return None
def __iter__(self):
return iter(self._db)
def __getitem__(self,key):
return ContactsDb.Contact(self._db.get_entry(key),self)
def __delitem__(self,key):
self._db.delete_entry(key)
def __len__(self):
return self._db.entry_count()
def add_contact(self):
return ContactsDb.Contact(self._db.create_entry(),self,locked='as_new_contact')
def keys(self):
return list(self._db)
def values(self):
return [self[k] for k in self]
def items(self):
return [(k,self[k]) for k in self]
def _build_vcard_flags(self,include_x=0,ett_format=0,exclude_uid=0,decrease_access_count=0,increase_access_count=0,import_single_contact=0):
vcard_flags=0
if include_x:
vcard_flags|=_contacts.vcard_include_x
if ett_format:
vcard_flags|=_contacts.vcard_ett_format
if exclude_uid:
vcard_flags|=_contacts.vcard_exclude_uid
if decrease_access_count:
vcard_flags|=_contacts.vcard_dec_access_count
if increase_access_count:
vcard_flags|=_contacts.vcard_inc_access_count
if import_single_contact:
vcard_flags|=_contacts.vcard_import_single_contact
return vcard_flags
def import_vcards(self,vcards,include_x=1,ett_format=1,import_single_contact=0):
vcard_flags=self._build_vcard_flags(include_x,ett_format,0,0,0,import_single_contact)
return [self[x] for x in self._db.import_vcards(unicode(vcards),vcard_flags)]
def export_vcards(self,vcard_ids,include_x=1,ett_format=1,exclude_uid=0):
vcard_flags=self._build_vcard_flags(include_x,ett_format,exclude_uid)
return self._db.export_vcards(tuple(vcard_ids),vcard_flags)
def find(self,searchterm):
return [self[x] for x in self._db.find(unicode(searchterm),tuple(self._simple_field_types))]
def compact_required(self):
return self._db.compact_recommended()
def compact(self):
return self._db.compact()
class ContactsIterator(object):
def __init__(self,db,_iter):
self.db=db
self._iter=_iter
def next(self):
return self.db[self._iter.next()]
def __iter__(self):
return self
class Contact(object):
def __init__(self,_contact,db,locked=0):
self._contact=_contact
self.db=db
self._locked=locked
def _data(self,key):
return self._contact.entry_data()[key]
id=property(lambda self:self._data('uniqueid'))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -