File indexing completed on 2025-03-16 11:17:21
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 /* 0007 * This class tries to match a phonenumber to one of your contacts. 0008 * This is not an easy tasks and involves some heuristics and tradeoffs. 0009 * 0010 * It works by maintaining a mapping from phonenumbers to KPeople URIs. 0011 * Since phonenumbers can be written in different formats the numbers are 0012 * normalized to a common form before comparing. 0013 * 0014 * If a contact's phonenumber in the address book is saved without a country 0015 * code then we need to guess a country. Guessing the country based on the locale 0016 * is problematic for people that have e.g. their phone in English but live 0017 * in Germany and assume the German country code in their address book. 0018 * Querying the country based on the cell network/MCC is problematic when travelling 0019 * abroad and the MCC changes. 0020 * 0021 * Our heuristic works like this: 0022 * First we normalize the number based on the cell network country and store the mapping. 0023 * If the locale's country is different to the cell network country we normalize the number 0024 * based on that and add it to the mapping as well. 0025 * When a call is received we first normalize the number based on the cell network country and 0026 * ask the mapping. If there is no entry we do the same based on the locale country. 0027 * 0028 * This covers the case of someone from Germany with English locale and the case of someone 0029 * from Germany using German locale travelling to France. It does not cover the case of 0030 * someone from Germany using English locale travelling to France. 0031 * 0032 * When the MCC changes, i.e. when we cross the border the mapping is cleared and redone with the new MCC. 0033 */ 0034 0035 #pragma once 0036 0037 #include <KPeople/PersonsModel> 0038 #include <QObject> 0039 0040 #include <unordered_map> 0041 0042 class ContactPhoneNumberMapper : public QObject 0043 { 0044 Q_OBJECT 0045 0046 public: 0047 /** 0048 * @brief Returns the KPeople URI belonging to phone number, 0049 * provided a contact exists containing the phone number. 0050 * If that is not the case, an empty string is returned. 0051 * @param phone number 0052 * @param guess the country 0053 * if a contact's phonenumber in the address book 0054 * is saved without a country code 0055 * @return the uri belonging to the phone number 0056 */ 0057 QString uriForNumber(const QString &phoneNumber) const; 0058 0059 static ContactPhoneNumberMapper &instance(bool testMode = false); 0060 0061 Q_SIGNALS: 0062 /** 0063 * @brief contactsChanged is emitted whenever the ContactMapper has new data, 0064 * because a contact was added to KPeople 0065 * @param list of affected numbers 0066 */ 0067 void contactsChanged(const QVector<QString> phoneNumbers); 0068 0069 public Q_SLOTS: 0070 /** 0071 * @brief changeCountry should be executed by the daemon via appropriate signal 0072 * @param new two-letter country code 0073 */ 0074 void changeCountry(const QString &countryCode); 0075 0076 private Q_SLOTS: 0077 void processRows(const int first, const int last); 0078 0079 private: 0080 explicit ContactPhoneNumberMapper(bool testMode); 0081 [[nodiscard]] std::string normalizeNumber(const std::string &numberString) const; 0082 0083 KPeople::PersonsModel *_model; 0084 std::unordered_map<std::string, QString> _numberToUri; 0085 0086 std::string _cellCountry; 0087 std::string _localeCountry; 0088 };