Commit 3d920d81 authored by Anthony Léonard's avatar Anthony Léonard Committed by Olivier SOLDANO

modernize avatar placeholder

Default avatar displayed for new contacts is replaced by a more modern
color circle with a capital letter inside.

The color palette used is the same as in the GNOME client. It comes
from the material.io website and is a 16 color subset of the full one
proposed by Google.

The letter is the first one of the bestName() corresponding to the
current item. The “Segoe UI” font is used as recommended by Windows
design guidelines.

Change-Id: I4c8c5729a77c0ff52d18de33c8e2fb8b5b1d7a88
Reviewed-by: default avatarOlivier Soldano <olivier.soldano@savoirfairelinux.com>
parent 3dad1751
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <QIODevice> #include <QIODevice>
#include <QByteArray> #include <QByteArray>
#include <QBuffer> #include <QBuffer>
#include <QPainter>
#include "person.h" #include "person.h"
#include "call.h" #include "call.h"
...@@ -34,7 +35,7 @@ ...@@ -34,7 +35,7 @@
#include "profile.h" #include "profile.h"
#include "utils.h" #include "utils.h"
#include "ringthemeutils.h"
#undef interface #undef interface
/*Namespace Interfaces collide with QBuffer*/ /*Namespace Interfaces collide with QBuffer*/
...@@ -49,10 +50,6 @@ QByteArray QImageToByteArray(QImage image) ...@@ -49,10 +50,6 @@ QByteArray QImageToByteArray(QImage image)
namespace Interfaces { namespace Interfaces {
PixbufManipulator::PixbufManipulator()
: fallbackAvatar_(QImage(":/images/user/btn-default-userpic.svg"))
{}
QImage QImage
PixbufManipulator::scaleAndFrame(const QImage photo, const QSize& size) PixbufManipulator::scaleAndFrame(const QImage photo, const QSize& size)
{ {
...@@ -63,7 +60,9 @@ QVariant ...@@ -63,7 +60,9 @@ QVariant
PixbufManipulator::callPhoto(Call* c, const QSize& size, bool displayPresence) PixbufManipulator::callPhoto(Call* c, const QSize& size, bool displayPresence)
{ {
if (!c || c->type() == Call::Type::CONFERENCE){ if (!c || c->type() == Call::Type::CONFERENCE){
return QVariant::fromValue(scaleAndFrame(fallbackAvatar_, size)); return QVariant::fromValue(fallbackAvatar(size,
c->peerContactMethod()->uri().userinfo().at(0).toLatin1(),
c->peerContactMethod()->bestName().at(0).toUpper().toLatin1()));
} }
return callPhoto(c->peerContactMethod(), size, displayPresence); return callPhoto(c->peerContactMethod(), size, displayPresence);
} }
...@@ -74,7 +73,9 @@ PixbufManipulator::callPhoto(const ContactMethod* n, const QSize& size, bool dis ...@@ -74,7 +73,9 @@ PixbufManipulator::callPhoto(const ContactMethod* n, const QSize& size, bool dis
if (n && n->contact()) { if (n && n->contact()) {
return contactPhoto(n->contact(), size, displayPresence); return contactPhoto(n->contact(), size, displayPresence);
} else { } else {
return QVariant::fromValue(scaleAndFrame(fallbackAvatar_, size)); return QVariant::fromValue(fallbackAvatar(size,
n->uri().userinfo().at(0).toLatin1(),
n->bestName().at(0).toUpper().toLatin1()));
} }
} }
...@@ -93,7 +94,9 @@ PixbufManipulator::contactPhoto(Person* c, const QSize& size, bool displayPresen ...@@ -93,7 +94,9 @@ PixbufManipulator::contactPhoto(Person* c, const QSize& size, bool displayPresen
if (c->photo().isValid()){ if (c->photo().isValid()){
photo = c->photo().value<QImage>(); photo = c->photo().value<QImage>();
} else { } else {
photo = fallbackAvatar_; photo = fallbackAvatar(size,
c->phoneNumbers().at(0)->uri().userinfo().at(0).toLatin1(),
c->phoneNumbers().at(0)->bestName().at(0).toUpper().toLatin1());
} }
return QVariant::fromValue(scaleAndFrame(photo, size)); return QVariant::fromValue(scaleAndFrame(photo, size));
} }
...@@ -105,7 +108,7 @@ QVariant PixbufManipulator::personPhoto(const QByteArray& data, const QString& t ...@@ -105,7 +108,7 @@ QVariant PixbufManipulator::personPhoto(const QByteArray& data, const QString& t
const char* c_str2 = ba.data(); const char* c_str2 = ba.data();
if (avatar.loadFromData(data.fromBase64(data), c_str2)) if (avatar.loadFromData(data.fromBase64(data), c_str2))
return Utils::getCirclePhoto(avatar, avatar.size().width()); return Utils::getCirclePhoto(avatar, avatar.size().width());
return fallbackAvatar_; return fallbackAvatar(imgSize_, '?', '?');
} }
QVariant QVariant
...@@ -182,7 +185,9 @@ QVariant PixbufManipulator::decorationRole(const Call* c) ...@@ -182,7 +185,9 @@ QVariant PixbufManipulator::decorationRole(const Call* c)
photo = c->peerContactMethod()->contact()->photo().value<QImage>(); photo = c->peerContactMethod()->contact()->photo().value<QImage>();
} }
else else
photo = fallbackAvatar_; photo = fallbackAvatar(imgSize_,
c->peerContactMethod()->uri().userinfo().at(0).toLatin1(),
c->peerContactMethod()->bestName().at(0).toUpper().toLatin1());
return QVariant::fromValue(scaleAndFrame(photo, imgSize_)); return QVariant::fromValue(scaleAndFrame(photo, imgSize_));
} }
...@@ -192,7 +197,9 @@ QVariant PixbufManipulator::decorationRole(const ContactMethod* cm) ...@@ -192,7 +197,9 @@ QVariant PixbufManipulator::decorationRole(const ContactMethod* cm)
if (cm && cm->contact() && cm->contact()->photo().isValid()) if (cm && cm->contact() && cm->contact()->photo().isValid())
photo = cm->contact()->photo().value<QImage>(); photo = cm->contact()->photo().value<QImage>();
else else
photo = fallbackAvatar_; photo = fallbackAvatar(imgSize_,
cm->uri().userinfo().at(0).toLatin1(),
cm->bestName().at(0).toUpper().toLatin1());
return QVariant::fromValue(scaleAndFrame(photo, imgSize_)); return QVariant::fromValue(scaleAndFrame(photo, imgSize_));
} }
...@@ -202,7 +209,9 @@ QVariant PixbufManipulator::decorationRole(const Person* p) ...@@ -202,7 +209,9 @@ QVariant PixbufManipulator::decorationRole(const Person* p)
if (p && p->photo().isValid()) if (p && p->photo().isValid())
photo = p->photo().value<QImage>(); photo = p->photo().value<QImage>();
else else
photo = fallbackAvatar_; photo = fallbackAvatar(imgSize_,
p->phoneNumbers().at(0)->uri().userinfo().at(0).toLatin1(),
p->phoneNumbers().at(0)->bestName().at(0).toUpper().toLatin1());
return QVariant::fromValue(scaleAndFrame(photo, imgSize_)); return QVariant::fromValue(scaleAndFrame(photo, imgSize_));
} }
...@@ -214,4 +223,31 @@ QVariant PixbufManipulator::decorationRole(const Account* acc) ...@@ -214,4 +223,31 @@ QVariant PixbufManipulator::decorationRole(const Account* acc)
imgSize_.width()); imgSize_.width());
} }
QImage PixbufManipulator::fallbackAvatar(const QSize size, const char color, const char letter)
{
// We start with a transparent avatar
QImage avatar(size, QImage::Format_ARGB32);
avatar.fill(Qt::transparent);
// We pick a color based on the passed character
QColor avColor = RingTheme::avatarColors_[color % 16];
// We draw a circle with this color
QPainter painter(&avatar);
painter.setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform);
painter.setPen(Qt::transparent);
painter.setBrush(avColor);
painter.drawEllipse(avatar.rect());
// Then we paint a letter in the circle
QFont segoeFont("Segoe UI", avatar.height()/2); // We use Segoe UI as recommended by Windows guidelines
painter.setFont(segoeFont);
painter.setPen(Qt::white);
QRect textRect = avatar.rect();
textRect.moveTop(textRect.top()-(avatar.height()/20)); // Empirical value that seems to correct centering nicely
painter.drawText(textRect, QString(letter), QTextOption(Qt::AlignCenter));
return avatar;
}
} // namespace Interfaces } // namespace Interfaces
...@@ -33,8 +33,6 @@ namespace Interfaces { ...@@ -33,8 +33,6 @@ namespace Interfaces {
class PixbufManipulator : public PixmapManipulatorI { class PixbufManipulator : public PixmapManipulatorI {
public: public:
PixbufManipulator();
QVariant callPhoto(Call* c, const QSize& size, bool displayPresence = true) override; QVariant callPhoto(Call* c, const QSize& size, bool displayPresence = true) override;
QVariant callPhoto(const ContactMethod* n, const QSize& size, bool displayPresence = true) override; QVariant callPhoto(const ContactMethod* n, const QSize& size, bool displayPresence = true) override;
QVariant contactPhoto(Person* c, const QSize& size, bool displayPresence = true) override; QVariant contactPhoto(Person* c, const QSize& size, bool displayPresence = true) override;
...@@ -56,9 +54,9 @@ public: ...@@ -56,9 +54,9 @@ public:
QVariant decorationRole(const Account* acc) override; QVariant decorationRole(const Account* acc) override;
private: private:
QImage fallbackAvatar_;
QImage scaleAndFrame(const QImage photo, const QSize& size); QImage scaleAndFrame(const QImage photo, const QSize& size);
const QSize imgSize_ {48, 48}; const QSize imgSize_ {48, 48};
static QImage fallbackAvatar(const QSize size, const char color, const char letter);
}; };
} // namespace Interfaces } // namespace Interfaces
......
...@@ -32,4 +32,23 @@ static const QColor lightRed_ {252, 91, 90}; ...@@ -32,4 +32,23 @@ static const QColor lightRed_ {252, 91, 90};
static const QColor darkRed_ {219, 55, 54}; static const QColor darkRed_ {219, 55, 54};
static const QColor green_ {127, 255, 0}; static const QColor green_ {127, 255, 0};
static const QColor avatarColors_[] {
{"#fff44336"}, //Red
{"#ffe91e63"}, //Pink
{"#ff9c27b0"}, //Purple
{"#ff673ab7"}, //Deep Purple
{"#ff3f51b5"}, //Indigo
{"#ff2196f3"}, //Blue
{"#ff00bcd4"}, //Cyan
{"#ff009688"}, //Teal
{"#ff4caf50"}, //Green
{"#ff8bc34a"}, //Light Green
{"#ff9e9e9e"}, //Grey
{"#ffcddc39"}, //Lime
{"#ffffc107"}, //Amber
{"#ffff5722"}, //Deep Orange
{"#ff795548"}, //Brown
{"#ff607d8b"} //Blue Grey
};
} }
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