Commit 78958055 authored by Ronan's avatar Ronan
Browse files

feat(src/components/contacts/ContactsListModel): on contact creation, try to...

feat(src/components/contacts/ContactsListModel): on contact creation, try to merge with existing contact
parent abe5bbdd
......@@ -138,6 +138,50 @@ next:
// -----------------------------------------------------------------------------
void ContactModel::mergeVcardModel (VcardModel *vcardModel) {
Q_ASSERT(vcardModel != nullptr);
qInfo() << QStringLiteral("Merge vcard into contact:") << this << vcardModel;
// 1. Merge avatar.
if (vcardModel->getAvatar().isEmpty())
vcardModel->setAvatar(mVcardModel->getAvatar());
// 2. Merge sip addresses, companies, emails and urls.
for (const auto &sipAddress : mVcardModel->getSipAddresses())
vcardModel->addSipAddress(sipAddress.toString());
for (const auto &company : mVcardModel->getCompanies())
vcardModel->addCompany(company.toString());
for (const auto &email : mVcardModel->getEmails())
vcardModel->addEmail(email.toString());
for (const auto &url : mVcardModel->getUrls())
vcardModel->addUrl(url.toString());
// 3. Merge address.
{
const QVariantMap &oldAddress = vcardModel->getAddress();
QVariantMap newAddress = vcardModel->getAddress();
static const char *attributes[4] = { "street", "locality", "postalCode", "country" };
bool needMerge = true;
for (const auto &attribute : attributes)
if (!newAddress[attribute].toString().isEmpty()) {
needMerge = false;
break;
}
if (needMerge) {
for (const auto &attribute : attributes)
newAddress[attribute] = oldAddress[attribute];
}
}
setVcardModel(vcardModel);
}
// -----------------------------------------------------------------------------
VcardModel *ContactModel::cloneVcardModel () const {
shared_ptr<linphone::Vcard> vcard = mVcardModel->mVcard->clone();
Q_ASSERT(vcard != nullptr);
......
......@@ -50,6 +50,8 @@ public:
VcardModel *getVcardModel () const;
void setVcardModel (VcardModel *vcardModel);
void mergeVcardModel (VcardModel *vcardModel);
Q_INVOKABLE VcardModel *cloneVcardModel () const;
signals:
......
......@@ -43,18 +43,21 @@ using namespace std;
// =============================================================================
template<class T>
inline shared_ptr<T> findBelCardValue (const list<shared_ptr<T> > &list, const QString &value) {
string match = ::Utils::qStringToLinphoneString(value);
inline shared_ptr<T> findBelCardValue (const list<shared_ptr<T> > &list, const string &value) {
auto it = find_if(
list.cbegin(), list.cend(), [&match](const shared_ptr<T> &entry) {
return match == entry->getValue();
list.cbegin(), list.cend(), [&value](const shared_ptr<T> &entry) {
return value == entry->getValue();
}
);
return it != list.cend() ? *it : nullptr;
}
template<class T>
inline shared_ptr<T> findBelCardValue (const list<shared_ptr<T> > &list, const QString &value) {
return findBelCardValue(list, ::Utils::qStringToLinphoneString(value));
}
inline bool isLinphoneDesktopPhoto (const shared_ptr<belcard::BelCardPhoto> &photo) {
return !photo->getValue().compare(0, sizeof(VCARD_SCHEME) - 1, VCARD_SCHEME);
}
......@@ -141,6 +144,11 @@ QString VcardModel::getAvatar () const {
);
}
inline QString getFileIdFromAppPath (const QString &path) {
const static QString appPrefix = QStringLiteral("image://%1/").arg(AvatarProvider::PROVIDER_ID);
return path.mid(appPrefix.length());
}
bool VcardModel::setAvatar (const QString &path) {
CHECK_VCARD_IS_WRITABLE(this);
......@@ -148,25 +156,30 @@ bool VcardModel::setAvatar (const QString &path) {
QString fileId;
QFile file;
// 1. Try to copy photo in avatars folder.
// 1. Try to copy photo in avatars folder if it's a right path file and
// not a application path like `image:`.
if (!path.isEmpty()) {
file.setFileName(path);
if (path.startsWith("image:"))
fileId = getFileIdFromAppPath(path);
else {
file.setFileName(path);
if (!file.exists() || QImageReader::imageFormat(path).size() == 0)
return false;
if (!file.exists() || QImageReader::imageFormat(path).size() == 0)
return false;
QFileInfo info(file);
QString uuid = QUuid::createUuid().toString();
fileId = QStringLiteral("%1.%2")
.arg(uuid.mid(1, uuid.length() - 2)) // Remove `{}`.
.arg(info.suffix());
QFileInfo info(file);
QString uuid = QUuid::createUuid().toString();
fileId = QStringLiteral("%1.%2")
.arg(uuid.mid(1, uuid.length() - 2)) // Remove `{}`.
.arg(info.suffix());
QString dest = ::Utils::linphoneStringToQString(Paths::getAvatarsDirPath()) + fileId;
QString dest = ::Utils::linphoneStringToQString(Paths::getAvatarsDirPath()) + fileId;
if (!file.copy(dest))
return false;
if (!file.copy(dest))
return false;
qInfo() << QStringLiteral("Update avatar of `%1`. (path=%2)").arg(getUsername()).arg(dest);
qInfo() << QStringLiteral("Update avatar of `%1`. (path=%2)").arg(getUsername()).arg(dest);
}
}
// 2. Remove oldest photo.
......@@ -298,6 +311,9 @@ bool VcardModel::addSipAddress (const QString &sipAddress) {
// Add sip address in belcard.
shared_ptr<belcard::BelCard> belcard = mVcard->getVcard();
if (findBelCardValue(belcard->getImpp(), interpretedSipAddress))
return false;
shared_ptr<belcard::BelCardImpp> value = belcard::BelCardGeneric::create<belcard::BelCardImpp>();
value->setValue(interpretedSipAddress);
......@@ -359,6 +375,9 @@ bool VcardModel::addCompany (const QString &company) {
CHECK_VCARD_IS_WRITABLE(this);
shared_ptr<belcard::BelCard> belcard = mVcard->getVcard();
if (findBelCardValue(belcard->getRoles(), company))
return false;
shared_ptr<belcard::BelCardRole> value = belcard::BelCardGeneric::create<belcard::BelCardRole>();
value->setValue(::Utils::qStringToLinphoneString(company));
......@@ -410,6 +429,9 @@ bool VcardModel::addEmail (const QString &email) {
CHECK_VCARD_IS_WRITABLE(this);
shared_ptr<belcard::BelCard> belcard = mVcard->getVcard();
if (findBelCardValue(belcard->getEmails(), email))
return false;
shared_ptr<belcard::BelCardEmail> value = belcard::BelCardGeneric::create<belcard::BelCardEmail>();
value->setValue(::Utils::qStringToLinphoneString(email));
......@@ -421,6 +443,7 @@ bool VcardModel::addEmail (const QString &email) {
qInfo() << QStringLiteral("Add new email on vcard: `%1`.").arg(email);
emit vcardUpdated();
return true;
}
......@@ -461,6 +484,9 @@ bool VcardModel::addUrl (const QString &url) {
CHECK_VCARD_IS_WRITABLE(this);
shared_ptr<belcard::BelCard> belcard = mVcard->getVcard();
if (findBelCardValue(belcard->getURLs(), url))
return false;
shared_ptr<belcard::BelCardURL> value = belcard::BelCardGeneric::create<belcard::BelCardURL>();
value->setValue(::Utils::qStringToLinphoneString(url));
......@@ -472,6 +498,7 @@ bool VcardModel::addUrl (const QString &url) {
qInfo() << QStringLiteral("Add new url on vcard: `%1`.").arg(url);
emit vcardUpdated();
return true;
}
......
......@@ -113,29 +113,44 @@ bool ContactsListModel::removeRows (int row, int count, const QModelIndex &paren
// -----------------------------------------------------------------------------
ContactModel *ContactsListModel::findContactModelFromSipAddress (const QString &sipAddress) const {
auto it = find_if(mList.begin(), mList.end(), [sipAddress](ContactModel *contactModel) {
auto it = find_if(mList.begin(), mList.end(), [&sipAddress](ContactModel *contactModel) {
return contactModel->getVcardModel()->getSipAddresses().contains(sipAddress);
});
return it != mList.end() ? *it : nullptr;
}
ContactModel *ContactsListModel::findContactModelFromUsername (const QString &username) const {
auto it = find_if(mList.begin(), mList.end(), [&username](ContactModel *contactModel) {
return contactModel->getVcardModel()->getUsername() == username;
});
return it != mList.end() ? *it : nullptr;
}
// -----------------------------------------------------------------------------
ContactModel *ContactsListModel::addContact (VcardModel *vcard) {
ContactModel *contact = new ContactModel(this, vcard);
ContactModel *ContactsListModel::addContact (VcardModel *vcardModel) {
// Try to merge vcardModel to an existing contact.
ContactModel *contact = findContactModelFromUsername(vcardModel->getUsername());
if (contact) {
contact->mergeVcardModel(vcardModel);
return contact;
}
contact = new ContactModel(this, vcardModel);
App::getInstance()->getEngine()->setObjectOwnership(contact, QQmlEngine::CppOwnership);
if (
mLinphoneFriends->addFriend(contact->mLinphoneFriend) !=
linphone::FriendListStatus::FriendListStatusOK
) {
qWarning() << QStringLiteral("Unable to add contact from vcard:") << vcard;
qWarning() << QStringLiteral("Unable to add contact from vcard:") << vcardModel;
delete contact;
return nullptr;
}
qInfo() << QStringLiteral("Add contact from vcard:") << contact << vcard;
qInfo() << QStringLiteral("Add contact from vcard:") << contact << vcardModel;
int row = mList.count();
......
......@@ -48,8 +48,9 @@ public:
bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override;
ContactModel *findContactModelFromSipAddress (const QString &sipAddress) const;
ContactModel *findContactModelFromUsername (const QString &username) const;
Q_INVOKABLE ContactModel *addContact (VcardModel *vcard);
Q_INVOKABLE ContactModel *addContact (VcardModel *vcardModel);
Q_INVOKABLE void removeContact (ContactModel *contact);
Q_INVOKABLE void cleanAvatars ();
......
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