Commit f4c56c99 authored by Ronan Abhamon's avatar Ronan Abhamon

feat(app): supports avatars

parent a34ca924
#include <QtDebug>
#include "Database.hpp" #include "Database.hpp"
#include "../utils.hpp" #include "../utils.hpp"
...@@ -20,5 +22,10 @@ QImage AvatarProvider::requestImage ( ...@@ -20,5 +22,10 @@ QImage AvatarProvider::requestImage (
QSize *, QSize *,
const 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;
} }
...@@ -5,24 +5,18 @@ ...@@ -5,24 +5,18 @@
#include <belcard/belcard.hpp> #include <belcard/belcard.hpp>
#include "../../app/AvatarProvider.hpp"
#include "../../app/Database.hpp" #include "../../app/Database.hpp"
#include "../../utils.hpp" #include "../../utils.hpp"
#include "ContactModel.hpp" #include "ContactModel.hpp"
#define VCARD_SCHEME "linphone-desktop:/"
using namespace std; using namespace std;
// =================================================================== // ===================================================================
inline shared_ptr<belcard::BelCard> getBelCard (
const shared_ptr<linphone::Friend> &linphone_friend
) {
shared_ptr<linphone::Vcard> vcard = linphone_friend->getVcard();
return *reinterpret_cast<shared_ptr<belcard::BelCard> *>(vcard.get());
}
// -------------------------------------------------------------------
Presence::PresenceStatus ContactModel::getPresenceStatus () const { Presence::PresenceStatus ContactModel::getPresenceStatus () const {
return m_presence_status; return m_presence_status;
} }
...@@ -37,15 +31,40 @@ QString ContactModel::getUsername () const { ...@@ -37,15 +31,40 @@ QString ContactModel::getUsername () const {
); );
} }
QString ContactModel::getAvatar () const {
// Find desktop avatar.
list<shared_ptr<belcard::BelCardPhoto> > photos =
m_linphone_friend->getVcard()->getBelcard()->getPhotos();
auto it = find_if(
photos.begin(), photos.end(), [](const shared_ptr<belcard::BelCardPhoto> &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) { bool ContactModel::setAvatar (const QString &path) {
// Try to copy photo in avatars folder. // 1. Try to copy photo in avatars folder.
QFile file(path); QFile file(path);
if (!file.exists() || QImageReader::imageFormat(path).size() == 0) if (!file.exists() || QImageReader::imageFormat(path).size() == 0)
return false; return false;
QFileInfo info(file); 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()) + QString dest = Utils::linphoneStringToQString(Database::getAvatarsPath()) +
file_id; file_id;
...@@ -55,22 +74,38 @@ bool ContactModel::setAvatar (const QString &path) { ...@@ -55,22 +74,38 @@ bool ContactModel::setAvatar (const QString &path) {
qInfo() << QStringLiteral("Update avatar of `%1`. (path=%2)") qInfo() << QStringLiteral("Update avatar of `%1`. (path=%2)")
.arg(getUsername()).arg(dest); .arg(getUsername()).arg(dest);
// Remove oldest photos. // 2. Edit vcard.
shared_ptr<belcard::BelCard> belCard = getBelCard(m_linphone_friend); m_linphone_friend->edit();
shared_ptr<belcard::BelCard> belCard = m_linphone_friend->getVcard()->getBelcard();
list<shared_ptr<belcard::BelCardPhoto> > photos = belCard->getPhotos();
for (const auto &photo : belCard->getPhotos()) { // 3. Remove oldest photo.
qDebug() << Utils::linphoneStringToQString(photo->getValue()); auto it = find_if(
belCard->removePhoto(photo); photos.begin(), photos.end(), [](const shared_ptr<belcard::BelCardPhoto> &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<belcard::BelCardPhoto> photo = shared_ptr<belcard::BelCardPhoto> photo =
belcard::BelCardGeneric::create<belcard::BelCardPhoto>(); belcard::BelCardGeneric::create<belcard::BelCardPhoto>();
photo->setValue(Utils::qStringToLinphoneString(file_id)); photo->setValue(VCARD_SCHEME + Utils::qStringToLinphoneString(file_id));
belCard->addPhoto(photo); belCard->addPhoto(photo);
m_linphone_friend->done();
emit contactUpdated(); emit contactUpdated();
return true; return true;
} }
......
...@@ -57,10 +57,7 @@ signals: ...@@ -57,10 +57,7 @@ signals:
private: private:
QString getUsername () const; QString getUsername () const;
QString getAvatar () const { QString getAvatar () const;
return "";
}
bool setAvatar (const QString &path); bool setAvatar (const QString &path);
Presence::PresenceStatus getPresenceStatus () const; Presence::PresenceStatus getPresenceStatus () const;
......
...@@ -6,9 +6,9 @@ Item { ...@@ -6,9 +6,9 @@ Item {
id: item id: item
property alias source: image.source property alias source: image.source
property alias status: image.status // READONLY!!!
property color backgroundColor: '#00000000' property color backgroundColor: '#00000000'
property color foregroundColor: '#00000000' property color foregroundColor: '#00000000'
// vec4(0.812, 0.843, 0.866, 1.0) 0.9
Item { Item {
id: imageContainer id: imageContainer
......
...@@ -20,6 +20,7 @@ RowLayout { ...@@ -20,6 +20,7 @@ RowLayout {
Avatar { Avatar {
anchors.centerIn: parent anchors.centerIn: parent
height: ChatStyle.entry.message.incoming.avatarSize height: ChatStyle.entry.message.incoming.avatarSize
image: _contact.avatar
username: LinphoneUtils.getContactUsername(_contact) username: LinphoneUtils.getContactUsername(_contact)
width: ChatStyle.entry.message.incoming.avatarSize width: ChatStyle.entry.message.incoming.avatarSize
} }
......
import QtQuick 2.7 import QtQuick 2.7
import QtGraphicalEffects 1.0
import Common 1.0 import Common 1.0
import Linphone 1.0 import Linphone 1.0
...@@ -11,10 +10,10 @@ import Utils 1.0 ...@@ -11,10 +10,10 @@ import Utils 1.0
Item { Item {
id: avatar id: avatar
property alias image: roundedImage.source
property alias presenceLevel: presenceLevel.level property alias presenceLevel: presenceLevel.level
property color backgroundColor: AvatarStyle.backgroundColor property color backgroundColor: AvatarStyle.backgroundColor
property string username property string username
property var image
property var _initialsRegex: /^\s*([^\s\.]+)(?:[\s\.]+([^\s\.]+))?/ property var _initialsRegex: /^\s*([^\s\.]+)(?:[\s\.]+([^\s\.]+))?/
...@@ -46,6 +45,7 @@ Item { ...@@ -46,6 +45,7 @@ Item {
anchors.fill: parent anchors.fill: parent
backgroundColor: avatar.backgroundColor backgroundColor: avatar.backgroundColor
source: avatar.image || ''
} }
Text { Text {
......
...@@ -38,7 +38,7 @@ Rectangle { ...@@ -38,7 +38,7 @@ Rectangle {
Layout.preferredHeight: ContactStyle.contentHeight Layout.preferredHeight: ContactStyle.contentHeight
Layout.preferredWidth: ContactStyle.contentHeight Layout.preferredWidth: ContactStyle.contentHeight
image: contact.avatar || '' image: contact.avatar
presenceLevel: contact.presenceLevel || Presence.White presenceLevel: contact.presenceLevel || Presence.White
username: LinphoneUtils.getContactUsername(contact) username: LinphoneUtils.getContactUsername(contact)
} }
......
...@@ -81,29 +81,23 @@ ColumnLayout { ...@@ -81,29 +81,23 @@ ColumnLayout {
spacing: ContactEditStyle.infoBar.spacing 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 { ActionButton {
Layout.preferredHeight: ContactEditStyle.infoBar.avatarSize Layout.preferredHeight: ContactEditStyle.infoBar.avatarSize
Layout.preferredWidth: ContactEditStyle.infoBar.avatarSize Layout.preferredWidth: ContactEditStyle.infoBar.avatarSize
icon: 'contact_card_photo' icon: 'contact_card_photo'
visible: !avatar.isLoaded()
onClicked: avatarChooser.open() onClicked: avatarChooser.open()
Avatar {
id: avatar
anchors.fill: parent
image: _contact.avatar
username: LinphoneUtils.getContactUsername(_contact)
visible: isLoaded() && !parent.hovered
}
} }
Text { Text {
......
...@@ -57,6 +57,7 @@ ColumnLayout { ...@@ -57,6 +57,7 @@ ColumnLayout {
Layout.preferredHeight: ConversationStyle.bar.avatarSize Layout.preferredHeight: ConversationStyle.bar.avatarSize
Layout.preferredWidth: ConversationStyle.bar.avatarSize Layout.preferredWidth: ConversationStyle.bar.avatarSize
image: _contact.avatar
presenceLevel: _contact.presenceLevel || Presence.White presenceLevel: _contact.presenceLevel || Presence.White
username: LinphoneUtils.getContactUsername(_contact) username: LinphoneUtils.getContactUsername(_contact)
} }
......
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