📄 abtable.cpp
字号:
break; } } if( !existing ) { PimContact *newContact = new PimContact(); newContact->setFileAs( name ); newContact->setFirstName( name ); if( phoneType < 0 ) phoneType = AbUtil::phoneFields[0]; newContact->setField( phoneType, number ); simCnts.append( newContact ); cnt = newContact; } cnt->setCustomField( "SIM_CONTACT", "1" ); cnt->setCustomField( AbUtil::simKeyForPhoneType( phoneType ), "1" ); } return simCnts;}/* parses the name and phone number type from the text part of a sim entry.*/void AbUtil::parseSimText( QString &name, int &phoneType ){ name = name.stripWhiteSpace(); phoneType = -1; //get the last token of the name QString lastToken; int i = name.length()-1; for( ; i > 0 && !name[i].isSpace() && name[i] != '/' ; --i ) lastToken.prepend( name[i].lower() ); bool stripLastToken = ( i > 0 && !name[i].isSpace() ) ? TRUE : FALSE; lastToken = lastToken.lower(); if( i > 0 ) // more than one token { //is it one of our Qtopia sim identifiers? phoneType = AbUtil::simTypeTextToPhoneType( lastToken ); if( phoneType < 0 ) { //FIXME : should these sim strings be translated? if( lastToken == "h" || lastToken == "hom" || lastToken == "home" ) phoneType = PimContact::HomePhone; else if( lastToken == "w" || lastToken == "b" || lastToken == "work" || lastToken == "bus" ) phoneType = PimContact::BusinessPhone; else if( lastToken == "m" || lastToken == "mob" || lastToken == "mobile" ) phoneType = PimContact::HomeMobile; } if( stripLastToken ) name = name.left( name.length()-(lastToken.length()+1) ); }}/* generates the text that should be stored for a sim entry. the generated text is just the contact name with '/' + simTypeText appended(see below).*/QString AbUtil::generateSimText( const QString &name, const int &phoneType ){ if( name.isEmpty() ) return name; //FIXME : Don't know if we should always use our own identifiers // would suck for the use case of using our sim in a different phone QString simTypeText = simTypeTextForPhoneType( phoneType ); int limitLength = SIM_TEXT_LIMIT; if( simTypeText.length() ) limitLength = SIM_TEXT_LIMIT - simTypeText.length() - 1; // -1 for the / QString limitedName; if( (int)name.length() > limitLength ) // name doesn't fit the limit, indicate such limitedName = name.left( limitLength-1 ) + SIM_PARTIAL_INDICATOR; else limitedName = name.left( limitLength ); if( simTypeText.isEmpty() ) return limitedName; else return limitedName + "/" + simTypeText;}/* sim type is the text appended to the end of the sim entry to mark it's type. eg this function would return "HP" for a phoneType of PimContact::HomePhone*/QString AbUtil::simTypeTextForPhoneType( const int &phoneType ){ // do something tricky an vague QString simKey = simKeyForPhoneType( phoneType ); if( simKey.isEmpty() ) return simKey; //4 is the length of SIM_ at the start of the string return simKey.right( simKey.length()-4 );}/* return the pimcontact phone type given the text type from the sim */int AbUtil::simTypeTextToPhoneType( const QString &typeText ){ QString tu = typeText.upper(); for( int i = 0 ; i < AbUtil::numPhoneFields ; ++i ) if( tu == AbUtil::simTypeTextForPhoneType( AbUtil::phoneFields[i] ).upper() ) return AbUtil::phoneFields[i]; return -1;}/* returns the 'sim key' given the pimcontact phone type. the sim key is the string used to store a flag that indicates that a particular number of the contact should be stored on the sim card. eg if the user wanted to store the home phone of a contact on the sim PimContact::customField( AbUtil::SIM_HP ) would contain a positive value.*/QString AbUtil::simKeyForPhoneType( int phoneType ){ switch( phoneType ) { case PimContact::HomePhone: return AbUtil::SIM_HP; case PimContact::HomeFax: return AbUtil::SIM_HF; case PimContact::HomeMobile: return AbUtil::SIM_HM; case PimContact::BusinessPhone: return AbUtil::SIM_BP; case PimContact::BusinessFax: return AbUtil::SIM_BF; case PimContact::BusinessMobile: return AbUtil::SIM_BM; case PimContact::BusinessPager: return AbUtil::SIM_BPA; } return QString::null;}uint AbUtil::numbersForSimCount( const PimContact &cnt ){ uint n = 0; for( int i = 0 ; i < numPhoneFields ; ++i ) { QString k = simKeyForPhoneType( phoneFields[i] ); if( cnt.customField( k ).length() && cnt.field( phoneFields[i] ).stripWhiteSpace().length() ) ++n; } return n;}//note : not numbers that are currently stored on the sim//just numbers that have been flagged to be stored on the simbool AbUtil::hasNumbersForSim( const PimContact &cnt ){ for( int i = 0 ; i < numPhoneFields ; ++i ) { QString k = simKeyForPhoneType( phoneFields[i] ); //number is to be stored on the sim and isn't empty if( cnt.customField( k ).length() && cnt.field( phoneFields[i] ).stripWhiteSpace().length() ) return TRUE; } return FALSE;}int AbUtil::SIM_TEXT_LIMIT = 20;int AbUtil::SIM_NUMBER_LIMIT = 60;void AbUtil::setSimFieldLimits( const QString &limits ){ if( limits.isEmpty() ) return; QStringList l = QStringList::split( ",", limits ); if( l.count() != 2 ) return; AbUtil::SIM_NUMBER_LIMIT = l[0].toInt(); AbUtil::SIM_TEXT_LIMIT = l[1].toInt(); qDebug("AbUtil::setSimFieldLimits( %d, %d )", SIM_NUMBER_LIMIT, SIM_TEXT_LIMIT );}/* syncs a contact with the numbers on the sim card. syncing means going through each number in the contact and- deleting any number matching the contacts name and number if the user doesn't want it on the sim or adding it to the sim or updating the entry on the sim*/void AbUtil::syncContactWithSim( PimContact &cnt, QValueList<PhoneBookEntry> &curSimList, PhoneBook *pb ){ PhoneLine *line = 0; if( !pb ) { line = new PhoneLine(); pb = line->phoneBook(); } /* idea for a cleaner algorithm ----------------------------- get the number of sim fields this contact has foreach entry in the local sim list if this entry's name matches the contact's file as add it to the freeslot list while num entries in the free slot list > number of sim fields in contact remove entry from sim remove entry from local list remove entry from free slot list for each sim field in contact if have a free slot in the free slot list update the slot on the sim card with sim field from contact remove this free slot from free slot list else add sim field to simcard */ QValueList<PimContact::ContactFields> simPhoneFields; if( AbUtil::hasNumbersForSim( cnt ) ) for( int i = 0 ; i < numPhoneFields ; ++i ) if( cnt.customField( simKeyForPhoneType( phoneFields[i] ) ).length() && cnt.field( phoneFields[i] ).stripWhiteSpace().length() ) simPhoneFields.append( (PimContact::ContactFields)phoneFields[i] ); //qDebug("numSimFields is %d", simPhoneFields.count()); bool flushPhoneBook = FALSE; const QString fileAs = cnt.fileAs(); const QString lowerFileAs = fileAs.lower(); QValueList<PhoneBookEntry> freeEntries; for( QValueList<PhoneBookEntry>::Iterator it = curSimList.begin() ; it != curSimList.end() ; ++it ) { QString simName = (*it).text(); int simPhoneType = -1; parseSimText( simName, simPhoneType ); bool partialName = FALSE; if( simName[simName.length()-1] == AbUtil::SIM_PARTIAL_INDICATOR ) { partialName = TRUE; simName = simName.left( simName.length()-1 ); } simName = simName.lower(); //sim entry matches if it's an exact match or partial name if( (!partialName && simName == lowerFileAs) || (partialName && lowerFileAs.startsWith( simName )) ) freeEntries.append( *it ); } //qDebug("%d free entries available", freeEntries.count()); while( freeEntries.count() > simPhoneFields.count() ) { QValueList<PhoneBookEntry>::Iterator pos = freeEntries.fromLast(); pb->remove( (*pos).index(), "SM", FALSE ); freeEntries.remove( pos ); curSimList.remove( *pos ); flushPhoneBook = TRUE; } //freeEntries.count <= numSimFields for( QValueList<PimContact::ContactFields>::Iterator it = simPhoneFields.begin() ; it != simPhoneFields.end() ; ++it ) { if( freeEntries.count() ) { QValueList<PhoneBookEntry>::Iterator pos = freeEntries.fromLast(); //qDebug("updating pos %d with %s", (*pos).index(), cnt.field((int)*it).latin1()); pb->update( (*pos).index(), cnt.field( (int)*it ).left( SIM_NUMBER_LIMIT ), generateSimText( fileAs, *it ), "SM", FALSE ); freeEntries.remove( pos ); } else { //qDebug("adding %s", cnt.field((int)*it).latin1()); pb->add( cnt.field( (int)*it ).left( SIM_NUMBER_LIMIT ), generateSimText( fileAs, *it ), "SM", FALSE ); } flushPhoneBook = TRUE; }#if 0 /* : go through each item in the current phone book list. delete any entries on the sim with this contact's fileas that don't have a number that matches any contact number that is to be stored on the sim if we find one that has this contact's file as and a matching number, update it. because the fileas and number are already the same, this can only mean it may have a different phone type. we remove it from the local simlist after updating, so that other duplicate numbers with different phone types in the contact don't all try and write to the same sim slot because they have the same numbers. */ for( QValueList<PhoneBookEntry>::Iterator it = curSimList.begin() ; it != curSimList.end() ; ) { QString name = (*it).text(); int tmp = -1; AbUtil::parseSimText( name, tmp ); if( name.lower() == lowerFileAs ) { qDebug("%s == %s", name.latin1(), fileAs.latin1()); int phoneType = -1; if( hnfs ) { for( int i = 0 ; i < AbUtil::numPhoneFields ; ++i ) if( !cnt.customField( AbUtil::simKeyForPhoneType( AbUtil::phoneFields[i] ) ).isEmpty() && PhoneUtils::matchPrefix( (*it).number(), cnt.field( AbUtil::phoneFields[i] ) ) ) { //this number is for the sim and it matches phoneType = AbUtil::phoneFields[i]; break; } } else qDebug("%s doesn't have any contacts for sim", fileAs.latin1()); //else this contact has no numbers for sim, so it can't match if( phoneType == -1 ) { qDebug("removing %s %s", fileAs.latin1(), (*it).number().latin1()); pb->remove( (*it).index(), "SM", FALSE ); flushPhoneBook = TRUE; } else { //this number on the sim matches a number in the contact. //if the types don't match, update QString simName = (*it).text(); int simPhoneType = -1; AbUtil::parseSimText( simName, simPhoneType ); if( simPhoneType == -1 || simPhoneType != phoneType ) { qDebug("updating %s %s", fileAs.latin1(), (*it).number().latin1()); pb->update( (*it).index(), cnt.field( phoneType ), AbUtil::generateSimText( fileAs, phoneType ), "SM", FALSE ); flushPhoneBook = TRUE; } else qDebug("simPhoneType == %d", simPhoneType); //this contact number is already on the sim, don't add it nonNewFields.append( (PimContact::ContactFields)phoneType ); } //remove from list. either updated ore moved it = curSimList.remove( it ); } //only inrement if fileas doesn't match ++it; } /* at this point, all obsolete numbers have been removed and existing numbers have been updated. every phone field that has a sim key and is not a non new field needs to be added. */ for( int i = 0 ; i < AbUtil::numPhoneFields ; ++i ) { QString simKey = simKeyForPhoneType( AbUtil::phoneFields[i] ); if( !nonNewFields.contains( (PimContact::ContactFields)AbUtil::phoneFields[i] )) qDebug("nonNewFields doesn't contain %d", AbUtil::phoneFields[i] ); else qDebug("nonNewFields does contain %d", AbUtil::phoneFields[i] ); if( !cnt.customField(simKey).isEmpty() && !nonNewFields.contains( (PimContact::ContactFields)AbUtil::phoneFields[i] )) { qDebug("adding %s-%s as a new sim entry", fileAs.latin1(), cnt.field(AbUtil::phoneFields[i]).latin1()); // have a new entry for the sim pb->add( cnt.field( AbUtil::phoneFields[i] ), AbUtil::generateSimText( fileAs, AbUtil::phoneFields[i] ), "SM", FALSE ); flushPhoneBook = TRUE; } }#endif if( flushPhoneBook ) pb->flush(); if( line ) delete line;}/*! Merges a simcontact with a normal contact.*/void AbUtil::mergeSimContact( PimContact &cnt, const PimContact &simCnt ){ /* TODO Not sure what to do here. If the contact in the addressbook has a home phone, but the simcard also has a contact that matches with a home phone, which one do you use? I don't think you want to make the user pick one or the other, because the cntacts could be matching because of a coincidental name match (eg 'John Smith'). For now i'll use whatever's on the simcard if the contact's value is empty or the values match, otherwise the sim card version gets ignored. */ for( int i = 0 ; i < AbUtil::numPhoneFields ; ++i ) { int pt = AbUtil::phoneFields[i]; if( (cnt.field( pt ).isEmpty() && !simCnt.field( pt ).isEmpty()) || PhoneUtils::matchPrefix( cnt.field( pt ), simCnt.field( pt ) ) ) { cnt.setField( pt, simCnt.field( pt ) ); } cnt.setCustomField( AbUtil::simKeyForPhoneType( pt ), simCnt.customField( AbUtil::simKeyForPhoneType( pt ) ) ); }}void AbUtil::unmergeSimContact( PimContact &cnt ){ for( int i = 0 ; i < AbUtil::numPhoneFields ; ++i ) cnt.removeCustomField( AbUtil::simKeyForPhoneType(AbUtil::phoneFields[i]) );}#endif#ifdef QTOPIA_DATA_LINKING#include <qtopia/qdl.h>#endifbool AbUtil::compareContacts( const PimContact &cnt1, const PimContact &cnt2 ){ // first check standard contact fields. for( int i = PimContact::NameTitle ; i != PimContact::ContactFieldsEnd ; ++i ) { if( cnt1.field( i ) != cnt2.field( i ) ) return FALSE; }#ifdef QTOPIA_PHONE if( cnt1.customField( "SIM_CONTACT" ) != cnt2.customField( "SIM_CONTACT" ) ) return FALSE; for( int i = 0 ; i < numPhoneFields ; ++i ) { QString k = simKeyForPhoneType( phoneFields[i] ); if( cnt1.customField( k ) != cnt2.customField( k ) ) return FALSE; } if( cnt1.customField("SIM_CONTACT").length() && cnt2.customField("SIM_CONTACT").length() ) return TRUE; // both sim contacts and all the data a sim contact can have matches. if( cnt1.customField( "tone" ) != cnt2.customField( "tone" ) ) return FALSE;#endif if( cnt1.categories() != cnt2.categories() ) return FALSE; //standard fields are equal. check custom fields we know of if( cnt1.customField( "BUSINESS_CONTACT" ) != cnt2.customField( "BUSINESS_CONTACT" ) ) return FALSE; if( cnt1.customField( "photofile" ) != cnt2.customField( "photofile" ) ) // FIXME : same filename doesn't mean same file contents return FALSE;#ifdef QTOPIA_DATA_LINKING if( cnt1.customField( QDL::DATA_KEY ) != cnt2.customField( QDL::DATA_KEY ) ) return FALSE;#endif return TRUE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -