File indexing completed on 2024-04-28 16:42:50

0001 // SPDX-FileCopyrightText: 2020 Jonah BrĂ¼chert <jbb@kaidan.im>
0002 // SPDX-FileCopyrightText: 2021 Alexey Andreyev <aa13q@ya.ru>
0003 //
0004 // SPDX-License-Identifier: LicenseRef-KDE-Accepted-GPL
0005 
0006 #include "contact-phone-number-mapper.h"
0007 
0008 #include <KPeopleBackend/AbstractContact>
0009 #include <QDebug>
0010 #include <QThread>
0011 
0012 #include "phone-number-utils.h"
0013 
0014 ContactPhoneNumberMapper &ContactPhoneNumberMapper::instance(bool testMode)
0015 {
0016     static ContactPhoneNumberMapper instance(testMode);
0017     return instance;
0018 }
0019 
0020 ContactPhoneNumberMapper::ContactPhoneNumberMapper(bool testMode)
0021     : QObject()
0022     , _model(new KPeople::PersonsModel(this))
0023 {
0024     _cellCountry = _localeCountry;
0025     if (testMode) {
0026         // Start right away since we don't wait on the country code
0027         processRows(0, _model->rowCount() - 1);
0028     }
0029 
0030     _localeCountry = phoneNumberUtils::localeCountryCode();
0031 
0032     // data updates
0033     // we only care about additional data, not remove one
0034     connect(_model, &QAbstractItemModel::rowsInserted, this, [this](const QModelIndex &, int first, int last) {
0035         if (_cellCountry.empty()) {
0036             // We can't process until we know the cell country info
0037             return;
0038         }
0039         processRows(first, last);
0040     });
0041     processRows(0, _model->rowCount() - 1);
0042 }
0043 
0044 void ContactPhoneNumberMapper::changeCountry(const QString &countryCode)
0045 {
0046     _cellCountry = countryCode.toStdString();
0047 
0048     _numberToUri.clear();
0049 
0050     // Once we know the country we can start processing the contacts
0051     processRows(0, _model->rowCount() - 1);
0052 }
0053 
0054 void ContactPhoneNumberMapper::processRows(const int first, const int last)
0055 {
0056     QVector<QString> affectedNumbers;
0057     for (int i = first; i <= last; i++) {
0058         const auto index = _model->index(i);
0059 
0060         // Yes, this code has to be illogical. PersonsModel::PersonVCardRole is actually supposed
0061         // to return an AbstractContact::Ptr, although the name suggests differneltly. Luckily we can get
0062         // the actual VCard from it.
0063         const auto phoneNumbers = _model->data(index, KPeople::PersonsModel::PersonVCardRole)
0064                                       .value<KPeople::AbstractContact::Ptr>()
0065                                       ->customProperty(KPeople::AbstractContact::AllPhoneNumbersProperty)
0066                                       .toStringList();
0067 
0068         const auto personUri = _model->data(index, KPeople::PersonsModel::PersonUriRole).toString();
0069 
0070         for (const QString &numberString : phoneNumbers) {
0071             const auto maybeNormalizedNumber = phoneNumberUtils::normalizeNumber(numberString.toStdString(), phoneNumberUtils::International, _cellCountry);
0072 
0073             if (std::holds_alternative<std::string>(maybeNormalizedNumber)) {
0074                 const auto &normalizedNumber = std::get<std::string>(maybeNormalizedNumber);
0075                 _numberToUri[normalizedNumber] = personUri;
0076                 affectedNumbers.append(QString::fromStdString(normalizedNumber));
0077             } else {
0078                 continue;
0079             }
0080 
0081             if (_cellCountry != _localeCountry) {
0082                 const auto maybeNormalizedNumberLocale =
0083                     phoneNumberUtils::normalizeNumber(numberString.toStdString(), phoneNumberUtils::International, _localeCountry);
0084 
0085                 if (std::holds_alternative<std::string>(maybeNormalizedNumberLocale)) {
0086                     const auto &normalizedNumber = std::get<std::string>(maybeNormalizedNumberLocale);
0087                     _numberToUri[normalizedNumber] = personUri;
0088                     affectedNumbers.append(QString::fromStdString(normalizedNumber));
0089                 }
0090             }
0091         }
0092     }
0093 
0094     Q_EMIT contactsChanged(affectedNumbers);
0095 }
0096 
0097 QString ContactPhoneNumberMapper::uriForNumber(const QString &phoneNumber) const
0098 {
0099     const auto maybeNormalizedNumber = phoneNumberUtils::normalizeNumber(phoneNumber.toStdString(), phoneNumberUtils::International, _cellCountry);
0100 
0101     if (std::holds_alternative<std::string>(maybeNormalizedNumber)) {
0102         const auto &normalizedNumber = std::get<std::string>(maybeNormalizedNumber);
0103         if (_numberToUri.contains(normalizedNumber)) {
0104             return _numberToUri.at(normalizedNumber);
0105         }
0106     } else {
0107         return QString();
0108     }
0109 
0110     if (_cellCountry != _localeCountry) {
0111         const auto maybeNormalizedNumberLocale = phoneNumberUtils::normalizeNumber(phoneNumber.toStdString(), phoneNumberUtils::International, _localeCountry);
0112 
0113         if (std::holds_alternative<std::string>(maybeNormalizedNumberLocale)) {
0114             const auto &normalizedNumber = std::get<std::string>(maybeNormalizedNumberLocale);
0115             if (_numberToUri.contains(normalizedNumber)) {
0116                 return _numberToUri.at(normalizedNumber);
0117             }
0118         }
0119     }
0120 
0121     return QString();
0122 }