Show
Ignore:
Timestamp:
07/09/07 10:02:18 (2 years ago)
Author:
daboo
Message:

Some 4.1 changes. Mostly vCard/CardDAV and CalDAV scheduling support.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • Mulberry/branches/v4.1d1/Sources_Common/Mail/AddressBook/CAddressBookManager.cp

    r19 r86  
    3434#include "CErrorHandler.h" 
    3535#include "CLDAPClient.h" 
    36 #include "CLocalAddressBook.h" 
    3736#include "CMessage.h" 
    3837#include "CMessageList.h" 
     
    5251CAddressBookManager* CAddressBookManager::sAddressBookManager = NULL; 
    5352 
    54 CAddressBookManager::CAddressBookManager() : mAdbks(false) 
    55 { 
    56         // Add item for local address books (always first) 
    57         cdstring* name = new cdstring; 
    58         name->FromResource("UI::AdbkMgr::Others"); 
    59         mAdbks.push_back(name, false); 
    60  
     53CAddressBookManager::CAddressBookManager() 
     54{ 
    6155        mLocalProto = NULL; 
    6256        mOSProto = NULL; 
     57         
     58        mProtos.set_delete_data(false); 
     59        mProtoCount = 0; 
     60 
     61        mAdbkNickName.set_delete_data(false); 
     62        mAdbkSearch.set_delete_data(false); 
    6363 
    6464        CAddressBookManager::sAddressBookManager = this; 
     
    8181        } 
    8282 
    83         // Close all locals 
    84         mAdbks.GetChildren()->at(0)->erase_children(); 
    85  
    8683        // Logoff each protocol (includes the local one) 
    8784        for(CAdbkProtocolList::iterator iter = mProtos.begin(); iter != mProtos.end(); iter++) 
     
    9289 
    9390        // Remove existing 
    94         for(CAddrLookupProtocolList::iterator iter = mLookups.begin(); iter != mLookups.end(); iter++) 
    95                 delete *iter; 
    9691        mLookups.clear(); 
    9792 
     
    114109void CAddressBookManager::AddProtocol(CAdbkProtocol* proto) 
    115110{ 
    116         // Add item for remote address books 
    117         mAdbks.push_back(proto->GetAdbkList()); 
     111        // Add item to root node 
     112        mRoot.AddChild(proto->GetStoreRoot()); 
    118113 
    119114        // Add to protos list 
    120115        mProtos.push_back(proto); 
     116        mProtoCount++; 
    121117 
    122118        // Broadcast change to all after adding 
     
    130126        Broadcast_Message(eBroadcast_RemoveAdbkAccount, proto); 
    131127 
    132         // Remove from list and delete 
    133         mAdbks.erase(proto->GetAdbkList()); 
     128        // Remove node from parent 
     129        proto->GetStoreRoot()->RemoveFromParent(); 
     130 
     131        // Delete protocol (will also delete the node) 
    134132        delete proto; 
    135133        proto = NULL; 
    136 } 
    137  
    138 // Get list of protocol names 
    139 void CAddressBookManager::GetProtocolNameList(cdstrvect& names) 
    140 { 
    141         // Always add local 
    142         cdstring* name = new cdstring; 
    143         name->FromResource("UI::AdbkMgr::Local"); 
    144         mAdbks.push_back(name, false); 
    145  
    146         // Add remaining protos 
    147         for(CAdbkProtocolList::iterator iter = mProtos.begin(); iter != mProtos.end(); iter++) 
    148                 names.push_back((*iter)->GetAccountName()); 
    149134} 
    150135 
     
    205190 
    206191// Sync with changed accounts 
    207 void CAddressBookManager::SyncAccounts(const CAddressAccountList& accts) 
     192void CAddressBookManager::SyncAccounts() 
    208193{ 
    209194        // Sync accounts for adbk and directory protocols 
    210         SyncProtos(accts); 
    211         SyncLookups(accts); 
     195        SyncProtos(); 
     196        SyncLookups(); 
    212197 
    213198        // Make sure 3-pane is told to re-instate previously open address books 
     
    217202 
    218203// Sync with changed accounts 
    219 void CAddressBookManager::SyncProtos(const CAddressAccountList& accts) 
     204void CAddressBookManager::SyncProtos() 
    220205{ 
    221206        // Only add local protocol if allowed by admin 
     
    228213                { 
    229214                        // First check if local exists 
    230                         if (mOSProto) 
     215                        if (mOSProto != NULL) 
    231216                        { 
    232217                                // Sync its account with prefs etc 
     
    248233 
    249234                // First check if local exists 
    250                 if (mLocalProto) 
     235                if (mLocalProto != NULL) 
    251236                { 
    252237                        // Sync its account with prefs etc 
     
    267252        // New smart alogorithm: compare protocol and protocol embedded in account 
    268253 
     254        // Sync remainder from prefs 
     255        const CAddressAccountList& accts = CPreferences::sPrefs->mAddressAccounts.GetValue(); 
     256 
    269257        // This maintains a list of protocols that need to be started 
    270258        CAdbkProtocolList started; 
     259        started.set_delete_data(false); 
    271260 
    272261        // First delete protocols not in accounts 
    273         unsigned long proto_offset = (mOSProto ? 1 : 0) + (mLocalProto ? 1 : 0); 
     262        unsigned long proto_offset = 0; 
     263        if (mOSProto != NULL) 
     264                proto_offset++; 
     265        if (mLocalProto != NULL) 
     266                proto_offset++; 
    274267        for(CAdbkProtocolList::iterator iter1 = mProtos.begin() + proto_offset; iter1 != mProtos.end(); iter1++) 
    275268        { 
     
    279272                for(CAddressAccountList::const_iterator iter2 = accts.begin(); !found && (iter2 != accts.end()); iter2++) 
    280273                { 
    281                         // Only if IMSP/ACAP 
     274                        // Only if IMSP/ACAP/CardDAV 
    282275                        if (((*iter2)->GetServerType() != CINETAccount::eIMSP) && 
    283                                 ((*iter2)->GetServerType() != CINETAccount::eACAP)) 
     276                                ((*iter2)->GetServerType() != CINETAccount::eACAP) && 
     277                                ((*iter2)->GetServerType() != CINETAccount::eCardDAVAdbk)) 
    284278                                continue; 
    285279 
     
    297291                        iter1 = mProtos.erase(iter1); 
    298292                        iter1--; 
     293                        mProtoCount--; 
    299294                } 
    300295        } 
     
    303298        for(CAddressAccountList::const_iterator iter2 = accts.begin(); iter2 != accts.end(); iter2++) 
    304299        { 
    305                 // Only if IMSP/ACAP 
     300                // Only if IMSP/ACAP/CardDAV 
    306301                if (((*iter2)->GetServerType() != CINETAccount::eIMSP) && 
    307                         ((*iter2)->GetServerType() != CINETAccount::eACAP)) 
     302                        ((*iter2)->GetServerType() != CINETAccount::eACAP) && 
     303                        ((*iter2)->GetServerType() != CINETAccount::eCardDAVAdbk)) 
    308304                        continue; 
    309305 
     
    311307 
    312308                // Look for protocol matching account 
    313                 unsigned long proto_offset = (mOSProto ? 1 : 0) + (mLocalProto ? 1 : 0); 
    314309                for(CAdbkProtocolList::iterator iter1 = mProtos.begin() + proto_offset; !found && (iter1 != mProtos.end()); iter1++) 
    315310                { 
     
    326321                                (*iter1)->SetAccount(*iter2); 
    327322 
    328                                 // Do login at start if required 
    329                                 if ((*iter2)->GetLogonAtStart() && !(*iter1)->IsLoggedOn()) 
    330                                         started.push_back(*iter1);; 
     323                                // Always do logon - protocol will handle forced disconnect state 
     324                                if (!(*iter1)->IsLoggedOn() && ((*iter1)->IsOffline() || (*iter2)->GetLogonAtStart())) 
     325                                        started.push_back(*iter1); 
    331326                        } 
    332327                } 
     
    342337                                AddProtocol(aAdbkProtocol); 
    343338 
    344                                 // Do login at start if required 
    345                                 if ((*iter2)->GetLogonAtStart()) 
     339                                // Always do logon - protocol will handle forced disconnect state 
     340                                if (aAdbkProtocol->IsOffline() || (*iter2)->GetLogonAtStart()) 
    346341                                        started.push_back(aAdbkProtocol); 
    347342                        } 
     
    359354 
    360355        // Only start local protocols if allowed by admin 
    361         if (mOSProto) 
     356        if (mOSProto != NULL) 
    362357                StartProtocol(mOSProto); 
    363         if (mLocalProto) 
     358        if (mLocalProto != NULL) 
    364359                StartProtocol(mLocalProto); 
    365360 
    366361        for(CAdbkProtocolList::const_iterator iter = started.begin(); iter != started.end(); iter++) 
    367362                StartProtocol(*iter); 
    368          
    369         // No need to do this - broadcasting of changes now takes care of it 
    370         // Force visual update 
    371         //UpdateWindows(); 
    372363} 
    373364 
    374365// Sync with changed accounts 
    375 void CAddressBookManager::SyncLookups(const CAddressAccountList& accts) 
    376 { 
     366void CAddressBookManager::SyncLookups() 
     367{ 
     368        // Sync remainder from prefs 
     369        const CAddressAccountList& accts = CPreferences::sPrefs->mAddressAccounts.GetValue(); 
     370 
    377371        // Remove existing 
    378         for(CAddrLookupProtocolList::iterator iter = mLookups.begin(); iter != mLookups.end(); iter++) 
    379                 delete *iter; 
    380372        mLookups.clear(); 
    381373 
     
    389381                case CAddressAccount::eIMSP: 
    390382                case CAddressAccount::eACAP: 
     383                case CAddressAccount::eCardDAVAdbk: 
    391384                        // Never - these are ADBKProtocols 
    392385                        break; 
     
    410403                        break; 
    411404                } 
    412         }        
    413 } 
    414  
    415 // Sync cache with prefs 
    416 void CAddressBookManager::SyncCache() 
    417 { 
    418 } 
    419  
    420 // Start local 
    421 void CAddressBookManager::StartLocal() 
    422 { 
    423         // Force window reset first 
    424         UpdateWindows(); 
    425  
    426         cdstring local_url = cFileURLScheme; 
    427         local_url += cURLLocalhost; 
    428  
    429         // Try every open at start adbk 
    430         for(cdstrvect::iterator iter = CPreferences::sPrefs->mAdbkOpenAtStartup.Value().begin(); 
    431                         iter != CPreferences::sPrefs->mAdbkOpenAtStartup.Value().end(); ) 
    432         { 
    433                 if (::strncmp(*iter, local_url, local_url.length()) ==0) 
    434                 { 
    435                         const char* adbk_name = ((const char*) *iter) + local_url.length(); 
    436  
    437                         // Convert URL to path name 
    438                         cdstring fname = adbk_name; 
    439                         char* p = fname; 
    440                         while(*p) 
    441                         { 
    442                                 if (*p == '/') *p = os_dir_delim; 
    443                                 p++; 
    444                         } 
    445                         fname.DecodeURL(); 
    446 #if __dest_os == __mac_os || __dest_os == __mac_os_x 
    447                         // Resolve to file spec 
    448                         MyCFString cfstr(fname, kCFStringEncodingUTF8); 
    449                         PPx::FSObject spec(cfstr); 
    450  
    451                         // Open (erase from list if it fails) 
    452                         if (spec.IsValid()) 
    453                                 CMulberryApp::sApp->OpenDocument(&spec); 
    454                         else 
    455                         { 
    456                                 if (CErrorHandler::PutCautionAlertRsrcStr(true, "Alerts::Adbk::NoLocalFound", fname.c_str()) == CErrorHandler::Ok) 
    457                                 { 
    458                                         iter = CPreferences::sPrefs->mAdbkOpenAtStartup.Value().erase(iter); 
    459                                         CPreferences::sPrefs->mAdbkOpenAtStartup.SetDirty(); 
    460                                         continue; 
    461                                 } 
    462                         } 
    463 #elif __dest_os == __win32_os 
    464                         // Open (erase from list if it fails) 
    465                         if (!CMulberryApp::sApp->OpenDocumentFile(fname.win_str())) 
    466                         { 
    467                                 if (CErrorHandler::PutCautionAlertRsrcStr(true, "Alerts::Adbk::NoLocalFound", fname) == CErrorHandler::Ok) 
    468                                 { 
    469                                         iter = CPreferences::sPrefs->mAdbkOpenAtStartup.Value().erase((cdstrvect::iterator) iter); 
    470                                         CPreferences::sPrefs->mAdbkOpenAtStartup.SetDirty(); 
    471                                         continue; 
    472                                 } 
    473                         } 
    474 #elif __dest_os == __linux_os 
    475                         // Open (erase from list if it fails) 
    476                         if (!CMulberryApp::sApp->OpenLocalAddressBook(fname)) 
    477                         { 
    478                                 if (CErrorHandler::PutCautionAlertRsrcStr(true, "Alerts::Adbk::NoLocalFound", fname) == CErrorHandler::Ok) 
    479                                 { 
    480                                         iter = CPreferences::sPrefs->mAdbkOpenAtStartup.Value().erase((cdstrvect::iterator) iter); 
    481                                         CPreferences::sPrefs->mAdbkOpenAtStartup.SetDirty(); 
    482                                         continue; 
    483                                 } 
    484                         } 
    485 #else 
    486 #error __dest_os 
    487 #endif 
    488                 } 
    489                  
    490                 iter++; 
    491405        } 
    492406} 
     
    511425                        proto->Logon(); 
    512426                        proto->LoadList(); 
    513                         proto->SyncList(); 
    514427                } 
    515428        } 
     
    556469        int pos = 0; 
    557470 
     471#ifdef _TODO 
    558472        if (FindProtocol(proto, pos)) 
    559473        { 
     
    564478                        (*iter)->GetTable()->RemoveChildren(temp, true); 
    565479        } 
     480#endif 
     481} 
     482 
     483// Get index of protocol in list 
     484long CAddressBookManager::GetProtocolIndex(const CAdbkProtocol* proto) const 
     485{ 
     486        CAdbkProtocolList::const_iterator found = ::find(mProtos.begin(), mProtos.end(), proto); 
     487        if (found != mProtos.end()) 
     488                return found - mProtos.begin(); 
     489        else 
     490                return -1; 
     491} 
     492 
     493bool CAddressBookManager::FindProtocol(const CAdbkProtocol* proto, unsigned long& pos) const 
     494{ 
     495        bool result = false; 
     496        pos = 1; 
     497 
     498        for(CAddressBookList::const_iterator iter = mRoot.GetChildren()->begin(); iter != mRoot.GetChildren()->end(); iter++, pos++) 
     499        { 
     500                if ((*iter)->GetProtocol() == proto) 
     501                { 
     502                        result = true; 
     503                        break; 
     504                } 
     505                pos += (*iter)->CountDescendants(); 
     506        } 
     507 
     508        return result; 
     509} 
     510 
     511// Move protocol 
     512void CAddressBookManager::MoveProtocol(long old_index, long new_index) 
     513{ 
     514        // Cannot move local or OS 
     515        if (((mLocalProto != NULL) || (mOSProto != NULL)) && (old_index == 0)) 
     516                return; 
     517        else if ((mLocalProto != NULL) && (mOSProto != NULL) && (old_index == 1)) 
     518                return; 
     519         
     520        // Determine index adjustment offset to remove local/web protos 
     521        uint32_t proto_offset = 0; 
     522        if (mLocalProto != NULL) 
     523                proto_offset++; 
     524        if (mOSProto != NULL) 
     525                proto_offset++; 
     526 
     527        // Cannot move above local or web 
     528        if (new_index < proto_offset) 
     529                new_index = proto_offset; 
     530 
     531        CAdbkProtocol* proto = mProtos.at(old_index); 
     532 
     533        // Broadcast change to all to remove it 
     534        Broadcast_Message(eBroadcast_RemoveAdbkAccount, proto); 
     535 
     536        // Remove node from parent 
     537        proto->GetStoreRoot()->RemoveFromParent(); 
     538 
     539        // Adjust count 
     540        if (old_index < new_index) 
     541                new_index--; 
     542 
     543        // Move protocol 
     544        mProtos.erase(mProtos.begin() + old_index); 
     545        if (new_index < (long) mProtos.size()) 
     546        { 
     547                // Add item to root node 
     548                mRoot.InsertChild(proto->GetStoreRoot(), new_index); 
     549 
     550                // Add to protos list 
     551                mProtos.insert(mProtos.begin() + new_index, proto); 
     552        } 
     553        else 
     554        { 
     555                // Add item to root node 
     556                mRoot.AddChild(proto->GetStoreRoot()); 
     557 
     558                // Add to protos list 
     559                mProtos.push_back(proto); 
     560} 
     561 
     562        // Adjust indices to remove local/web 
     563        old_index -= proto_offset; 
     564        new_index -= proto_offset; 
     565 
     566        // Move mail account 
     567        CAddressAccountList& accts = CPreferences::sPrefs->mAddressAccounts.Value(); 
     568        CAddressAccount* acct = accts.at(old_index); 
     569        accts.at(old_index) = NULL; 
     570        accts.erase(accts.begin() + old_index); 
     571        if (new_index < (long) mProtos.size() - 1 - proto_offset) 
     572                accts.insert(accts.begin() + new_index, acct); 
     573                else 
     574                accts.push_back(acct); 
     575        CPreferences::sPrefs->mAddressAccounts.SetDirty(); 
     576 
     577        // Add it back to visual display in new place 
     578        Broadcast_Message(eBroadcast_InsertAdbkAccount, proto); 
     579} 
     580 
     581const CAddressBook* CAddressBookManager::GetNode(const cdstring& adbk) const 
     582{ 
     583        const CAddressBook* result = NULL; 
     584        for(CAdbkProtocolList::const_iterator iter = mProtos.begin(); iter != mProtos.end(); iter++) 
     585        { 
     586                result = (*iter)->GetNode(adbk); 
     587                if (result != NULL) 
     588                        return result; 
     589} 
     590 
     591        return NULL; 
     592        } 
     593 
     594// Managing the store 
     595CAddressBook* CAddressBookManager::NewAddressBook(CAdbkProtocol* proto, const cdstring& name, bool directory) 
     596{ 
     597        if ((proto == NULL) || name.empty()) 
     598        return NULL; 
     599 
     600        // Create account name 
     601        cdstring acct_name = proto->GetAccountName(); 
     602        acct_name += cMailAccountSeparator; 
     603        acct_name += name; 
     604 
     605        // Determine the parent node for the new one 
     606        CAddressBook* parent = proto->GetParentNode(acct_name); 
     607        if (parent == NULL) 
     608                return NULL; 
     609 
     610        // Create a new node 
     611        CAddressBook* node = new CAddressBook(proto, parent, !directory, directory, name); 
     612        parent->AddChild(node, true); 
     613 
     614        try 
     615        { 
     616                // Try to create it 
     617                node->GetProtocol()->CreateAdbk(node); 
     618 
     619                // Make sure protocol list is in sync after create 
     620                node->GetProtocol()->ListChanged(); 
     621 
     622                // Write out an empty calendar with the appropriate name 
     623                if (!directory) 
     624                { 
     625} 
     626 
     627                // Now insert into parent 
     628                Broadcast_Message(eBroadcast_InsertNode, node); 
     629        } 
     630        catch(...) 
     631        { 
     632                CLOG_LOGCATCH(...); 
     633                 
     634                // Clean-up 
     635                node->RemoveFromParent(); 
     636                delete node; 
     637                 
     638                CLOG_LOGRETHROW; 
     639                throw; 
     640        } 
     641 
     642        SyncAddressBook(node, true); 
     643 
     644        return node; 
     645} 
     646 
     647void CAddressBookManager::RenameAddressBook(CAddressBook* node, const cdstring& new_name) 
     648{ 
     649        // Cache account name for preference change 
     650        cdstring old_acct_name = node->GetAccountName(); 
     651        cdstring old_acct_url = node->GetURL(); 
     652 
     653        // Now rename the actual node 
     654        node->GetProtocol()->RenameAdbk(node, new_name); 
     655         
     656        // Change the node name locally 
     657        node->NewName(new_name); 
     658        cdstring new_acct_name = node->GetAccountName(); 
     659        cdstring new_acct_url = node->GetURL(); 
     660 
     661        // Rename in preferences 
     662        CPreferences::sPrefs->RenameAddressBook(old_acct_name, new_acct_name); 
     663        CPreferences::sPrefs->RenameAddressBookURL(old_acct_url, new_acct_url); 
     664 
     665        // Check for actual calendar rather than directory 
     666        if (!node->IsDirectory()) 
     667        { 
     668#ifdef _TODO 
     669                // If the calendar is open rename the calendar object and do an immediate write 
     670                iCal::CICalendar* cal = node->GetCalendar(); 
     671                auto_ptr<iCal::CICalendar> opened; 
     672                try 
     673                { 
     674                        if (cal == NULL) 
     675                        { 
     676                                opened.reset(new iCal::CICalendar); 
     677                                cal = opened.get(); 
     678                                 
     679                                // Give it to the node - this will activate the node 
     680                                node->SetCalendar(cal); 
     681                                 
     682                                // Now read the calendar data 
     683                                node->GetProtocol()->ReadFullCalendar(*node, *cal); 
     684} 
     685 
     686                        // Change the name in the calendar 
     687                        cal->EditName(node->GetShortName()); 
     688                         
     689                        // Now write the calendar data 
     690                        node->GetProtocol()->WriteFullCalendar(*node, *cal); 
     691                         
     692                        // Clean-up 
     693                        if (opened.get() != NULL) 
     694                        { 
     695                                node->SetCalendar(NULL); 
     696                        } 
     697                } 
     698                catch(...) 
     699                { 
     700                        CLOG_LOGCATCH(...); 
     701                         
     702                        // Clean-up 
     703                        if (opened.get() != NULL) 
     704                        { 
     705                                node->SetCalendar(NULL); 
     706                } 
     707                 
     708                        CLOG_LOGRETHROW; 
     709                        throw; 
     710                } 
     711#endif 
     712        } 
     713 
     714        // Now adjust node position 
     715         
     716        // First remove it from any listeners whilst it is still linked in to parent 
     717        Broadcast_Message(eBroadcast_RemoveNode, node); 
     718         
     719        // Now remove it from its parent and re-insert in proper location 
     720        node->RemoveFromParent(); 
     721         
     722        CAddressBook* parent_node = node->GetProtocol()->GetParentNode(node->GetAccountName()); 
     723        if (parent_node) 
     724        { 
     725                parent_node->AddChild(node, true); 
     726                Broadcast_Message(eBroadcast_InsertNode, node); 
     727} 
     728 
     729        // Make sure protocol list is in sync after rename 
     730        node->GetProtocol()->ListChanged(); 
     731 
     732} 
     733 
     734void CAddressBookManager::DeleteAddressBook(CAddressBook* node) 
     735{ 
     736        // Remove it from any listeners whilst it is still linked in to parent 
     737        Broadcast_Message(eBroadcast_DeleteNode, node); 
     738 
     739        // Now remove from parent's list 
     740        node->RemoveFromParent(); 
     741 
     742        // Cache account name for preference change 
     743        cdstring acct_name = node->GetAccountName(); 
     744        cdstring acct_url = node->GetURL(); 
     745 
     746        // Now remove the actual node (node is deleted after this) 
     747        node->GetProtocol()->DeleteAdbk(node); 
     748         
     749        // Make sure protocol list is in sync after rename 
     750        node->GetProtocol()->ListChanged(); 
     751 
     752        SyncAddressBook(node, false); 
     753 
     754        // Remove tha actual object 
     755        delete node; 
     756 
     757        // Remove from preferences 
     758        CPreferences::sPrefs->DeleteAddressBook(acct_name); 
     759        CPreferences::sPrefs->DeleteAddressBookURL(acct_url); 
    566760} 
    567761 
     
    574768                { 
    575769                        // Only add if not already present 
    576                         CFlatAdbkList::iterator found = ::find(mAdbkNickName.begin(), mAdbkNickName.end(), adbk); 
     770                        CAddressBookList::iterator found = ::find(mAdbkNickName.begin(), mAdbkNickName.end(), adbk); 
    577771                        if (found == mAdbkNickName.end())</