1 // frmMain.cpp - Main window form.
3 // (c) 2012-2015 Xestia Software Development.
5 // This file is part of Xestia Address Book.
7 // Xestia Address Book is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by the
9 // Free Software Foundation, version 3 of the license.
11 // Xestia Address Book is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License along
17 // with Xestia Address Book. If not, see <http://www.gnu.org/licenses/>
26 #include <wx/tokenzr.h>
28 #include <wx/mstream.h>
29 #include <wx/fs_mem.h>
31 #include <wx/filesys.h>
33 #include <wx/stdpaths.h>
34 #include <wx/fileconf.h>
35 #include <wx/gdicmn.h>
41 #include "frmPreferences.h"
42 #include "frmNewAccount.h"
43 #include "actmgr/frmActivityMgr.h"
44 #include "frmContact.h"
45 #include "frmConflictResolution.h"
46 #include "frmInvalidSSLCertificate.h"
47 #include "search/frmSearch.h"
48 #include "frmSSLCertificate.h"
49 #include "frmUpdate.h"
50 #include "import/frmImportResults.h"
53 #include "common/preferences.h"
54 #include "common/getcontactinfo.h"
55 #include "common/events.h"
56 #include "common/dirs.h"
57 #include "vcard/vcard.h"
58 #include "contacteditor/frmContactEditor.h"
59 #include "import/import.h"
60 #include "export/export.h"
61 #include "widgets/XABContactMenu.h"
62 #include "widgets/XABAccountView.h"
66 // Define the event types.
68 DEFINE_EVENT_TYPE(CE_UPDATECONTACTLIST);
69 DEFINE_EVENT_TYPE(SE_UPDATECONTACTNOTIF);
70 DEFINE_EVENT_TYPE(CE_OPENCONTACT);
71 DEFINE_EVENT_TYPE(CE_OPENCONTACTLIST);
72 DEFINE_EVENT_TYPE(CE_NEWCONTACT);
73 DEFINE_EVENT_TYPE(CE_EDITCONTACT);
74 DEFINE_EVENT_TYPE(CE_DELETECONTACT);
75 DEFINE_EVENT_TYPE(CE_REVEALCONTACT);
76 DEFINE_EVENT_TYPE(CE_REMOVECONTACT);
77 DEFINE_EVENT_TYPE(CE_REMOVESEARCH);
78 DEFINE_EVENT_TYPE(SYNC_EMPTYSERVER);
79 DEFINE_EVENT_TYPE(ACTMGR_START);
80 DEFINE_EVENT_TYPE(ACTMGR_SHUFFLE);
81 DEFINE_EVENT_TYPE(ACTMGR_STOP);
82 DEFINE_EVENT_TYPE(WINDOW_ADD);
83 DEFINE_EVENT_TYPE(WINDOW_EDIT);
84 DEFINE_EVENT_TYPE(WINDOW_CLOSE);
85 DEFINE_EVENT_TYPE(CONNSTAT_UPDATE);
86 DEFINE_EVENT_TYPE(INVALIDSSLCERT);
87 DEFINE_EVENT_TYPE(INVALIDSSLCERTSTRING);
88 DEFINE_EVENT_TYPE(GETSELECTEDLIST);
89 DEFINE_EVENT_TYPE(SYNCACCOUNT);
90 DEFINE_EVENT_TYPE(IMPORT_RESULTSSHOW);
91 DEFINE_EVENT_TYPE(RELOADCONTACTLIST);
92 DEFINE_EVENT_TYPE(REFRESHADDRESSBOOK);
93 #if defined(__APPLE__)
94 DEFINE_EVENT_TYPE(INVALIDSSLTRUST);
97 // Setup the event table using the event types.
99 BEGIN_EVENT_TABLE(frmMain, wxFrame)
100 EVT_COMMAND(wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, frmMain::ConflictResolution)
101 EVT_COMMAND(wxID_ANY, CE_UPDATECONTACTLIST, frmMain::UpdateContactList)
102 EVT_COMMAND(wxID_ANY, SE_UPDATECONTACTNOTIF, frmMain::UpdateSearchContactLists)
103 EVT_COMMAND(wxID_ANY, CE_OPENCONTACT, frmMain::OpenContactInfo)
104 EVT_COMMAND(wxID_ANY, CE_OPENCONTACTLIST, frmMain::OpenContactInfoList)
105 EVT_COMMAND(wxID_ANY, CE_NEWCONTACT, frmMain::ShowContactEditorNew)
106 EVT_COMMAND(wxID_ANY, CE_EDITCONTACT, frmMain::ShowContactEditorEdit)
107 EVT_COMMAND(wxID_ANY, CE_DELETECONTACT, frmMain::DeleteContact)
108 EVT_COMMAND(wxID_ANY, CE_REVEALCONTACT, frmMain::RevealContact)
109 EVT_COMMAND(wxID_ANY, CE_REMOVESEARCH, frmMain::RemoveContactsWindowPointer)
110 EVT_COMMAND(wxID_ANY, SYNC_EMPTYSERVER, frmMain::EmptyServerDialog)
111 EVT_COMMAND(wxID_ANY, ACTMGR_START, frmMain::ActivityIconStart)
112 EVT_COMMAND(wxID_ANY, ACTMGR_SHUFFLE, frmMain::ActivityIconShuffle)
113 EVT_COMMAND(wxID_ANY, ACTMGR_STOP, frmMain::ActivityIconStop)
114 EVT_COMMAND(wxID_ANY, WINDOW_ADD, frmMain::WindowAdd)
115 EVT_COMMAND(wxID_ANY, WINDOW_EDIT, frmMain::WindowEdit)
116 EVT_COMMAND(wxID_ANY, WINDOW_CLOSE, frmMain::WindowDelete)
117 EVT_COMMAND(wxID_ANY, CONNSTAT_UPDATE, frmMain::UpdateConnectionStatus)
118 EVT_COMMAND(wxID_ANY, INVALIDSSLCERT, frmMain::InvalidSSLCertificate)
119 EVT_COMMAND(wxID_ANY, INVALIDSSLCERTSTRING, frmMain::InvalidSSLCertificateString)
120 EVT_COMMAND(wxID_ANY, GETSELECTEDLIST, frmMain::GetSelectedList)
121 EVT_COMMAND(wxID_ANY, SYNCACCOUNT, frmMain::SyncAccount)
122 EVT_COMMAND(wxID_ANY, IMPORT_RESULTSSHOW, frmMain::ShowImportResults)
123 EVT_COMMAND(wxID_ANY, RELOADCONTACTLIST, frmMain::ReloadContactList)
124 EVT_COMMAND(wxID_ANY, REFRESHADDRESSBOOK, frmMain::RefreshAddressBook)
125 #if defined(__APPLE__)
126 EVT_COMMAND(wxID_ANY, INVALIDSSLTRUST, frmMain::DisplayTrustPanel)
130 frmMain::frmMain( wxWindow* parent )
135 // Setup the account icons.
137 wxMemoryInputStream astream(icons_accinet_png, sizeof(icons_accinet_png));
138 wxMemoryInputStream bstream(icons_acclocal_png, sizeof(icons_acclocal_png));
139 wxMemoryInputStream cstream(icons_accgroup_png, sizeof(icons_accgroup_png));
140 wxMemoryInputStream dstream(icons_accnone_png, sizeof(icons_accnone_png));
141 wxMemoryInputStream estream(icons_accunsupported_png, sizeof(icons_accunsupported_png));
143 wxImage icons_accinet_png(astream, wxBITMAP_TYPE_PNG);
144 wxBitmap AccInet(icons_accinet_png, -1);
146 wxIAccInet.CopyFromBitmap(AccInet);
148 wxImage icons_acclocal_png(bstream, wxBITMAP_TYPE_PNG);
149 wxBitmap AccNIcon(icons_acclocal_png, -1);
151 wxIAccNIcon.CopyFromBitmap(AccNIcon);
153 wxImage icons_accgroup_png(cstream, wxBITMAP_TYPE_PNG);
154 wxBitmap AccGrp(icons_accgroup_png, -1);
156 wxIAccGrp.CopyFromBitmap(AccGrp);
158 wxImage icons_accnone_png(dstream, wxBITMAP_TYPE_PNG);
159 wxBitmap AccNone(icons_accnone_png, -1);
161 wxIAccNone.CopyFromBitmap(AccNone);
163 wxImage icons_accunsupported_png(estream, wxBITMAP_TYPE_PNG);
164 wxBitmap AccUnsupported(icons_accunsupported_png, -1);
165 wxIcon wxIAccUnsupported;
166 wxIAccUnsupported.CopyFromBitmap(AccUnsupported);
168 AccountID = AccImgList->Add(wxIAccNIcon);
169 AccountNetID = AccImgList->Add(wxIAccInet);
170 AccountGrpID = AccImgList->Add(wxIAccGrp);
171 AccountNoneID = AccImgList->Add(wxIAccNone);
172 AccountUnsupportedID = AccImgList->Add(wxIAccUnsupported);
174 bmpIcon->SetIcon(AccImgList->GetIcon(AccountNoneID));
176 // Setup the status bar icons.
180 wxMemoryInputStream sslstream(icons_ssl_png, sizeof(icons_ssl_png));
181 wxMemoryInputStream sslwarningstream(icons_sslwarning_png, sizeof(icons_sslwarning_png));
182 wxMemoryInputStream nosslstream(icons_nossl_png, sizeof(icons_nossl_png));
184 wxImage icons_ssl_png(sslstream, wxBITMAP_TYPE_PNG);
185 imgSSL = new wxBitmap(icons_ssl_png, -1);
187 wxImage icons_sslwarning_png(sslwarningstream, wxBITMAP_TYPE_PNG);
188 imgSSLWarning = new wxBitmap(icons_sslwarning_png, -1);
190 wxImage icons_nossl_png(nosslstream, wxBITMAP_TYPE_PNG);
191 imgNoSSL = new wxBitmap(icons_nossl_png, -1);
195 wxMemoryInputStream addaddressbook(toolbar_addaddressbook_png, sizeof(toolbar_addaddressbook_png));
196 wxMemoryInputStream preferences(toolbar_preferences_png, sizeof(toolbar_preferences_png));
197 wxMemoryInputStream searchcontacts(toolbar_searchcontacts_png, sizeof(toolbar_searchcontacts_png));
198 wxMemoryInputStream addcontact(toolbar_addcontact_png, sizeof(toolbar_addcontact_png));
199 wxMemoryInputStream editcontact(toolbar_editcontact_png, sizeof(toolbar_editcontact_png));
200 wxMemoryInputStream deletecontact(toolbar_deletecontact_png, sizeof(toolbar_deletecontact_png));
202 wxImage toolbar_addaddressbook_png(addaddressbook, wxBITMAP_TYPE_PNG);
203 imgAddAddressBook = new wxBitmap (toolbar_addaddressbook_png, -1);
204 tblMain->SetToolNormalBitmap(tbtNewAccount->GetId(), *imgAddAddressBook);
206 wxImage toolbar_preferences_png(preferences, wxBITMAP_TYPE_PNG);
207 imgPreferences = new wxBitmap (toolbar_preferences_png, -1);
208 tblMain->SetToolNormalBitmap(tbtPreferences->GetId(), *imgPreferences);
210 wxImage toolbar_searchcontacts_png(searchcontacts, wxBITMAP_TYPE_PNG);
211 imgSearchContacts = new wxBitmap (toolbar_searchcontacts_png, -1);
212 tblMain->SetToolNormalBitmap(tbtSearch->GetId(), *imgSearchContacts);
214 wxImage toolbar_addcontact_png(addcontact, wxBITMAP_TYPE_PNG);
215 imgAddContact = new wxBitmap (toolbar_addcontact_png, -1);
216 tblMain->SetToolNormalBitmap(tbtAddContact->GetId(), *imgAddContact);
218 wxImage toolbar_editcontact_png(editcontact, wxBITMAP_TYPE_PNG);
219 imgEditContact = new wxBitmap (toolbar_editcontact_png, -1);
220 tblMain->SetToolNormalBitmap(tbtEditContact->GetId(), *imgEditContact);
222 wxImage toolbar_deletecontact_png(deletecontact, wxBITMAP_TYPE_PNG);
223 imgDeleteContact = new wxBitmap (toolbar_deletecontact_png, -1);
224 tblMain->SetToolNormalBitmap(tbtDeleteContact->GetId(), *imgDeleteContact);
228 wxMemoryInputStream act1(icons_act1_png, sizeof(icons_act1_png));
229 wxMemoryInputStream act2(icons_act2_png, sizeof(icons_act2_png));
230 wxMemoryInputStream act3(icons_act3_png, sizeof(icons_act3_png));
231 wxMemoryInputStream act4(icons_act4_png, sizeof(icons_act4_png));
232 wxMemoryInputStream actsleep(icons_actsleep_png, sizeof(icons_actsleep_png));
234 wxImage icons_actsleep_png(actsleep, wxBITMAP_TYPE_PNG);
235 imgActIconSleep = new wxBitmap (icons_actsleep_png, -1);
237 wxImage icons_act1_png(act1, wxBITMAP_TYPE_PNG);
238 imgActIcon1 = new wxBitmap (icons_act1_png, -1);
240 wxIAct1icon.CopyFromBitmap(*imgActIcon1);
242 wxImage icons_act2_png(act2, wxBITMAP_TYPE_PNG);
243 imgActIcon2 = new wxBitmap (icons_act2_png, -1);
245 wxIAct2icon.CopyFromBitmap(*imgActIcon2);
247 wxImage icons_act3_png(act3, wxBITMAP_TYPE_PNG);
248 imgActIcon3 = new wxBitmap (icons_act3_png, -1);
250 wxIAct3icon.CopyFromBitmap(*imgActIcon3);
252 wxImage icons_act4_png(act4, wxBITMAP_TYPE_PNG);
253 imgActIcon4 = new wxBitmap (icons_act4_png, -1);
255 wxIAct4icon.CopyFromBitmap(*imgActIcon4);
257 // Online/Offline icons.
259 wxMemoryInputStream onlinestream(icons_online_png, sizeof(icons_online_png));
260 wxMemoryInputStream offlinestream(icons_offline_png, sizeof(icons_offline_png));
262 wxImage icons_online_png(onlinestream, wxBITMAP_TYPE_PNG);
263 imgOnline = new wxBitmap(icons_online_png, -1);
265 wxImage icons_offline_png(offlinestream, wxBITMAP_TYPE_PNG);
266 imgOffline = new wxBitmap(icons_offline_png, -1);
268 // Setup the account view.
270 AccCtrl->SetPopupControl(treAccounts);
271 AccCtrl->SetPopupMaxHeight(175);
272 AccCtrl->SetPopupMinWidth(250);
273 treAccounts->AssignImageList(AccImgList);
275 wxListItem ColumnData;
277 ColumnData.SetText(wxT("Name0"));
278 ColumnData.SetWidth(320);
279 lstContacts->InsertColumn(0, ColumnData);
281 treAccounts->Connect(wxEVT_LEFT_DCLICK, wxTreeEventHandler(frmMain::LoadContactList), NULL, this);
282 treAccounts->Connect(wxEVT_TREE_SEL_CHANGED, wxTreeEventHandler(frmMain::LoadContactList), NULL, this);
284 #if defined(__HAIKU__)
286 #elif defined(__WIN32__)
288 int stbBottomData [4] = { -1, 8, 8, 8 };
292 int stbBottomData [4] = { -1, 20, 20, 20 };
296 stbBottom->SetFieldsCount(4, stbBottomData);
297 stbBottom->SetMinHeight(16);
302 stbBottom->GetFieldRect(1, rectOnline);
303 stbBottom->GetFieldRect(2, rectSSL);
304 stbBottom->GetFieldRect(3, rectActivity);
306 SSLToolTip = new wxToolTip(wxT(""));
308 imgConnStatus = new wxStaticBitmap(stbBottom, wxID_ANY, wxNullBitmap, wxPoint((rectOnline.GetX()),(rectOnline.GetY())), wxDefaultSize, 0 );
309 imgConnStatus->SetBitmap(*imgOnline);
310 imgConnStatus->Connect( wxEVT_LEFT_DCLICK, wxCommandEventHandler( frmMain::ToggleConnectionStatus ), NULL, this );
312 imgSSLStatus = new wxStaticBitmap(stbBottom, wxID_ANY, wxNullBitmap, wxPoint((rectSSL.GetX()),(rectSSL.GetY())), wxDefaultSize, 0 );
313 imgSSLStatus->SetBitmap(*imgNoSSL);
314 imgSSLStatus->SetToolTip(SSLToolTip);
315 imgSSLStatus->Connect( wxEVT_LEFT_DCLICK, wxCommandEventHandler( frmMain::ShowSSLCertificates ), NULL, this );
317 imgActivityStatus = new wxStaticBitmap(stbBottom, wxID_ANY, wxNullBitmap, wxPoint((rectActivity.GetX()),(rectActivity.GetY())), wxDefaultSize, 0);
318 imgActivityStatus->SetBitmap(*imgActIconSleep);
319 imgActivityStatus->Connect( wxEVT_LEFT_DCLICK, wxCommandEventHandler( frmMain::ShowActivityWindow ), NULL, this );
321 // Setup the window menu.
323 // By default should be:
328 // Contact editor windows:
334 mnuContactWindows = new wxMenuItem( mnuManage, wxID_ANY, wxString( _("Contact windows:") ), wxEmptyString, wxITEM_NORMAL );
335 mnuWindow->Append( mnuContactWindows );
337 mnuWindow->AppendSeparator();
339 mnuContactEditorWindows = new wxMenuItem( mnuManage, wxID_ANY, wxString( _("Contact editor windows:") ), wxEmptyString, wxITEM_NORMAL );
340 mnuWindow->Append( mnuContactEditorWindows );
342 mnuWindow->AppendSeparator();
344 mnuSearchWindows = new wxMenuItem( mnuManage, wxID_ANY, wxString( wxT("Search windows:") ), wxEmptyString, wxITEM_NORMAL );
345 mnuWindow->Append( mnuSearchWindows );
347 #if defined(__WIN32__)
352 mnuContactWindows->SetFont(fontstyle);
353 mnuContactEditorWindows->SetFont(fontstyle);
354 mnuSearchWindows->SetFont(fontstyle);
358 mnuContactWindows->Enable(FALSE);
359 mnuContactEditorWindows->Enable(FALSE);
360 mnuSearchWindows->Enable(FALSE);
364 // Hide unimplemented functions.
370 void frmMain::QuitApp( wxCloseEvent& event )
373 // Run the QuitApp function.
379 void frmMain::QuitApp( wxCommandEvent& event )
382 // Run the QuitApp function.
388 void frmMain::QuitApp()
391 // Function to run when quitting.
393 // Write out the ETag databases.
395 ETagProcTimer.Stop();
396 ETagProcTimer.Notify();
398 // Save Preferences: Save the window position if that option is enabled.
400 wxString SetFilename = GetUserPrefDir();
402 #if defined(__HAIKU__)
406 #elif defined(__WIN32__)
408 SetFilename.Append(wxT("settings"));
410 #elif defined(__APPLE__)
412 TerminateHelpBrowserProcess();
418 SetFilename.Append(wxT("settings"));
422 wxFileConfig *cfgfile = new wxFileConfig("", "", SetFilename);
424 bool SaveWindowPos = FALSE;
425 wxString SaveWindowInc;
426 cfgfile->Read(wxT("SaveWindowPosition"), &SaveWindowInc);
428 if (SaveWindowInc == wxT("true")){
430 SaveWindowPos = TRUE;
434 if (SaveWindowPos == TRUE){
436 wxRect frmMainPos = GetRect();
438 cfgfile->Write(wxT("WindowPositionX"), frmMainPos.GetX());
439 cfgfile->Write(wxT("WindowPositionY"), frmMainPos.GetY());
440 cfgfile->Write(wxT("WindowPositionHeight"), frmMainPos.GetHeight());
441 cfgfile->Write(wxT("WindowPositionWidth"), frmMainPos.GetWidth());
448 // Everything closed... exit.
456 void frmMain::ShowActivityWindow( wxCommandEvent& event )
459 // Open the activity manager window.
461 frmActivityMgr *frameActMgr = static_cast<frmActivityMgr*>(ActMgrPtr);
462 frameActMgr->OpenWindow();
467 void frmMain::ShowAboutWindow( wxCommandEvent& event )
470 // Show the about window.
472 frmAbout *frameAbout = new frmAbout ( this );
473 frameAbout->SetupAboutWindow();
474 frameAbout->ShowModal();
480 void frmMain::OpenPreferences( wxCommandEvent& event)
483 // Close all windows first.
485 if (CloseAllWindows() == false)
490 // Open the preferences window.
492 ReloadAccounts = FALSE;
494 frmPreferences *framePreferences = new frmPreferences ( this );
495 framePreferences->SetupPointers(&ReloadAccounts);
496 framePreferences->ShowModal();
497 delete framePreferences;
498 framePreferences = NULL;
500 if (ReloadAccounts == TRUE){
502 // Reload the accounts as a change has been made within
503 // the application and clear the current contact information.
505 this->LoadPreferences(true);
506 this->ResetContactInfo();
512 void frmMain::OpenNewABDialog( wxCommandEvent& event)
515 // Open the new account dialog.
517 ReloadAccounts = FALSE;
519 frmNewAccount *frameNewAccount = new frmNewAccount ( this );
520 frameNewAccount->SetupPointers(&ReloadAccounts);
521 frameNewAccount->ShowModal();
522 delete frameNewAccount;
523 frameNewAccount = NULL;
525 if (ReloadAccounts == TRUE){
527 // Reload the accounts as a change has been made within
530 this->LoadPreferences(true);
536 void frmMain::LoadContactList( wxTreeEvent& event )
539 // Load the contact list.
541 // Clear all existing variables.
543 lstContacts->DeleteAllItems();
545 treAccounts->SetAccount();
547 wxTreeItemIdValue cookie;
548 wxTreeItemId next = treAccounts->GetRootItem();
549 wxString AccountName;
550 wxString AccountDir, AccountType, AccountDirFinal, AccountTypeFinal;
551 wxString AccountDirCmb;
552 long selectedaccount = 0;
554 wxTreeItemId selectedChild = treAccounts->GetSelection();
555 wxTreeItemId nextChild;
557 wxTreeItemId ActiveItemId = treAccounts->GetFocusedItem();
558 int ActiveItemIcon = treAccounts->GetItemImage(ActiveItemId, wxTreeItemIcon_Normal);
560 int SCImg = treAccounts->GetItemImage(selectedChild);
561 int AccountIndex = 0;
563 bmpIcon->SetIcon(AccImgList->GetIcon(SCImg));
565 // Process each account.
567 for (int i = 0; i < prefaccounts.GetCount(); i++){
569 if (ActiveItemIcon == 2){
571 std::multimap<wxTreeItemId, int>::iterator AGTiter = AccountGroupTreeId.find(ActiveItemId);
572 std::multimap<int, int>::iterator AGLiter = AccountGroupList.find(AGTiter->second);
573 int ActiveAccountG = AGLiter->second;
575 if (i == ActiveAccountG){
577 AccountDir.Append(prefaccounts.GetAccountDirectory(i));
578 AccountType.Append(prefaccounts.GetAccountType(i));
583 if (AccountType == wxT("CardDAV")){
584 AccountTypeFinal.Append(wxT("carddav"));
585 } else if (AccountType == wxT("Local")){
586 imgSSLStatus->SetBitmap(*imgOffline);
587 SSLToolTip->SetTip(wxT("SSL status is not applicable for this account"));
588 AccountTypeFinal.Append(wxT("local"));
590 imgSSLStatus->SetBitmap(*imgOffline);
591 SSLToolTip->SetTip(wxT("SSL status is not applicable for this account"));
592 AccountTypeFinal.Append(AccountType.Lower());
603 nextChild = treAccounts->GetFirstChild(next, cookie);
605 nextChild = treAccounts->GetNextSibling(nextChild);
608 AccountName = treAccounts->GetItemText(nextChild);
610 if (nextChild == selectedChild){
612 AccountDir.Append(prefaccounts.GetAccountDirectory(i));
613 AccountType.Append(prefaccounts.GetAccountType(i));
618 if (AccountType == wxT("CardDAV")){
619 AccountTypeFinal.Append(wxT("carddav"));
620 } else if (AccountType == wxT("Local")){
621 SSLToolTip->SetTip(wxT("SSL status is not applicable for this account"));
622 AccountTypeFinal.Append(wxT("local"));
624 AccountTypeFinal.Append(AccountType.Lower());
633 if (selectedaccount >= prefaccounts.GetCount()){
635 // The account selected isn't there so return.
643 // Open the directory and get the list of .vcf files
644 // in that directory.
646 ActiveAccount = AccountDir + wxT(".") + AccountTypeFinal;
647 ActiveAccountType = AccountType;
649 SetupSSLStatus(AccountIndex);
651 AccountDirFinal.Clear();
652 AccountDirFinal = GetAccountDir(AccountDir + wxT(".") + AccountTypeFinal, FALSE);
654 ContactsFileIndex.Clear();
656 wxString vCardFilename;
657 wxString vCardFilenameFull;
658 wxString vCardDataString;
659 wxStringTokenizer vcardfileline;
661 wxString setname, setvalue;
662 std::multimap<wxString, wxString, std::greater<wxString>> vCardNamesAsc;
663 std::multimap<wxString, wxString, std::less<wxString>> vCardNamesDsc;
664 long ContactIndex = 1;
665 long ContactSeekPoint = 0;
667 wxDir vcardaccdir(AccountDirFinal);
669 // Get the wxTreeItemId and image icon and compare it to the list.
671 if (ActiveItemIcon == AccountGrpID){
673 // It's a group so load the file containing the group and
674 // get the members of the group.
679 std::multimap<wxTreeItemId, int>::iterator AGTiter = AccountGroupTreeId.find(ActiveItemId);
680 std::multimap<int, wxString>::iterator AGFiter = AccountGroupFilename.find(AGTiter->second);
682 Group.LoadFile(AGFiter->second);
684 ArrayvCardOutData vCardMember = Group.GetByPartial(wxT("MEMBER"));
686 for (int i = 0; i < vCardMember.PropCount; i++){
688 vCardMember.PropValues[i].Trim();
689 if (vCardMember.PropValues[i].Left(9) == wxT("urn:uuid:")){
691 wxString NewPropValue;
692 NewPropValue = vCardMember.PropValues[i].Mid(9, wxString::npos);
693 vCardMember.PropValues[i] = NewPropValue;
699 bool ProcFiles = vcardaccdir.GetFirst(&vCardFilename, wxEmptyString, wxDIR_FILES);
703 if (vCardFilename.Right(4) == wxT(".vcf") ||
704 vCardFilename.Right(4) == wxT(".VCF") ||
705 vCardFilename.Right(5) == wxT(".vcard") ||
706 vCardFilename.Right(5) == wxT(".VCARD")){
709 bool FoundMember = FALSE;
711 vCardFilenameFull.Append(AccountDirFinal);
712 vCardFilenameFull.Append(wxT("/"));
713 vCardFilenameFull.Append(vCardFilename);
715 Person.LoadFile(vCardFilenameFull);
717 UIDCode = Person.Get(wxT("UID"));
719 for (int i = 0; i < vCardMember.PropCount; i++){
721 if (vCardMember.PropValues[i] == UIDCode){
729 if (FoundMember == FALSE){
731 vCardFilename.Clear();
732 vCardFilenameFull.Clear();
733 vCardDataString.Clear();
734 ProcFiles = vcardaccdir.GetNext(&vCardFilename);
739 if (Person.MeetBaseSpecification()){
743 // Split the name into sections.
745 vCardName NameData = Person.GetName();
747 vCardDataString = NameData.Forename + wxT(" ") + NameData.Surname;
749 } else if (SortMode == 2){
751 // Split the name into sections.
753 vCardName NameData = Person.GetName();
755 vCardDataString = NameData.Surname + wxT(", ") + NameData.Forename;
757 } else if (SortMode == 3){
759 // Check and make sure that the top most nickname is used.
761 vCardDataString = Person.Get(wxT("NICKNAME"));
763 if (vCardDataString.IsEmpty()){
765 vCardDataString = wxT("(no nickname)");
769 } else if (SortMode == 4){
771 vCardDataString = Person.Get(wxT("FN"));
775 if (AscendingMode == TRUE){
776 vCardNamesAsc.insert(std::make_pair(vCardDataString, vCardFilenameFull));
778 vCardNamesDsc.insert(std::make_pair(vCardDataString, vCardFilenameFull));
785 vCardFilename.Clear();
786 vCardFilenameFull.Clear();
787 vCardDataString.Clear();
788 ProcFiles = vcardaccdir.GetNext(&vCardFilename);
794 bool ProcFiles = vcardaccdir.GetFirst(&vCardFilename, wxEmptyString, wxDIR_FILES);
797 if (vCardFilename.Right(4) == wxT(".vcf") ||
798 vCardFilename.Right(4) == wxT(".VCF") ||
799 vCardFilename.Right(5) == wxT(".vcard") ||
800 vCardFilename.Right(5) == wxT(".VCARD")){
804 vCardFilenameFull.Append(AccountDirFinal);
805 vCardFilenameFull.Append(vCardFilename);
807 Person.LoadFile(vCardFilenameFull);
809 if (Person.MeetBaseSpecification()){
813 // Split the name into sections.
815 vCardDataString = Person.Get(wxT("N"));
817 vCardName NameData = Person.GetName();
819 vCardDataString = NameData.Forename + wxT(" ") + NameData.Surname;
821 } else if (SortMode == 2){
823 // Split the name into sections.
825 vCardName NameData = Person.GetName();
827 vCardDataString = NameData.Surname + wxT(", ") + NameData.Forename;
829 } else if (SortMode == 3){
831 // Check and make sure that the top most nickname is used.
833 vCardDataString = Person.Get(wxT("NICKNAME"));
835 if (vCardDataString.IsEmpty()){
837 vCardDataString = wxT("(no nickname)");
841 } else if (SortMode == 4){
843 vCardDataString = Person.Get(wxT("FN"));
847 if (AscendingMode == TRUE){
849 vCardNamesAsc.insert(std::make_pair(vCardDataString, vCardFilenameFull));
853 vCardNamesDsc.insert(std::make_pair(vCardDataString, vCardFilenameFull));
861 vCardFilename.Clear();
862 vCardFilenameFull.Clear();
863 vCardDataString.Clear();
864 ProcFiles = vcardaccdir.GetNext(&vCardFilename);
871 // Insert the data into the control.
873 if (AscendingMode == TRUE){
874 for (std::map<wxString, wxString>::iterator iter = vCardNamesAsc.begin();
875 iter != vCardNamesAsc.end(); ++iter){
877 wxListItem ContactInfo;
879 ContactInfo.SetId(0);
880 ContactInfo.SetText(_("Mooo"));
881 ContactInfo.SetData(ContactSeekPoint);
882 ContactIndex = lstContacts->InsertItem(ContactInfo);
884 lstContacts->SetItem(ContactIndex, 0, iter->first);
886 ContactsFileIndex.Insert(iter->second, ContactSeekPoint);
893 for (std::map<wxString, wxString>::iterator iter = vCardNamesDsc.begin();
894 iter != vCardNamesDsc.end(); ++iter){
896 wxListItem ContactInfo;
898 ContactInfo.SetId(0);
899 ContactInfo.SetText(_("Mooo"));
900 ContactInfo.SetData(ContactSeekPoint);
901 ContactIndex = lstContacts->InsertItem(ContactInfo);
903 lstContacts->SetItem(ContactIndex, 0, iter->first);
904 ContactsFileIndex.Insert(iter->second, ContactSeekPoint);
913 void frmMain::ShowContactInfo( wxListEvent& event )
916 // Display the contact information.
918 long intSelected = -1;
919 long ContactSeekNum = -1;
921 // Check if several contacts have been selected.
923 int ContactTotal = 0;
927 intSelected = lstContacts->GetNextItem(intSelected,
929 wxLIST_STATE_SELECTED);
931 if (intSelected == -1){
941 if (ContactTotal == 0){
942 htmContactData->SetPage(wxT(""));
946 if (ContactTotal > 1){
948 htmContactData->SetPage(wxString::Format(wxT("%i contacts selected."), ContactTotal));
949 ActiveFilename.Clear();
954 intSelected = lstContacts->GetNextItem(intSelected,
956 wxLIST_STATE_SELECTED);
958 ContactSeekNum = lstContacts->GetItemData(intSelected);
961 wxString wxSContactString;
962 wxString ContactLine;
965 size_t ContactLineLen;
966 bool ExtraLineSeek = FALSE;
967 int QuoteBreakPoint = 0;
969 bool PropertyFind = FALSE;
970 bool QuoteMode = FALSE;
972 wxString wxSPropertyNextLine;
973 wxString wxSProperty;
974 wxString wxSPropertySeg1;
975 wxString wxSPropertySeg2;
977 // Check if we are using wxWidgets version 2.8 or less and
978 // execute the required command accordingly.
980 #if wxABI_VERSION < 20900
981 ContactFile.Open(ContactsFileIndex[ContactSeekNum].c_str(), wxT("r"));
983 ContactFile.Open(ContactsFileIndex[ContactSeekNum], wxT("r"));
986 if (ContactFile.IsOpened() == FALSE){
992 ContactFile.ReadAll(&wxSContactString, wxConvAuto());
996 std::map<int, wxString> ContactFileLines;
997 std::map<int, wxString>::iterator striter;
999 wxStringTokenizer wSTContactFileLines(wxSContactString, wxT("\r\n"));
1001 int ContactLineSeek = 0;
1003 while (wSTContactFileLines.HasMoreTokens() == TRUE){
1005 ContactLine = wSTContactFileLines.GetNextToken();
1006 ContactFileLines.insert(std::make_pair(ContactLineSeek, ContactLine));
1011 if (ContactSeekNum < 0){
1015 for (std::map<int, wxString>::iterator iter = ContactFileLines.begin();
1016 iter != ContactFileLines.end(); ++iter){
1018 // Find the colon which splits the start bit from the data part.
1020 ContactLine = iter->second;
1022 while (ExtraLineSeek == TRUE){
1024 // Check if there is extra data on the next line
1025 // (indicated by space or tab at the start) and add data.
1029 if (iter == ContactFileLines.end()){
1036 wxSPropertyNextLine = iter->second;
1039 if (wxSPropertyNextLine.Mid(0, 1) == wxT(" ") || wxSPropertyNextLine.Mid(0, 1) == wxT("\t")){
1041 wxSPropertyNextLine.Remove(0, 1);
1042 ContactLine.Append(wxSPropertyNextLine);
1047 ExtraLineSeek = FALSE;
1053 ContactLineLen = ContactLine.Len();
1055 // Make sure we are not in quotation mode.
1056 // Make sure colon does not have \ or \\ before it.
1058 for (int i = 0; i <= ContactLineLen; i++){
1060 if ((ContactLine.Mid(i, 1) == wxT(";") || ContactLine.Mid(i, 1) == wxT(":")) && PropertyFind == TRUE){
1062 PropertyFind = FALSE;
1064 } else if (PropertyFind == TRUE){
1066 wxSProperty.Append(ContactLine.Mid(i, 1));
1070 if (ContactLine.Mid(i, 1) == wxT("\"")){
1072 if (QuoteMode == TRUE){
1084 if (ContactLine.Mid(i, 1) == wxT(":") && ContactLine.Mid((i - 1), 1) != wxT("\\") && QuoteMode == FALSE){
1086 QuoteBreakPoint = i;
1093 // Split that line at the point into two variables (ignore the colon).
1095 wxSPropertySeg1 = ContactLine.Mid(0, QuoteBreakPoint);
1096 wxSPropertySeg2 = ContactLine.Mid((QuoteBreakPoint + 1));
1098 // Insert both into the vCard data file.
1100 Person.AddRaw(wxSPropertySeg1, wxSPropertySeg2);
1103 PropertyFind = TRUE;
1104 ExtraLineSeek = TRUE;
1106 QuoteBreakPoint = 0;
1107 ContactLine.Clear();
1108 wxSProperty.Clear();
1112 OldSessionID = SessionID;
1113 SessionID = wxString::Format(wxT("%i"), rand() % 32768);
1114 LoadContactData(&Person, htmContactData, SessionID, OldSessionID, &MemoryFileList, ContactBackgroundColour);
1115 ActiveFilename = ContactsFileIndex[ContactSeekNum];
1119 void frmMain::ShowContactEditorNew( wxCommandEvent& event )
1122 // Open a contact editor window to write a new contact with.
1124 // Check if there is an account selected and if not
1125 // return immediately.
1127 if (ActiveAccount.IsEmpty()){
1133 // Check if the account type is a valid account type, otherwise
1134 // display an error message.
1136 if (ActiveAccountType != "CardDAV" && ActiveAccountType != "carddav" &&
1137 ActiveAccountType != "Local" && ActiveAccountType != "local"){
1139 wxMessageBox(_("Cannot add a new contact as the account type is unsupported."), _("Unsupported account type"), wxICON_ERROR);
1144 // Add Pointer to SetupPointers for the ETagDB.
1146 wxMemoryInputStream istream(bigimgs_contactpersonicon48_png, sizeof(bigimgs_contactpersonicon48_png));
1147 wxImage bigimgs_contactpersonicon48i(istream, wxBITMAP_TYPE_PNG);
1148 wxBitmap contacticonbmp(bigimgs_contactpersonicon48i, -1);
1150 contacticon.CopyFromBitmap(contacticonbmp);
1152 frmContactEditor *ContactEditor = new frmContactEditor( this );
1156 ContactEditor->SetUID(WindowMenuItemID);
1158 WindowData *WData = new WindowData;
1160 WData->DataType = 1;
1161 WData->WindowPointer = (void*)ContactEditor;
1162 WData->WindowID = WindowMenuItemID;
1164 wxCommandEvent addevent(WINDOW_ADD);
1165 addevent.SetClientData(WData);
1166 wxPostEvent(this, addevent);
1168 frmActivityMgr *frameActMgr = static_cast<frmActivityMgr*>(ActMgrPtr);
1169 ContactEditor->SetupHeaders();
1170 ContactEditor->SetupContact(ActiveAccount);
1171 ContactEditor->SetIcon(contacticon);
1172 ContactEditor->SetupPointers(frameActMgr, &ETagProcTimer, this);
1173 ContactEditor->Show(true);
1177 void frmMain::ShowContactEditorEdit( wxCommandEvent& event )
1180 // Open a contact editor window for editing an existing contact
1183 // Check if there is an account selected and if not
1184 // return immediately.
1186 int DataCheck = event.GetInt();
1188 if (ActiveAccount.IsEmpty() && DataCheck == 0){
1194 wxMemoryInputStream istream(bigimgs_contactpersonicon48_png, sizeof(bigimgs_contactpersonicon48_png));
1195 wxImage bigimgs_contactpersonicon48i(istream, wxBITMAP_TYPE_PNG);
1196 wxBitmap contacticonbmp(bigimgs_contactpersonicon48i, -1);
1198 contacticon.CopyFromBitmap(contacticonbmp);
1200 // Check if a contact has been selected.
1202 long intSelected = -1;
1203 long intContactSeekNum = -1;
1205 intSelected = lstContacts->GetNextItem(intSelected,
1207 wxLIST_STATE_SELECTED);
1209 if (intSelected == -1){
1215 intContactSeekNum = lstContacts->GetItemData(intSelected);
1217 // Get the filename of the selected contact.
1219 frmActivityMgr *frameActMgr = static_cast<frmActivityMgr*>(ActMgrPtr);
1220 frmContactEditor *ContactEditor = new frmContactEditor( this );
1224 ContactEditor->SetUID(WindowMenuItemID);
1226 WindowData *WData = new WindowData;
1228 WData->DataType = 1;
1229 WData->WindowPointer = (void*)ContactEditor;
1230 WData->WindowID = WindowMenuItemID;
1232 wxCommandEvent addevent(WINDOW_ADD);
1233 addevent.SetClientData(WData);
1234 wxPostEvent(this, addevent);
1236 ContactEditor->SetupPointers(frameActMgr, &ETagProcTimer, this);
1237 ContactEditor->SetupHeaders();
1239 if (ActiveAccountType != "CardDAV" && ActiveAccountType != "carddav" &&
1240 ActiveAccountType != "Local" && ActiveAccountType != "local"){
1242 ContactEditor->SetupAccountData(true);
1246 // Check if pointer is NULL (not from the search forms) or not.
1248 if (DataCheck == 0){
1250 ContactEditor->LoadContact(ContactsFileIndex[intContactSeekNum]);
1251 ContactEditor->SetupContact(ActiveAccount);
1255 UCNotif *uc = (UCNotif*)event.GetClientData();
1259 ContactEditor->SetupContact(ActiveAccount);
1260 ContactEditor->LoadContact(ContactsFileIndex[intContactSeekNum]);
1264 ContactEditor->SetupContact(uc->ContactAccount);
1265 ContactEditor->LoadContact(uc->ContactFilename);
1274 ContactEditor->SetIcon(contacticon);
1275 ContactEditor->Show(true);
1279 void frmMain::RefreshAddressBook( wxCommandEvent& event ){
1281 // Refresh the address book data.
1283 // Check if ActiveAccount is empty. If not then check if
1284 // account type is not local otherwise continue.
1286 if (!ActiveAccount.IsEmpty()){
1288 if (ActiveAccountType == wxT("CardDAV") || ActiveAccountType == wxT("carddav")){
1290 // Account type is not local.
1292 frmActivityMgr *frameActMgr = static_cast<frmActivityMgr*>(ActMgrPtr);
1293 frameActMgr->AddTask(3, wxT(""), ActiveAccount,
1294 wxT(""), wxT(""), wxT(""), wxT(""));
1298 wxMessageBox(_("The refresh address book command is not supported with this type of account."), wxT("Not supported"), wxICON_ERROR);
1306 void frmMain::OpenContactInfoList( wxListEvent& event )
1309 // Open the contact information window.
1311 wxStringTokenizer vcardfileline;
1314 wxString setname, setvalue;
1318 long intSelected = -1;
1319 long intContactSeekNum = -1;
1321 intSelected = lstContacts->GetNextItem(intSelected,
1323 wxLIST_STATE_SELECTED);
1325 intContactSeekNum = lstContacts->GetItemData(intSelected);
1327 if (intContactSeekNum == -1){
1333 Person.LoadFile(ContactsFileIndex[intContactSeekNum]);
1335 wxMemoryInputStream istream(bigimgs_contactpersonicon48_png, sizeof(bigimgs_contactpersonicon48_png));
1336 wxImage bigimgs_contactpersonicon48i(istream, wxBITMAP_TYPE_PNG);
1337 wxBitmap contacticonbmp(bigimgs_contactpersonicon48i, -1);
1339 contacticon.CopyFromBitmap(contacticonbmp);
1341 frmContact *Contact = new frmContact( this );
1343 // Add to window list.
1347 Contact->SetUID(WindowMenuItemID);
1349 WindowData *WData = new WindowData;
1351 WData->DataType = 0;
1352 WData->WindowPointer = (void*)Contact;
1353 WData->WindowID = WindowMenuItemID;
1355 wxCommandEvent addevent(WINDOW_ADD);
1356 addevent.SetClientData(WData);
1357 wxPostEvent(this, addevent);
1359 Contact->SetupPointers(&MemoryFileList);
1360 Contact->SetBackgroundColour(ContactBackgroundColour.GetAsString(wxC2S_CSS_SYNTAX));
1361 Contact->SetupContactData(&Person);
1363 Contact->SetIcon(contacticon);
1364 Contact->Show(true);
1368 void frmMain::OpenContactInfoList( wxCommandEvent& event ){
1370 // Open a list of contact information windows.
1373 OpenContactInfoList(pevent);
1377 void frmMain::OpenContactInfo( wxCommandEvent& event )
1380 // Open the contact information window.
1382 UCNotif *uc = (UCNotif*)event.GetClientData();
1384 wxStringTokenizer vcardfileline;
1387 wxString setname, setvalue;
1391 Person.LoadFile(uc->ContactFilename);
1393 wxMemoryInputStream istream(bigimgs_contactpersonicon48_png, sizeof(bigimgs_contactpersonicon48_png));
1394 wxImage bigimgs_contactpersonicon48i(istream, wxBITMAP_TYPE_PNG);
1395 wxBitmap contacticonbmp(bigimgs_contactpersonicon48i, -1);
1397 contacticon.CopyFromBitmap(contacticonbmp);
1399 frmContact *Contact = new frmContact( this );
1401 // Add to window list.
1405 Contact->SetUID(WindowMenuItemID);
1407 WindowData *WData = new WindowData;
1409 WData->DataType = 0;
1410 WData->WindowPointer = (void*)Contact;
1411 WData->WindowID = WindowMenuItemID;
1413 wxCommandEvent addevent(WINDOW_ADD);
1414 addevent.SetClientData(WData);
1415 wxPostEvent(this, addevent);
1417 Contact->SetupPointers(&MemoryFileList);
1418 Contact->SetBackgroundColour(ContactBackgroundColour.GetAsString(wxC2S_CSS_SYNTAX));
1419 Contact->SetupContactData(&Person);
1421 Contact->SetIcon(contacticon);
1422 Contact->Show(true);
1427 void frmMain::LoadPreferences( wxActivateEvent& event)
1430 // Load the preferences.
1432 this->LoadPreferences(true);
1436 void frmMain::LoadPreferences(bool skipWindowSizeReload){
1438 // Load the preferences.
1440 wxString preffilename = GetUserPrefDir();
1442 XABPreferences preferences(preffilename);
1444 // Clear the active account/filename information and account list.
1447 ActiveAccountType = "";
1448 ActiveFilename = "";
1449 lstContacts->DeleteAllItems();
1451 // Setup the main window position (if needed).
1453 bool SaveWindowPos = preferences.GetBoolData(wxT("SaveWindowPosition"));
1454 bool HideLocalABs = preferences.GetBoolData(wxT("HideLocalAddressBooks"));
1455 bool UseBackgroundContactColour = preferences.GetBoolData(wxT("UseBackgroundContactColour"));
1457 if (SaveWindowPos == true && skipWindowSizeReload == false){
1459 this->SetSize(preferences.GetMainWindowData());
1463 if (UseBackgroundContactColour == true){
1465 ContactBackgroundColour = preferences.GetBackgroundContactColourData();
1469 ContactBackgroundColour = wxTransparentColour;
1473 treAccounts->DeleteAllItems();
1475 wxTreeItemId RootNode = treAccounts->AddRoot(wxT("Root Item"), AccountNoneID);
1477 // Stop all account timers and remove the accounts.
1479 for (std::map<wxString, wxAccountSyncTimer*>::iterator iter = AccountSyncTimers.begin();
1480 iter != AccountSyncTimers.end(); iter++){
1482 wxAccountSyncTimer *AccTmrPtr = iter->second;
1490 #if defined(__WIN32__)
1492 for (std::map<int, PCCERT_CONTEXT>::iterator CertificateIter = AccountCertificateData.begin();
1493 CertificateIter != AccountCertificateData.end(); CertificateIter++){
1495 CertFreeCertificateContext(CertificateIter->second);
1499 AccountCertificateData.clear();
1503 AccountSyncTimers.clear();
1506 wxString AccDirFull;
1507 wxString AccDirFullSfx;
1509 wxString AccDirFinal;
1510 AccountAccDirList.clear();
1511 AccountGroupList.clear();
1512 AccountGroupFilename.clear();
1513 AccountGroupTreeId.clear();
1514 wxTreeItemId AccountTreeId;
1515 wxTreeItemId GroupTreeId;
1518 // Relaod the accounts for the ETagProcTimer.
1520 ETagProcTimer.ReloadAccounts();
1522 for (int i = 0; i < preferences.accounts.GetCount(); i++){
1524 if ((preferences.accounts.GetAccountType(i) == wxT("Local") ||
1525 preferences.accounts.GetAccountType(i) == wxT("local")) && HideLocalABs == true){
1531 if (preferences.accounts.GetAccountDirectory(i).IsEmpty()){
1537 AccDir = preferences.accounts.GetAccountDirectory(i);
1538 AccDirFull = preferences.accounts.GetAccountDirectory(i);
1540 AccDirFull.Append(wxT("."));
1541 AccDirFullSfx.Append(preferences.accounts.GetAccountType(i));
1542 AccDirFullSfx.LowerCase();
1543 AccDirFullSfx.Trim();
1544 AccDirFull.Append(AccDirFullSfx);
1545 AccName = preferences.accounts.GetAccountName(i);
1547 AccountAccDirList.insert(std::make_pair(i, AccDirFull));
1549 if (preferences.accounts.GetAccountType(i) == wxT("CardDAV") ||
1550 preferences.accounts.GetAccountType(i) == wxT("carddav")){
1552 // TODO: Check if the directory exists before doing anything.
1556 // Add a new timer using the existing account details.
1558 wxAccountSyncTimer *ActTmrPtr = new wxAccountSyncTimer;
1560 ActTmrPtr->SetupData(AccDirFull, AccName);
1561 ActTmrPtr->SetupPointers(this, ActMgrPtr, ETagProcTimer.GetPointer(AccDirFull));
1562 ActTmrPtr->Start((int)(preferences.accounts.GetAccountRefresh(i) * 1000));
1563 ActTmrPtr->SetOwner(this);
1564 ActTmrPtr->Notify();
1566 // Add the timer to the list of timers.
1568 AccountSyncTimers.insert(std::make_pair(AccDirFull, ActTmrPtr));
1570 AccountTreeId = treAccounts->AppendItem(RootNode, preferences.accounts.GetAccountName(i), AccountNetID, -1);
1572 } else if (preferences.accounts.GetAccountType(i) == wxT("Local") ||
1573 preferences.accounts.GetAccountType(i) == wxT("local")) {
1575 AccountTreeId = treAccounts->AppendItem(RootNode, preferences.accounts.GetAccountName(i), AccountID, -1);
1579 AccountTreeId = treAccounts->AppendItem(RootNode, preferences.accounts.GetAccountName(i), AccountUnsupportedID, -1);
1583 // Go through the account directory and find contact files with
1584 // 'KIND:group' set and add them to the list of groups for the account.
1586 AccDirFinal = GetAccountDir(AccDirFull, FALSE);
1588 wxDir vcardaccdir(AccDirFinal);
1590 wxString vCardFilename;
1591 wxString vCardDataString;
1592 wxString vCardFilenameFull;
1594 bool ProcFiles = vcardaccdir.GetFirst(&vCardFilename, wxEmptyString, wxDIR_FILES);
1598 if (vCardFilename.Right(4) == wxT(".vcf") ||
1599 vCardFilename.Right(4) == wxT(".VCF") ||
1600 vCardFilename.Right(5) == wxT(".vcard") ||
1601 vCardFilename.Right(5) == wxT(".VCARD")){
1605 vCardFilenameFull.Append(AccDirFinal);
1606 vCardFilenameFull.Append(wxT("/"));
1607 vCardFilenameFull.Append(vCardFilename);
1609 Person.LoadFile(vCardFilenameFull);
1611 if (Person.MeetBaseSpecification()){
1613 vCardDataString = Person.Get(wxT("KIND"));
1615 if (vCardDataString == wxT("group")){
1617 // The vCard kind is a group. Add to the account's group list.
1619 GroupTreeId = treAccounts->AppendItem(AccountTreeId, Person.Get(wxT("FN")), AccountGrpID, -1);
1620 treAccounts->SetItemHasChildren(AccountTreeId, TRUE);
1621 AccountGroupList.insert(std::make_pair(intGroupID, i));
1622 AccountGroupFilename.insert(std::make_pair(intGroupID, vCardFilenameFull));
1623 AccountGroupTreeId.insert(std::make_pair(GroupTreeId, intGroupID));
1633 vCardFilename.Clear();
1634 vCardFilenameFull.Clear();
1635 vCardDataString.Clear();
1636 ProcFiles = vcardaccdir.GetNext(&vCardFilename);
1640 // Clearup for next account.
1644 AccDirFullSfx.clear();
1645 AccDirFinal.clear();
1650 // Load the account settings as they are needed for connecting
1653 prefaccounts = preferences.accounts;
1657 void frmMain::ConflictResolution(wxCommandEvent& event){
1659 // Display the conflict resolution window.
1661 frmConflictResolution *frameCR = new frmConflictResolution ( this );
1662 vCardConflictObj *vCardConfObj = (vCardConflictObj*)event.GetClientData();
1663 vCard *ClientDataPtr = vCardConfObj->vCardLocalData;
1664 vCard *ServerDataPtr = vCardConfObj->vCardServerData;
1665 frameCR->LoadData(ClientDataPtr, ServerDataPtr, &MemoryFileList, ContactBackgroundColour.GetAsString(wxC2S_CSS_SYNTAX));
1666 frameCR->ShowModal();
1668 int FinalConflictResult = frameCR->GetResult();
1670 wxCommandEvent event2(ACTMGR_RESUMEPROC);
1671 event2.SetClientData(vCardConfObj->QRNotifData);
1672 event2.SetInt(FinalConflictResult);
1677 frmActivityMgr *frameActMgr = static_cast<frmActivityMgr*>(ActMgrPtr);
1678 wxPostEvent(frameActMgr, event2);
1682 void frmMain::UpdateContactList(wxCommandEvent& event){
1684 // Update the contact list in the main window.
1686 UCNotif *ucd = (UCNotif*)event.GetClientData();
1688 // Check if the active account is being displayed in the
1689 // main window. If not, skip and delete the data.
1691 long longSelected = -1;
1692 int intSelectedData = 0;
1694 if (ActiveAccount == ucd->ContactAccount){
1696 // Look at the list of contacts and if it matches the
1697 // filename then update the name.
1701 longSelected = lstContacts->GetNextItem(longSelected,
1703 wxLIST_STATE_DONTCARE);
1705 if (longSelected == -1){
1711 intSelectedData = (int)lstContacts->GetItemData(longSelected);
1713 if (ucd->ContactFilename == ContactsFileIndex[intSelectedData]){
1715 // Work out which sorting mode we are in.
1719 // First Name, Last Name.
1721 if (ucd->ContactNameArray.Forename == wxT("") && ucd->ContactNameArray.Surname == wxT(""))
1723 lstContacts->SetItem(longSelected, 0, ucd->ContactName);
1727 lstContacts->SetItem(longSelected, 0, ucd->ContactNameArray.Forename + wxT(" ") + ucd->ContactNameArray.Surname);
1730 } else if (SortMode == 2){
1732 // Last Name, First Name.
1734 if (ucd->ContactNameArray.Forename == wxT("") && ucd->ContactNameArray.Surname == wxT(""))
1736 lstContacts->SetItem(longSelected, 0, wxT(", ") + ucd->ContactName);
1740 lstContacts->SetItem(longSelected, 0, ucd->ContactNameArray.Surname + wxT(", ") + ucd->ContactNameArray.Forename);
1743 } else if (SortMode == 3){
1747 if (ucd->ContactNickname == wxT(""))
1749 lstContacts->SetItem(longSelected, 0, _("(no nickname)"));
1753 lstContacts->SetItem(longSelected, 0, ucd->ContactNickname);
1756 } else if (SortMode == 4){
1760 lstContacts->SetItem(longSelected, 0, ucd->ContactName);
1767 // If the filename is the one loaded into the
1768 // browser control, then update this too.
1770 if (ActiveFilename == ContactsFileIndex[intSelectedData]){
1772 wxListEvent nullevent;
1773 ShowContactInfo(nullevent);
1781 for (std::map<int, void*>::iterator WindowIter = WindowListPointers.begin();
1782 WindowIter != WindowListPointers.end(); WindowIter++){
1784 if (WindowListType[WindowIter->first] != 0){
1790 frmContact *frmContactPtr = static_cast<frmContact*>(WindowIter->second);
1792 if (frmContactPtr->GetFilename() == ucd->ContactFilename){
1794 vCard UpdatedPerson;
1795 UpdatedPerson.LoadFile(ucd->ContactFilename);
1796 frmContactPtr->SetBackgroundColour(ContactBackgroundColour.GetAsString(wxC2S_CSS_SYNTAX));
1797 frmContactPtr->SetupContactData(&UpdatedPerson);
1803 // Send message to search window controller subroutine and
1804 // pass that notification onto the search windows.
1806 // Setup the new pointer to use the existing UCNotif without
1809 UCNotif *ucd2 = ucd;
1811 wxCommandEvent sup(SE_UPDATECONTACTNOTIF);
1812 sup.SetClientData(ucd2);
1813 wxPostEvent(this, sup);
1815 // Clear up the unused pointer.
1821 void frmMain::SetupPointers(void *ActMgrPtrInc){
1823 // Setup the pointers for the main window.
1825 ActMgrPtr = ActMgrPtrInc;
1829 void frmMain::SetupForm(){
1831 frmActivityMgr *frameActMgr = static_cast<frmActivityMgr*>(ActMgrPtr);
1832 frameActMgr->SetupPointers(&ETagProcTimer, this);
1834 // Setup the contact information icons for later.
1836 wxFileSystem::AddHandler(new wxMemoryFSHandler);
1840 wxMemoryInputStream ciptostream(icons_cipto_png, sizeof(icons_cipto_png));
1841 ciicon_png.LoadFile(ciptostream, wxBITMAP_TYPE_PNG);
1842 wxMemoryFSHandler::AddFile(wxT("cipto.png"), ciicon_png, wxBITMAP_TYPE_PNG);
1844 wxMemoryInputStream cilogstream(icons_cilog_png, sizeof(icons_cilog_png));
1845 ciicon_png.LoadFile(cilogstream, wxBITMAP_TYPE_PNG);
1846 wxMemoryFSHandler::AddFile(wxT("cilog.png"), ciicon_png, wxBITMAP_TYPE_PNG);
1848 wxMemoryInputStream cisndstream(icons_cisnd_png, sizeof(icons_cisnd_png));
1849 ciicon_png.LoadFile(cisndstream, wxBITMAP_TYPE_PNG);
1850 wxMemoryFSHandler::AddFile(wxT("cisnd.png"), ciicon_png, wxBITMAP_TYPE_PNG);
1852 wxMemoryInputStream cikeystream(icons_cikey_png, sizeof(icons_cikey_png));
1853 ciicon_png.LoadFile(cikeystream, wxBITMAP_TYPE_PNG);
1854 wxMemoryFSHandler::AddFile(wxT("cikey.png"), ciicon_png, wxBITMAP_TYPE_PNG);
1856 wxMemoryInputStream civenstream(icons_civen_png, sizeof(icons_civen_png));
1857 ciicon_png.LoadFile(civenstream, wxBITMAP_TYPE_PNG);
1858 wxMemoryFSHandler::AddFile(wxT("civen.png"), ciicon_png, wxBITMAP_TYPE_PNG);
1860 wxMemoryInputStream ciextstream(icons_ciext_png, sizeof(icons_ciext_png));
1861 ciicon_png.LoadFile(ciextstream, wxBITMAP_TYPE_PNG);
1862 wxMemoryFSHandler::AddFile(wxT("ciext.png"), ciicon_png, wxBITMAP_TYPE_PNG);
1864 LoadPreferences(false);
1868 void frmMain::UpdateSearchContactLists(wxCommandEvent& event){
1870 // Update the contact lists in the search windows.
1872 // Go through each of the search windows and
1873 // send the required notification to update the
1874 // contact information.
1876 // Get the event notification data.
1878 UCNotif *ucd = (UCNotif*)event.GetClientData();
1880 // Process each search window giving the new details.
1882 for (std::map<void*,wxString>::iterator switer = SearchWindowList.begin();
1883 switer != SearchWindowList.end(); switer++){
1885 // Duplicate the event notification data.
1887 UCNotif *ucd2 = new UCNotif;
1889 ucd2->ContactAccount = ucd->ContactAccount;
1890 ucd2->ContactFilename = ucd->ContactFilename;
1891 ucd2->ContactName = ucd->ContactName;
1892 ucd2->ContactNickname = ucd->ContactNickname;
1893 ucd2->ContactNameArray = ucd->ContactNameArray;
1895 // Pass the data to the search window for processing.
1897 frmSearch *frameSCH = static_cast<frmSearch*>(switer->first);
1898 wxCommandEvent schupdate(SE_UPDATERESULT);
1899 schupdate.SetClientData(ucd2);
1900 wxPostEvent(frameSCH, schupdate);
1902 // Clear up the pointer prior to variable deletion.
1913 void frmMain::OpenFindContactsWindow(wxCommandEvent& event){
1915 // Open a new search window.
1919 frmSearch *frameSCH = new frmSearch ( this );
1920 frameSCH->SetUID(WindowMenuItemID);
1921 frameSCH->Show(true);
1923 WindowData *WData = new WindowData;
1925 WData->DataType = 2;
1926 WData->WindowPointer = (void*)frameSCH;
1927 WData->WindowID = WindowMenuItemID;
1929 wxCommandEvent addevent(WINDOW_ADD);
1930 addevent.SetClientData(WData);
1931 wxPostEvent(this, addevent);
1933 // Add pointer to the list of open search windows.
1935 SearchWindowList.insert(std::make_pair(frameSCH, wxT("Search")));
1941 void frmMain::RemoveContactsWindowPointer(wxCommandEvent& event){
1943 // Remove the pointer for a contact window from the
1946 void *frameSCH = (void*)event.GetClientData();
1948 SearchWindowList.erase(frameSCH);
1954 void frmMain::RemoveContactEditorWindowPointer(wxCommandEvent& event){
1956 // Remove the pointer for a contact editor window from
1959 void *frameSCH = (void*)event.GetClientData();
1961 SearchWindowList.erase(frameSCH);
1967 void frmMain::RevealContact(wxCommandEvent& event){
1969 // Reveal a contact in the main window.
1971 UCNotif *uc = (UCNotif*)event.GetClientData();
1973 // Switch the account to the one passed.
1975 wxTreeItemIdValue cookie;
1976 wxTreeItemId next = treAccounts->GetRootItem();
1977 wxTreeItemId nextChild;
1979 for (int i = 0; i < prefaccounts.GetCount(); i++){
1982 nextChild = treAccounts->GetFirstChild(next, cookie);
1984 nextChild = treAccounts->GetNextSibling(nextChild);
1987 if (uc->ContactAccount == AccountAccDirList[i]){
1989 treAccounts->SelectItem(nextChild, TRUE);
1990 AccCtrl->SetText(treAccounts->GetItemText(nextChild));
1996 // Switch the contact to the one passed.
1998 long longSelected = -1;
1999 int intSelectedData = 0;
2003 longSelected = lstContacts->GetNextItem(longSelected,
2005 wxLIST_STATE_DONTCARE);
2007 if (longSelected == -1){
2013 intSelectedData = (int)lstContacts->GetItemData(longSelected);
2015 // Compare the filename with the one received.
2016 // If they match then select it.
2018 if (ContactsFileIndex[intSelectedData] == uc->ContactFilename){
2022 lstContacts->SetItemState(longSelected, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
2023 lstContacts->EnsureVisible(longSelected);
2027 lstContacts->SetItemState(longSelected, 0, wxLIST_STATE_SELECTED);
2035 void frmMain::DeleteContact(wxCommandEvent& event){
2037 // Delete a contact from the main window.
2039 // Check if a contact is selected.
2041 long intSelected = -1;
2042 long intContactSeekNum = -1;
2043 wxString wxSContactName;
2045 intSelected = lstContacts->GetNextItem(intSelected,
2047 wxLIST_STATE_SELECTED);
2049 if (intSelected == -1){
2053 // Check if the account type is a valid account type, otherwise
2054 // display an error message.
2056 if (ActiveAccountType != "CardDAV" && ActiveAccountType != "carddav" &&
2057 ActiveAccountType != "Local" && ActiveAccountType != "local"){
2059 wxMessageBox(_("Cannot delete contact as the account type is unsupported."), _("Unsupported account type"), wxICON_ERROR);
2064 frmActivityMgr *frameActMgr = static_cast<frmActivityMgr*>(ActMgrPtr);
2066 // Get the item data of the contact.
2068 intContactSeekNum = lstContacts->GetItemData(intSelected);
2070 // Get the name of the contact.
2072 wxSContactName = lstContacts->GetItemText(intSelected);
2074 // Display a message confirming if the contact should
2077 int QuestionResponse;
2079 QuestionResponse = wxMessageBox(_("Are you sure you want to delete this contact?"), _("Delete contact"), wxYES_NO, this);
2081 if (QuestionResponse == wxNO){
2083 // Exit the subroutine
2089 // Delete the contact.
2091 if (!wxRemoveFile(ContactsFileIndex[intContactSeekNum])){
2093 wxMessageBox(_("Unable to delete the contact."), _("Cannot delete contact"), wxOK, this);
2098 // Remove the contact from the list.
2100 lstContacts->DeleteItem(intSelected);
2102 // Update the search windows, removing the deleted
2105 UCNotif *ucd = new UCNotif;
2107 ucd->ContactAccount = ActiveAccount;
2108 ucd->ContactFilename = ContactsFileIndex[intContactSeekNum];
2110 for (std::map<void*,wxString>::iterator switer = SearchWindowList.begin();
2111 switer != SearchWindowList.end(); switer++){
2113 // Duplicate the event notification data.
2115 UCNotif *ucd2 = new UCNotif;
2117 ucd2->ContactAccount = ucd->ContactAccount;
2118 ucd2->ContactFilename = ucd->ContactFilename;
2120 // Pass the data to the search window for processing.
2122 frmSearch *frameSCH = static_cast<frmSearch*>(switer->first);
2123 wxCommandEvent schdelete(SE_DELETERESULT);
2124 schdelete.SetClientData(ucd2);
2125 wxPostEvent(frameSCH, schdelete);
2127 // Clear up the pointer prior to variable deletion.
2134 // Clear the wxHTMLWindow.
2136 wxString EmptyPage = wxT("");
2138 htmContactData->SetPage(EmptyPage);
2140 wxStringTokenizer wSTFilename(ContactsFileIndex[intContactSeekNum], wxT("/"));
2142 wxString wxSplitFilename;
2143 wxString wxSDataURL;
2145 while(wSTFilename.HasMoreTokens()){
2147 wxSplitFilename = wSTFilename.GetNextToken();
2151 if (ActiveAccountType == wxT("CardDAV") || ActiveAccountType == wxT("carddav")){
2153 // Update the ETagDB and mark it as deleted.
2155 ETagDB *ETagDBPtr = ETagProcTimer.GetPointer(ActiveAccount);
2157 ETagDBPtr->UpdateETag(wxSplitFilename, wxT("DELETED"));
2159 // Get the Data URL.
2161 wxTreeItemIdValue cookie;
2162 wxTreeItemId next = treAccounts->GetRootItem();
2164 wxTreeItemId selectedChild = treAccounts->GetSelection();
2165 wxTreeItemId nextChild;
2167 for (int i = 0; i < prefaccounts.GetCount(); i++){
2170 nextChild = treAccounts->GetFirstChild(next, cookie);
2172 nextChild = treAccounts->GetNextSibling(nextChild);
2175 if (nextChild == selectedChild){
2177 wxSDataURL = prefaccounts.GetAccountDirPrefix(i) + wxT("/") + wxSplitFilename;
2184 // Add task to the activity monitor to delete the contact.
2186 frameActMgr->AddTask(2, wxSContactName, ActiveAccount, wxSDataURL, wxSplitFilename, ContactsFileIndex[intContactSeekNum], wxT(""));
2190 // Clear the variable. Don't delete as it will mess things up.
2192 ContactsFileIndex[intContactSeekNum] = wxT("");
2199 void frmMain::EmptyServerDialog(wxCommandEvent& event){
2201 // Display this message when the server information has changed
2204 QRNotif *qrn = (QRNotif *)event.GetClientData();
2206 int QResponse = wxMessageBox(_("The list of contacts on the server is empty. Upload all locally stored contacts for this account now?"), _("No contacts on server"), wxYES_NO, this);
2208 if (QResponse == wxNO){
2214 wxCommandEvent event2(ACTMGR_RESUMEPROC);
2215 event2.SetInt(*qrn->QResponse);
2216 event2.SetClientData(qrn->PausePtr);
2218 frmActivityMgr *frameActMgr = static_cast<frmActivityMgr*>(ActMgrPtr);
2220 wxPostEvent(frameActMgr, event2);
2224 void frmMain::DeleteContactSync(wxString &Account, wxString &Filename){
2226 // Remove the contact from the window after syncronising.
2228 // Check which account is currently active in the window.
2229 // If it is different from the one passed to this subroutine then
2230 // exit from the subroutine.
2232 if (Account != ActiveAccount){
2236 long longSelected = -1;
2237 int intSelectedData = 0;
2241 longSelected = lstContacts->GetNextItem(longSelected,
2243 wxLIST_STATE_DONTCARE);
2245 if (longSelected == -1){
2251 intSelectedData = (int)lstContacts->GetItemData(longSelected);
2253 // Compare the filename with the one received.
2254 // If they match then select it.
2256 if (ContactsFileIndex[intSelectedData] == Filename){
2258 // Remove the contact from the window.
2260 lstContacts->DeleteItem(intSelectedData);
2262 // Check if contact is the selected contact in the HTML window and
2263 // if it is then clear the window.
2265 if (ActiveFilename == Filename){
2267 wxString EmptyPage = wxT("");
2268 htmContactData->SetPage(EmptyPage);
2282 void frmMain::SortFNLN( wxCommandEvent& event ) {
2284 // Sort first name then last name.
2286 wxTreeEvent NullEvent;
2288 LoadContactList(NullEvent);
2292 void frmMain::SortLNFN( wxCommandEvent& event ) {
2294 // Sort last name then first name.
2296 wxTreeEvent NullEvent;
2298 LoadContactList(NullEvent);
2302 void frmMain::SortNickname( wxCommandEvent& event ) {
2304 // Sort by nickname.
2306 wxTreeEvent NullEvent;
2308 LoadContactList(NullEvent);
2312 void frmMain::SortDisplayAs( wxCommandEvent& event ) {
2314 // Sort by Display As name.
2316 wxTreeEvent NullEvent;
2318 LoadContactList(NullEvent);
2322 void frmMain::SortAscending( wxCommandEvent& event ) {
2326 wxTreeEvent NullEvent;
2327 AscendingMode = TRUE;
2328 LoadContactList(NullEvent);
2332 void frmMain::SortDescending( wxCommandEvent& event ) {
2336 wxTreeEvent NullEvent;
2337 AscendingMode = FALSE;
2338 LoadContactList(NullEvent);
2342 void frmMain::ToggleStatusBar( wxCommandEvent& event ) {
2344 // Toggle the appearance of the status bar.
2346 if (stbBottom->IsShown() == TRUE){
2360 void frmMain::ActivityIconStart( wxCommandEvent& event ){
2362 // Display the activity icon.
2364 imgActivityStatus->SetBitmap(*imgActIcon1);
2365 ActivityIconStatus = 0;
2369 void frmMain::ActivityIconShuffle( wxCommandEvent& event ){
2371 // Shuffle through the activity icons.
2373 switch (ActivityIconStatus){
2376 imgActivityStatus->SetBitmap(*imgActIcon1);
2377 ActivityIconStatus = 1;
2380 imgActivityStatus->SetBitmap(*imgActIcon2);
2381 ActivityIconStatus = 2;
2384 imgActivityStatus->SetBitmap(*imgActIcon3);
2385 ActivityIconStatus = 3;
2388 imgActivityStatus->SetBitmap(*imgActIcon4);
2389 ActivityIconStatus = 0;
2392 ActivityIconStatus = 0;
2398 void frmMain::ActivityIconStop( wxCommandEvent& event ){
2400 // Display the sleep icon.
2402 imgActivityStatus->SetBitmap(*imgActIconSleep);
2406 void frmMain::UpdateSBIconPlacement( wxSizeEvent& event ){
2408 // Set the placement of the status bar icons.
2410 if (imgConnStatus == 0 || imgSSLStatus == 0 || imgActivityStatus == 0){
2418 wxRect rectActivity;
2419 stbBottom->GetFieldRect(1, rectOnline);
2420 stbBottom->GetFieldRect(2, rectSSL);
2421 stbBottom->GetFieldRect(3, rectActivity);
2423 imgConnStatus->Move(rectOnline.GetX(),rectOnline.GetY());
2424 imgSSLStatus->Move(rectSSL.GetX(),rectSSL.GetY());
2425 imgActivityStatus->Move(rectActivity.GetX(),rectActivity.GetY());
2429 XABViewMode frmMain::GetViewMode(){
2431 // Set the view mode of the contact list.
2435 xvm.SortMode = SortMode;
2436 xvm.AscendingMode = AscendingMode;
2442 void frmMain::WindowAdd( wxCommandEvent &event ){
2444 // Add a window to the window list.
2446 WindowData *WData = (WindowData*)event.GetClientData();
2450 if (WData->DataType == 0){
2454 int intID = mnuContactWindows->GetId();
2456 mnuWindow->FindChildItem(intID, &pos);
2457 wxMenuItem *mnuNewItem = new wxMenuItem(NULL, WData->WindowID, wxT("Contact Window #") + wxString::Format(wxT("%i"), WData->WindowID), wxEmptyString, wxITEM_NORMAL, NULL);
2458 mnuNewItem->SetId(WData->WindowID);
2459 WindowListPointersMenu.insert(std::make_pair(WData->WindowID, mnuNewItem));
2460 WindowListPointers.insert(std::make_pair(WData->WindowID, WData->WindowPointer));
2461 WindowListType.insert(std::make_pair(WData->WindowID, 0));
2462 mnuWindow->Insert((pos + 1), mnuNewItem);
2463 this->Connect(mnuNewItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(frmMain::ShowContactWindow));
2465 } else if (WData->DataType == 1){
2467 // Contact Editor Window
2469 int intID = mnuContactEditorWindows->GetId();
2471 mnuWindow->FindChildItem(intID, &pos);
2472 wxMenuItem *mnuNewItem = new wxMenuItem(NULL, WData->WindowID, wxT("Contact Editor Window #") + wxString::Format(wxT("%i"), WData->WindowID), wxEmptyString, wxITEM_NORMAL, NULL);
2473 mnuNewItem->SetId(WData->WindowID);
2474 WindowListPointersMenu.insert(std::make_pair(WData->WindowID, mnuNewItem));
2475 WindowListPointers.insert(std::make_pair(WData->WindowID, WData->WindowPointer));
2476 WindowListType.insert(std::make_pair(WData->WindowID, 1));
2477 mnuWindow->Insert((pos + 1), mnuNewItem);
2478 this->Connect(mnuNewItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(frmMain::ShowContactEditorWindow));
2480 } else if (WData->DataType == 2){
2484 int intID = mnuSearchWindows->GetId();
2486 mnuWindow->FindChildItem(intID, &pos);
2487 wxMenuItem *mnuNewItem = new wxMenuItem(NULL, WData->WindowID, wxT("Search Window #") + wxString::Format(wxT("%i"), WData->WindowID), wxEmptyString, wxITEM_NORMAL, NULL);
2488 mnuNewItem->SetId(WData->WindowID);
2489 WindowListPointersMenu.insert(std::make_pair(WData->WindowID, mnuNewItem));
2490 WindowListPointers.insert(std::make_pair(WData->WindowID, WData->WindowPointer));
2491 WindowListType.insert(std::make_pair(WData->WindowID, 2));
2492 mnuWindow->Insert((pos + 1), mnuNewItem);
2493 this->Connect(mnuNewItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(frmMain::ShowSearchWindow));
2502 void frmMain::WindowEdit( wxCommandEvent &event ){
2504 // Edit a window in the window list.
2506 WindowData *WData = (WindowData*)event.GetClientData();
2508 if (WData->DataType == 0){
2510 // Get the window title and use that.
2512 frmContact *frmContactPtr = static_cast<frmContact*>(WData->WindowPointer);
2514 wxString WindowTitle = frmContactPtr->GetTitle();
2516 std::map<int, wxMenuItem*>::iterator MenuIter = WindowListPointersMenu.find(WData->WindowID);
2518 MenuIter->second->SetItemLabel(WindowTitle);
2520 } else if (WData->DataType == 1){
2522 // Get the window title and use that.
2524 frmContactEditor *frmCEPtr = static_cast<frmContactEditor*>(WData->WindowPointer);
2526 wxString WindowTitle = frmCEPtr->GetTitle();
2528 std::map<int, wxMenuItem*>::iterator MenuIter = WindowListPointersMenu.find(WData->WindowID);
2530 if (WindowTitle.IsEmpty()){
2532 MenuIter->second->SetItemLabel(_("Unnamed Contact"));
2536 MenuIter->second->SetItemLabel(WindowTitle);
2547 void frmMain::WindowDelete( wxCommandEvent &event ){
2549 // Delete a window from the window list.
2551 WindowData *WData = (WindowData*)event.GetClientData();
2553 std::map<int, wxMenuItem*>::iterator MenuIter = WindowListPointersMenu.find(WData->WindowID);
2555 mnuWindow->Remove(MenuIter->second);
2557 delete MenuIter->second;
2558 MenuIter->second = NULL;
2560 WindowListPointersMenu.erase(WData->WindowID);
2561 WindowListPointers.erase(WData->WindowID);
2562 WindowListType.erase(WData->WindowID);
2569 void frmMain::ShowContactWindow( wxCommandEvent &event ){
2571 // Show a contact window from the window list.
2573 std::map<int, void*>::iterator WindowIter = WindowListPointers.find(event.GetId());
2575 frmContact *frmContactPtr = static_cast<frmContact*>(WindowIter->second);
2577 frmContactPtr->Show();
2578 frmContactPtr->Raise();
2582 void frmMain::ShowContactEditorWindow( wxCommandEvent &event ){
2584 // Show a contact editor window from the window list.
2586 std::map<int, void*>::iterator WindowIter = WindowListPointers.find(event.GetId());
2588 frmContactEditor *frmCEPtr = static_cast<frmContactEditor*>(WindowIter->second);
2595 void frmMain::ShowSearchWindow( wxCommandEvent &event ){
2597 // Show a search window from the window list.
2599 std::map<int, void*>::iterator WindowIter = WindowListPointers.find(event.GetId());
2601 frmSearch *frmSearchPtr = static_cast<frmSearch*>(WindowIter->second);
2603 frmSearchPtr->Show();
2604 frmSearchPtr->Raise();
2608 void frmMain::ToggleConnectionStatus( wxCommandEvent &event ){
2610 // Toggle the online/offline connection status.
2612 frmActivityMgr *frameActMgr = static_cast<frmActivityMgr*>(ActMgrPtr);
2613 wxCommandEvent toggconn(ACTMGR_TOGGLECONN);
2614 wxPostEvent(frameActMgr, toggconn);
2618 void frmMain::ShowSSLCertificates( wxCommandEvent &event ){
2620 // Check the account type before continuing.
2622 wxString SeekAccount;
2623 wxString AccTypeLower;
2627 #if defined(__APPLE__)
2629 std::map<int, SecTrustRef>::iterator SSLTrustIter;
2631 for (int i = 0; i < prefaccounts.GetCount(); i++){
2633 SeekAccount.Append(prefaccounts.GetAccountDirectory(i));
2634 AccType.Append(prefaccounts.GetAccountType(i));
2635 AccountSSL = prefaccounts.GetAccountSSL(i);
2636 AccTypeLower = AccType.MakeLower();
2637 SeekAccount.Append(wxT("."));
2638 SeekAccount.Append(AccTypeLower);
2640 if (SeekAccount == ActiveAccount){
2642 if (AccTypeLower == wxT("local")){
2648 if (AccountSSL == false){
2654 SSLTrustIter = AccountTrustData.find(i);
2656 // Setup and display the form.
2658 DisplayCertificate(SSLTrustIter->second);
2662 SeekAccount.Clear();
2663 AccTypeLower.Clear();
2668 #elif defined(__WIN32__)
2670 std::map<int, PCCERT_CONTEXT>::iterator SSLCertificateIter;
2672 for (int i = 0; i < prefaccounts.GetCount(); i++){
2674 SeekAccount.Append(prefaccounts.GetAccountDirectory(i));
2675 AccType.Append(prefaccounts.GetAccountType(i));
2676 AccountSSL = prefaccounts.GetAccountSSL(i);
2677 AccTypeLower = AccType.MakeLower();
2678 SeekAccount.Append(wxT("."));
2679 SeekAccount.Append(AccTypeLower);
2681 if (SeekAccount == ActiveAccount){
2683 if (AccTypeLower == wxT("local")){
2689 if (AccountSSL == false){
2695 SSLCertificateIter = AccountCertificateData.find(i);
2697 // Setup and display the form.
2699 if (SSLCertificateIter->second->pCertInfo == NULL){
2701 wxMessageBox("No certificate information is available due to invalid connection details, connection being in progress or invalid certificate data received.");
2705 BOOL ModifiedCertificateData;
2706 CRYPTUI_VIEWCERTIFICATE_STRUCTW CertificateData = BuildCertificateData(SSLCertificateIter->second, (HWND)this->GetHandle());
2708 if (!CryptUIDlgViewCertificate(&CertificateData, &ModifiedCertificateData)){
2709 wxMessageBox(_("An error occured while trying to open the certificate dialog."), _("Error opening Certificate Information dialog"));
2714 //DisplayCertificate(SSLTrustIter->second);
2718 SeekAccount.Clear();
2719 AccTypeLower.Clear();
2726 std::map<int, SSLCertCollectionString>::iterator SSLColIter;
2728 for (int i = 0; i < prefaccounts.GetCount(); i++){
2730 SeekAccount.Append(prefaccounts.GetAccountDirectory(i));
2731 AccType.Append(prefaccounts.GetAccountType(i));
2732 AccountSSL = prefaccounts.GetAccountSSL(i);
2733 AccTypeLower = AccType.MakeLower();
2734 SeekAccount.Append(wxT("."));
2735 SeekAccount.Append(AccTypeLower);
2737 if (SeekAccount == ActiveAccount){
2739 if (AccTypeLower == wxT("local")){
2745 if (AccountSSL == false){
2751 SSLColIter = AccountSSLData.find(i);
2753 SSLCertCollectionString SSLCertInfo = SSLColIter->second;
2755 frmSSLCertificate *frameSSLCert = new frmSSLCertificate ( this );
2756 frameSSLCert->StartCertFrom(0);
2757 frameSSLCert->SetupCertsString(SSLCertInfo);
2758 frameSSLCert->ShowModal();
2760 delete frameSSLCert;
2761 frameSSLCert = NULL;
2765 SeekAccount.Clear();
2766 AccTypeLower.Clear();
2775 void frmMain::ShowSSLInfo( wxCommandEvent &event ){
2777 // Check the account type before continuing.
2781 void frmMain::HideSSLInfo( wxCommandEvent &event ){
2783 // Check the account type before continuing.
2787 void frmMain::UpdateConnectionStatus( wxCommandEvent &event ){
2789 if (event.GetInt() == 0){
2791 imgConnStatus->SetBitmap(*imgOnline);
2795 imgConnStatus->SetBitmap(*imgOffline);
2801 void frmMain::InvalidSSLCertificate( wxCommandEvent &event ){
2803 // Display the form for showing an invalid SSL certificate.
2805 frmInvalidSSLCertificate *frameISC = new frmInvalidSSLCertificate ( this );
2806 SSLInvalidCertNotifObj *SSLICNObj = (SSLInvalidCertNotifObj*)event.GetClientData();
2807 SSLCertCollection SSLCCData = SSLICNObj->CertCollection;
2808 wxString AccountName = SSLICNObj->AccountName;
2809 frameISC->LoadData(SSLCCData, AccountName);
2810 frameISC->ShowModal();
2812 int FinalConflictResult = frameISC->GetResult();
2814 wxCommandEvent event2(ACTMGR_RESUMEPROC);
2815 event2.SetClientData(SSLICNObj->QRNotifData);
2816 event2.SetInt(FinalConflictResult);
2821 frmActivityMgr *frameActMgr = static_cast<frmActivityMgr*>(ActMgrPtr);
2822 wxPostEvent(frameActMgr, event2);
2826 void frmMain::InvalidSSLCertificateString( wxCommandEvent &event ){
2828 // Display the form for showing an invalid SSL certificate.
2830 frmInvalidSSLCertificate *frameISC = new frmInvalidSSLCertificate ( this );
2831 SSLInvalidCertNotifObjString *SSLICNObj = (SSLInvalidCertNotifObjString*)event.GetClientData();
2832 SSLCertCollectionString SSLCCData = SSLICNObj->CertCollection;
2833 wxString AccountName = SSLICNObj->AccountName;
2834 frameISC->LoadData(SSLCCData, AccountName);
2835 frameISC->ShowModal();
2837 int FinalConflictResult = frameISC->GetResult();
2839 wxCommandEvent event2(ACTMGR_RESUMEPROC);
2840 event2.SetClientData(SSLICNObj->QRNotifData);
2841 event2.SetInt(FinalConflictResult);
2846 frmActivityMgr *frameActMgr = static_cast<frmActivityMgr*>(ActMgrPtr);
2847 wxPostEvent(frameActMgr, event2);
2851 void frmMain::PauseAllTimers(){
2853 // Pause all the account timers.
2855 for (std::map<wxString, wxAccountSyncTimer*>::iterator ASTiter = AccountSyncTimers.begin();
2856 ASTiter != AccountSyncTimers.end(); ASTiter++){
2858 ASTiter->second->Stop();
2864 void frmMain::ResumeAllTimers(){
2866 // Resume all the account timers.
2868 for (std::map<wxString, wxAccountSyncTimer*>::iterator ASTiter = AccountSyncTimers.begin();
2869 ASTiter != AccountSyncTimers.end(); ASTiter++){
2871 ASTiter->second->Start();
2877 #if defined(__APPLE__)
2879 #elif defined(__WIN32__)
2881 void frmMain::UpdateSSLAccountStatus(int AccountID, int SSLStatus, PCCERT_CONTEXT CertificateContext){
2883 // Delete existing data.
2885 std::map<int, PCCERT_CONTEXT>::iterator CertificateIter = AccountCertificateData.find(AccountID);
2887 if (CertificateIter != AccountCertificateData.end()){
2888 CertFreeCertificateContext(CertificateIter->second);
2891 AccountCertificateData.erase(AccountID);
2892 AccountSSLResult.erase(AccountID);
2896 AccountCertificateData.insert(std::make_pair(AccountID, CertificateContext));
2897 AccountSSLResult.insert(std::make_pair(AccountID, SSLStatus));
2903 void frmMain::UpdateSSLAccountStatus(int AccountID, int SSLStatus, SSLCertCollectionString SSLCertInc){
2905 // Delete existing data.
2907 AccountSSLData.erase(AccountID);
2908 AccountSSLResult.erase(AccountID);
2912 AccountSSLData.insert(std::make_pair(AccountID, SSLCertInc));
2913 AccountSSLResult.insert(std::make_pair(AccountID, SSLStatus));
2919 void frmMain::SetupSSLStatus( int AccountID ){
2921 // Check if account ID given is
2922 // the active account and if not, do nothing.
2925 wxString AccTypeLower;
2927 AccType = prefaccounts.GetAccountType(AccountID);
2928 AccTypeLower = AccType.MakeLower();
2930 wxString AccountIDName = prefaccounts.GetAccountDirectory(AccountID) + wxT(".") +
2933 if (AccountIDName != ActiveAccount){
2939 // Check the account type is a supported account type.
2941 if (AccType != "CardDAV" && AccType != "carddav" &&
2942 AccType != "Local" && AccType != "local"){
2944 SSLToolTip->SetTip(wxT("SSL is not enabled for this account"));
2945 imgSSLStatus->SetBitmap(*imgNoSSL);
2950 // Check if the account has SSL enabled.
2952 bool SSLInUse = prefaccounts.GetAccountSSL(AccountID);
2954 if (SSLInUse == FALSE){
2956 SSLToolTip->SetTip(wxT("SSL is not enabled for this account"));
2957 imgSSLStatus->SetBitmap(*imgNoSSL);
2961 // Get the SSL Collection Data.
2963 std::map<int,int>::iterator SSLResultIter = AccountSSLResult.find(AccountID);
2965 // Check if a result value has been set.
2967 if (SSLResultIter == AccountSSLResult.end()){
2969 imgSSLStatus->SetBitmap(*imgSSLWarning);
2970 SSLToolTip->SetTip(wxT("Unable to determine SSL information for the '") + prefaccounts.GetAccountName(AccountID) + wxT("' account."));
2975 if (SSLResultIter->second == 1){
2977 imgSSLStatus->SetBitmap(*imgSSLWarning);
2978 SSLToolTip->SetTip(wxT("Invalid certificate(s) received for '") +
2979 prefaccounts.GetAccountName(AccountID) +
2980 wxT("' (Connection denied by user)\n\nDouble click for more information."));
2982 } else if (SSLResultIter->second == 0){
2984 imgSSLStatus->SetBitmap(*imgSSL);
2985 SSLToolTip->SetTip(wxT("Account '") +
2986 prefaccounts.GetAccountName(AccountID) +
2987 wxT("' secured using SSL\n\nDouble click for more information."));
2995 void frmMain::CheckUpdates( wxCommandEvent& event ){
2997 // Check for updates to Xestia Address Book.
2999 frmUpdate *frameUpdate = new frmUpdate ( this );
3000 frameUpdate->FetchData();
3001 frameUpdate->ShowModal();
3005 void frmMain::OpenImportDialog( wxCommandEvent& event ){
3007 // Run the import contacts function.
3013 void frmMain::OpenExportDialog( wxCommandEvent& event ){
3015 // Check if an account and at least one contact is selected
3016 // before continuing.
3018 wxArrayString ArrData;
3020 if (ActiveAccount.IsEmpty()){
3026 int ContactSelected = 0;
3027 int ContactsCollected = 0;
3028 long longSelected = -1;
3032 longSelected = lstContacts->GetNextItem(longSelected,
3034 wxLIST_STATE_SELECTED);
3036 if (longSelected == -1){
3042 int FileID = (int)lstContacts->GetItemData(longSelected);
3044 ArrData.Insert(ContactsFileIndex[FileID],
3045 ContactsCollected, 1);
3051 if (ContactSelected == 0){
3057 // Run the export contacts system.
3059 ExportRun(this, &ArrData);
3063 void frmMain::GetListControl(wxListCtrl *lstContactsPtr,
3064 wxArrayString *ContactsFileIndexPtr){
3066 // Set the list control pointers.
3068 lstContactsPtr = lstContacts;
3069 ContactsFileIndexPtr = &ContactsFileIndex;
3073 void frmMain::GetSelectedList( wxCommandEvent& event ){
3075 // Get the array of contact filenames.
3077 wxArrayString *ArrData = (wxArrayString*)event.GetClientData();
3079 // Process them into an array of files.
3081 long longSelected = -1;
3082 int ContactsCollected = 0;
3083 wxString ContactFilename;
3087 longSelected = lstContacts->GetNextItem(longSelected,
3089 wxLIST_STATE_SELECTED);
3091 if (longSelected == -1){
3097 // Get the file information and add to the list.
3099 int FileID = (int)lstContacts->GetItemData(longSelected);
3101 ArrData->Insert(ContactsFileIndex[FileID],
3102 ContactsCollected, 1);
3104 ContactsCollected++;
3105 ContactFilename.Clear();
3113 void frmMain::SyncAccount( wxCommandEvent& event ){
3115 // Syncronise the selected account.
3117 wxString AccNameInc = event.GetString();
3119 frmActivityMgr *frameActMgr = static_cast<frmActivityMgr*>(ActMgrPtr);
3120 frameActMgr->AddTask(3, wxT(""), AccNameInc,
3121 wxT(""), wxT(""), wxT(""), wxT(""));
3125 void frmMain::ShowHelp( wxCommandEvent& event ){
3127 // Based on the operating system, work out where
3128 // the documentation should be.
3131 #if defined(__HAIKU__)
3133 #elif defined(__WIN32__)
3135 #elif defined(__APPLE__)
3136 DisplayHelpBrowser();
3140 // Get the LANG environment variable
3142 char *languageEnvironmentVariableChar = getenv("LANG");
3143 std::string languageEnvironmentVariable(languageEnvironmentVariableChar);
3145 int executeResult = 0;
3147 wxString documentPath = wxString::Format("/usr/local/share/doc/xestiaab/%s.fodt",
3148 wxString(languageEnvironmentVariable).BeforeFirst('.', nullptr));
3149 std::string commandToExecute = "odthelpbrowser -d " + documentPath.ToStdString();
3151 if (wxFileExists(documentPath))
3152 executeResult = system(commandToExecute.c_str());
3154 if (executeResult == 0)
3157 #if XSDAB_RELEASE == 0
3158 documentPath = wxString::Format("/usr/share/doc/xestiaab/%s.fodt",
3159 wxString(languageEnvironmentVariable).BeforeFirst('.', nullptr));
3160 commandToExecute = "odthelpbrowser -d " + documentPath.ToStdString();
3162 if (wxFileExists(documentPath))
3163 executeResult = system(commandToExecute.c_str());
3165 if (executeResult == 0)
3169 // Attempt to launch using the "default" language.
3171 if (wxFileExists("/usr/share/doc/xestiaab/en_GB.fodt") && executeResult > 0)
3173 commandToExecute = "odthelpbrowser -d " + documentPath.ToStdString();
3174 executeResult = system(commandToExecute.c_str());
3176 else if (wxFileExists("/usr/local/share/doc/xestiaab/en_GB.fodt") && executeResult > 0)
3178 commandToExecute = "odthelpbrowser -d " + documentPath.ToStdString();
3179 executeResult = system(commandToExecute.c_str());
3182 if (executeResult == 0)
3187 #if XSDAB_RELEASE == 0
3188 wxMessageBox(_("The help documentation is not available.\n\nYou can view the documentation that came with your source package."), _("Help documentation missing!"));
3191 wxMessageBox(_("The help documentation is not available in the usual locations on the system. Please visit https://xestia.co.uk/addressbook for documentation"), _("Help documentation missing!"));
3197 void frmMain::ShowImportResults( wxCommandEvent &event ){
3199 // Show the results of importing contacts.
3201 std::map<int,wxString> *ResultData = (std::map<int,wxString>*)event.GetClientData();
3203 frmImportResults *frmIR = new frmImportResults(this);
3204 frmIR->LoadData(ResultData, event.GetInt(), (int)event.GetExtraLong());
3215 void frmMain::ReloadContactList( wxCommandEvent &event ){
3217 // Check if the account name given is the current
3218 // account selected.
3220 if (ActiveAccount == event.GetString()){
3222 wxTreeEvent NullEvent;
3223 LoadContactList(NullEvent);
3229 void frmMain::ShowContactMenu( wxMouseEvent& event ){
3231 // Show the contact menu when a right click occurs
3232 // in the contacts list.
3234 bool EnableRefresh = FALSE;
3236 if (!ActiveAccount.IsEmpty() && (ActiveAccountType == "CardDAV" ||
3237 ActiveAccountType == "carddav" ||
3238 ActiveAccountType == "Local" ||
3239 ActiveAccountType == "local")){
3241 EnableRefresh = TRUE;
3245 ContactMenu->SetupPointers(this, lstContacts, EnableRefresh);
3247 this->PopupMenu(ContactMenu->MenuPointer(), wxDefaultPosition);
3251 void frmMain::ResetContactInfo(){
3253 // Reset the contact information to an empty page.
3255 wxString EmptyPage = wxT("");
3256 htmContactData->SetPage(EmptyPage);
3257 AccCtrl->SetValue("");
3261 bool frmMain::CloseAllWindows()
3263 // Attempt to close all windows.
3265 if (WindowListPointersMenu.size() == 0)
3270 if (wxMessageBox(_("Before preforming the action, all windows that are open will need to close. Do you wish to continue?"), _("Close All Windowss"), wxYES_NO) == wxYES)
3272 for(std::map<int, void*>::iterator windowIter = WindowListPointers.begin();
3273 windowIter != WindowListPointers.end(); windowIter++)
3275 wxWindow *windowPointer = static_cast<wxWindow*>(windowIter->second);
3276 windowPointer->Close();