Skip to content
Snippets Groups Projects
Commit 173cf2be authored by Ming Rui Zhang's avatar Ming Rui Zhang
Browse files

migration: use image provider to show avatar image

1. Use avatarimageprovider
2. Remove redundant base64 code

Change-Id: I2a2517890e95b4a9f9a363fbea2251d6d5dd1c8f
parent b4b56aec
No related branches found
No related tags found
No related merge requests found
......@@ -21,12 +21,8 @@
#include "smartlistmodel.h"
#include "lrcinstance.h"
#include "pixbufmanipulator.h"
#include "utils.h"
#include "api/contactmodel.h"
#include "globalinstances.h"
#include <QDateTime>
SmartListModel::SmartListModel(QObject* parent,
......@@ -148,7 +144,6 @@ SmartListModel::roleNames() const
QHash<int, QByteArray> roles;
roles[DisplayName] = "DisplayName";
roles[DisplayID] = "DisplayID";
roles[Picture] = "Picture";
roles[Presence] = "Presence";
roles[URI] = "URI";
roles[UnreadMessagesCount] = "UnreadMessagesCount";
......@@ -163,6 +158,7 @@ SmartListModel::roleNames() const
roles[SectionName] = "SectionName";
roles[AccountId] = "AccountId";
roles[Draft] = "Draft";
roles[PictureUid] = "PictureUid";
return roles;
}
......@@ -183,6 +179,8 @@ void
SmartListModel::fillConversationsList()
{
beginResetModel();
fillContactAvatarUidMap(LRCInstance::getCurrentAccountInfo().contactModel->getAllContacts());
auto* convModel = LRCInstance::getCurrentConversationModel();
conversations_.clear();
......@@ -208,6 +206,39 @@ SmartListModel::updateConversation(const QString& convUid)
}
}
void
SmartListModel::updateContactAvatarUid(const QString& contactUri)
{
contactAvatarUidMap_[contactUri] = Utils::generateUid();
}
void
SmartListModel::fillContactAvatarUidMap(const ContactModel::ContactInfoMap& contacts)
{
if (contacts.size() == 0) {
contactAvatarUidMap_.clear();
return;
}
if (contactAvatarUidMap_.isEmpty() || contacts.size() != contactAvatarUidMap_.size()) {
bool useContacts = contacts.size() > contactAvatarUidMap_.size();
auto contactsKeyList = contacts.keys();
auto contactAvatarUidMapKeyList = contactAvatarUidMap_.keys();
for (int i = 0;
i < (useContacts ? contactsKeyList.size() : contactAvatarUidMapKeyList.size());
++i) {
// Insert or update
if (i < contactsKeyList.size() && !contactAvatarUidMap_.contains(contactsKeyList.at(i)))
contactAvatarUidMap_.insert(contactsKeyList.at(i), Utils::generateUid());
// Remove
if (i < contactAvatarUidMapKeyList.size()
&& !contacts.contains(contactAvatarUidMapKeyList.at(i)))
contactAvatarUidMap_.remove(contactAvatarUidMapKeyList.at(i));
}
}
}
void
SmartListModel::toggleSection(const QString& section)
{
......@@ -241,12 +272,10 @@ SmartListModel::getConversationItemData(const conversation::Info& item,
return QVariant();
}
auto& contactModel = accountInfo.contactModel;
// Since we are using image provider right now, image url representation should be unique to
// be able to use the image cache, account avatar will only be updated once PictureUid changed
switch (role) {
case Role::Picture: {
auto contactImage
= GlobalInstances::pixmapManipulator().decorationRole(item, accountInfo).value<QImage>();
return QString::fromLatin1(Utils::QImageToByteArray(contactImage).toBase64().data());
}
case Role::DisplayName: {
if (!item.participants.isEmpty()) {
auto& contact = contactModel->getContact(item.participants[0]);
......@@ -268,10 +297,15 @@ SmartListModel::getConversationItemData(const conversation::Info& item,
}
return QVariant(false);
}
case Role::PictureUid: {
if (!item.participants.isEmpty()) {
return QVariant(contactAvatarUidMap_[item.participants[0]]);
}
return QVariant("");
}
case Role::URI: {
if (!item.participants.isEmpty()) {
auto& contact = contactModel->getContact(item.participants[0]);
return QVariant(contact.profileInfo.uri);
return QVariant(item.participants[0]);
}
return QVariant("");
}
......@@ -331,13 +365,13 @@ SmartListModel::getConversationItemData(const conversation::Info& item,
if (!convInfo.uid.isEmpty()) {
auto* callModel = LRCInstance::getCurrentCallModel();
const auto call = callModel->getCall(convInfo.callId);
return QVariant(callModel->hasCall(convInfo.callId)
return QVariant(
callModel->hasCall(convInfo.callId)
&& ((!call.isOutgoing
&& (call.status == lrc::api::call::Status::IN_PROGRESS
|| call.status == lrc::api::call::Status::PAUSED
|| call.status == lrc::api::call::Status::INCOMING_RINGING))
|| (call.isOutgoing
&& call.status != lrc::api::call::Status::ENDED)));
|| (call.isOutgoing && call.status != lrc::api::call::Status::ENDED)));
}
return QVariant(false);
}
......
......@@ -24,6 +24,7 @@
#include "api/contact.h"
#include "api/conversation.h"
#include "api/conversationmodel.h"
#include "api/contactmodel.h"
#include <QAbstractItemModel>
......@@ -42,7 +43,6 @@ public:
enum Role {
DisplayName = Qt::UserRole + 1,
DisplayID,
Picture,
Presence,
URI,
UnreadMessagesCount,
......@@ -58,6 +58,7 @@ public:
CallState,
SectionName,
AccountId,
PictureUid,
Draft
};
Q_ENUM(Role)
......@@ -85,15 +86,28 @@ public:
Q_INVOKABLE void fillConversationsList();
Q_INVOKABLE void updateConversation(const QString& conv);
/*
* This function is to update contact avatar uuid for current account when there's an contact
* avatar changed.
*/
Q_INVOKABLE void updateContactAvatarUid(const QString& contactUri);
private:
QVariant getConversationItemData(const ConversationInfo& item,
const AccountInfo& accountInfo,
int role) const;
/*
* Give a uuid for each contact avatar for current account and it will serve PictureUid role
*/
void fillContactAvatarUidMap(const ContactModel::ContactInfoMap& contacts);
/*
* List sectioning.
*/
Type listModelType_;
QMap<QString, bool> sectionState_;
QMap<ConferenceableItem, ConferenceableValue> conferenceables_;
QMap<QString, QString> contactAvatarUidMap_;
ConversationModel::ConversationQueue conversations_;
};
......@@ -25,9 +25,7 @@
#include "globalsystemtray.h"
#include "jamiavatartheme.h"
#include "lrcinstance.h"
#include "pixbufmanipulator.h"
#include <globalinstances.h>
#include <qrencode.h>
#include <QApplication>
......@@ -43,6 +41,7 @@
#include <QSvgRenderer>
#include <QTranslator>
#include <QtConcurrent/QtConcurrent>
#include <QUuid>
#ifdef Q_OS_WIN
#include <lmcons.h>
......@@ -245,14 +244,52 @@ Utils::GetISODate()
#endif
}
QString
Utils::getContactImageString(const QString& accountId, const QString& uid)
QImage
Utils::contactPhoto(const QString& contactUri, const QSize& size)
{
return QString::fromLatin1(
Utils::QImageToByteArray(
Utils::conversationPhoto(uid, LRCInstance::getAccountInfo(accountId)))
.toBase64()
.data());
QImage photo;
try {
/*
* Get first contact photo.
*/
auto& accountInfo = LRCInstance::accountModel().getAccountInfo(LRCInstance::getCurrAccId());
auto contactInfo = accountInfo.contactModel->getContact(contactUri);
auto contactPhoto = contactInfo.profileInfo.avatar;
auto bestName = Utils::bestNameForContact(contactInfo);
auto bestId = Utils::bestIdForContact(contactInfo);
if (accountInfo.profileInfo.type == lrc::api::profile::Type::SIP
&& contactInfo.profileInfo.type == lrc::api::profile::Type::TEMPORARY) {
photo = Utils::fallbackAvatar(QString(), QString());
} else if (contactInfo.profileInfo.type == lrc::api::profile::Type::TEMPORARY
&& contactInfo.profileInfo.uri.isEmpty()) {
photo = Utils::fallbackAvatar(QString(), QString());
} else if (!contactPhoto.isEmpty()) {
QByteArray byteArray = contactPhoto.toLocal8Bit();
photo = contactPhotoFromBase64(byteArray, nullptr);
if (photo.isNull()) {
auto avatarName = contactInfo.profileInfo.uri == bestName ? QString() : bestName;
photo = Utils::fallbackAvatar("ring:" + contactInfo.profileInfo.uri, avatarName);
}
} else {
auto avatarName = contactInfo.profileInfo.uri == bestName ? QString() : bestName;
photo = Utils::fallbackAvatar("ring:" + contactInfo.profileInfo.uri, avatarName);
}
} catch (...) {
}
return Utils::scaleAndFrame(photo, size);
}
QImage
Utils::contactPhotoFromBase64(const QByteArray& data, const QString& type)
{
QImage avatar;
const bool ret = avatar.loadFromData(QByteArray::fromBase64(data), type.toLatin1());
if (!ret) {
qDebug() << "Utils: vCard image loading failed";
return QImage();
}
return Utils::getCirclePhoto(avatar, avatar.size().width());
}
QImage
......@@ -549,21 +586,6 @@ Utils::getReplyMessageBox(QWidget* widget, const QString& title, const QString&
return false;
}
QImage
Utils::conversationPhoto(const QString& convUid,
const lrc::api::account::Info& accountInfo,
bool filtered)
{
auto* convModel = LRCInstance::getCurrentConversationModel();
const auto convInfo = convModel->getConversationForUID(convUid);
if (!convInfo.uid.isEmpty()) {
return GlobalInstances::pixmapManipulator()
.decorationRole(convInfo, accountInfo)
.value<QImage>();
}
return QImage();
}
QColor
Utils::getAvatarColor(const QString& canonicalUri)
{
......@@ -587,10 +609,12 @@ Utils::getAvatarColor(const QString& canonicalUri)
QImage
Utils::fallbackAvatar(const QString& canonicalUriStr, const QString& letterStr, const QSize& size)
{
auto sizeToUse = size.height() >= defaultAvatarSize.height() ? size : defaultAvatarSize;
/*
* We start with a transparent avatar.
*/
QImage avatar(size, QImage::Format_ARGB32);
QImage avatar(sizeToUse, QImage::Format_ARGB32);
avatar.fill(Qt::transparent);
/*
......@@ -651,7 +675,7 @@ Utils::fallbackAvatar(const QString& canonicalUriStr, const QString& letterStr,
painter.drawPixmap(overlayRect, QPixmap(":/images/default_avatar_overlay.svg"));
}
return avatar;
return avatar.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
}
QImage
......@@ -802,7 +826,7 @@ Utils::accountPhoto(const lrc::api::account::Info& accountInfo, const QSize& siz
QImage photo;
if (!accountInfo.profileInfo.avatar.isEmpty()) {
QByteArray ba = accountInfo.profileInfo.avatar.toLocal8Bit();
photo = GlobalInstances::pixmapManipulator().personPhoto(ba, nullptr).value<QImage>();
photo = contactPhotoFromBase64(ba, nullptr);
} else {
auto bestId = bestIdForAccount(accountInfo);
auto bestName = bestNameForAccount(accountInfo);
......@@ -843,3 +867,9 @@ Utils::isImage(const QString& fileExt)
return true;
return false;
}
QString
Utils::generateUid()
{
return QUuid::createUuid().toString();
}
......@@ -100,11 +100,9 @@ bool getReplyMessageBox(QWidget* widget, const QString& title, const QString& te
* Image manipulation
*/
static const QSize defaultAvatarSize {128, 128};
QString getContactImageString(const QString& accountId, const QString& uid);
QImage contactPhotoFromBase64(const QByteArray& data, const QString& type);
QImage contactPhoto(const QString& contactUri, const QSize& size = defaultAvatarSize);
QImage getCirclePhoto(const QImage original, int sizePhoto);
QImage conversationPhoto(const QString& convUid,
const lrc::api::account::Info& accountInfo,
bool filtered = false);
QColor getAvatarColor(const QString& canonicalUri);
QImage fallbackAvatar(const QString& canonicalUriStr,
const QString& letterStr = QString(),
......@@ -123,6 +121,7 @@ QImage cropImage(const QImage& img);
QPixmap pixmapFromSvg(const QString& svg_resource, const QSize& size);
QImage setupQRCode(QString ringID, int margin);
bool isImage(const QString& fileExt);
QString generateUid();
/*
* Misc
......
......@@ -105,12 +105,6 @@ UtilsAdapter::checkStartupLink()
return Utils::CheckStartupLink(L"Jami");
}
const QString
UtilsAdapter::getContactImageString(const QString& accountId, const QString& uid)
{
return Utils::getContactImageString(accountId, uid);
}
const QString
UtilsAdapter::getBestName(const QString& accountId, const QString& uid)
{
......@@ -356,17 +350,6 @@ UtilsAdapter::getAbsPath(QString path)
#endif
}
QString
UtilsAdapter::getCroppedImageBase64FromFile(QString fileName, int size)
{
auto image = Utils::cropImage(QImage(fileName));
auto croppedImage = image.scaled(size,
size,
Qt::KeepAspectRatioByExpanding,
Qt::SmoothTransformation);
return QString::fromLatin1(Utils::QImageToByteArray(croppedImage).toBase64().data());
}
bool
UtilsAdapter::checkShowPluginsButton()
{
......
......@@ -44,7 +44,6 @@ public:
Q_INVOKABLE bool createStartupLink();
Q_INVOKABLE QString GetRingtonePath();
Q_INVOKABLE bool checkStartupLink();
Q_INVOKABLE const QString getContactImageString(const QString& accountId, const QString& uid);
Q_INVOKABLE void removeConversation(const QString& accountId,
const QString& uid,
bool banContact = false);
......@@ -77,7 +76,6 @@ public:
Q_INVOKABLE QString toFileInfoName(QString inputFileName);
Q_INVOKABLE QString toFileAbsolutepath(QString inputFileName);
Q_INVOKABLE QString getAbsPath(QString path);
Q_INVOKABLE QString getCroppedImageBase64FromFile(QString fileName, int size);
Q_INVOKABLE bool checkShowPluginsButton();
Q_INVOKABLE QString fileName(const QString& path);
Q_INVOKABLE QString getExt(const QString& path);
......
......@@ -385,14 +385,13 @@ Rectangle {
}
onSaveProfile: {
SettingsAdapter.setCurrAccAvatar(profilePage.boothImgBase64)
if (profilePage.profileImg)
SettingsAdapter.setCurrAccAvatar(profilePage.profileImg)
AccountAdapter.setCurrAccDisplayName(profilePage.displayName)
leave()
}
onLeavePage: {
leave()
}
onLeavePage: leave()
}
}
}
......
......@@ -32,8 +32,6 @@ Rectangle {
property alias text_sipPasswordEditAlias: sipPasswordEdit.text
property int preferredHeight: createSIPAccountPageColumnLayout.implicitHeight
property var boothImgBase64: null
signal createAccount
signal leavePage
......
......@@ -26,11 +26,13 @@ import "../../commoncomponents"
Rectangle {
id: root
property alias profileImg: setAvatarWidget.boothImg
property int preferredHeight: profilePageColumnLayout.implicitHeight
function initializeOnShowUp() {
setAvatarWidget.hasAvatar = false
setAvatarWidget.setAvatarImage(AvatarImage.Mode.Default, "")
clearAllTextFields()
boothImgBase64 = ""
saveProfileBtn.spinnerTriggered = true
}
......@@ -48,7 +50,6 @@ Rectangle {
signal saveProfile
property var showBottom: false
property alias boothImgBase64: setAvatarWidget.imgBase64
property alias displayName: aliasEdit.text
property bool isRdv: false
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment