| 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++; |
| | 480 | #endif |
| | 481 | } |
| | 482 | |
| | 483 | // Get index of protocol in list |
| | 484 | long 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 | |
| | 493 | bool 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 |
| | 512 | void 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 | |
| | 581 | const 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 |
| | 595 | CAddressBook* 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 | |
| | 647 | void 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 | |
| | 734 | void 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); |