From 70ad267535da656369bcdd820e228eea6399db66 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> Date: Mon, 11 Aug 2014 23:12:28 +0200 Subject: [PATCH] [ #53076 ] Implement shared D-Pointers for PhoneNumber objects --- src/phonedirectorymodel.cpp | 26 ++-- src/phonenumber.cpp | 250 ++++++++++++++++++++++++------------ src/phonenumber.h | 27 +++- 3 files changed, 202 insertions(+), 101 deletions(-) diff --git a/src/phonedirectorymodel.cpp b/src/phonedirectorymodel.cpp index 3e0c3596..70140118 100644 --- a/src/phonedirectorymodel.cpp +++ b/src/phonedirectorymodel.cpp @@ -285,7 +285,7 @@ PhoneNumber* PhoneDirectoryModel::getNumber(const QString& uri, const QString& t NumberWrapper* wrap = m_hDirectory[strippedUri]; if (wrap) { PhoneNumber* nb = wrap->numbers[0]; - if ((!nb->m_hasType) && (!type.isEmpty())) { + if ((!nb->hasType()) && (!type.isEmpty())) { nb->setCategory(NumberCategoryModel::instance()->getCategory(type)); } return nb; @@ -293,7 +293,7 @@ PhoneNumber* PhoneDirectoryModel::getNumber(const QString& uri, const QString& t //Too bad, lets create one PhoneNumber* number = new PhoneNumber(strippedUri,NumberCategoryModel::instance()->getCategory(type)); - number->m_Index = m_lNumbers.size(); + number->setIndex(m_lNumbers.size()); m_lNumbers << number; connect(number,SIGNAL(callAdded(Call*)),this,SLOT(slotCallAdded(Call*))); connect(number,SIGNAL(changed()),this,SLOT(slotChanged())); @@ -344,7 +344,7 @@ PhoneNumber* PhoneDirectoryModel::getNumber(const QString& uri, Account* account //TODO only do it is hostname match if (!number->account()) number->setAccount(account); - if ((!number->m_hasType) && (!type.isEmpty())) { + if ((!number->hasType()) && (!type.isEmpty())) { number->setCategory(NumberCategoryModel::instance()->getCategory(type)); } hasContact |= number->contact()!= nullptr; @@ -358,7 +358,7 @@ PhoneNumber* PhoneDirectoryModel::getNumber(const QString& uri, Account* account //TODO only do it is hostname match if (!number->account()) number->setAccount(account); - if ((!number->m_hasType) && (!type.isEmpty())) { + if ((!number->hasType()) && (!type.isEmpty())) { number->setCategory(NumberCategoryModel::instance()->getCategory(type)); } if (number->contact()) { @@ -390,7 +390,7 @@ PhoneNumber* PhoneDirectoryModel::getNumber(const QString& uri, Account* account //Create the number PhoneNumber* number = new PhoneNumber(strippedUri,NumberCategoryModel::instance()->getCategory(type)); number->setAccount(account); - number->m_Index = m_lNumbers.size(); + number->setIndex( m_lNumbers.size()); m_lNumbers << number; connect(number,SIGNAL(callAdded(Call*)),this,SLOT(slotCallAdded(Call*))); connect(number,SIGNAL(changed()),this,SLOT(slotChanged())); @@ -420,7 +420,7 @@ PhoneNumber* PhoneDirectoryModel::getNumber(const QString& uri, Contact* contact } } foreach(PhoneNumber* number, wrap->numbers) { - if ((!number->m_hasType) && (!type.isEmpty())) { + if ((!number->hasType()) && (!type.isEmpty())) { number->setCategory(NumberCategoryModel::instance()->getCategory(type)); } if (((!contact) || number->contact() == contact) && ((!account) || number->account() == account)) @@ -432,7 +432,7 @@ PhoneNumber* PhoneDirectoryModel::getNumber(const QString& uri, Contact* contact PhoneNumber* number = new PhoneNumber(strippedUri,NumberCategoryModel::instance()->getCategory(type)); number->setAccount(account); number->setContact(contact); - number->m_Index = m_lNumbers.size(); + number->setIndex(m_lNumbers.size()); m_lNumbers << number; connect(number,SIGNAL(callAdded(Call*)),this,SLOT(slotCallAdded(Call*))); connect(number,SIGNAL(changed()),this,SLOT(slotChanged())); @@ -486,24 +486,24 @@ void PhoneDirectoryModel::slotCallAdded(Call* call) PhoneNumber* tmp = m_lPopularityIndex[currentIndex-1]; m_lPopularityIndex[currentIndex-1] = number; m_lPopularityIndex[currentIndex ] = tmp ; - tmp->m_PopularityIndex++; + tmp->setPopularityIndex(tmp->popularityIndex()+1); currentIndex--; } while (currentIndex && m_lPopularityIndex[currentIndex-1]->callCount() < number->callCount()); - number->m_PopularityIndex = currentIndex; + number->setPopularityIndex(currentIndex); emit layoutChanged(); } //The top 10 is not complete, a call count of "1" is enough to make it else if (m_lPopularityIndex.size() < 10 && currentIndex == -1) { m_lPopularityIndex << number; - number->m_PopularityIndex = m_lPopularityIndex.size()-1; + number->setPopularityIndex(m_lPopularityIndex.size()-1); emit layoutChanged(); } //The top 10 is full, but this number just made it to the top 10 else if (currentIndex == -1 && m_lPopularityIndex.size() >= 10 && m_lPopularityIndex[9] != number && m_lPopularityIndex[9]->callCount() < number->callCount()) { PhoneNumber* tmp = m_lPopularityIndex[9]; - tmp->m_PopularityIndex = -1; + tmp->setPopularityIndex(-1); m_lPopularityIndex[9] = number; - number->m_PopularityIndex = 9; + number->setPopularityIndex(9); emit tmp->changed(); emit number->changed(); } @@ -519,7 +519,7 @@ void PhoneDirectoryModel::slotChanged() { PhoneNumber* number = qobject_cast<PhoneNumber*>(sender()); if (number) { - const int idx = number->m_Index; + const int idx = number->index(); #ifndef NDEBUG if (idx<0) qDebug() << "Invalid slotChanged() index!" << idx; diff --git a/src/phonenumber.cpp b/src/phonenumber.cpp index 86dbf4a9..0ce3c6bd 100644 --- a/src/phonenumber.cpp +++ b/src/phonenumber.cpp @@ -27,25 +27,57 @@ QHash<int,Call*> PhoneNumber::m_shMostUsed = QHash<int,Call*>(); const PhoneNumber* PhoneNumber::m_spBlank = nullptr; + +class PrivatePhoneNumber { +public: + PrivatePhoneNumber(const QString& number, NumberCategory* cat, PhoneNumber::Type st); + NumberCategory* m_pCategory ; + bool m_Present ; + QString m_PresentMessage ; + bool m_Tracked ; + Contact* m_pContact ; + Account* m_pAccount ; + time_t m_LastUsed ; + QList<Call*> m_lCalls ; + int m_PopularityIndex ; + QString m_MostCommonName ; + QHash<QString,int> m_hNames ; + bool m_hasType ; + uint m_LastWeekCount ; + uint m_LastTrimCount ; + bool m_HaveCalled ; + int m_Index ; + bool m_IsBookmark ; + int m_TotalSeconds ; + QString m_Uid ; + QString m_PrimaryName_cache; + QString m_Uri ; + PhoneNumber::Type m_Type ; +}; + const PhoneNumber* PhoneNumber::BLANK() { if (!m_spBlank) { m_spBlank = new PhoneNumber("",NumberCategoryModel::other()); - const_cast<PhoneNumber*>(m_spBlank)->m_Type = PhoneNumber::Type::BLANK; + const_cast<PhoneNumber*>(m_spBlank)->d->m_Type = PhoneNumber::Type::BLANK; } return m_spBlank; } -///Constructor -PhoneNumber::PhoneNumber(const QString& number, NumberCategory* cat, Type st) : QObject(PhoneDirectoryModel::instance()), - m_Uri(stripUri(number)),m_pCategory(cat),m_Tracked(false),m_Present(false),m_LastUsed(0), +PrivatePhoneNumber::PrivatePhoneNumber(const QString& number, NumberCategory* cat, PhoneNumber::Type st) : + m_Uri(PhoneNumber::stripUri(number)),m_pCategory(cat),m_Tracked(false),m_Present(false),m_LastUsed(0), m_Type(st),m_PopularityIndex(-1),m_pContact(nullptr),m_pAccount(nullptr), m_LastWeekCount(0),m_LastTrimCount(0),m_HaveCalled(false),m_IsBookmark(false),m_TotalSeconds(0), m_Index(-1) +{} + +///Constructor +PhoneNumber::PhoneNumber(const QString& number, NumberCategory* cat, Type st) : QObject(PhoneDirectoryModel::instance()), +d(new PrivatePhoneNumber(number,cat,st)) { - setObjectName(m_Uri); - m_hasType = cat != NumberCategoryModel::other(); - if (m_hasType) { + setObjectName(d->m_Uri); + d->m_hasType = cat != NumberCategoryModel::other(); + if (d->m_hasType) { NumberCategoryModel::instance()->registerNumber(this); } } @@ -58,104 +90,134 @@ PhoneNumber::~PhoneNumber() bool PhoneNumber::isTracked() const { //If the number doesn't support it, ignore the flag - return supportPresence() && m_Tracked; + return supportPresence() && d->m_Tracked; } ///Is this number present bool PhoneNumber::isPresent() const { - return m_Tracked && m_Present; + return d->m_Tracked && d->m_Present; } ///This number presence status string QString PhoneNumber::presenceMessage() const { - return m_PresentMessage; + return d->m_PresentMessage; } ///Return the number QString PhoneNumber::uri() const { - return m_Uri ; + return d->m_Uri ; +} + +///This phone number has a type +bool PhoneNumber::hasType() const +{ + return d->m_hasType; +} + +///Protected getter to get the number index +int PhoneNumber::index() const +{ + return d->m_Index; } ///Return the phone number type NumberCategory* PhoneNumber::category() const { - return m_pCategory ; + return d->m_pCategory ; } ///Return this number associated account, if any Account* PhoneNumber::account() const { - return m_pAccount; + return d->m_pAccount; } ///Return this number associated contact, if any Contact* PhoneNumber::contact() const { - return m_pContact; + return d->m_pContact; } ///Return when this number was last used time_t PhoneNumber::lastUsed() const { - return m_LastUsed; + return d->m_LastUsed; } ///Set this number default account void PhoneNumber::setAccount(Account* account) { - m_pAccount = account; - if (m_pAccount) - connect (m_pAccount,SIGNAL(destroyed(QObject*)),this,SLOT(accountDestroyed(QObject*))); + d->m_pAccount = account; + if (d->m_pAccount) + connect (d->m_pAccount,SIGNAL(destroyed(QObject*)),this,SLOT(accountDestroyed(QObject*))); emit changed(); } ///Set this number contact void PhoneNumber::setContact(Contact* contact) { - m_pContact = contact; - if (contact && m_Type != PhoneNumber::Type::TEMPORARY) { - PhoneDirectoryModel::instance()->indexNumber(this,m_hNames.keys()+QStringList(contact->formattedName())); - m_PrimaryName_cache = contact->formattedName(); - emit primaryNameChanged(m_PrimaryName_cache); + d->m_pContact = contact; + if (contact && d->m_Type != PhoneNumber::Type::TEMPORARY) { + PhoneDirectoryModel::instance()->indexNumber(this,d->m_hNames.keys()+QStringList(contact->formattedName())); + d->m_PrimaryName_cache = contact->formattedName(); + emit primaryNameChanged(d->m_PrimaryName_cache); } emit changed(); } +///Protected setter to set if there is a type +void PhoneNumber::setHasType(bool value) +{ + d->m_hasType = value; +} + +///Protected setter to set the PhoneDirectoryModel index +void PhoneNumber::setIndex(int value) +{ + d->m_Index = value; +} + +///Protected setter to change the popularity index +void PhoneNumber::setPopularityIndex(int value) +{ + d->m_PopularityIndex = value; +} + void PhoneNumber::setCategory(NumberCategory* cat) { - if (cat == m_pCategory) return; - if (m_hasType) + if (cat == d->m_pCategory) return; + if (d->m_hasType) NumberCategoryModel::instance()->unregisterNumber(this); - m_hasType = cat != NumberCategoryModel::other(); - m_pCategory = cat; - if (m_hasType) + d->m_hasType = cat != NumberCategoryModel::other(); + d->m_pCategory = cat; + if (d->m_hasType) NumberCategoryModel::instance()->registerNumber(this); emit changed(); } void PhoneNumber::setBookmarked(bool bookmarked ) { - m_IsBookmark = bookmarked; + d->m_IsBookmark = bookmarked; } ///Force an Uid on this number (instead of hash) void PhoneNumber::setUid(const QString& uri) { - m_Uid = uri; + d->m_Uid = uri; } ///Attempt to change the number type bool PhoneNumber::setType(PhoneNumber::Type t) { - if (m_Type == PhoneNumber::Type::BLANK) + if (d->m_Type == PhoneNumber::Type::BLANK) return false; if (account() && t == PhoneNumber::Type::ACCOUNT) { if (account()->supportPresenceSubscribe()) { - m_Tracked = true; //The daemon will init the tracker itself + d->m_Tracked = true; //The daemon will init the tracker itself emit trackedChanged(true); } - m_Type = t; + d->m_Type = t; return true; } return false; @@ -164,11 +226,11 @@ bool PhoneNumber::setType(PhoneNumber::Type t) ///Set if this number is tracking presence information void PhoneNumber::setTracked(bool track) { - if (track != m_Tracked) { //Subscribe only once + if (track != d->m_Tracked) { //Subscribe only once //You can't subscribe without account - if (track && !m_pAccount) return; - m_Tracked = track; - DBus::PresenceManager::instance().subscribeBuddy(m_pAccount->id(),fullUri(),track); + if (track && !d->m_pAccount) return; + d->m_Tracked = track; + DBus::PresenceManager::instance().subscribeBuddy(d->m_pAccount->id(),fullUri(),track); emit changed(); emit trackedChanged(track); } @@ -177,16 +239,16 @@ void PhoneNumber::setTracked(bool track) ///Allow phonedirectorymodel to change presence status void PhoneNumber::setPresent(bool present) { - if (m_Present != present) { - m_Present = present; + if (d->m_Present != present) { + d->m_Present = present; emit presentChanged(present); } } void PhoneNumber::setPresenceMessage(const QString& message) { - if (m_PresentMessage != message) { - m_PresentMessage = message; + if (d->m_PresentMessage != message) { + d->m_PresentMessage = message; emit presenceMessageChanged(message); } } @@ -194,42 +256,42 @@ void PhoneNumber::setPresenceMessage(const QString& message) ///Return the current type of the number PhoneNumber::Type PhoneNumber::type() const { - return m_Type; + return d->m_Type; } ///Return the number of calls from this number int PhoneNumber::callCount() const { - return m_lCalls.size(); + return d->m_lCalls.size(); } uint PhoneNumber::weekCount() const { - return m_LastWeekCount; + return d->m_LastWeekCount; } uint PhoneNumber::trimCount() const { - return m_LastTrimCount; + return d->m_LastTrimCount; } bool PhoneNumber::haveCalled() const { - return m_HaveCalled; + return d->m_HaveCalled; } ///Best bet for this person real name QString PhoneNumber::primaryName() const { //Compute the primary name - if (m_PrimaryName_cache.isEmpty()) { + if (d->m_PrimaryName_cache.isEmpty()) { QString ret; - if (m_hNames.size() == 1) - ret = m_hNames.constBegin().key(); + if (d->m_hNames.size() == 1) + ret = d->m_hNames.constBegin().key(); else { QString toReturn = tr("Unknown"); int max = 0; - for (QHash<QString,int>::const_iterator i = m_hNames.begin(); i != m_hNames.end(); ++i) { + for (QHash<QString,int>::const_iterator i = d->m_hNames.begin(); i != d->m_hNames.end(); ++i) { if (i.value() > max) { max = i.value(); toReturn = i.key (); @@ -237,32 +299,32 @@ QString PhoneNumber::primaryName() const } ret = toReturn; } - const_cast<PhoneNumber*>(this)->m_PrimaryName_cache = ret; - emit const_cast<PhoneNumber*>(this)->primaryNameChanged(m_PrimaryName_cache); + const_cast<PhoneNumber*>(this)->d->m_PrimaryName_cache = ret; + emit const_cast<PhoneNumber*>(this)->primaryNameChanged(d->m_PrimaryName_cache); } //Fallback: Use the URI - if (m_PrimaryName_cache.isEmpty()) { + if (d->m_PrimaryName_cache.isEmpty()) { return uri(); } //Return the cached primaryname - return m_PrimaryName_cache; + return d->m_PrimaryName_cache; } ///Is this number bookmarked bool PhoneNumber::isBookmarked() const { - return m_IsBookmark; + return d->m_IsBookmark; } ///If this number could (theoretically) support presence status bool PhoneNumber::supportPresence() const { //Without an account, presence is impossible - if (!m_pAccount) + if (!d->m_pAccount) return false; //The account also have to support it - if (!m_pAccount->supportPresenceSubscribe()) + if (!d->m_pAccount->supportPresenceSubscribe()) return false; //In the end, it all come down to this, is the number tracked @@ -278,52 +340,52 @@ QVariant PhoneNumber::icon() const ///The number of seconds spent with the URI (from history) int PhoneNumber::totalSpentTime() const { - return m_TotalSeconds; + return d->m_TotalSeconds; } ///Return this number unique identifier (hash) QString PhoneNumber::uid() const { - return m_Uid.isEmpty()?toHash():m_Uid; + return d->m_Uid.isEmpty()?toHash():d->m_Uid; } ///Return all calls from this number QList<Call*> PhoneNumber::calls() const { - return m_lCalls; + return d->m_lCalls; } ///Return the phonenumber position in the popularity index int PhoneNumber::popularityIndex() const { - return m_PopularityIndex; + return d->m_PopularityIndex; } QHash<QString,int> PhoneNumber::alternativeNames() const { - return m_hNames; + return d->m_hNames; } ///Add a call to the call list, notify listener void PhoneNumber::addCall(Call* call) { if (!call) return; - m_Type = PhoneNumber::Type::USED; - m_lCalls << call; - m_TotalSeconds += call->stopTimeStamp() - call->startTimeStamp(); + d->m_Type = PhoneNumber::Type::USED; + d->m_lCalls << call; + d->m_TotalSeconds += call->stopTimeStamp() - call->startTimeStamp(); time_t now; ::time ( &now ); if (now - 3600*24*7 < call->stopTimeStamp()) - m_LastWeekCount++; + d->m_LastWeekCount++; if (now - 3600*24*7*15 < call->stopTimeStamp()) - m_LastTrimCount++; + d->m_LastTrimCount++; if (call->historyState() == Call::LegacyHistoryState::OUTGOING || call->direction() == Call::Direction::OUTGOING) - m_HaveCalled = true; + d->m_HaveCalled = true; emit callAdded(call); - if (call->startTimeStamp() > m_LastUsed) - m_LastUsed = call->startTimeStamp(); + if (call->startTimeStamp() > d->m_LastUsed) + d->m_LastUsed = call->startTimeStamp(); emit changed(); } @@ -337,15 +399,15 @@ QString PhoneNumber::toHash() const ///Return the domaine of an URI (<sip:12345@example.com>) QString PhoneNumber::hostname() const { - if (m_Uri.indexOf('@') != -1) { - return m_Uri.split('@')[1].left(m_Uri.split('@')[1].size()); + if (d->m_Uri.indexOf('@') != -1) { + return d->m_Uri.split('@')[1].left(d->m_Uri.split('@')[1].size()); } return QString(); } QString PhoneNumber::fullUri() const { - return QString("<sip:%1>").arg(m_Uri); + return QString("<sip:%1>").arg(d->m_Uri); } @@ -365,20 +427,44 @@ QString PhoneNumber::stripUri(const QString& uri) ///Increment name counter and update indexes void PhoneNumber::incrementAlternativeName(const QString& name) { - const bool needReIndexing = !m_hNames[name]; - m_hNames[name]++; - if (needReIndexing && m_Type != PhoneNumber::Type::TEMPORARY) { - PhoneDirectoryModel::instance()->indexNumber(this,m_hNames.keys()+(m_pContact?(QStringList(m_pContact->formattedName())):QStringList())); + const bool needReIndexing = !d->m_hNames[name]; + d->m_hNames[name]++; + if (needReIndexing && d->m_Type != PhoneNumber::Type::TEMPORARY) { + PhoneDirectoryModel::instance()->indexNumber(this,d->m_hNames.keys()+(d->m_pContact?(QStringList(d->m_pContact->formattedName())):QStringList())); //Invalid m_PrimaryName_cache - if (!m_pContact) - m_PrimaryName_cache.clear(); + if (!d->m_pContact) + d->m_PrimaryName_cache.clear(); } } void PhoneNumber::accountDestroyed(QObject* o) { - if (o == m_pAccount) - m_pAccount = nullptr; + if (o == d->m_pAccount) + d->m_pAccount = nullptr; +} + +/** + * Merge two phone number to share the same data. This avoid having to change + * pointers all over the place. The PhoneNumber objects remain intact, the + * PhoneDirectoryModel will replace the old references, but existing ones will + * keep working. + */ +bool PhoneNumber::merge(PhoneNumber* other) +{ + Q_UNUSED(other) + //TODO + //Check if the merge is valid + + //Disconnect signal + + //Merge the alternative names + + //Swap the pointer + + //Emit contact changed + + //Change the D-Pointer + return false; } /************************************************************************************ @@ -389,7 +475,7 @@ void PhoneNumber::accountDestroyed(QObject* o) void TemporaryPhoneNumber::setUri(const QString& uri) { - m_Uri = uri; + d->m_Uri = uri; emit changed(); } diff --git a/src/phonenumber.h b/src/phonenumber.h index 870dd5ea..03678612 100644 --- a/src/phonenumber.h +++ b/src/phonenumber.h @@ -25,6 +25,7 @@ #include <QStringList> #include <QtCore/QSize> #include <QtCore/QObject> +#include <QtCore/QSharedPointer> //SFLPhone class Account; @@ -34,11 +35,14 @@ class PhoneNumberPrivate; class TemporaryPhoneNumber; class NumberCategory; +class PrivatePhoneNumber; + ///PhoneNumber: represent a phone number class LIB_EXPORT PhoneNumber : public QObject { Q_OBJECT public: friend class PhoneDirectoryModel; + friend class PrivatePhoneNumber; virtual ~PhoneNumber(); //Properties @@ -126,10 +130,6 @@ protected: //Constructor PhoneNumber(const QString& uri, NumberCategory* cat, Type st = Type::UNUSED); - //Attributes - QString m_Uri ; - PhoneNumber::Type m_Type ; - //Helper static QString stripUri(const QString& uri); @@ -137,10 +137,25 @@ protected: void setPresent(bool present); void setPresenceMessage(const QString& message); + //PhoneDirectoryModel mutator + bool merge(PhoneNumber* other); + + //Getter + bool hasType() const; + int index() const; + + //Setter + void setHasType(bool value); + void setIndex(int value); + void setPopularityIndex(int value); + + //Many phone numbers can have the same "d" if they were merged + QSharedPointer<PrivatePhoneNumber> d; + private: friend class PhoneNumberPrivate; - //Attributes + /*//Attributes NumberCategory* m_pCategory ; bool m_Present ; QString m_PresentMessage ; @@ -160,7 +175,7 @@ private: bool m_IsBookmark ; int m_TotalSeconds ; QString m_Uid ; - QString m_PrimaryName_cache; + QString m_PrimaryName_cache;*/ //Static attributes static QHash<int,Call*> m_shMostUsed ; -- GitLab