Commit 4f16551b authored by Ronan Abhamon's avatar Ronan Abhamon

feat(src/components/contact/VcardModel): api refactoring and better usage (avatars broken)

parent 5537900b
......@@ -31,7 +31,7 @@ using namespace std;
AuthenticationNotifier::AuthenticationNotifier (QObject *parent) : QObject(parent) {
QObject::connect(
&(*CoreManager::getInstance()->getHandlers()), &CoreHandlers::authenticationRequested,
CoreManager::getInstance()->getHandlers().get(), &CoreHandlers::authenticationRequested,
this, &AuthenticationNotifier::handleAuthenticationRequested
);
}
......
......@@ -57,7 +57,7 @@ CallModel::CallModel (shared_ptr<linphone::Call> call) {
}
QObject::connect(
&(*CoreManager::getInstance()->getHandlers()), &CoreHandlers::callStateChanged,
CoreManager::getInstance()->getHandlers().get(), &CoreHandlers::callStateChanged,
this, [this](const shared_ptr<linphone::Call> &call, linphone::CallState state) {
if (call != mCall)
return;
......
......@@ -52,7 +52,7 @@ inline QList<CallModel *>::iterator findCallModel (
CallsListModel::CallsListModel (QObject *parent) : QAbstractListModel(parent) {
mCoreHandlers = CoreManager::getInstance()->getHandlers();
QObject::connect(
&(*mCoreHandlers), &CoreHandlers::callStateChanged,
mCoreHandlers.get(), &CoreHandlers::callStateChanged,
this, [this](const shared_ptr<linphone::Call> &call, linphone::CallState state) {
switch (state) {
case linphone::CallStateIncomingReceived:
......@@ -195,7 +195,7 @@ void CallsListModel::removeCall (const shared_ptr<linphone::Call> &call) {
} catch (const out_of_range &) {
// Can be a bug. Or the call model not exists because the linphone call state
// `CallStateIncomingReceived`/`CallStateOutgoingInit` was not notified.
qWarning() << QStringLiteral("Unable to found linphone call:") << &(*call);
qWarning() << QStringLiteral("Unable to found linphone call:") << call.get();
return;
}
......
......@@ -179,8 +179,8 @@ ChatModel::ChatModel (QObject *parent) : QAbstractListModel(parent) {
core->getSipAddressesModel()->connectToChatModel(this);
QObject::connect(&(*mCoreHandlers), &CoreHandlers::messageReceived, this, &ChatModel::handleMessageReceived);
QObject::connect(&(*mCoreHandlers), &CoreHandlers::callStateChanged, this, &ChatModel::handleCallStateChanged);
QObject::connect(mCoreHandlers.get(), &CoreHandlers::messageReceived, this, &ChatModel::handleMessageReceived);
QObject::connect(mCoreHandlers.get(), &CoreHandlers::callStateChanged, this, &ChatModel::handleCallStateChanged);
}
ChatModel::~ChatModel () {
......
......@@ -34,32 +34,21 @@ ContactModel::ContactModel (QObject *parent, shared_ptr<linphone::Friend> linpho
Q_ASSERT(linphoneFriend != nullptr);
mLinphoneFriend = linphoneFriend;
mVcardModel = new VcardModel(linphoneFriend->getVcard());
App::getInstance()->getEngine()->setObjectOwnership(mVcardModel, QQmlEngine::CppOwnership);
mLinphoneFriend->setData("contact-model", *this);
setVcardModelInternal(new VcardModel(linphoneFriend->getVcard()));
}
ContactModel::ContactModel (QObject *parent, VcardModel *vcardModel) : QObject(parent) {
Q_ASSERT(vcardModel != nullptr);
QQmlEngine *engine = App::getInstance()->getEngine();
if (engine->objectOwnership(vcardModel) == QQmlEngine::CppOwnership) {
qWarning() << QStringLiteral("A contact is already linked to this vcard:") << vcardModel;
abort();
}
Q_ASSERT(vcardModel->mVcard != nullptr);
Q_ASSERT(!vcardModel->mIsReadOnly);
mLinphoneFriend = linphone::Friend::newFromVcard(vcardModel->mVcard);
mLinphoneFriend->setData("contact-model", *this);
mVcardModel = vcardModel;
engine->setObjectOwnership(vcardModel, QQmlEngine::CppOwnership);
qInfo() << QStringLiteral("Create contact from vcard:") << this << vcardModel;
setVcardModelInternal(vcardModel);
}
// -----------------------------------------------------------------------------
......@@ -75,18 +64,47 @@ void ContactModel::refreshPresence () {
// -----------------------------------------------------------------------------
void ContactModel::startEdit () {
mLinphoneFriend->edit();
mOldSipAddresses = mVcardModel->getSipAddresses();
VcardModel *ContactModel::getVcardModel () const {
return mVcardModel;
}
void ContactModel::endEdit () {
void ContactModel::setVcardModel (VcardModel *vcardModel) {
VcardModel *oldVcardModel = mVcardModel;
qInfo() << QStringLiteral("Remove vcard on contact:") << this << oldVcardModel;
oldVcardModel->mIsReadOnly = false;
oldVcardModel->mAvatarIsReadOnly = vcardModel->getAvatar() == oldVcardModel->getAvatar();
oldVcardModel->deleteLater();
qInfo() << QStringLiteral("Set vcard on contact:") << this << vcardModel;
setVcardModelInternal(vcardModel);
// Flush vcard.
mLinphoneFriend->done();
updateSipAddresses(oldVcardModel);
}
void ContactModel::setVcardModelInternal (VcardModel *vcardModel) {
Q_ASSERT(vcardModel != nullptr);
Q_ASSERT(vcardModel != mVcardModel);
mVcardModel = vcardModel;
mVcardModel->mAvatarIsReadOnly = false;
mVcardModel->mIsReadOnly = true;
App::getInstance()->getEngine()->setObjectOwnership(mVcardModel, QQmlEngine::CppOwnership);
if (mLinphoneFriend->getVcard() != vcardModel->mVcard)
mLinphoneFriend->setVcard(vcardModel->mVcard);
}
void ContactModel::updateSipAddresses (VcardModel *oldVcardModel) {
QVariantList oldSipAddresses = oldVcardModel->getSipAddresses();
QVariantList sipAddresses = mVcardModel->getSipAddresses();
QSet<QString> done;
for (const auto &variantA : mOldSipAddresses) {
for (const auto &variantA : oldSipAddresses) {
next:
const QString &sipAddress = variantA.toString();
if (done.contains(sipAddress))
......@@ -102,7 +120,7 @@ next:
emit sipAddressRemoved(sipAddress);
}
mOldSipAddresses.clear();
oldSipAddresses.clear();
for (const auto &variant : sipAddresses) {
const QString &sipAddress = variant.toString();
......@@ -116,10 +134,21 @@ next:
emit contactUpdated();
}
void ContactModel::abortEdit () {
mOldSipAddresses.clear();
// -----------------------------------------------------------------------------
emit contactUpdated();
VcardModel *ContactModel::cloneVcardModel () const {
shared_ptr<linphone::Vcard> vcard = mVcardModel->mVcard->clone();
Q_ASSERT(vcard != nullptr);
Q_ASSERT(vcard->getVcard() != nullptr);
mLinphoneFriend->edit();
VcardModel *vcardModel = new VcardModel(vcard);
vcardModel->mIsReadOnly = false;
qInfo() << QStringLiteral("Clone vcard from contact:") << this << vcardModel;
return vcardModel;
}
// -----------------------------------------------------------------------------
......@@ -131,24 +160,3 @@ Presence::PresenceStatus ContactModel::getPresenceStatus () const {
Presence::PresenceLevel ContactModel::getPresenceLevel () const {
return Presence::getPresenceLevel(getPresenceStatus());
}
// -----------------------------------------------------------------------------
VcardModel *ContactModel::getVcardModel () const {
return mVcardModel;
}
void ContactModel::setVcardModel (VcardModel *vcardModel) {
Q_ASSERT(vcardModel != nullptr);
Q_ASSERT(vcardModel != mVcardModel);
QQmlEngine *engine = App::getInstance()->getEngine();
engine->setObjectOwnership(vcardModel, QQmlEngine::CppOwnership);
engine->setObjectOwnership(mVcardModel, QQmlEngine::JavaScriptOwnership);
qInfo() << QStringLiteral("Set vcard on contact:") << this << vcardModel;
qInfo() << QStringLiteral("Remove vcard on contact:") << this << mVcardModel;
mLinphoneFriend->setVcard(vcardModel->mVcard);
mVcardModel = vcardModel;
}
......@@ -47,13 +47,11 @@ public:
void refreshPresence ();
Q_INVOKABLE void startEdit ();
Q_INVOKABLE void endEdit ();
Q_INVOKABLE void abortEdit ();
VcardModel *getVcardModel () const;
void setVcardModel (VcardModel *vcardModel);
Q_INVOKABLE VcardModel *cloneVcardModel () const;
signals:
void contactUpdated ();
......@@ -63,11 +61,12 @@ signals:
void sipAddressRemoved (const QString &sipAddress);
private:
void setVcardModelInternal (VcardModel *vcardModel);
void updateSipAddresses (VcardModel *oldVcardModel);
Presence::PresenceStatus getPresenceStatus () const;
Presence::PresenceLevel getPresenceLevel () const;
QVariantList mOldSipAddresses;
VcardModel *mVcardModel;
std::shared_ptr<linphone::Friend> mLinphoneFriend;
};
......
......@@ -36,6 +36,8 @@
#define VCARD_SCHEME "linphone-desktop:/"
#define CHECK_VCARD_IS_WRITABLE(VCARD) Q_ASSERT(VCARD->mIsReadOnly == false)
using namespace std;
// =============================================================================
......@@ -93,10 +95,13 @@ VcardModel::VcardModel (shared_ptr<linphone::Vcard> vcard) {
}
VcardModel::~VcardModel () {
// If it's a detached Vcard and if necessary the linked photo must be destroyed from fs.
if (App::getInstance()->getEngine()->objectOwnership(this) != QQmlEngine::CppOwnership) {
if (!mIsReadOnly) {
qInfo() << QStringLiteral("Destroy detached vcard:") << this;
// If it's a detached Vcard and if necessary the linked photo must be destroyed from fs.
if (mAvatarIsReadOnly)
return;
shared_ptr<belcard::BelCardPhoto> photo(findBelcardPhoto(mVcard->getVcard()));
if (!photo)
return;
......@@ -116,19 +121,6 @@ VcardModel::~VcardModel () {
// -----------------------------------------------------------------------------
VcardModel *VcardModel::clone () const {
shared_ptr<linphone::Vcard> vcard = mVcard->clone();
Q_ASSERT(vcard != nullptr);
Q_ASSERT(vcard->getVcard() != nullptr);
VcardModel *vcardModel = new VcardModel(vcard);
qInfo() << QStringLiteral("Clone vcard:") << this << vcardModel;
return vcardModel;
}
// -----------------------------------------------------------------------------
QString VcardModel::getAvatar () const {
// Find desktop avatar.
shared_ptr<belcard::BelCardPhoto> photo = findBelcardPhoto(mVcard->getVcard());
......@@ -144,6 +136,8 @@ QString VcardModel::getAvatar () const {
}
bool VcardModel::setAvatar (const QString &path) {
CHECK_VCARD_IS_WRITABLE(this);
shared_ptr<belcard::BelCard> belcard = mVcard->getVcard();
// Remove avatar if path is empty.
......@@ -174,7 +168,9 @@ bool VcardModel::setAvatar (const QString &path) {
qInfo() << QStringLiteral("Update avatar of `%1`. (path=%2)").arg(getUsername()).arg(dest);
// 2. Remove oldest photo.
removeBelcardPhoto(belcard);
if (!mAvatarIsReadOnly)
removeBelcardPhoto(belcard);
mAvatarIsReadOnly = false;
// 3. Update new photo.
shared_ptr<belcard::BelCardPhoto> photo = belcard::BelCardGeneric::create<belcard::BelCardPhoto>();
......@@ -195,6 +191,8 @@ QString VcardModel::getUsername () const {
}
void VcardModel::setUsername (const QString &username) {
CHECK_VCARD_IS_WRITABLE(this);
if (username.length() == 0 || username == getUsername())
return;
......@@ -235,24 +233,32 @@ QVariantMap VcardModel::getAddress () const {
}
void VcardModel::setStreet (const QString &street) {
CHECK_VCARD_IS_WRITABLE(this);
shared_ptr<belcard::BelCardAddress> address = getOrCreateBelCardAddress(mVcard->getVcard());
address->setStreet(::Utils::qStringToLinphoneString(street));
emit vcardUpdated();
}
void VcardModel::setLocality (const QString &locality) {
CHECK_VCARD_IS_WRITABLE(this);
shared_ptr<belcard::BelCardAddress> address = getOrCreateBelCardAddress(mVcard->getVcard());
address->setLocality(::Utils::qStringToLinphoneString(locality));
emit vcardUpdated();
}
void VcardModel::setPostalCode (const QString &postalCode) {
CHECK_VCARD_IS_WRITABLE(this);
shared_ptr<belcard::BelCardAddress> address = getOrCreateBelCardAddress(mVcard->getVcard());
address->setPostalCode(::Utils::qStringToLinphoneString(postalCode));
emit vcardUpdated();
}
void VcardModel::setCountry (const QString &country) {
CHECK_VCARD_IS_WRITABLE(this);
shared_ptr<belcard::BelCardAddress> address = getOrCreateBelCardAddress(mVcard->getVcard());
address->setCountry(::Utils::qStringToLinphoneString(country));
emit vcardUpdated();
......@@ -276,6 +282,8 @@ QVariantList VcardModel::getSipAddresses () const {
}
bool VcardModel::addSipAddress (const QString &sipAddress) {
CHECK_VCARD_IS_WRITABLE(this);
// Check sip address format.
shared_ptr<linphone::Address> linphoneAddress = CoreManager::getInstance()->getCore()->interpretUrl(
::Utils::qStringToLinphoneString(sipAddress)
......@@ -303,6 +311,8 @@ bool VcardModel::addSipAddress (const QString &sipAddress) {
}
void VcardModel::removeSipAddress (const QString &sipAddress) {
CHECK_VCARD_IS_WRITABLE(this);
shared_ptr<belcard::BelCard> belcard = mVcard->getVcard();
list<shared_ptr<belcard::BelCardImpp> > addresses = belcard->getImpp();
shared_ptr<belcard::BelCardImpp> value = findBelCardValue(addresses, sipAddress);
......@@ -325,12 +335,8 @@ void VcardModel::removeSipAddress (const QString &sipAddress) {
}
bool VcardModel::updateSipAddress (const QString &oldSipAddress, const QString &sipAddress) {
if (oldSipAddress == sipAddress || !addSipAddress(sipAddress))
return false;
removeSipAddress(oldSipAddress);
return true;
return addSipAddress(sipAddress);
}
// -----------------------------------------------------------------------------
......@@ -345,6 +351,8 @@ QVariantList VcardModel::getCompanies () const {
}
bool VcardModel::addCompany (const QString &company) {
CHECK_VCARD_IS_WRITABLE(this);
shared_ptr<belcard::BelCard> belcard = mVcard->getVcard();
shared_ptr<belcard::BelCardRole> value = belcard::BelCardGeneric::create<belcard::BelCardRole>();
value->setValue(::Utils::qStringToLinphoneString(company));
......@@ -361,6 +369,8 @@ bool VcardModel::addCompany (const QString &company) {
}
void VcardModel::removeCompany (const QString &company) {
CHECK_VCARD_IS_WRITABLE(this);
shared_ptr<belcard::BelCard> belcard = mVcard->getVcard();
shared_ptr<belcard::BelCardRole> value = findBelCardValue(belcard->getRoles(), company);
......@@ -376,12 +386,8 @@ void VcardModel::removeCompany (const QString &company) {
}
bool VcardModel::updateCompany (const QString &oldCompany, const QString &company) {
if (oldCompany == company || !addCompany(company))
return false;
removeCompany(oldCompany);
return true;
return addCompany(company);
}
// -----------------------------------------------------------------------------
......@@ -396,6 +402,8 @@ QVariantList VcardModel::getEmails () const {
}
bool VcardModel::addEmail (const QString &email) {
CHECK_VCARD_IS_WRITABLE(this);
shared_ptr<belcard::BelCard> belcard = mVcard->getVcard();
shared_ptr<belcard::BelCardEmail> value = belcard::BelCardGeneric::create<belcard::BelCardEmail>();
value->setValue(::Utils::qStringToLinphoneString(email));
......@@ -412,6 +420,8 @@ bool VcardModel::addEmail (const QString &email) {
}
void VcardModel::removeEmail (const QString &email) {
CHECK_VCARD_IS_WRITABLE(this);
shared_ptr<belcard::BelCard> belcard = mVcard->getVcard();
shared_ptr<belcard::BelCardEmail> value = findBelCardValue(belcard->getEmails(), email);
......@@ -427,12 +437,8 @@ void VcardModel::removeEmail (const QString &email) {
}
bool VcardModel::updateEmail (const QString &oldEmail, const QString &email) {
if (oldEmail == email || !addEmail(email))
return false;
removeEmail(oldEmail);
return true;
return addEmail(email);
}
// -----------------------------------------------------------------------------
......@@ -447,6 +453,8 @@ QVariantList VcardModel::getUrls () const {
}
bool VcardModel::addUrl (const QString &url) {
CHECK_VCARD_IS_WRITABLE(this);
shared_ptr<belcard::BelCard> belcard = mVcard->getVcard();
shared_ptr<belcard::BelCardURL> value = belcard::BelCardGeneric::create<belcard::BelCardURL>();
value->setValue(::Utils::qStringToLinphoneString(url));
......@@ -463,6 +471,8 @@ bool VcardModel::addUrl (const QString &url) {
}
void VcardModel::removeUrl (const QString &url) {
CHECK_VCARD_IS_WRITABLE(this);
shared_ptr<belcard::BelCard> belcard = mVcard->getVcard();
shared_ptr<belcard::BelCardURL> value = findBelCardValue(belcard->getURLs(), url);
......@@ -478,10 +488,6 @@ void VcardModel::removeUrl (const QString &url) {
}
bool VcardModel::updateUrl (const QString &oldUrl, const QString &url) {
if (oldUrl == url || !addUrl(url))
return false;
removeUrl(oldUrl);
return true;
return addUrl(url);
}
......@@ -50,6 +50,12 @@ public:
// ---------------------------------------------------------------------------
bool getIsReadOnly () const {
return mIsReadOnly;
}
// ---------------------------------------------------------------------------
QString getAvatar () const;
bool setAvatar (const QString &path);
......@@ -66,8 +72,6 @@ public:
// ---------------------------------------------------------------------------
Q_INVOKABLE VcardModel *clone () const;
Q_INVOKABLE bool addSipAddress (const QString &sipAddress);
Q_INVOKABLE void removeSipAddress (const QString &sipAddress);
Q_INVOKABLE bool updateSipAddress (const QString &oldSipAddress, const QString &sipAddress);
......@@ -97,6 +101,9 @@ signals:
// ---------------------------------------------------------------------------
private:
bool mIsReadOnly = true;
bool mAvatarIsReadOnly = true;
std::shared_ptr<linphone::Vcard> mVcard;
};
......
......@@ -143,9 +143,9 @@ void ContactsListModel::cleanAvatars () {
qInfo() << QStringLiteral("Delete all avatars.");
for (const auto &contact : mList) {
contact->startEdit();
contact->getVcardModel()->setAvatar("");
contact->endEdit();
VcardModel *vcardModel = contact->cloneVcardModel();
vcardModel->setAvatar("");
contact->setVcardModel(vcardModel);
}
}
......
......@@ -52,7 +52,7 @@ inline AccountSettingsModel::RegistrationState mapLinphoneRegistrationStateToUi
AccountSettingsModel::AccountSettingsModel (QObject *parent) : QObject(parent) {
QObject::connect(
&(*CoreManager::getInstance()->getHandlers()), &CoreHandlers::registrationStateChanged,
CoreManager::getInstance()->getHandlers().get(), &CoreHandlers::registrationStateChanged,
this, &AccountSettingsModel::handleRegistrationStateChanged
);
}
......
......@@ -47,9 +47,9 @@ SipAddressesModel::SipAddressesModel (QObject *parent) : QAbstractListModel(pare
QObject::connect(contacts, &ContactsListModel::sipAddressAdded, this, &SipAddressesModel::handleSipAddressAdded);
QObject::connect(contacts, &ContactsListModel::sipAddressRemoved, this, &SipAddressesModel::handleSipAddressRemoved);
QObject::connect(&(*mCoreHandlers), &CoreHandlers::messageReceived, this, &SipAddressesModel::handleMessageReceived);
QObject::connect(&(*mCoreHandlers), &CoreHandlers::callStateChanged, this, &SipAddressesModel::handleCallStateChanged);
QObject::connect(&(*mCoreHandlers), &CoreHandlers::presenceReceived, this, &SipAddressesModel::handlePresenceReceived);
QObject::connect(mCoreHandlers.get(), &CoreHandlers::messageReceived, this, &SipAddressesModel::handleMessageReceived);
QObject::connect(mCoreHandlers.get(), &CoreHandlers::callStateChanged, this, &SipAddressesModel::handleCallStateChanged);
QObject::connect(mCoreHandlers.get(), &CoreHandlers::presenceReceived, this, &SipAddressesModel::handlePresenceReceived);
}
// -----------------------------------------------------------------------------
......
......@@ -17,7 +17,7 @@ function handleContactUpdated () {
} else {
// Edition not ended, the contact was updated in other place.
// Update fields with new data.
contactEdit._vcard = contact.vcard.clone()
contactEdit._vcard = contact.cloneVcardModel()
}
}
......@@ -59,9 +59,7 @@ function handleVcardChanged (vcard) {
function editContact () {
var contact = contactEdit._contact
contact.startEdit()
contactEdit._vcard = contact.vcard.clone()
contactEdit._vcard = contact.cloneVcardModel()
contactEdit._edition = true
window.lockView({
......@@ -91,7 +89,6 @@ function save () {
if (contact) {
contact.vcard = vcard
contact.endEdit()
window.unlockView()
} else {
contactEdit._contact = Linphone.ContactsListModel.addContact(vcard)
......@@ -103,7 +100,6 @@ function cancel () {
if (contact) {
contactEdit._vcard = contact.vcard
contact.abortEdit()
window.unlockView()
contactEdit._edition = false
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment