diff --git a/src/phonedirectorymodel.cpp b/src/phonedirectorymodel.cpp index c1155eb04386139a66ea89cb2d581d0bb2f46a01..59b42476c93819f2ee533b11fb8a46a1bd6df91c 100644 --- a/src/phonedirectorymodel.cpp +++ b/src/phonedirectorymodel.cpp @@ -304,7 +304,6 @@ void PhoneDirectoryModel::setAccount(PhoneNumber* number, Account* account ) { //After all this, it is possible the number is now a duplicate foreach(PhoneNumber* n, wrap->numbers) { if (n != number && n->account() && n->account() == number->account()) { - //qDebug() << "DUPLICATE"; number->merge(n); } } @@ -314,6 +313,91 @@ void PhoneDirectoryModel::setAccount(PhoneNumber* number, Account* account ) { } } +/** + * This version of getNumber() try to get a phone number with a contact from an URI and account + * It will also try to attach an account to existing numbers. This is not 100% reliable, but + * it is correct often enough to do it. + */ +PhoneNumber* PhoneDirectoryModel::getNumber(const QString& uri, Account* account, const QString& type) +{ + return getNumber(uri,nullptr,account,type); +} + +///Add new information to existing numbers and try to merge +PhoneNumber* PhoneDirectoryModel::fillDetails(NumberWrapper* wrap, const URI& strippedUri, Account* account, Contact* contact, const QString& type,bool& hasContact) +{ + //TODO pick the best URI + //TODO the account hostname change corner case + if (wrap) { + foreach(PhoneNumber* number, wrap->numbers) { + + //BEGIN Check if contact can be set + + //Check if the contact is compatible + const bool hasCompatibleContact = contact && ( + (!number->contact()) + || ( + (number->contact()->uid() == contact->uid()) + && number->contact() != contact + ) + ); + + //Check if the URI match + const bool hasCompatibleURI = hasCompatibleContact && (number->uri().hasHostname()?( + /* Has hostname */ + strippedUri == number->uri() + /* Something with an hostname can be used with IP2IP */ //TODO support DHT here + || (account && account->id() == Account::ProtocolName::IP2IP) + ) : ( /* Has no hostname */ + number->account() && number->uri()+'@'+number->account()->hostname() == strippedUri + )); + + //Check if the account is compatible + const bool hasCompatibleAccount = hasCompatibleURI && ((!account) + || (!number->account()) + /* Direct match, this is always valid */ + || (account == number->account()) + /* IP2IP is a special case */ //TODO support DHT here + || ( + account->id() == Account::ProtocolName::IP2IP + && strippedUri.hasHostname() + )); + + //TODO the Display name could be used to influence the choice + + //If everything match, set the contact + if (hasCompatibleAccount) + number->setContact(contact); + //END Check if the contact can be set + + + //BEGIN Check is account can be set + // Try to match the account + // Not perfect, but better than ignoring the high probabilities + //TODO only do it is hostname match + if ((!account) || account != number->account()) { + + if (account && (!contact) && !number->account()) + setAccount(number,account); + + //Set a type, this has low probabilities of being invalid + if ((!number->hasType()) && (!type.isEmpty())) { + number->setCategory(NumberCategoryModel::instance()->getCategory(type)); + } + + hasContact |= number->contact()!= nullptr; + + //We already have enough information to confirm the choice + if (contact && number->contact() &&((contact->uid()) == number->contact()->uid())) + return number; + } + //END Check is account can be set + } + } + return nullptr; +} + +///Return/create a number when no information is available PhoneNumber* PhoneDirectoryModel::getNumber(const QString& uri, const QString& type) { const URI strippedUri(uri); @@ -335,11 +419,6 @@ PhoneNumber* PhoneDirectoryModel::getNumber(const QString& uri, const QString& t const QString hn = number->uri().hostname(); - //Check if we are lucky enough to have a single registered account with the same hostname - /*if (!hn.isEmpty()) { - - }*/ - emit layoutChanged(); if (!wrap) { wrap = new NumberWrapper(); @@ -350,50 +429,14 @@ PhoneNumber* PhoneDirectoryModel::getNumber(const QString& uri, const QString& t return number; } -/** - * This version of getNumber() try to get a phone number with a contact from an URI and account - * It will also try to attach an account to existing numbers. This is not 100% reliable, but - * it is correct often enough to do it. - */ -PhoneNumber* PhoneDirectoryModel::getNumber(const QString& uri, Account* account, const QString& type) -{ - return getNumber(uri,nullptr,account,type); -} - -PhoneNumber* PhoneDirectoryModel::fillDetails(NumberWrapper* wrap, Account* account, Contact* contact, const QString& type,bool& hasContact) -{ - if (wrap) { - foreach(PhoneNumber* number, wrap->numbers) { - //Not perfect, but better than ignoring the high probabilities - //TODO only do it is hostname match - if ((!contact) && account && !number->account()) - setAccount(number,account); - - //Set a type, this has low probabilities of being invalid - if ((!number->hasType()) && (!type.isEmpty())) { - number->setCategory(NumberCategoryModel::instance()->getCategory(type)); - } - - //If the contact has not already been set and account match, set it - if (account && account == number->account() && contact && !((*contact) == number->contact())) - number->setContact(contact); - - //We already have enough information to confirm the choice - if (contact && number->contact() &&((contact->uid()) == number->contact()->uid())) - return number; - hasContact |= number->contact()!= nullptr; - } - } - return nullptr; -} - +///Create a number when a more information is available duplicated ones PhoneNumber* PhoneDirectoryModel::getNumber(const QString& uri, Contact* contact, Account* account, const QString& type) { const URI strippedUri(uri); //Try to use a PhoneNumber with a contact when possible, work only after the //contact are loaded - bool hasContact = false; + bool hasContact(false),hasContact2(false); //See if the number is already loaded NumberWrapper* wrap = m_hDirectory[strippedUri]; @@ -409,11 +452,13 @@ PhoneNumber* PhoneDirectoryModel::getNumber(const QString& uri, Contact* contact } //Check - PhoneNumber* confirmedCandidate = fillDetails(wrap,account,contact,type,hasContact); + PhoneNumber* confirmedCandidate = fillDetails(wrap,strippedUri,account,contact,type,hasContact); //URIs can be represented in multiple way, check if a more verbose version //already exist - PhoneNumber* confirmedCandidate2 = fillDetails(wrap2,account,contact,type,hasContact); + PhoneNumber* confirmedCandidate2 = nullptr; + if (!hasContact) + confirmedCandidate2 = fillDetails(wrap2,strippedUri,account,contact,type,hasContact2); PhoneNumber* confirmedCandidate3 = nullptr; @@ -427,7 +472,7 @@ PhoneNumber* PhoneDirectoryModel::getNumber(const QString& uri, Contact* contact foreach(PhoneNumber* number, wrap2->numbers) { if (number->account() == account) { if (contact && ((!number->contact()) || (contact->uid() == number->contact()->uid()))) - number->setContact(contact); + number->setContact(contact); //TODO Check all cases from fillDetails() //TODO add alternate URI confirmedCandidate3 = number; break; @@ -436,7 +481,6 @@ PhoneNumber* PhoneDirectoryModel::getNumber(const QString& uri, Contact* contact } } - //qDebug() << "-----CANDID" << confirmedCandidate3 << confirmedCandidate << confirmedCandidate2; //If multiple PhoneNumber are confirmed, then they are the same, merge them if (confirmedCandidate3 && (confirmedCandidate || confirmedCandidate2)) { confirmedCandidate3->merge(confirmedCandidate?confirmedCandidate:confirmedCandidate2); @@ -459,16 +503,16 @@ PhoneNumber* PhoneDirectoryModel::getNumber(const QString& uri, Contact* contact //No better candidates were found than the original assumption, use it if (wrap) { foreach(PhoneNumber* number, wrap->numbers) { - if (((!account) || number->account() == account) && ((!contact) || ((*contact) == number->contact()))) { + if (((!account) || number->account() == account) && ((!contact) || ((*contact) == number->contact()) || (!number->contact()))) { if (contact && (!number->contact() || (contact->uid() == number->contact()->uid()))) number->setContact(contact); + return number; } } } //Create the number - //qDebug() << "CREATE" << strippedUri << account << contact; PhoneNumber* number = new PhoneNumber(strippedUri,NumberCategoryModel::instance()->getCategory(type)); number->setAccount(account); number->setIndex( m_lNumbers.size()); diff --git a/src/phonedirectorymodel.h b/src/phonedirectorymodel.h index 6664faa7a025277b5920c26bfedc36982ba09aef..fd90f3ec6f6be2ebb01913e39e8e3ea76e483a86 100644 --- a/src/phonedirectorymodel.h +++ b/src/phonedirectorymodel.h @@ -24,6 +24,7 @@ #include <QtCore/QAbstractTableModel> //SFLPhone +#include "uri.h" class PhoneNumber ; class Contact ; class Account ; @@ -116,7 +117,7 @@ private: //Helpers void indexNumber(PhoneNumber* number, const QStringList& names ); void setAccount (PhoneNumber* number, Account* account ); - PhoneNumber* fillDetails(NumberWrapper* wrap, Account* account, Contact* contact, const QString& type, bool& hasContact); + PhoneNumber* fillDetails(NumberWrapper* wrap, const URI& strippedUri, Account* account, Contact* contact, const QString& type, bool& hasContact); //Singleton static PhoneDirectoryModel* m_spInstance; diff --git a/src/phonenumber.cpp b/src/phonenumber.cpp index ca7c91a42c9e3a1043acc9070813d7384284e7cf..b1e826439c14c22d555f3715099e6ac6f27ec7b5 100644 --- a/src/phonenumber.cpp +++ b/src/phonenumber.cpp @@ -499,6 +499,10 @@ bool PhoneNumber::merge(PhoneNumber* other) if ((!other) || other == this || other->d == d) return false; + //This is invalid, those are different numbers + if (account() && other->account() && account() != other->account()) + return false; + //TODO Check if the merge is valid //TODO Merge the alternative names diff --git a/src/uri.h b/src/uri.h index 2df19f4d8e90ee056d959461a9dd00416eecde45..152c635100ae73aad702493ef428cd24e69ab7a2 100644 --- a/src/uri.h +++ b/src/uri.h @@ -58,8 +58,7 @@ * * authority = [ userinfo "@" ] host [ ":" port ] * - * "For - * example, the semicolon (";") and equals ("=") reserved characters are + * "For example, the semicolon (";") and equals ("=") reserved characters are * often used to delimit parameters and parameter values applicable to * that segment. The comma (",") reserved character is often used for * similar purposes. For example, one URI producer might use a segment