From f4c56c99c341c1e5bdd191e82e68e78a366540af Mon Sep 17 00:00:00 2001 From: Ronan Abhamon Date: Tue, 6 Dec 2016 16:09:21 +0100 Subject: [PATCH] feat(app): supports avatars --- tests/src/app/AvatarProvider.cpp | 9 ++- .../src/components/contacts/ContactModel.cpp | 71 ++++++++++++++----- .../src/components/contacts/ContactModel.hpp | 5 +- .../ui/modules/Common/Image/RoundedImage.qml | 2 +- .../modules/Linphone/Chat/IncomingMessage.qml | 1 + tests/ui/modules/Linphone/Contact/Avatar.qml | 4 +- tests/ui/modules/Linphone/Contact/Contact.qml | 2 +- tests/ui/views/App/MainWindow/ContactEdit.qml | 26 +++---- .../ui/views/App/MainWindow/Conversation.qml | 1 + 9 files changed, 78 insertions(+), 43 deletions(-) diff --git a/tests/src/app/AvatarProvider.cpp b/tests/src/app/AvatarProvider.cpp index 8bc6f1bcf..d4b1d3717 100644 --- a/tests/src/app/AvatarProvider.cpp +++ b/tests/src/app/AvatarProvider.cpp @@ -1,3 +1,5 @@ +#include + #include "Database.hpp" #include "../utils.hpp" @@ -20,5 +22,10 @@ QImage AvatarProvider::requestImage ( QSize *, const QSize & ) { - return QImage(m_avatars_path + id); + QImage image(m_avatars_path + id); + + if (image.isNull()) + qWarning() << QStringLiteral("Unable to load: `%1`.").arg(id); + + return image; } diff --git a/tests/src/components/contacts/ContactModel.cpp b/tests/src/components/contacts/ContactModel.cpp index e821caf4e..f13612947 100644 --- a/tests/src/components/contacts/ContactModel.cpp +++ b/tests/src/components/contacts/ContactModel.cpp @@ -5,24 +5,18 @@ #include +#include "../../app/AvatarProvider.hpp" #include "../../app/Database.hpp" #include "../../utils.hpp" #include "ContactModel.hpp" +#define VCARD_SCHEME "linphone-desktop:/" + using namespace std; // =================================================================== -inline shared_ptr getBelCard ( - const shared_ptr &linphone_friend -) { - shared_ptr vcard = linphone_friend->getVcard(); - return *reinterpret_cast *>(vcard.get()); -} - -// ------------------------------------------------------------------- - Presence::PresenceStatus ContactModel::getPresenceStatus () const { return m_presence_status; } @@ -37,15 +31,40 @@ QString ContactModel::getUsername () const { ); } +QString ContactModel::getAvatar () const { + // Find desktop avatar. + list > photos = + m_linphone_friend->getVcard()->getBelcard()->getPhotos(); + auto it = find_if( + photos.begin(), photos.end(), [](const shared_ptr &photo) { + return !photo->getValue().compare(0, sizeof(VCARD_SCHEME) - 1, VCARD_SCHEME); + } + ); + + // Returns right path. + if (it == photos.end()) + return ""; + + return QStringLiteral("image://%1/%2") + .arg(AvatarProvider::PROVIDER_ID) + .arg(Utils::linphoneStringToQString( + (*it)->getValue().substr(sizeof(VCARD_SCHEME) - 1) + )); +} + bool ContactModel::setAvatar (const QString &path) { - // Try to copy photo in avatars folder. + // 1. Try to copy photo in avatars folder. QFile file(path); if (!file.exists() || QImageReader::imageFormat(path).size() == 0) return false; QFileInfo info(file); - QString file_id = QUuid::createUuid().toString() + "." + info.suffix(); + QString uuid = QUuid::createUuid().toString(); + QString file_id = QStringLiteral("%1.%2") + .arg(uuid.mid(1, uuid.length() - 2)) // Remove `{}`. + .arg(info.suffix()); + QString dest = Utils::linphoneStringToQString(Database::getAvatarsPath()) + file_id; @@ -55,22 +74,38 @@ bool ContactModel::setAvatar (const QString &path) { qInfo() << QStringLiteral("Update avatar of `%1`. (path=%2)") .arg(getUsername()).arg(dest); - // Remove oldest photos. - shared_ptr belCard = getBelCard(m_linphone_friend); + // 2. Edit vcard. + m_linphone_friend->edit(); - for (const auto &photo : belCard->getPhotos()) { - qDebug() << Utils::linphoneStringToQString(photo->getValue()); - belCard->removePhoto(photo); + shared_ptr belCard = m_linphone_friend->getVcard()->getBelcard(); + list > photos = belCard->getPhotos(); + + // 3. Remove oldest photo. + auto it = find_if( + photos.begin(), photos.end(), [](const shared_ptr &photo) { + return !photo->getValue().compare(0, sizeof(VCARD_SCHEME) - 1, VCARD_SCHEME); + } + ); + + if (it != photos.end()) { + QString image_path(Utils::linphoneStringToQString( + Database::getAvatarsPath() + (*it)->getValue().substr(sizeof(VCARD_SCHEME) - 1) + )); + if (!QFile::remove(image_path)) + qWarning() << QStringLiteral("Unable to remove `%1`.").arg(image_path); + belCard->removePhoto(*it); } - // Update. + // 4. Update. shared_ptr photo = belcard::BelCardGeneric::create(); - photo->setValue(Utils::qStringToLinphoneString(file_id)); + photo->setValue(VCARD_SCHEME + Utils::qStringToLinphoneString(file_id)); belCard->addPhoto(photo); + m_linphone_friend->done(); emit contactUpdated(); + return true; } diff --git a/tests/src/components/contacts/ContactModel.hpp b/tests/src/components/contacts/ContactModel.hpp index 588ac2823..ade9ab88a 100644 --- a/tests/src/components/contacts/ContactModel.hpp +++ b/tests/src/components/contacts/ContactModel.hpp @@ -57,10 +57,7 @@ signals: private: QString getUsername () const; - QString getAvatar () const { - return ""; - } - + QString getAvatar () const; bool setAvatar (const QString &path); Presence::PresenceStatus getPresenceStatus () const; diff --git a/tests/ui/modules/Common/Image/RoundedImage.qml b/tests/ui/modules/Common/Image/RoundedImage.qml index e9df6c4eb..1e9ea5c35 100644 --- a/tests/ui/modules/Common/Image/RoundedImage.qml +++ b/tests/ui/modules/Common/Image/RoundedImage.qml @@ -6,9 +6,9 @@ Item { id: item property alias source: image.source + property alias status: image.status // READONLY!!! property color backgroundColor: '#00000000' property color foregroundColor: '#00000000' - // vec4(0.812, 0.843, 0.866, 1.0) 0.9 Item { id: imageContainer diff --git a/tests/ui/modules/Linphone/Chat/IncomingMessage.qml b/tests/ui/modules/Linphone/Chat/IncomingMessage.qml index 042ab4739..b4098cd33 100644 --- a/tests/ui/modules/Linphone/Chat/IncomingMessage.qml +++ b/tests/ui/modules/Linphone/Chat/IncomingMessage.qml @@ -20,6 +20,7 @@ RowLayout { Avatar { anchors.centerIn: parent height: ChatStyle.entry.message.incoming.avatarSize + image: _contact.avatar username: LinphoneUtils.getContactUsername(_contact) width: ChatStyle.entry.message.incoming.avatarSize } diff --git a/tests/ui/modules/Linphone/Contact/Avatar.qml b/tests/ui/modules/Linphone/Contact/Avatar.qml index 3b286af1c..bc38c3a80 100644 --- a/tests/ui/modules/Linphone/Contact/Avatar.qml +++ b/tests/ui/modules/Linphone/Contact/Avatar.qml @@ -1,5 +1,4 @@ import QtQuick 2.7 -import QtGraphicalEffects 1.0 import Common 1.0 import Linphone 1.0 @@ -11,10 +10,10 @@ import Utils 1.0 Item { id: avatar - property alias image: roundedImage.source property alias presenceLevel: presenceLevel.level property color backgroundColor: AvatarStyle.backgroundColor property string username + property var image property var _initialsRegex: /^\s*([^\s\.]+)(?:[\s\.]+([^\s\.]+))?/ @@ -46,6 +45,7 @@ Item { anchors.fill: parent backgroundColor: avatar.backgroundColor + source: avatar.image || '' } Text { diff --git a/tests/ui/modules/Linphone/Contact/Contact.qml b/tests/ui/modules/Linphone/Contact/Contact.qml index 9b014ad17..68f4f53cb 100644 --- a/tests/ui/modules/Linphone/Contact/Contact.qml +++ b/tests/ui/modules/Linphone/Contact/Contact.qml @@ -38,7 +38,7 @@ Rectangle { Layout.preferredHeight: ContactStyle.contentHeight Layout.preferredWidth: ContactStyle.contentHeight - image: contact.avatar || '' + image: contact.avatar presenceLevel: contact.presenceLevel || Presence.White username: LinphoneUtils.getContactUsername(contact) } diff --git a/tests/ui/views/App/MainWindow/ContactEdit.qml b/tests/ui/views/App/MainWindow/ContactEdit.qml index 3ebdb9d2b..e739f23c1 100644 --- a/tests/ui/views/App/MainWindow/ContactEdit.qml +++ b/tests/ui/views/App/MainWindow/ContactEdit.qml @@ -81,29 +81,23 @@ ColumnLayout { spacing: ContactEditStyle.infoBar.spacing - Avatar { - id: avatar - - height: ContactEditStyle.infoBar.avatarSize - width: ContactEditStyle.infoBar.avatarSize - - username: LinphoneUtils.getContactUsername(_contact) - visible: isLoaded() - - MouseArea { - anchors.fill: parent - onClicked: avatarChooser.open() - } - } - ActionButton { Layout.preferredHeight: ContactEditStyle.infoBar.avatarSize Layout.preferredWidth: ContactEditStyle.infoBar.avatarSize icon: 'contact_card_photo' - visible: !avatar.isLoaded() onClicked: avatarChooser.open() + + Avatar { + id: avatar + + anchors.fill: parent + + image: _contact.avatar + username: LinphoneUtils.getContactUsername(_contact) + visible: isLoaded() && !parent.hovered + } } Text { diff --git a/tests/ui/views/App/MainWindow/Conversation.qml b/tests/ui/views/App/MainWindow/Conversation.qml index c51fb144f..2a28d6b5b 100644 --- a/tests/ui/views/App/MainWindow/Conversation.qml +++ b/tests/ui/views/App/MainWindow/Conversation.qml @@ -57,6 +57,7 @@ ColumnLayout { Layout.preferredHeight: ConversationStyle.bar.avatarSize Layout.preferredWidth: ConversationStyle.bar.avatarSize + image: _contact.avatar presenceLevel: _contact.presenceLevel || Presence.White username: LinphoneUtils.getContactUsername(_contact) }