From f26e5e937520a93069a26edabd95386e38e0023f Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> Date: Mon, 16 Dec 2013 12:12:40 -0500 Subject: [PATCH] [ #36988 ] Fix a race condition when changing the number of PhoneNumbers --- src/contact.cpp | 7 ++++++- src/contact.h | 2 ++ src/contactproxymodel.cpp | 27 ++++++++++++++++++++++++++- src/contactproxymodel.h | 4 +++- 4 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/contact.cpp b/src/contact.cpp index 96d544d3..3bc1ecd1 100644 --- a/src/contact.cpp +++ b/src/contact.cpp @@ -121,14 +121,19 @@ const QString& Contact::department() const return m_Department; } -///Set the phone number (type and number) +///Set the phone number (type and number) void Contact::setPhoneNumbers(PhoneNumbers numbers) { + const int oldCount(m_Numbers.size()),newCount(numbers.size()); foreach(PhoneNumber* n, m_Numbers) disconnect(n,SIGNAL(presentChanged(bool)),this,SLOT(slotPresenceChanged())); m_Numbers = numbers; + if (newCount < oldCount) //Rows need to be removed from models first + emit phoneNumberCountAboutToChange(newCount,oldCount); foreach(PhoneNumber* n, m_Numbers) connect(n,SIGNAL(presentChanged(bool)),this,SLOT(slotPresenceChanged())); + if (newCount > oldCount) //Need to be updated after the data to prevent invalid memory access + emit phoneNumberCountChanged(newCount,oldCount); emit changed(); } diff --git a/src/contact.h b/src/contact.h index 8e6a4118..5ad75034 100644 --- a/src/contact.h +++ b/src/contact.h @@ -133,6 +133,8 @@ Q_SIGNALS: void presenceChanged( PhoneNumber* ); void statusChanged ( bool ); void changed ( ); + void phoneNumberCountChanged(int,int); + void phoneNumberCountAboutToChange(int,int); protected: //Presence secret methods diff --git a/src/contactproxymodel.cpp b/src/contactproxymodel.cpp index b96f4de6..d7a44fa0 100644 --- a/src/contactproxymodel.cpp +++ b/src/contactproxymodel.cpp @@ -94,6 +94,8 @@ ContactTreeBinder::ContactTreeBinder(ContactProxyModel* m,ContactTreeNode* n) : QObject(),m_pTreeNode(n),m_pModel(m) { connect(n->m_pContact,SIGNAL(changed()),this,SLOT(slotContactChanged())); + connect(n->m_pContact,SIGNAL(phoneNumberCountChanged(int,int)),this,SLOT(slotPhoneNumberCountChanged(int,int))); + connect(n->m_pContact,SIGNAL(phoneNumberCountAboutToChange(int,int)),this,SLOT(slotPhoneNumberCountAboutToChange(int,int))); } @@ -101,7 +103,9 @@ void ContactTreeBinder::slotContactChanged() { const QModelIndex idx = m_pModel->index(m_pTreeNode->m_Index,0,m_pModel->index(m_pTreeNode->m_pParent3->m_Index,0)); const QModelIndex lastPhoneIdx = m_pModel->index(m_pTreeNode->m_pContact->phoneNumbers().size()-1,0,idx); - emit m_pModel->dataChanged(idx,lastPhoneIdx); + emit m_pModel->dataChanged(idx,idx); + if (lastPhoneIdx.isValid()) //Need to be done twice + emit m_pModel->dataChanged(m_pModel->index(0,0,idx),lastPhoneIdx); } void ContactTreeBinder::slotStatusChanged() @@ -109,6 +113,27 @@ void ContactTreeBinder::slotStatusChanged() } +void ContactTreeBinder::slotPhoneNumberCountChanged(int count, int oldCount) +{ + const QModelIndex idx = m_pModel->index(m_pTreeNode->m_Index,0,m_pModel->index(m_pTreeNode->m_pParent3->m_Index,0)); + if (count > oldCount) { + const QModelIndex lastPhoneIdx = m_pModel->index(oldCount-1,0,idx); + m_pModel->beginInsertRows(idx,oldCount,count-1); + m_pModel->endInsertRows(); + } + emit m_pModel->dataChanged(idx,idx); +} + +void ContactTreeBinder::slotPhoneNumberCountAboutToChange(int count, int oldCount) +{ + const QModelIndex idx = m_pModel->index(m_pTreeNode->m_Index,0,m_pModel->index(m_pTreeNode->m_pParent3->m_Index,0)); + if (count < oldCount) { + //If count == 1, disable all children + m_pModel->beginRemoveRows(idx,count == 1?0:count,oldCount-1); + m_pModel->endRemoveRows(); + } +} + // ContactProxyModel::ContactProxyModel(AbstractContactBackend* parent,int role, bool showAll) : QAbstractItemModel(QCoreApplication::instance()), m_pModel(parent),m_Role(role),m_ShowAll(showAll),m_lCategoryCounter() diff --git a/src/contactproxymodel.h b/src/contactproxymodel.h index f9454c43..a655a7db 100644 --- a/src/contactproxymodel.h +++ b/src/contactproxymodel.h @@ -85,7 +85,7 @@ private Q_SLOTS: void slotContactAdded(Contact* c); }; -class ContactTreeBinder : public QObject { +class ContactTreeBinder : public QObject { //FIXME Qt5 remove when dropping Qt4 Q_OBJECT public: ContactTreeBinder(ContactProxyModel* m,ContactTreeNode* n); @@ -95,6 +95,8 @@ private: private Q_SLOTS: void slotContactChanged(); void slotStatusChanged(); + void slotPhoneNumberCountChanged(int,int); + void slotPhoneNumberCountAboutToChange(int,int); }; #endif -- GitLab