File indexing completed on 2024-05-12 07:52:03
0001 /* 0002 SPDX-FileCopyrightText: 2012 Aleix Pol Gonzalez <aleixpol@blue-systems.com> 0003 SPDX-FileCopyrightText: 2013 David Edmundson <david@davidedmundson.co.uk> 0004 0005 SPDX-License-Identifier: LGPL-2.1-or-later 0006 */ 0007 0008 #include "kpeople_debug.h" 0009 #include "match_p.h" 0010 #include "matchessolver_p.h" 0011 #include "personmanager_p.h" 0012 #include "personsmodel.h" 0013 0014 #include <QString> 0015 0016 using namespace KPeople; 0017 0018 MatchesSolver::MatchesSolver(const QList<Match> &matches, PersonsModel *model, QObject *parent) 0019 : KJob(parent) 0020 , m_matches(matches) 0021 , m_model(model) 0022 { 0023 } 0024 0025 void MatchesSolver::start() 0026 { 0027 QMetaObject::invokeMethod(this, "startMatching", Qt::QueuedConnection); 0028 } 0029 0030 void MatchesSolver::startMatching() 0031 { 0032 // Will contain all the sets to be merged 0033 QHash<QString, QSet<QString>> jobsData; 0034 // has a relation of each person, to know where it is 0035 QHash<QString, QString> destinationResolver; 0036 for (const Match &m : std::as_const(m_matches)) { 0037 QString urlA = m.indexA.data(PersonsModel::PersonUriRole).toString(); 0038 QString urlB = m.indexB.data(PersonsModel::PersonUriRole).toString(); 0039 Q_ASSERT(urlA != urlB); 0040 0041 const bool inA = destinationResolver.contains(urlA); 0042 const bool inB = destinationResolver.contains(urlB); 0043 if (inA && inB) { 0044 // Both are in already, so we have to merge both sets 0045 destinationResolver[urlB] = urlA; 0046 jobsData[urlA] = jobsData.take(urlB); 0047 0048 // we've put all items pointed to by urlA, to the B set 0049 // now we re-assign anything pointing to B as pointing to A 0050 // because they are the same 0051 const auto keys = destinationResolver.keys(urlB); 0052 auto it = keys.constBegin(); 0053 const auto end = keys.constEnd(); 0054 for (; it != end; ++it) { 0055 destinationResolver[*it] = urlA; 0056 } 0057 } else { 0058 // if A is in but not B, we want B wherever A is 0059 if (inA) { 0060 qSwap(urlB, urlA); 0061 } 0062 // in case B is anywhere, add A to that set, otherwise just insert B 0063 const QString mergeUrl = destinationResolver.value(urlB, urlB); 0064 0065 QSet<QString> &jobs = jobsData[mergeUrl]; 0066 jobs.insert(urlB); 0067 jobs.insert(urlA); 0068 0069 // remember where urlA and urlB are 0070 Q_ASSERT(urlA != mergeUrl); 0071 destinationResolver.insert(urlA, mergeUrl); 0072 if (urlB != mergeUrl) { 0073 destinationResolver.insert(urlB, mergeUrl); 0074 } 0075 } 0076 } 0077 0078 for (const QSet<QString> &uris : std::as_const(jobsData)) { 0079 if (PersonManager::instance()->mergeContacts(uris.values()).isEmpty()) { 0080 qCWarning(KPEOPLE_LOG) << "error: failing to merge contacts: " << uris; 0081 } 0082 } 0083 emitResult(); 0084 } 0085 0086 #include "moc_matchessolver_p.cpp"