File indexing completed on 2024-11-24 04:43:04
0001 /* 0002 SPDX-FileCopyrightText: 2014-2024 Laurent Montel <montel@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "mergecontacts.h" 0008 #include "kaddressbookmergelibprivate_debug.h" 0009 0010 using namespace KABMergeContacts; 0011 using namespace KContacts; 0012 MergeContacts::MergeContacts(const Akonadi::Item::List &items) 0013 : mListItem(items) 0014 { 0015 } 0016 0017 MergeContacts::~MergeContacts() = default; 0018 0019 void MergeContacts::setItems(const Akonadi::Item::List &items) 0020 { 0021 mListItem = items; 0022 } 0023 0024 KContacts::Addressee MergeContacts::mergedContact(bool excludeConflictPart) 0025 { 0026 KContacts::Addressee newContact; 0027 if (mListItem.count() <= 1) { 0028 return newContact; 0029 } 0030 bool firstAddress = true; 0031 for (const Akonadi::Item &item : std::as_const(mListItem)) { 0032 if (item.hasPayload<KContacts::Addressee>()) { 0033 auto address = item.payload<KContacts::Addressee>(); 0034 if (firstAddress) { 0035 firstAddress = false; 0036 newContact = address; 0037 } else { 0038 mergeToContact(newContact, address, excludeConflictPart); 0039 } 0040 } 0041 } 0042 return newContact; 0043 } 0044 0045 void MergeContacts::mergeToContact(KContacts::Addressee &newContact, const KContacts::Addressee &fromContact, bool excludeConflictPart) 0046 { 0047 // Duplicate notes. 0048 const QString fromContactNote = fromContact.note(); 0049 if (!fromContactNote.isEmpty()) { 0050 QString newContactNote = newContact.note(); 0051 if (!newContactNote.isEmpty()) { 0052 newContactNote += QLatin1Char('\n'); 0053 } 0054 newContactNote += fromContactNote; 0055 newContact.setNote(newContactNote); 0056 } 0057 // Duplicate emails 0058 const QStringList emails = fromContact.emails(); 0059 if (!emails.isEmpty()) { 0060 QStringList newContactsEmail = newContact.emails(); 0061 for (const QString &email : emails) { 0062 if (!newContactsEmail.contains(email)) { 0063 newContactsEmail.append(email); 0064 } 0065 } 0066 newContact.setEmails(newContactsEmail); 0067 } 0068 // Merge Categories 0069 const QStringList categories = fromContact.categories(); 0070 if (!categories.isEmpty()) { 0071 QStringList newContactsCategories = newContact.categories(); 0072 for (const QString &category : categories) { 0073 if (!newContactsCategories.contains(category)) { 0074 newContactsCategories.append(category); 0075 } 0076 } 0077 newContact.setCategories(newContactsCategories); 0078 } 0079 0080 // Merge Phone 0081 const PhoneNumber::List listPhone = fromContact.phoneNumbers(); 0082 if (!listPhone.isEmpty()) { 0083 const PhoneNumber::List newContactsPhone = newContact.phoneNumbers(); 0084 for (const PhoneNumber &phone : listPhone) { 0085 if (!newContactsPhone.contains(phone)) { 0086 newContact.insertPhoneNumber(phone); 0087 } 0088 } 0089 } 0090 0091 // Merge Address 0092 const Address::List listAddress = fromContact.addresses(); 0093 if (!listAddress.isEmpty()) { 0094 const Address::List newContactsAddress = newContact.addresses(); 0095 for (const Address &addr : listAddress) { 0096 if (!newContactsAddress.contains(addr)) { 0097 newContact.insertAddress(addr); 0098 } 0099 } 0100 } 0101 0102 // Merge Impp 0103 const Impp::List listImpp = fromContact.imppList(); 0104 if (!listImpp.isEmpty()) { 0105 const Impp::List newContactsImpp = newContact.imppList(); 0106 for (const Impp &impp : listImpp) { 0107 if (!newContactsImpp.contains(impp)) { 0108 newContact.insertImpp(impp); 0109 } 0110 } 0111 } 0112 0113 if (!excludeConflictPart) { 0114 // Merge Name 0115 if (newContact.name().isEmpty() && !fromContact.name().isEmpty()) { 0116 newContact.setName(fromContact.name()); 0117 } 0118 // Merge organization 0119 if (newContact.organization().isEmpty() && !fromContact.organization().isEmpty()) { 0120 newContact.setOrganization(fromContact.organization()); 0121 } 0122 // Merge NickName 0123 if (newContact.nickName().isEmpty() && !fromContact.nickName().isEmpty()) { 0124 newContact.setNickName(fromContact.nickName()); 0125 } 0126 // Merge Title 0127 if (newContact.title().isEmpty() && !fromContact.title().isEmpty()) { 0128 newContact.setTitle(fromContact.title()); 0129 } 0130 // Merge Departement 0131 if (newContact.department().isEmpty() && !fromContact.department().isEmpty()) { 0132 newContact.setDepartment(fromContact.department()); 0133 } 0134 // Merge FamilyName 0135 if (newContact.familyName().isEmpty() && !fromContact.familyName().isEmpty()) { 0136 newContact.setFamilyName(fromContact.familyName()); 0137 } 0138 // Merge HomePage 0139 if (newContact.url().url().isEmpty() && !fromContact.url().url().isEmpty()) { 0140 newContact.setUrl(fromContact.url()); 0141 } 0142 // Merge geo 0143 if (newContact.geo().isValid() && !fromContact.geo().isValid()) { 0144 newContact.setGeo(fromContact.geo()); 0145 } 0146 // Merge Photo 0147 if (newContact.photo().isEmpty() && !fromContact.photo().isEmpty()) { 0148 newContact.setPhoto(fromContact.photo()); 0149 } 0150 0151 // Merge Birthday 0152 if (!newContact.birthday().isValid() && !fromContact.birthday().isValid()) { 0153 newContact.setBirthday(fromContact.birthday()); 0154 } 0155 0156 // Merge Logo 0157 if (newContact.logo().isEmpty() && !fromContact.logo().isEmpty()) { 0158 newContact.setLogo(fromContact.logo()); 0159 } 0160 0161 // Merge Blog 0162 mergeCustomValue(fromContact, QStringLiteral("BlogFeed"), newContact); 0163 // Merge profession 0164 mergeCustomValue(fromContact, QStringLiteral("X-Profession"), newContact); 0165 // Merge Office 0166 mergeCustomValue(fromContact, QStringLiteral("X-Office"), newContact); 0167 // Merge ManagersName 0168 mergeCustomValue(fromContact, QStringLiteral("X-ManagersName"), newContact); 0169 // Merge AssistantsName 0170 mergeCustomValue(fromContact, QStringLiteral("X-AssistantsName"), newContact); 0171 // Merge SpousesName 0172 mergeCustomValue(fromContact, QStringLiteral("X-SpousesName"), newContact); 0173 // Merge Anniversary 0174 mergeCustomValue(fromContact, QStringLiteral("X-Anniversary"), newContact); 0175 // Merge Key 0176 } 0177 } 0178 0179 void MergeContacts::mergeCustomValue(const KContacts::Addressee &fromContact, const QString &variable, KContacts::Addressee &newContact) 0180 { 0181 const QString newValue = newContact.custom(QStringLiteral("KADDRESSBOOK"), variable); 0182 const QString value = fromContact.custom(QStringLiteral("KADDRESSBOOK"), variable); 0183 if (newValue.isEmpty() && !value.isEmpty()) { 0184 newContact.insertCustom(QStringLiteral("KADDRESSBOOK"), variable, value); 0185 } 0186 } 0187 0188 MergeContacts::ConflictInformations MergeContacts::requiresManualSelectionOfInformation() 0189 { 0190 MergeContacts::ConflictInformations result = None; 0191 if (mListItem.count() < 2) { 0192 return result; 0193 } 0194 KContacts::Addressee newContact; 0195 for (const Akonadi::Item &item : std::as_const(mListItem)) { 0196 if (item.hasPayload<KContacts::Addressee>()) { 0197 const auto address = item.payload<KContacts::Addressee>(); 0198 // Test Birthday 0199 if (address.birthday().date().isValid()) { 0200 if (newContact.birthday().date().isValid()) { 0201 if (newContact.birthday().date() != address.birthday().date()) { 0202 result |= Birthday; 0203 } 0204 } else { 0205 newContact.setBirthday(address.birthday()); 0206 } 0207 } 0208 0209 // Test Geo 0210 const KContacts::Geo geo = address.geo(); 0211 if (geo.isValid()) { 0212 if (newContact.geo().isValid()) { 0213 if (newContact.geo() != geo) { 0214 result |= Geo; 0215 } 0216 } else { 0217 newContact.setGeo(address.geo()); 0218 } 0219 } 0220 // Test Photo 0221 const KContacts::Picture photo = address.photo(); 0222 if (!photo.isEmpty()) { 0223 if (!newContact.photo().isEmpty()) { 0224 if (newContact.photo() != photo) { 0225 result |= Photo; 0226 } 0227 } else { 0228 newContact.setPhoto(address.photo()); 0229 } 0230 } 0231 // Test Logo 0232 const KContacts::Picture logo = address.logo(); 0233 if (!logo.isEmpty()) { 0234 if (!newContact.logo().isEmpty()) { 0235 if (newContact.logo() != logo) { 0236 result |= Logo; 0237 } 0238 } else { 0239 newContact.setLogo(address.logo()); 0240 } 0241 } 0242 // Test Name 0243 const QString name = address.name(); 0244 if (!name.isEmpty()) { 0245 if (!newContact.name().isEmpty()) { 0246 if (newContact.name() != name) { 0247 result |= Name; 0248 } 0249 } else { 0250 newContact.setName(address.name()); 0251 } 0252 } 0253 // Test NickName 0254 const QString nickName = address.nickName(); 0255 if (!nickName.isEmpty()) { 0256 if (!newContact.nickName().isEmpty()) { 0257 if (newContact.nickName() != nickName) { 0258 result |= NickName; 0259 } 0260 } else { 0261 newContact.setNickName(address.nickName()); 0262 } 0263 } 0264 // Test Organization 0265 const QString organization = address.organization(); 0266 if (!organization.isEmpty()) { 0267 if (!newContact.organization().isEmpty()) { 0268 if (newContact.organization() != organization) { 0269 result |= Organization; 0270 } 0271 } else { 0272 newContact.setOrganization(address.organization()); 0273 } 0274 } 0275 // Test Title 0276 const QString title = address.title(); 0277 if (!title.isEmpty()) { 0278 if (!newContact.title().isEmpty()) { 0279 if (newContact.title() != title) { 0280 result |= Title; 0281 } 0282 } else { 0283 newContact.setTitle(address.title()); 0284 } 0285 } 0286 // Test Departement 0287 const QString departement = address.department(); 0288 if (!departement.isEmpty()) { 0289 if (!newContact.department().isEmpty()) { 0290 if (newContact.department() != departement) { 0291 result |= Departement; 0292 } 0293 } else { 0294 newContact.setDepartment(address.department()); 0295 } 0296 } 0297 // Test HomePage 0298 const QUrl url = address.url().url(); 0299 if (url.isValid() && !url.isEmpty()) { 0300 if (newContact.url().url().isValid() && !newContact.url().url().isEmpty()) { 0301 if (newContact.url().url() != url) { 0302 result |= HomePage; 0303 } 0304 } else { 0305 newContact.setUrl(address.url()); 0306 } 0307 } 0308 // Test FamilyName 0309 const QString familyName = address.familyName(); 0310 if (!familyName.isEmpty()) { 0311 if (!newContact.familyName().isEmpty()) { 0312 if (newContact.familyName() != familyName) { 0313 result |= FamilyName; 0314 } 0315 } else { 0316 newContact.setFamilyName(address.familyName()); 0317 } 0318 } 0319 // Test Blog 0320 checkCustomValue(address, QStringLiteral("BlogFeed"), newContact, result, Blog); 0321 // Test profession 0322 checkCustomValue(address, QStringLiteral("X-Profession"), newContact, result, Profession); 0323 // Test profession 0324 checkCustomValue(address, QStringLiteral("X-Office"), newContact, result, Office); 0325 // Test ManagersName 0326 checkCustomValue(address, QStringLiteral("X-ManagersName"), newContact, result, ManagerName); 0327 // Test AssistantsName 0328 checkCustomValue(address, QStringLiteral("X-AssistantsName"), newContact, result, Assistant); 0329 // Test SpousesName 0330 checkCustomValue(address, QStringLiteral("X-SpousesName"), newContact, result, PartnerName); 0331 // Test Anniversary 0332 checkCustomValue(address, QStringLiteral("X-Anniversary"), newContact, result, Anniversary); 0333 } 0334 } 0335 qCDebug(KADDRESSBOOKMERGELIBPRIVATE_LOG) << " result " << result; 0336 return result; 0337 } 0338 0339 void MergeContacts::checkCustomValue(const KContacts::Addressee &address, 0340 const QString &variable, 0341 KContacts::Addressee &newContact, 0342 MergeContacts::ConflictInformations &result, 0343 MergeContacts::ConflictInformation conflict) 0344 { 0345 const QString value = address.custom(QStringLiteral("KADDRESSBOOK"), variable); 0346 if (!value.isEmpty()) { 0347 const QString newValue = newContact.custom(QStringLiteral("KADDRESSBOOK"), variable); 0348 if (!newValue.isEmpty()) { 0349 if (newValue != value) { 0350 result |= conflict; 0351 } 0352 } else { 0353 newContact.insertCustom(QStringLiteral("KADDRESSBOOK"), variable, value); 0354 } 0355 } 0356 }