diff --git a/src/contactmethod.cpp b/src/contactmethod.cpp index cb0a50d6a02a326cfc13cc09dd1ef54dbcb06422..fd39ec8031ccb52b589f5828997303f8c2420aa1 100644 --- a/src/contactmethod.cpp +++ b/src/contactmethod.cpp @@ -91,6 +91,11 @@ void ContactMethodPrivate::rebased(ContactMethod* other) emit n->rebased(other); } +void ContactMethodPrivate::registeredNameSet(const QString& name) +{ + foreach (ContactMethod* n, m_lParents) + emit n->registeredNameSet(name); +} const ContactMethod* ContactMethod::BLANK() { @@ -320,9 +325,24 @@ void ContactMethod::setTracked(bool track) } /// Set the registered name -void ContactMethod::setRegisteredName(const QString& registeredName) +void ContactMethodPrivate::setRegisteredName(const QString& registeredName) { - d_ptr->m_RegisteredName = registeredName; + if (registeredName.isEmpty() || registeredName == m_RegisteredName) + return; + + // If this happens, better create another ContactMethod manually to avoid + // all the corner cases. Doing this, for example, allows to keep track of + // the name in the private index of unique names kept by the + // PhoneDirectoryModel + if (!m_RegisteredName.isEmpty()) { + qWarning() << "A registered name is already set for this ContactMethod" + << m_RegisteredName << registeredName; + return; + } + + m_RegisteredName = registeredName; + registeredNameSet(registeredName); + changed(); } ///Allow phonedirectorymodel to change presence status diff --git a/src/contactmethod.h b/src/contactmethod.h index f9e725e6b7cbb11b9459c861015c73f36f846e47..f7af5b610363171da5d7507664b571b2fcb60cf0 100644 --- a/src/contactmethod.h +++ b/src/contactmethod.h @@ -88,7 +88,7 @@ public: Q_PROPERTY(URI::ProtocolHint protocolHint READ protocolHint ) Q_PROPERTY(bool isReachable READ isReachable ) Q_PROPERTY(Certificate* certificate READ certificate ) - Q_PROPERTY(QString registeredName READ registeredName WRITE setRegisteredName ) + Q_PROPERTY(QString registeredName READ registeredName NOTIFY registeredNameSet ) Q_PROPERTY(QString getBestId READ getBestId ) // Q_PROPERTY(QHash<QString,int> alternativeNames READ alternativeNames ) @@ -145,7 +145,6 @@ public: Q_INVOKABLE void setAccount (Account* account ); Q_INVOKABLE void setPerson (Person* contact ); Q_INVOKABLE void setTracked (bool track ); - Q_INVOKABLE void setRegisteredName(const QString& registeredName); void setCategory (NumberCategory* cat ); void setBookmarked (bool bookmarked ); void setUid (const QString& uri ); @@ -232,6 +231,8 @@ Q_SIGNALS: void contactChanged(Person* newContact, Person* oldContact); /// The number of unread text messages has changed void unreadTextMessageCountChanged(); + /// When the registered name is set + void registeredNameSet(const QString& name); }; Q_DECLARE_METATYPE(ContactMethod*) diff --git a/src/phonedirectorymodel.cpp b/src/phonedirectorymodel.cpp index a598ed876e3b177571f3874b6edb4bfa55a18444..8acf19ff42b08003057495afe3716735d5b0c287 100644 --- a/src/phonedirectorymodel.cpp +++ b/src/phonedirectorymodel.cpp @@ -36,6 +36,7 @@ #include "collectioninterface.h" #include "dbus/presencemanager.h" #include "globalinstances.h" +#include "private/contactmethod_p.h" #include "interfaces/pixmapmanipulatori.h" #include "personmodel.h" #include "dbus/configurationmanager.h" @@ -322,6 +323,7 @@ void PhoneDirectoryModelPrivate::setAccount(ContactMethod* number, Account* acco wrap = new NumberWrapper(); m_hDirectory [extendedUri] = wrap; m_hSortedNumbers[extendedUri] = wrap; + wrap->numbers << number; } else { @@ -817,13 +819,55 @@ PhoneDirectoryModelPrivate::slotRegisteredNameFound(const Account* account, Name foreach (ContactMethod* cm, wrap->numbers) { if (cm->account() == account) { cm->incrementAlternativeName(name, QDateTime::currentDateTime().toTime_t()); - cm->setRegisteredName(name); + cm->d_ptr->setRegisteredName(name); + + // Add the CM to the directory using the registered name too. + // Note that in theory the wrapper can exist already if the + // user was either offline in a call attempt or if there is a + // collision with a SIP account. + if (!m_hDirectory.contains(name)) { + //TODO support multiple name service, use proper URIs for names + auto wrap2 = new NumberWrapper(); + m_hDirectory [name] = wrap2; + m_hSortedNumbers[name] = wrap2; + wrap2->numbers << cm; + } + else { + auto wrapper = m_hDirectory.value(name); + // Merge the existing CMs now that it is known that the RingId match the username + foreach(ContactMethod* n, wrapper->numbers) { + + // If the account is the same and (as we know) it is a registered name + // there is 100% porbability of match + const bool compAccount = n->account() && + n->account() == cm->account(); + + // Less certain, but close enough. We have a contact with a phone + // number corresponding with a registeredName and `ring:` in front. + // it *could* use a different name service. Anyway, for now this + // isn't widespread enough to care. + const bool compContact = (!n->account()) && n->contact() && + n->uri().schemeType() == URI::SchemeType::RING; + + if (n != cm && (compAccount || compContact)) { + n->merge(cm); + } + } + } + + // Only add it once + if (!m_hDirectory[name]->numbers.indexOf(cm)) { + //TODO check if some deduplication can be performed + m_hDirectory[name]->numbers << cm; + } } else { qDebug() << "registered name: uri matches but not account" << name << address << account << cm->account(); } } } else { // got a registered name for a CM which hasn't been created yet + // This can be left as-is to save memory. Those CMs are never freed. + // It is generally preferred to create as little as possible. } } diff --git a/src/private/contactmethod_p.h b/src/private/contactmethod_p.h index b9d8a023838da0151c8a4359b89aaf03699aa2eb..4e3be2c7e1219070aef62d44013711beddff5c5b 100644 --- a/src/private/contactmethod_p.h +++ b/src/private/contactmethod_p.h @@ -59,10 +59,12 @@ public: void trackedChanged(bool); void primaryNameChanged(const QString& name); void rebased(ContactMethod* other); + void registeredNameSet(const QString& registeredName); //Helpers void setTextRecording(Media::TextRecording* r); void setCertificate (Certificate*); + void setRegisteredName(const QString& registeredName); private: ContactMethod* q_ptr;