mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-05-07 14:44:01 +00:00
feat(src/components/contacts/ContactsListModel): on contact creation, try to merge with existing contact
This commit is contained in:
parent
abe5bbdddc
commit
78958055f8
5 changed files with 113 additions and 24 deletions
|
|
@ -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 ();
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue