1 // frmContactEditor-Save.cpp - frmContactEditor save contact subroutines.
3 // (c) 2012-2016 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/>
19 #include "frmContactEditor.h"
21 #include "../version.h"
22 #include "../vcard/vcard.h"
23 #include "../vcard/vcard34conv.h"
24 #include "../common/textprocessing.h"
25 #include "../common/preferences.h"
26 #include "../common/uuid.h"
27 #include "../common/dirs.h"
29 void frmContactEditor::SaveContact( wxCommandEvent& event )
32 // Do not save if the account is an unsupported account.
34 if (boolUnsupportedAccount == true){
36 wxMessageBox(_("Cannot make changes to a contact from an unsupported account type."), _("Unsupported account"), wxICON_ERROR);
41 // Check if Display As combo box has a value in it.
42 // Do not go any further if there is no value.
44 wxString cmbDisplayAsValue = cmbDisplayAs->GetValue();
46 if (cmbDisplayAsValue.IsEmpty()){
48 wxMessageBox(_("Display As value cannot be left blank."), _("Display As value empty"), wxICON_ERROR);
53 // Save the updated contact data.
56 wxString FilenameFinal;
57 bool ReplaceContact = FALSE;
59 if (StartupEditMode == TRUE){
61 if (cmbType->GetCurrentSelection() == 1 ||
62 cmbType->GetCurrentSelection() == 3 ||
63 cmbType->GetCurrentSelection() == 4){
67 // Mark contact for replacing.
69 ReplaceContact = TRUE;
74 } else if (cmbType->GetCurrentSelection() == 2){
76 if (IsGroup == FALSE){
78 // Mark contact for replacing.
80 ReplaceContact = TRUE;
87 if (ReplaceContact == TRUE){
89 wxString wxDelSplitFilename;
90 wxString wxDelFinalFilename;
91 wxString wxSDelDataURL;
92 wxStringTokenizer wSTDelFilename(wxSContactFilename, wxT("/"));
94 while(wSTDelFilename.HasMoreTokens()){
96 wxDelSplitFilename = wSTDelFilename.GetNextToken();
100 wxSDelDataURL = wxDelSplitFilename;
102 // Delete the contact from the server as it will be useless in certain
103 // address book clients.
105 ActMgrPtr->AddTask(2, cmbDisplayAs->GetValue(), wxSContactAccount, wxSDelDataURL, wxDelSplitFilename, wxSContactFilename, wxT(""));
107 // Clear the filename so the trigger to recreate the UID is done.
109 wxSContactFilename.Clear();
116 if (wxSContactFilename.IsEmpty()){
118 // Generate a random UUID.
120 ContactEditorData.UIDToken = GenerateUUID();
121 ContactEditorData.UIDToken = ContactEditorData.UIDToken.MakeUpper();
123 // Setup the filename.
125 FilenameFinal = GetAccountDir(wxSContactAccount, FALSE);
127 #if defined(__HAIKU__)
129 #elif defined(__WIN32__)
131 FilenameFinal = GetAccountDir(wxSContactAccount, FALSE);
132 FilenameFinal.Append(ContactEditorData.UIDToken);
133 FilenameFinal.Append(wxT(".vcf"));
134 wxSContactFilename = FilenameFinal;
138 FilenameFinal = GetAccountDir(wxSContactAccount, FALSE);
139 FilenameFinal.Append(ContactEditorData.UIDToken);
140 FilenameFinal.Append(wxT(".vcf"));
141 wxSContactFilename = FilenameFinal;
147 if (ContactEditorData.UIDToken.IsEmpty()){
149 // UID Token is empty. (Shouldn't be).
150 // Generate a new UID Token.
152 ContactEditorData.UIDToken = GenerateUUID();
153 ContactEditorData.UIDToken = ContactEditorData.UIDToken.MakeUpper();
157 FilenameFinal = wxSContactFilename;
161 // Setup the data and write it into the account folder.
163 // Begin preperations to write the contact to a file.
166 std::map<int,int>::iterator intiter;
167 std::map<int,wxString>::iterator striter;
169 // Set some values for saving.
171 ContactEditorData.NameForename = txtForename->GetValue();
172 ContactEditorData.NameSurname = txtSurname->GetValue();
173 ContactEditorData.NameOtherNames = txtOtherNames->GetValue();
174 ContactEditorData.NameTitle = txtTitle->GetValue();
175 ContactEditorData.NameSuffix = txtSuffix->GetValue();
177 ContactEditorData.GenderDetails = txtGenderDescription->GetValue();
179 // Process Birthday: Get Day, Month & Year.
181 wxDateTime BirthdayDate;
182 wxDateTime::Month BirthdayMonth;
185 wxString DataBeforeT;
187 wxString FinalBirthdayString;
188 bool ProcessDataAfterT = FALSE;
190 BirthdayDate = dapBirthday->GetValue();
192 if (!txtBirthday->IsEmpty()){
194 // Birthday value is text so use this.
196 ContactEditorData.Birthday = txtBirthday->GetValue();
198 } else if (BirthdayDate.IsValid()){
200 BirthdayDay = BirthdayDate.GetDay();
201 BirthdayMonth = BirthdayDate.GetMonth();
202 BirthdayYear = BirthdayDate.GetYear();
204 // Look for T and replace data before this.
206 wxStringTokenizer wSTDate(ContactEditorData.Birthday, wxT("T"));
208 while (wSTDate.HasMoreTokens()){
210 if (ProcessDataAfterT == FALSE){
212 DataBeforeT = wSTDate.GetNextToken();
213 ProcessDataAfterT = TRUE;
217 DataAfterT = wSTDate.GetNextToken();
224 // If there is not T then replace altogether.
226 wxString FinalBirthdayDay;
227 wxString FinalBirthdayMonth;
228 wxString FinalBirthdayYear;
230 if (BirthdayDay < 10){
232 FinalBirthdayDay = wxT("0") + wxString::Format(wxT("%i"), BirthdayDay);
236 FinalBirthdayDay = wxString::Format(wxT("%i"), BirthdayDay);
240 if (((int)BirthdayMonth + 1) < 10){
242 FinalBirthdayMonth = wxT("0") + wxString::Format(wxT("%i"), ((int)BirthdayMonth + 1));
246 FinalBirthdayMonth = wxString::Format(wxT("%i"), ((int)BirthdayMonth + 1));
250 if (BirthdayYear == 0){
252 FinalBirthdayYear = wxT("--");
256 FinalBirthdayYear = wxString::Format(wxT("%i"), BirthdayYear);
260 if (!DataAfterT.IsEmpty()){
262 FinalBirthdayString = FinalBirthdayYear + FinalBirthdayMonth + FinalBirthdayDay + wxT("T") + DataAfterT;
266 FinalBirthdayString = FinalBirthdayYear + FinalBirthdayMonth + FinalBirthdayDay;
270 if(!FinalBirthdayString.IsEmpty()){
272 ContactEditorData.Birthday = FinalBirthdayString;
278 // Process Anniversary: Get Day, Month & Year.
280 wxDateTime AnniversaryDate;
281 wxDateTime::Month AnniversaryMonth;
286 wxString FinalAnniversaryString;
287 ProcessDataAfterT = FALSE;
289 AnniversaryDate = dapAnniversary->GetValue();
291 if (!txtAnniversary->IsEmpty()){
293 // Birthday value is text so use this.
295 ContactEditorData.Anniversary = txtAnniversary->GetValue();
297 } else if (AnniversaryDate.IsValid()){
299 AnniversaryDay = AnniversaryDate.GetDay();
300 AnniversaryMonth = AnniversaryDate.GetMonth();
301 AnniversaryYear = AnniversaryDate.GetYear();
303 // Look for T and replace data before this.
305 wxStringTokenizer wSTDate(ContactEditorData.Anniversary, wxT("T"));
307 while (wSTDate.HasMoreTokens()){
309 if (ProcessDataAfterT == FALSE){
311 DataBeforeT = wSTDate.GetNextToken();
312 ProcessDataAfterT = TRUE;
316 DataAfterT = wSTDate.GetNextToken();
323 // If there is not T then replace altogether.
325 wxString FinalAnniversaryDay;
326 wxString FinalAnniversaryMonth;
327 wxString FinalAnniversaryYear;
329 if (AnniversaryDay < 10){
331 FinalAnniversaryDay = wxT("0") + wxString::Format(wxT("%i"), AnniversaryDay);
335 FinalAnniversaryDay = wxString::Format(wxT("%i"), AnniversaryDay);
339 if (((int)AnniversaryMonth + 1) < 10){
341 FinalAnniversaryMonth = wxT("0") + wxString::Format(wxT("%i"), ((int)AnniversaryMonth + 1));
345 FinalAnniversaryMonth = wxString::Format(wxT("%i"), ((int)AnniversaryMonth + 1));
349 if (AnniversaryYear == 0){
351 FinalAnniversaryYear = wxT("--");
355 FinalAnniversaryYear = wxString::Format(wxT("%i"), AnniversaryYear);
359 if (!DataAfterT.IsEmpty()){
361 FinalAnniversaryString = FinalAnniversaryYear + FinalAnniversaryMonth + FinalAnniversaryDay + wxT("T") + DataAfterT;
365 FinalAnniversaryString = FinalAnniversaryYear + FinalAnniversaryMonth + FinalAnniversaryDay;
369 if(!FinalAnniversaryString.IsEmpty()){
371 ContactEditorData.Birthday = FinalAnniversaryString;
377 // Process full name.
379 if (ContactEditorData.FullNamesList.size() > 0){
381 ContactEditorData.FullNamesList[0] = cmbDisplayAs->GetValue();
385 ContactEditorData.FullNamesList.insert(std::make_pair(0, cmbDisplayAs->GetValue()));
386 ContactEditorData.FullNamesListAltID.insert(std::make_pair(0, wxT("")));
387 ContactEditorData.FullNamesListPID.insert(std::make_pair(0, wxT("")));
388 ContactEditorData.FullNamesListType.insert(std::make_pair(0, wxT("")));
389 ContactEditorData.FullNamesListLanguage.insert(std::make_pair(0, wxT("")));
390 ContactEditorData.FullNamesListPref.insert(std::make_pair(0, 0));
391 ContactEditorData.FullNamesListTokens.insert(std::make_pair(0, wxT("")));
396 ContactEditorData.SaveFile(FilenameFinal);
398 vCard34Conv ConvFileFun;
402 ConvFileFun.ConvertToV3(FilenameFinal, &wxSData);
404 wxString AccountDirPrefix;
408 #if defined(__HAIKU__)
410 #elif defined(__APPLE__)
412 PrefDir = GetUserPrefDir();
414 wxStringTokenizer wSTFilename(wxSContactFilename, wxT("/"));
416 #elif defined(__WIN32__)
418 PrefDir = GetUserPrefDir();
420 wxStringTokenizer wSTFilename(wxSContactFilename, wxT("\\"));
424 PrefDir = GetUserPrefDir();
426 wxStringTokenizer wSTFilename(wxSContactFilename, wxT("/"));
430 XABPreferences PrefData(PrefDir);
432 wxString AccountType;
434 for (int i = 0; i < PrefData.accounts.GetCount(); i++){
436 AccountDir = PrefData.accounts.GetAccountDirectory(i) + wxT(".carddav");
438 if (AccountDir == wxSContactAccount){
440 AccountDirPrefix = PrefData.accounts.GetAccountDirPrefix(i);
441 AccountDirPrefix.Trim();
442 AccountType = PrefData.accounts.GetAccountType(i);
449 wxString wxSplitFilename;
452 while(wSTFilename.HasMoreTokens()){
454 wxSplitFilename = wSTFilename.GetNextToken();
458 wxSDataURL = wxSplitFilename;
460 // Find out if the filename exists in the table.
462 if (AccountType == wxT("CardDAV") || AccountType == wxT("carddav")){
465 wxString ETagOriginal;
467 ETagDB *ETagDBPtr = NULL;
469 ETagDBPtr = ETagTmrPtr->GetPointer(wxSContactAccount);
471 wxString wxSETag = ETagDBPtr->GetETag(wxSplitFilename);
472 wxString wxSETagOrig = ETagDBPtr->GetETagOriginal(wxSplitFilename);
474 if (wxSETagOrig.IsEmpty()){
476 // Generate the ETag.
478 wxSETagOrig = wxString::Format(wxT("%X%X%X%X"), rand() % 1024, rand() % 1024, rand() % 1024, rand() % 1024);
482 if (wxSETag.IsEmpty()){
484 // Update empty ETag.
486 wxSETag = wxSETagOrig;
487 ETagDBPtr->AddETag(wxSplitFilename, wxSETag, "");
491 // Don't change original ETag.
493 wxSETag = wxString::Format(wxT("%X%X%X%X"), rand() % 1024, rand() % 1024, rand() % 1024, rand() % 1024);
494 ETagDBPtr->UpdateETag(wxSplitFilename, wxSETag);
498 if (EditMode == FALSE){
500 ActMgrPtr->AddTask(0, cmbDisplayAs->GetValue(), wxSContactAccount, wxSDataURL, wxSplitFilename, FilenameFinal, wxSData);
502 FMTimer.SetFilename(FilenameFinal);
503 FMTimer.UpdateTimestamp();
504 FMTimer.Start(10000, FALSE);
506 wxCommandEvent reloadevent(RELOADCONTACTLIST);
507 reloadevent.SetString(wxSContactAccount);
508 wxPostEvent(this->GetParent(), reloadevent);
512 ActMgrPtr->AddTask(1, cmbDisplayAs->GetValue(), wxSContactAccount, wxSDataURL, wxSplitFilename, FilenameFinal, wxSData);
513 FMTimer.UpdateTimestamp();
514 FMTimer.Start(10000, FALSE);
520 // Send a notification to update the main window
521 // with the new details.
526 // TODO: Workout nickname settings by priority and
531 NameData.Forename = txtForename->GetValue();
532 NameData.Surname = txtSurname->GetValue();
533 NameData.OtherNames = txtOtherNames->GetValue();
534 NameData.Title = txtTitle->GetValue();
535 NameData.Suffix = txtSuffix->GetValue();
537 ucd->ContactAccount = wxSContactAccount;
538 ucd->ContactFilename = FilenameFinal;
539 ucd->ContactName = cmbDisplayAs->GetValue();
540 ucd->ContactNameArray = NameData;
542 for (std::map<int,wxString>::iterator gniter = ContactEditorData.GeneralNicknamesList.begin();
543 gniter != ContactEditorData.GeneralNicknamesList.end(); gniter++){
545 ucd->ContactNickname = gniter->second;
550 wxCommandEvent event2(CE_UPDATECONTACTLIST);
551 event2.SetClientData(ucd);
552 wxPostEvent(MainPtr, event2);
556 void frmContactEditor::SaveCloseContact( wxCommandEvent& event )
559 // Save the updated contact data and close the form.
561 wxCommandEvent NullEvent;
562 this->SaveContact(NullEvent);