// SPDX-FileCopyrightText: 2020 Jonah BrĂ¼chert // SPDX-FileCopyrightText: 2021 Alexey Andreyev // // SPDX-License-Identifier: LicenseRef-KDE-Accepted-GPL /* * This class tries to match a phonenumber to one of your contacts. * This is not an easy tasks and involves some heuristics and tradeoffs. * * It works by maintaining a mapping from phonenumbers to KPeople URIs. * Since phonenumbers can be written in different formats the numbers are * normalized to a common form before comparing. * * If a contact's phonenumber in the address book is saved without a country * code then we need to guess a country. Guessing the country based on the locale * is problematic for people that have e.g. their phone in English but live * in Germany and assume the German country code in their address book. * Querying the country based on the cell network/MCC is problematic when travelling * abroad and the MCC changes. * * Our heuristic works like this: * First we normalize the number based on the cell network country and store the mapping. * If the locale's country is different to the cell network country we normalize the number * based on that and add it to the mapping as well. * When a call is received we first normalize the number based on the cell network country and * ask the mapping. If there is no entry we do the same based on the locale country. * * This covers the case of someone from Germany with English locale and the case of someone * from Germany using German locale travelling to France. It does not cover the case of * someone from Germany using English locale travelling to France. * * When the MCC changes, i.e. when we cross the border the mapping is cleared and redone with the new MCC. */ #pragma once #include #include #include class ContactPhoneNumberMapper : public QObject { Q_OBJECT public: /** * @brief Returns the KPeople URI belonging to phone number, * provided a contact exists containing the phone number. * If that is not the case, an empty string is returned. * @param phone number * @param guess the country * if a contact's phonenumber in the address book * is saved without a country code * @return the uri belonging to the phone number */ QString uriForNumber(const QString &phoneNumber) const; static ContactPhoneNumberMapper &instance(bool testMode = false); Q_SIGNALS: /** * @brief contactsChanged is emitted whenever the ContactMapper has new data, * because a contact was added to KPeople * @param list of affected numbers */ void contactsChanged(const QVector phoneNumbers); public Q_SLOTS: /** * @brief changeCountry should be executed by the daemon via appropriate signal * @param new two-letter country code */ void changeCountry(const QString &countryCode); private Q_SLOTS: void processRows(const int first, const int last); private: explicit ContactPhoneNumberMapper(bool testMode); [[nodiscard]] std::string normalizeNumber(const std::string &numberString) const; KPeople::PersonsModel *m_model; std::unordered_map m_numberToUri; std::string m_cellCountry; std::string m_localeCountry; };