mirror of https://github.com/procxx/kepka.git
New empty user/chat photos: with filled background and initials.
This commit is contained in:
parent
204d91d567
commit
1d8e76aa08
|
@ -258,29 +258,22 @@ historyForwardChooseBg: #0000004c;
|
|||
historyForwardChooseFg: windowFgActive;
|
||||
|
||||
historyPeer1NameFg: #c03d33; // red
|
||||
historyPeer1UserpicBg: #ed9482;
|
||||
historyPeer1UserpicFg: #d3644b;
|
||||
historyPeer1UserpicBg: #e57979;
|
||||
historyPeer2NameFg: #4fad2d; // green
|
||||
historyPeer2UserpicBg: #a8db92;
|
||||
historyPeer2UserpicFg: #75c057;
|
||||
historyPeer2UserpicBg: #80d066;
|
||||
historyPeer3NameFg: #d09306; // yellow
|
||||
historyPeer3UserpicBg: #efd289;
|
||||
historyPeer3UserpicFg: #e4a861;
|
||||
historyPeer3UserpicBg: #ecd074;
|
||||
historyPeer4NameFg: windowActiveTextFg; // blue
|
||||
historyPeer4UserpicBg: #8fbfe9;
|
||||
historyPeer4UserpicFg: #649fd3;
|
||||
historyPeer4UserpicBg: #6fb1e4;
|
||||
historyPeer5NameFg: #8544d6; // purple
|
||||
historyPeer5UserpicBg: #9992e4;
|
||||
historyPeer5UserpicFg: #7b72cf;
|
||||
historyPeer5UserpicBg: #cc90e2;
|
||||
historyPeer6NameFg: #cd4073; // pink
|
||||
historyPeer6UserpicBg: #ffa9c3;
|
||||
historyPeer6UserpicFg: #e87497;
|
||||
historyPeer6UserpicBg: #f078ae;
|
||||
historyPeer7NameFg: #2996ad; // sea
|
||||
historyPeer7UserpicBg: #8eccdb;
|
||||
historyPeer7UserpicFg: #5eb2c7;
|
||||
historyPeer7UserpicBg: #73cdd0;
|
||||
historyPeer8NameFg: #ce671b; // orange
|
||||
historyPeer8UserpicBg: #f7b37c;
|
||||
historyPeer8UserpicFg: #de8d62;
|
||||
historyPeer8UserpicBg: #fba76f;
|
||||
historyPeerUserpicFg: windowFgActive;
|
||||
|
||||
historyScrollBarBg: #556e837a;
|
||||
historyScrollBarBgOver: #556e83bc;
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 1.2 KiB |
Binary file not shown.
Before Width: | Height: | Size: 4.9 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.9 KiB |
Binary file not shown.
Before Width: | Height: | Size: 8.7 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.8 KiB |
Binary file not shown.
Before Width: | Height: | Size: 7.5 KiB |
|
@ -214,29 +214,22 @@ historyUnreadBarFg: #538bb4;
|
|||
historyForwardChooseBg: #0000004c;
|
||||
historyForwardChooseFg: #ffffff; // windowActiveTextFg;
|
||||
historyPeer1NameFg: #c03d33;
|
||||
historyPeer1UserpicBg: #ed9482;
|
||||
historyPeer1UserpicFg: #d3644b;
|
||||
historyPeer1UserpicBg: #e57979;
|
||||
historyPeer2NameFg: #4fad2d;
|
||||
historyPeer2UserpicBg: #a8db92;
|
||||
historyPeer2UserpicFg: #75c057;
|
||||
historyPeer2UserpicBg: #80d066;
|
||||
historyPeer3NameFg: #d09306;
|
||||
historyPeer3UserpicBg: #efd289;
|
||||
historyPeer3UserpicFg: #e4a861;
|
||||
historyPeer3UserpicBg: #ecd074;
|
||||
historyPeer4NameFg: #168acd; // windowShadowFg;
|
||||
historyPeer4UserpicBg: #8fbfe9;
|
||||
historyPeer4UserpicFg: #649fd3;
|
||||
historyPeer4UserpicBg: #6fb1e4;
|
||||
historyPeer5NameFg: #8544d6;
|
||||
historyPeer5UserpicBg: #9992e4;
|
||||
historyPeer5UserpicFg: #7b72cf;
|
||||
historyPeer5UserpicBg: #cc90e2;
|
||||
historyPeer6NameFg: #cd4073;
|
||||
historyPeer6UserpicBg: #ffa9c3;
|
||||
historyPeer6UserpicFg: #e87497;
|
||||
historyPeer6UserpicBg: #f078ae;
|
||||
historyPeer7NameFg: #2996ad;
|
||||
historyPeer7UserpicBg: #8eccdb;
|
||||
historyPeer7UserpicFg: #5eb2c7;
|
||||
historyPeer7UserpicBg: #73cdd0;
|
||||
historyPeer8NameFg: #ce671b;
|
||||
historyPeer8UserpicBg: #f7b37c;
|
||||
historyPeer8UserpicFg: #de8d62;
|
||||
historyPeer8UserpicBg: #fba76f;
|
||||
historyPeerUserpicFg: #ffffff; // windowActiveTextFg;
|
||||
historyScrollBarBg: #556e837a;
|
||||
historyScrollBarBgOver: #556e83bc;
|
||||
historyScrollBg: #556e834c;
|
||||
|
|
|
@ -1201,7 +1201,7 @@ void RevokePublicLinkBox::resizeEvent(QResizeEvent *e) {
|
|||
|
||||
void RevokePublicLinkBox::paintChat(Painter &p, const ChatRow &row, bool selected) const {
|
||||
auto peer = row.peer;
|
||||
peer->paintUserpicLeft(p, st::contactsPhotoSize, st::contactsPadding.left(), st::contactsPadding.top(), width());
|
||||
peer->paintUserpicLeft(p, st::contactsPadding.left(), st::contactsPadding.top(), width(), st::contactsPhotoSize);
|
||||
|
||||
p.setPen(st::contactsNameFg);
|
||||
|
||||
|
|
|
@ -462,7 +462,6 @@ void RichDeleteMessageBox::deleteAndClear() {
|
|||
ConfirmInviteBox::ConfirmInviteBox(QWidget*, const QString &title, const MTPChatPhoto &photo, int count, const QVector<UserData*> &participants)
|
||||
: _title(this, st::confirmInviteTitle)
|
||||
, _status(this, st::confirmInviteStatus)
|
||||
, _photo(chatDefPhoto(0))
|
||||
, _participants(participants) {
|
||||
_title->setText(title);
|
||||
QString status;
|
||||
|
@ -483,6 +482,9 @@ ConfirmInviteBox::ConfirmInviteBox(QWidget*, const QString &title, const MTPChat
|
|||
}
|
||||
}
|
||||
}
|
||||
if (!_photo) {
|
||||
_photoEmpty.set(0, title);
|
||||
}
|
||||
}
|
||||
|
||||
void ConfirmInviteBox::prepare() {
|
||||
|
@ -528,12 +530,16 @@ void ConfirmInviteBox::paintEvent(QPaintEvent *e) {
|
|||
|
||||
Painter p(this);
|
||||
|
||||
p.drawPixmap((width() - st::confirmInvitePhotoSize) / 2, st::confirmInvitePhotoTop, _photo->pixCircled(st::confirmInvitePhotoSize, st::confirmInvitePhotoSize));
|
||||
if (_photo) {
|
||||
p.drawPixmap((width() - st::confirmInvitePhotoSize) / 2, st::confirmInvitePhotoTop, _photo->pixCircled(st::confirmInvitePhotoSize, st::confirmInvitePhotoSize));
|
||||
} else {
|
||||
_photoEmpty.paint(p, (width() - st::confirmInvitePhotoSize) / 2, st::confirmInvitePhotoTop, width(), st::confirmInvitePhotoSize);
|
||||
}
|
||||
|
||||
int sumWidth = _participants.size() * _userWidth;
|
||||
int left = (width() - sumWidth) / 2;
|
||||
for_const (auto user, _participants) {
|
||||
user->paintUserpicLeft(p, st::confirmInviteUserPhotoSize, left + (_userWidth - st::confirmInviteUserPhotoSize) / 2, st::confirmInviteUserPhotoTop, width());
|
||||
user->paintUserpicLeft(p, left + (_userWidth - st::confirmInviteUserPhotoSize) / 2, st::confirmInviteUserPhotoTop, width(), st::confirmInviteUserPhotoSize);
|
||||
left += _userWidth;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -207,6 +207,7 @@ private:
|
|||
object_ptr<Ui::FlatLabel> _title;
|
||||
object_ptr<Ui::FlatLabel> _status;
|
||||
ImagePtr _photo;
|
||||
EmptyUserpic _photoEmpty;
|
||||
QVector<UserData*> _participants;
|
||||
|
||||
int _userWidth = 0;
|
||||
|
|
|
@ -955,7 +955,7 @@ void ContactsBox::Inner::paintDialog(Painter &p, TimeMs ms, PeerData *peer, Cont
|
|||
checkedRatio = data->checkbox->checkedAnimationRatio();
|
||||
data->checkbox->paint(p, ms, st::contactsPadding.left(), st::contactsPadding.top(), width());
|
||||
} else {
|
||||
peer->paintUserpicLeft(p, st::contactsPhotoSize, st::contactsPadding.left(), st::contactsPadding.top(), width());
|
||||
peer->paintUserpicLeft(p, st::contactsPadding.left(), st::contactsPadding.top(), width(), st::contactsPhotoSize);
|
||||
}
|
||||
|
||||
int namex = st::contactsPadding.left() + st::contactsPhotoSize + st::contactsPadding.left();
|
||||
|
@ -1013,7 +1013,7 @@ void ContactsBox::Inner::paintDisabledCheckUserpic(Painter &p, PeerData *peer, i
|
|||
auto iconBorderPen = st::contactsPhotoCheckbox.check.border->p;
|
||||
iconBorderPen.setWidth(st::contactsPhotoCheckbox.selectWidth);
|
||||
|
||||
peer->paintUserpicLeft(p, userpicRadius * 2, userpicLeft, userpicTop, width());
|
||||
peer->paintUserpicLeft(p, userpicLeft, userpicTop, width(), userpicRadius * 2);
|
||||
|
||||
{
|
||||
PainterHighQualityEnabler hq(p);
|
||||
|
|
|
@ -43,7 +43,7 @@ QString cantInviteError();
|
|||
|
||||
inline Ui::RoundImageCheckbox::PaintRoundImage PaintUserpicCallback(PeerData *peer) {
|
||||
return [peer](Painter &p, int x, int y, int outerWidth, int size) {
|
||||
peer->paintUserpicLeft(p, size, x, y, outerWidth);
|
||||
peer->paintUserpicLeft(p, x, y, outerWidth, size);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -271,7 +271,7 @@ void MembersBox::Inner::paintDialog(Painter &p, TimeMs ms, PeerData *peer, Membe
|
|||
data->ripple.reset();
|
||||
}
|
||||
}
|
||||
peer->paintUserpicLeft(p, st::contactsPhotoSize, st::contactsPadding.left(), st::contactsPadding.top(), width());
|
||||
peer->paintUserpicLeft(p, st::contactsPadding.left(), st::contactsPadding.top(), width(), st::contactsPhotoSize);
|
||||
|
||||
p.setPen(st::contactsNameFg);
|
||||
|
||||
|
|
|
@ -127,9 +127,11 @@ SendFilesBox::SendFilesBox(QWidget*, const QString &phone, const QString &firstn
|
|||
: _contactPhone(phone)
|
||||
, _contactFirstName(firstname)
|
||||
, _contactLastName(lastname) {
|
||||
_nameText.setText(st::semiboldTextStyle, lng_full_name(lt_first_name, _contactFirstName, lt_last_name, _contactLastName), _textNameOptions);
|
||||
auto name = lng_full_name(lt_first_name, _contactFirstName, lt_last_name, _contactLastName);
|
||||
_nameText.setText(st::semiboldTextStyle, name, _textNameOptions);
|
||||
_statusText = _contactPhone;
|
||||
_statusWidth = qMax(_nameText.maxWidth(), st::normalFont->width(_statusText));
|
||||
_contactPhotoEmpty.set(0, name);
|
||||
}
|
||||
|
||||
void SendFilesBox::prepare() {
|
||||
|
@ -280,7 +282,7 @@ void SendFilesBox::paintEvent(QPaintEvent *e) {
|
|||
auto &icon = _fileIsImage ? st::historyFileOutImage : st::historyFileOutDocument;
|
||||
icon.paintInCenter(p, inner);
|
||||
} else {
|
||||
p.drawPixmapLeft(x + st::msgFilePadding.left(), y + st::msgFilePadding.top(), width(), userDefPhoto(1)->pixCircled(st::msgFileSize));
|
||||
_contactPhotoEmpty.paint(p, x + st::msgFilePadding.left(), y + st::msgFilePadding.top(), width(), st::msgFileSize);
|
||||
}
|
||||
} else {
|
||||
QRect rthumb(rtlrect(x + st::msgFileThumbPadding.left(), y + st::msgFileThumbPadding.top(), st::msgFileThumbSize, st::msgFileThumbSize, width()));
|
||||
|
|
|
@ -89,6 +89,7 @@ private:
|
|||
QString _contactPhone;
|
||||
QString _contactFirstName;
|
||||
QString _contactLastName;
|
||||
EmptyUserpic _contactPhotoEmpty;
|
||||
|
||||
base::lambda<void(const QStringList &files, bool compressed, const QString &caption, bool ctrlShiftEnter)> _confirmedCallback;
|
||||
base::lambda<void()> _cancelledCallback;
|
||||
|
|
|
@ -320,21 +320,24 @@ inline T snap(const T &v, const T &_min, const T &_max) {
|
|||
template <typename T>
|
||||
class ManagedPtr {
|
||||
public:
|
||||
ManagedPtr() : ptr(0) {
|
||||
}
|
||||
ManagedPtr(T *p) : ptr(p) {
|
||||
ManagedPtr() = default;
|
||||
ManagedPtr(T *p) : _data(p) {
|
||||
}
|
||||
T *operator->() const {
|
||||
return ptr;
|
||||
return _data;
|
||||
}
|
||||
T *v() const {
|
||||
return ptr;
|
||||
return _data;
|
||||
}
|
||||
|
||||
explicit operator bool() const {
|
||||
return _data != nullptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
using Parent = ManagedPtr<T>;
|
||||
T *_data = nullptr;
|
||||
|
||||
T *ptr;
|
||||
typedef ManagedPtr<T> Parent;
|
||||
};
|
||||
|
||||
QString translitRusEng(const QString &rus);
|
||||
|
|
|
@ -66,7 +66,7 @@ void paintRow(Painter &p, const RippleRow *row, History *history, HistoryItem *i
|
|||
if (onlyBackground) return;
|
||||
|
||||
auto userpicPeer = (history->peer->migrateTo() ? history->peer->migrateTo() : history->peer);
|
||||
userpicPeer->paintUserpicLeft(p, st::dialogsPhotoSize, st::dialogsPadding.x(), st::dialogsPadding.y(), fullWidth);
|
||||
userpicPeer->paintUserpicLeft(p, st::dialogsPadding.x(), st::dialogsPadding.y(), fullWidth, st::dialogsPhotoSize);
|
||||
|
||||
auto nameleft = st::dialogsPadding.x() + st::dialogsPhotoSize + st::dialogsPhotoPadding;
|
||||
auto namewidth = fullWidth - nameleft - st::dialogsPadding.x();
|
||||
|
|
|
@ -297,7 +297,7 @@ void DialogsInner::paintPeerSearchResult(Painter &p, const PeerSearchResult *res
|
|||
|
||||
auto peer = result->peer;
|
||||
auto userpicPeer = (peer->migrateTo() ? peer->migrateTo() : peer);
|
||||
userpicPeer->paintUserpicLeft(p, st::dialogsPhotoSize, st::dialogsPadding.x(), st::dialogsPadding.y(), getFullWidth());
|
||||
userpicPeer->paintUserpicLeft(p, st::dialogsPadding.x(), st::dialogsPadding.y(), getFullWidth(), st::dialogsPhotoSize);
|
||||
|
||||
auto nameleft = st::dialogsPadding.x() + st::dialogsPhotoSize + st::dialogsPhotoPadding;
|
||||
auto namewidth = fullWidth - nameleft - st::dialogsPadding.x();
|
||||
|
@ -344,7 +344,7 @@ void DialogsInner::paintSearchInPeer(Painter &p, int fullWidth, bool onlyBackgro
|
|||
p.fillRect(fullRect, st::dialogsBg);
|
||||
if (onlyBackground) return;
|
||||
|
||||
_searchInPeer->paintUserpicLeft(p, st::dialogsPhotoSize, st::dialogsPadding.x(), st::dialogsPadding.y(), getFullWidth());
|
||||
_searchInPeer->paintUserpicLeft(p, st::dialogsPadding.x(), st::dialogsPadding.y(), getFullWidth(), st::dialogsPhotoSize);
|
||||
|
||||
auto nameleft = st::dialogsPadding.x() + st::dialogsPhotoSize + st::dialogsPhotoPadding;
|
||||
auto namewidth = fullWidth - nameleft - st::dialogsPadding.x() * 2 - st::dialogsCancelSearch.width;
|
||||
|
|
|
@ -618,7 +618,7 @@ void FieldAutocompleteInner::paintEvent(QPaintEvent *e) {
|
|||
}
|
||||
}
|
||||
user->loadUserpic();
|
||||
user->paintUserpicLeft(p, st::mentionPhotoSize, st::mentionPadding.left(), i * st::mentionHeight + st::mentionPadding.top(), width());
|
||||
user->paintUserpicLeft(p, st::mentionPadding.left(), i * st::mentionHeight + st::mentionPadding.top(), width(), st::mentionPhotoSize);
|
||||
|
||||
p.setPen(selected ? st::mentionNameFgOver : st::mentionNameFg);
|
||||
user->nameText.drawElided(p, 2 * st::mentionPadding.left() + st::mentionPhotoSize, i * st::mentionHeight + st::mentionTop, namewidth);
|
||||
|
@ -663,7 +663,7 @@ void FieldAutocompleteInner::paintEvent(QPaintEvent *e) {
|
|||
toHighlight += '@' + user->username;
|
||||
}
|
||||
user->loadUserpic();
|
||||
user->paintUserpicLeft(p, st::mentionPhotoSize, st::mentionPadding.left(), i * st::mentionHeight + st::mentionPadding.top(), width());
|
||||
user->paintUserpicLeft(p, st::mentionPadding.left(), i * st::mentionHeight + st::mentionPadding.top(), width(), st::mentionPhotoSize);
|
||||
|
||||
auto commandText = '/' + toHighlight;
|
||||
|
||||
|
|
|
@ -145,23 +145,6 @@ historyViewsOutIcon: icon {{ "history_views", historyOutIconFg }};
|
|||
historyViewsOutSelectedIcon: icon {{ "history_views", historyOutIconFgSelected }};
|
||||
historyViewsInvertedIcon: icon {{ "history_views", historySendingInvertedIconFg }};
|
||||
|
||||
historyPeer1UserpicPerson: icon {{ size(120px, 120px), historyPeer1UserpicBg }, { "userpic_person", historyPeer1UserpicFg }};
|
||||
historyPeer1UserpicChat: icon {{ size(120px, 120px), historyPeer1UserpicBg }, { "userpic_chat", historyPeer1UserpicFg }};
|
||||
historyPeer1UserpicChannel: icon {{ size(120px, 120px), historyPeer1UserpicBg }, { "userpic_channel", historyPeer1UserpicFg }};
|
||||
historyPeer2UserpicPerson: icon {{ size(120px, 120px), historyPeer2UserpicBg }, { "userpic_person", historyPeer2UserpicFg }};
|
||||
historyPeer2UserpicChat: icon {{ size(120px, 120px), historyPeer2UserpicBg }, { "userpic_chat", historyPeer2UserpicFg }};
|
||||
historyPeer2UserpicChannel: icon {{ size(120px, 120px), historyPeer2UserpicBg }, { "userpic_channel", historyPeer2UserpicFg }};
|
||||
historyPeer3UserpicPerson: icon {{ size(120px, 120px), historyPeer3UserpicBg }, { "userpic_person", historyPeer3UserpicFg }};
|
||||
historyPeer3UserpicChat: icon {{ size(120px, 120px), historyPeer3UserpicBg }, { "userpic_chat", historyPeer3UserpicFg }};
|
||||
historyPeer3UserpicChannel: icon {{ size(120px, 120px), historyPeer3UserpicBg }, { "userpic_channel", historyPeer3UserpicFg }};
|
||||
historyPeer4UserpicPerson: icon {{ size(120px, 120px), historyPeer4UserpicBg }, { "userpic_person", historyPeer4UserpicFg }};
|
||||
historyPeer4UserpicChat: icon {{ size(120px, 120px), historyPeer4UserpicBg }, { "userpic_chat", historyPeer4UserpicFg }};
|
||||
historyPeer4UserpicChannel: icon {{ size(120px, 120px), historyPeer4UserpicBg }, { "userpic_channel", historyPeer4UserpicFg }};
|
||||
historyPeer5UserpicPerson: icon {{ size(120px, 120px), historyPeer5UserpicBg }, { "userpic_person", historyPeer5UserpicFg }};
|
||||
historyPeer6UserpicPerson: icon {{ size(120px, 120px), historyPeer6UserpicBg }, { "userpic_person", historyPeer6UserpicFg }};
|
||||
historyPeer7UserpicPerson: icon {{ size(120px, 120px), historyPeer7UserpicBg }, { "userpic_person", historyPeer7UserpicFg }};
|
||||
historyPeer8UserpicPerson: icon {{ size(120px, 120px), historyPeer8UserpicBg }, { "userpic_person", historyPeer8UserpicFg }};
|
||||
|
||||
historyComposeField: FlatTextarea {
|
||||
textColor: historyComposeAreaFg;
|
||||
bgColor: historyComposeAreaBg;
|
||||
|
@ -391,6 +374,8 @@ historyBubbleTailInRightSelected: icon {{ "bubble_tail-flip_horizontal", msgInBg
|
|||
historyBubbleTailOutRight: icon {{ "bubble_tail-flip_horizontal", msgOutBg }};
|
||||
historyBubbleTailOutRightSelected: icon {{ "bubble_tail-flip_horizontal", msgOutBgSelected }};
|
||||
|
||||
historyPeerUserpicFont: semiboldFont;
|
||||
|
||||
historyStatusFg: windowSubTextFg;
|
||||
historyStatusFgActive: windowActiveTextFg;
|
||||
historyStatusFgTyping: historyStatusFgActive;
|
||||
|
|
|
@ -2235,16 +2235,17 @@ HistoryContact::HistoryContact(HistoryItem *parent, int32 userId, const QString
|
|||
, _lname(last)
|
||||
, _phone(App::formatPhone(phone)) {
|
||||
_name.setText(st::semiboldTextStyle, lng_full_name(lt_first_name, first, lt_last_name, last).trimmed(), _textNameOptions);
|
||||
|
||||
_phonew = st::normalFont->width(_phone);
|
||||
}
|
||||
|
||||
void HistoryContact::initDimensions() {
|
||||
_maxw = st::msgFileMinWidth;
|
||||
|
||||
_contact = _userId ? App::userLoaded(_userId) : 0;
|
||||
_contact = _userId ? App::userLoaded(_userId) : nullptr;
|
||||
if (_contact) {
|
||||
_contact->loadUserpic();
|
||||
} else {
|
||||
_photoEmpty.set(qAbs(_userId ? _userId : _parent->id) % kUserColorsCount, _name.originalText());
|
||||
}
|
||||
if (_contact && _contact->contact > 0) {
|
||||
_linkl = sendMessageClickHandler(_contact);
|
||||
|
@ -2305,12 +2306,15 @@ void HistoryContact::draw(Painter &p, const QRect &r, TextSelection selection, T
|
|||
|
||||
QRect rthumb(rtlrect(st::msgFileThumbPadding.left(), st::msgFileThumbPadding.top() - topMinus, st::msgFileThumbSize, st::msgFileThumbSize, width));
|
||||
if (_contact) {
|
||||
_contact->paintUserpic(p, st::msgFileThumbSize, rthumb.x(), rthumb.y());
|
||||
_contact->paintUserpic(p, rthumb.x(), rthumb.y(), st::msgFileThumbSize);
|
||||
} else {
|
||||
p.drawPixmap(rthumb.topLeft(), userDefPhoto(qAbs(_userId) % kUserColorsCount)->pixCircled(st::msgFileThumbSize, st::msgFileThumbSize));
|
||||
_photoEmpty.paint(p, st::msgFileThumbPadding.left(), st::msgFileThumbPadding.top() - topMinus, width, st::msgFileThumbSize);
|
||||
}
|
||||
if (selected) {
|
||||
App::roundRect(p, rthumb, p.textPalette().selectOverlay, SelectedOverlaySmallCorners);
|
||||
PainterHighQualityEnabler hq(p);
|
||||
p.setBrush(p.textPalette().selectOverlay);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.drawEllipse(rthumb);
|
||||
}
|
||||
|
||||
bool over = ClickHandler::showAsActive(_linkl);
|
||||
|
@ -2323,8 +2327,7 @@ void HistoryContact::draw(Painter &p, const QRect &r, TextSelection selection, T
|
|||
nameright = st::msgFilePadding.left();
|
||||
statustop = st::msgFileStatusTop - topMinus;
|
||||
|
||||
QRect inner(rtlrect(st::msgFilePadding.left(), st::msgFilePadding.top() - topMinus, st::msgFileSize, st::msgFileSize, width));
|
||||
p.drawPixmap(inner.topLeft(), userDefPhoto(qAbs(_parent->id) % kUserColorsCount)->pixCircled(st::msgFileSize, st::msgFileSize));
|
||||
_photoEmpty.paint(p, st::msgFilePadding.left(), st::msgFilePadding.top() - topMinus, width, st::msgFileSize);
|
||||
}
|
||||
int32 namewidth = width - nameleft - nameright;
|
||||
|
||||
|
|
|
@ -636,6 +636,7 @@ private:
|
|||
int _phonew = 0;
|
||||
QString _fname, _lname, _phone;
|
||||
Text _name;
|
||||
EmptyUserpic _photoEmpty;
|
||||
|
||||
ClickHandlerPtr _linkl;
|
||||
int _linkw = 0;
|
||||
|
|
|
@ -553,7 +553,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
|
|||
|
||||
// paint the userpic if it intersects the painted rect
|
||||
if (userpicTop + st::msgPhotoSize > r.top()) {
|
||||
message->from()->paintUserpicLeft(p, st::msgPhotoSize, st::historyPhotoLeft, userpicTop, message->history()->width);
|
||||
message->from()->paintUserpicLeft(p, st::historyPhotoLeft, userpicTop, message->history()->width, st::msgPhotoSize);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
|
|
@ -146,7 +146,11 @@ ImagePtr ItemBase::getResultThumb() const {
|
|||
|
||||
QPixmap ItemBase::getResultContactAvatar(int width, int height) const {
|
||||
if (_result->_type == Result::Type::Contact) {
|
||||
return userDefPhoto(qHash(_result->_id) % kUserColorsCount)->pixCircled(width, height);
|
||||
auto result = EmptyUserpic(qHash(_result->_id) % kUserColorsCount, _result->getLayoutTitle()).generate(width);
|
||||
if (result.height() != height * cIntRetinaFactor()) {
|
||||
result = result.scaled(QSize(width, height) * cIntRetinaFactor(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||
}
|
||||
return std_::move(result);
|
||||
}
|
||||
return QPixmap();
|
||||
}
|
||||
|
|
|
@ -3874,7 +3874,7 @@ PeerData *_readPeer(FileReadDescriptor &from, int32 fileVersion = 0) {
|
|||
user->inputUser = MTP_inputUser(MTP_int(peerToUser(user->id)), MTP_long((user->access == UserNoAccess) ? 0 : user->access));
|
||||
}
|
||||
|
||||
user->setUserpic(photoLoc.isNull() ? ImagePtr(userDefPhoto(user->colorIndex)) : ImagePtr(photoLoc));
|
||||
user->setUserpic(photoLoc.isNull() ? ImagePtr() : ImagePtr(photoLoc));
|
||||
}
|
||||
} else if (result->isChat()) {
|
||||
ChatData *chat = result->asChat();
|
||||
|
@ -3902,7 +3902,7 @@ PeerData *_readPeer(FileReadDescriptor &from, int32 fileVersion = 0) {
|
|||
chat->input = MTP_inputPeerChat(MTP_int(peerToChat(chat->id)));
|
||||
chat->inputChat = MTP_int(peerToChat(chat->id));
|
||||
|
||||
chat->setUserpic(photoLoc.isNull() ? ImagePtr(chatDefPhoto(chat->colorIndex)) : ImagePtr(photoLoc));
|
||||
chat->setUserpic(photoLoc.isNull() ? ImagePtr() : ImagePtr(photoLoc));
|
||||
}
|
||||
} else if (result->isChannel()) {
|
||||
ChannelData *channel = result->asChannel();
|
||||
|
@ -3924,7 +3924,7 @@ PeerData *_readPeer(FileReadDescriptor &from, int32 fileVersion = 0) {
|
|||
channel->input = MTP_inputPeerChannel(MTP_int(peerToChannel(channel->id)), MTP_long(access));
|
||||
channel->inputChannel = MTP_inputChannel(MTP_int(peerToChannel(channel->id)), MTP_long(access));
|
||||
|
||||
channel->setUserpic(photoLoc.isNull() ? ImagePtr((channel->isMegagroup() ? chatDefPhoto(channel->colorIndex) : channelDefPhoto(channel->colorIndex))) : ImagePtr(photoLoc));
|
||||
channel->setUserpic(photoLoc.isNull() ? ImagePtr() : ImagePtr(photoLoc));
|
||||
}
|
||||
}
|
||||
if (!wasLoaded) {
|
||||
|
|
|
@ -96,7 +96,7 @@ void PeerListWidget::paintItem(Painter &p, int x, int y, Item *item, bool select
|
|||
}
|
||||
int skip = st::profileMemberPhotoPosition.x();
|
||||
|
||||
item->peer->paintUserpicLeft(p, st::profileMemberPhotoSize, x + st::profileMemberPhotoPosition.x(), y + st::profileMemberPhotoPosition.y(), width());
|
||||
item->peer->paintUserpicLeft(p, x + st::profileMemberPhotoPosition.x(), y + st::profileMemberPhotoPosition.y(), width(), st::profileMemberPhotoSize);
|
||||
|
||||
if (item->name.isEmpty()) {
|
||||
item->name.setText(st::msgNameStyle, App::peerName(item->peer), _textNameOptions);
|
||||
|
|
|
@ -236,7 +236,7 @@ void InnerWidget::paintRow(Painter &p, int index, TimeMs ms) {
|
|||
|
||||
x += st::profileCommonGroupsPadding.left();
|
||||
y += st::profileCommonGroupsPadding.top();
|
||||
item->peer->paintUserpic(p, st::profileCommonGroupsPhotoSize, rtl() ? (width() - x - st::profileCommonGroupsPhotoSize) : x, y);
|
||||
item->peer->paintUserpic(p, rtl() ? (width() - x - st::profileCommonGroupsPhotoSize) : x, y, st::profileCommonGroupsPhotoSize);
|
||||
|
||||
x += st::profileCommonGroupsPhotoSize + st::profileCommonGroupsNameLeft;
|
||||
y += st::profileCommonGroupsNameTop;
|
||||
|
|
|
@ -115,7 +115,7 @@ QPixmap UserpicButton::prepareUserpicPixmap() const {
|
|||
image.fill(Qt::transparent);
|
||||
{
|
||||
Painter p(&image);
|
||||
_peer->paintUserpic(p, width(), 0, 0);
|
||||
_peer->paintUserpic(p, 0, 0, width());
|
||||
}
|
||||
return App::pixmapFromImageInPlace(std_::move(image));
|
||||
}
|
||||
|
|
|
@ -74,40 +74,140 @@ style::color peerColor(int index) {
|
|||
return peerColors[index];
|
||||
}
|
||||
|
||||
ImagePtr userDefPhoto(int index) {
|
||||
static const ImagePtr userDefPhotos[kUserColorsCount] = {
|
||||
generateUserpicImage(st::historyPeer1UserpicPerson),
|
||||
generateUserpicImage(st::historyPeer2UserpicPerson),
|
||||
generateUserpicImage(st::historyPeer3UserpicPerson),
|
||||
generateUserpicImage(st::historyPeer4UserpicPerson),
|
||||
generateUserpicImage(st::historyPeer5UserpicPerson),
|
||||
generateUserpicImage(st::historyPeer6UserpicPerson),
|
||||
generateUserpicImage(st::historyPeer7UserpicPerson),
|
||||
generateUserpicImage(st::historyPeer8UserpicPerson),
|
||||
style::color peerUserpicColor(int index) {
|
||||
static style::color peerColors[kUserColorsCount] = {
|
||||
st::historyPeer1UserpicBg,
|
||||
st::historyPeer2UserpicBg,
|
||||
st::historyPeer3UserpicBg,
|
||||
st::historyPeer4UserpicBg,
|
||||
st::historyPeer5UserpicBg,
|
||||
st::historyPeer6UserpicBg,
|
||||
st::historyPeer7UserpicBg,
|
||||
st::historyPeer8UserpicBg,
|
||||
};
|
||||
return userDefPhotos[index];
|
||||
return peerColors[index];
|
||||
}
|
||||
|
||||
ImagePtr chatDefPhoto(int index) {
|
||||
static const ImagePtr chatDefPhotos[kChatColorsCount] = {
|
||||
generateUserpicImage(st::historyPeer1UserpicChat),
|
||||
generateUserpicImage(st::historyPeer2UserpicChat),
|
||||
generateUserpicImage(st::historyPeer3UserpicChat),
|
||||
generateUserpicImage(st::historyPeer4UserpicChat),
|
||||
};
|
||||
return chatDefPhotos[index];
|
||||
class EmptyUserpic::Impl {
|
||||
public:
|
||||
Impl(int index, const QString &name) : _color(peerUserpicColor(index)) {
|
||||
fillString(name);
|
||||
}
|
||||
|
||||
void paint(Painter &p, int x, int y, int size);
|
||||
|
||||
private:
|
||||
void fillString(const QString &name);
|
||||
|
||||
style::color _color;
|
||||
QString _string;
|
||||
|
||||
};
|
||||
|
||||
void EmptyUserpic::Impl::paint(Painter &p, int x, int y, int size) {
|
||||
auto fontsize = (size * 13) / 33;
|
||||
auto font = st::historyPeerUserpicFont->f;
|
||||
font.setPixelSize(fontsize);
|
||||
|
||||
PainterHighQualityEnabler hq(p);
|
||||
p.setBrush(_color);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.drawEllipse(x, y, size, size);
|
||||
|
||||
p.setFont(font);
|
||||
p.setBrush(Qt::NoBrush);
|
||||
p.setPen(st::historyPeerUserpicFg);
|
||||
p.drawText(QRect(x, y, size, size), _string, QTextOption(style::al_center));
|
||||
}
|
||||
|
||||
ImagePtr channelDefPhoto(int index) {
|
||||
static const ImagePtr channelDefPhotos[kChannelColorsCount] = {
|
||||
generateUserpicImage(st::historyPeer1UserpicChannel),
|
||||
generateUserpicImage(st::historyPeer2UserpicChannel),
|
||||
generateUserpicImage(st::historyPeer3UserpicChannel),
|
||||
generateUserpicImage(st::historyPeer4UserpicChannel),
|
||||
};
|
||||
return channelDefPhotos[index];
|
||||
void EmptyUserpic::Impl::fillString(const QString &name) {
|
||||
QList<QString> letters;
|
||||
QList<int> levels;
|
||||
auto level = 0;
|
||||
auto letterFound = false;
|
||||
auto ch = name.constData(), end = ch + name.size();
|
||||
while (ch != end) {
|
||||
auto emojiLength = 0;
|
||||
if (auto emoji = emojiFromText(ch, end, &emojiLength)) {
|
||||
ch += emojiLength;
|
||||
} else if (ch->isHighSurrogate()) {
|
||||
++ch;
|
||||
if (ch != end && ch->isLowSurrogate()) {
|
||||
++ch;
|
||||
}
|
||||
} else if (!letterFound && ch->isLetterOrNumber()) {
|
||||
letterFound = true;
|
||||
if (ch + 1 != end && chIsDiac(*(ch + 1))) {
|
||||
letters.push_back(QString(ch, 2));
|
||||
levels.push_back(level);
|
||||
++ch;
|
||||
} else {
|
||||
letters.push_back(QString(ch, 1));
|
||||
levels.push_back(level);
|
||||
}
|
||||
++ch;
|
||||
} else {
|
||||
if (*ch == ' ') {
|
||||
level = 0;
|
||||
letterFound = false;
|
||||
} else if (letterFound && *ch == '-') {
|
||||
level = 1;
|
||||
letterFound = true;
|
||||
}
|
||||
++ch;
|
||||
}
|
||||
}
|
||||
|
||||
// We prefer the second letter to be after ' ', but it can also be after '-'.
|
||||
_string = QString();
|
||||
if (!letters.isEmpty()) {
|
||||
_string += letters.front();
|
||||
auto bestIndex = 0;
|
||||
auto bestLevel = 2;
|
||||
for (auto i = letters.size(); i != 1;) {
|
||||
if (levels[--i] < bestLevel) {
|
||||
bestIndex = i;
|
||||
bestLevel = levels[i];
|
||||
}
|
||||
}
|
||||
if (bestIndex > 0) {
|
||||
_string += letters[bestIndex];
|
||||
}
|
||||
}
|
||||
_string = _string.toUpper();
|
||||
}
|
||||
|
||||
EmptyUserpic::EmptyUserpic() = default;
|
||||
|
||||
EmptyUserpic::EmptyUserpic(int index, const QString &name) : _impl(std_::make_unique<Impl>(index, name)) {
|
||||
}
|
||||
|
||||
void EmptyUserpic::set(int index, const QString &name) {
|
||||
_impl = std_::make_unique<Impl>(index, name);
|
||||
}
|
||||
|
||||
void EmptyUserpic::clear() {
|
||||
_impl.reset();
|
||||
}
|
||||
|
||||
void EmptyUserpic::paint(Painter &p, int x, int y, int outerWidth, int size) const {
|
||||
t_assert(_impl != nullptr);
|
||||
_impl->paint(p, rtl() ? (outerWidth - x - size) : x, y, size);
|
||||
}
|
||||
|
||||
QPixmap EmptyUserpic::generate(int size) {
|
||||
auto result = QImage(QSize(size, size) * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
|
||||
result.setDevicePixelRatio(cRetinaFactor());
|
||||
result.fill(Qt::transparent);
|
||||
{
|
||||
Painter p(&result);
|
||||
paint(p, 0, 0, size, size);
|
||||
}
|
||||
return App::pixmapFromImageInPlace(std_::move(result));
|
||||
}
|
||||
|
||||
EmptyUserpic::~EmptyUserpic() = default;
|
||||
|
||||
using UpdateFlag = Notify::PeerUpdate::Flag;
|
||||
|
||||
NotifySettings globalNotifyAll, globalNotifyUsers, globalNotifyChats;
|
||||
|
@ -115,9 +215,9 @@ NotifySettingsPtr globalNotifyAllPtr = UnknownNotifySettings, globalNotifyUsersP
|
|||
|
||||
PeerData::PeerData(const PeerId &id) : id(id)
|
||||
, colorIndex(peerColorIndex(id))
|
||||
, color(peerColor(colorIndex))
|
||||
, _userpic(isUser() ? userDefPhoto(colorIndex) : ((isChat() || isMegagroup()) ? chatDefPhoto(colorIndex) : channelDefPhoto(colorIndex))) {
|
||||
, color(peerColor(colorIndex)) {
|
||||
nameText.setText(st::msgNameStyle, QString(), _textNameOptions);
|
||||
_userpicEmpty.set(colorIndex, QString());
|
||||
}
|
||||
|
||||
void PeerData::updateNameDelayed(const QString &newName, const QString &newNameOrPhone, const QString &newUsername) {
|
||||
|
@ -138,6 +238,9 @@ void PeerData::updateNameDelayed(const QString &newName, const QString &newNameO
|
|||
++nameVersion;
|
||||
name = newName;
|
||||
nameText.setText(st::msgNameStyle, name, _textNameOptions);
|
||||
if (!_userpic) {
|
||||
_userpicEmpty.set(colorIndex, name);
|
||||
}
|
||||
|
||||
Notify::PeerUpdate update(this);
|
||||
update.flags |= UpdateFlag::NameChanged;
|
||||
|
@ -170,39 +273,55 @@ void PeerData::updateNameDelayed(const QString &newName, const QString &newNameO
|
|||
|
||||
void PeerData::setUserpic(ImagePtr userpic) {
|
||||
_userpic = userpic;
|
||||
if (!_userpic || !_userpic->loaded()) {
|
||||
_userpicEmpty.set(colorIndex, name);
|
||||
} else {
|
||||
_userpicEmpty.clear();
|
||||
}
|
||||
}
|
||||
|
||||
ImagePtr PeerData::currentUserpic() const {
|
||||
if (_userpic->loaded()) {
|
||||
return _userpic;
|
||||
if (_userpic) {
|
||||
_userpic->load();
|
||||
if (_userpic->loaded()) {
|
||||
_userpicEmpty.clear();
|
||||
return _userpic;
|
||||
}
|
||||
}
|
||||
_userpic->load();
|
||||
|
||||
if (isUser()) {
|
||||
return userDefPhoto(colorIndex);
|
||||
} else if (isMegagroup() || isChat()) {
|
||||
return chatDefPhoto(colorIndex);
|
||||
}
|
||||
return channelDefPhoto(colorIndex);
|
||||
return ImagePtr();
|
||||
}
|
||||
|
||||
void PeerData::paintUserpic(Painter &p, int size, int x, int y) const {
|
||||
p.drawPixmap(x, y, currentUserpic()->pixCircled(size, size));
|
||||
void PeerData::paintUserpic(Painter &p, int x, int y, int size) const {
|
||||
if (auto userpic = currentUserpic()) {
|
||||
p.drawPixmap(x, y, userpic->pixCircled(size, size));
|
||||
} else {
|
||||
_userpicEmpty.paint(p, x, y, x + size + x, size);
|
||||
}
|
||||
}
|
||||
|
||||
StorageKey PeerData::userpicUniqueKey() const {
|
||||
if (photoLoc.isNull() || !_userpic->loaded()) {
|
||||
if (photoLoc.isNull() || !_userpic || !_userpic->loaded()) {
|
||||
return StorageKey(0, (isUser() ? 0x1000 : ((isChat() || isMegagroup()) ? 0x2000 : 0x3000)) | colorIndex);
|
||||
}
|
||||
return storageKey(photoLoc);
|
||||
}
|
||||
|
||||
void PeerData::saveUserpic(const QString &path, int size) const {
|
||||
currentUserpic()->pixRounded(size, size, ImageRoundRadius::Small).save(path, "PNG");
|
||||
genUserpic(size).save(path, "PNG");
|
||||
}
|
||||
|
||||
QPixmap PeerData::genUserpic(int size) const {
|
||||
return currentUserpic()->pixRounded(size, size, ImageRoundRadius::Small);
|
||||
if (auto userpic = currentUserpic()) {
|
||||
return userpic->pixRounded(size, size, ImageRoundRadius::Small);
|
||||
}
|
||||
auto result = QImage(QSize(size, size) * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
|
||||
result.setDevicePixelRatio(cRetinaFactor());
|
||||
result.fill(Qt::transparent);
|
||||
{
|
||||
Painter p(&result);
|
||||
paintUserpic(p, 0, 0, size);
|
||||
}
|
||||
return App::pixmapFromImageInPlace(std_::move(result));
|
||||
}
|
||||
|
||||
const Text &BotCommand::descriptionText() const {
|
||||
|
@ -225,17 +344,17 @@ void UserData::setPhoto(const MTPUserProfilePhoto &p) { // see Local::readPeer a
|
|||
const auto &d(p.c_userProfilePhoto());
|
||||
newPhotoId = d.vphoto_id.v;
|
||||
newPhotoLoc = App::imageLocation(160, 160, d.vphoto_small);
|
||||
newPhoto = newPhotoLoc.isNull() ? userDefPhoto(colorIndex) : ImagePtr(newPhotoLoc);
|
||||
newPhoto = newPhotoLoc.isNull() ? ImagePtr() : ImagePtr(newPhotoLoc);
|
||||
//App::feedPhoto(App::photoFromUserPhoto(peerToUser(id), MTP_int(unixtime()), p));
|
||||
} break;
|
||||
default: {
|
||||
newPhotoId = 0;
|
||||
if (id == ServiceUserId) {
|
||||
if (_userpic.v() == userDefPhoto(colorIndex).v()) {
|
||||
if (!_userpic) {
|
||||
newPhoto = ImagePtr(App::pixmapFromImageInPlace(App::wnd()->iconLarge().scaledToWidth(160, Qt::SmoothTransformation)), "PNG");
|
||||
}
|
||||
} else {
|
||||
newPhoto = userDefPhoto(colorIndex);
|
||||
newPhoto = ImagePtr();
|
||||
}
|
||||
newPhotoLoc = StorageImageLocation();
|
||||
} break;
|
||||
|
@ -423,13 +542,13 @@ void ChatData::setPhoto(const MTPChatPhoto &p, const PhotoId &phId) { // see Loc
|
|||
newPhotoId = phId;
|
||||
}
|
||||
newPhotoLoc = App::imageLocation(160, 160, d.vphoto_small);
|
||||
newPhoto = newPhotoLoc.isNull() ? chatDefPhoto(colorIndex) : ImagePtr(newPhotoLoc);
|
||||
// photoFull = ImagePtr(640, 640, d.vphoto_big, chatDefPhoto(colorIndex));
|
||||
newPhoto = newPhotoLoc.isNull() ? ImagePtr() : ImagePtr(newPhotoLoc);
|
||||
// photoFull = newPhoto ? ImagePtr(640, 640, d.vphoto_big, ImagePtr()) : ImagePtr();
|
||||
} break;
|
||||
default: {
|
||||
newPhotoId = 0;
|
||||
newPhotoLoc = StorageImageLocation();
|
||||
newPhoto = chatDefPhoto(colorIndex);
|
||||
newPhoto = ImagePtr();
|
||||
// photoFull = ImagePtr();
|
||||
} break;
|
||||
}
|
||||
|
@ -479,13 +598,13 @@ void ChannelData::setPhoto(const MTPChatPhoto &p, const PhotoId &phId) { // see
|
|||
newPhotoId = phId;
|
||||
}
|
||||
newPhotoLoc = App::imageLocation(160, 160, d.vphoto_small);
|
||||
newPhoto = newPhotoLoc.isNull() ? (isMegagroup() ? chatDefPhoto(colorIndex) : channelDefPhoto(colorIndex)) : ImagePtr(newPhotoLoc);
|
||||
// photoFull = ImagePtr(640, 640, d.vphoto_big, (isMegagroup() ? chatDefPhoto(colorIndex) : channelDefPhoto(colorIndex)));
|
||||
newPhoto = newPhotoLoc.isNull() ? ImagePtr() : ImagePtr(newPhotoLoc);
|
||||
// photoFull = newPhoto ? ImagePtr(640, 640, d.vphoto_big, newPhoto) : ImagePtr();
|
||||
} break;
|
||||
default: {
|
||||
newPhotoId = 0;
|
||||
newPhotoLoc = StorageImageLocation();
|
||||
newPhoto = (isMegagroup() ? chatDefPhoto(colorIndex) : channelDefPhoto(colorIndex));
|
||||
newPhoto = ImagePtr();
|
||||
// photoFull = ImagePtr();
|
||||
} break;
|
||||
}
|
||||
|
|
|
@ -204,9 +204,30 @@ static constexpr int kChatColorsCount = 4;
|
|||
static constexpr int kChannelColorsCount = 4;
|
||||
|
||||
style::color peerColor(int index);
|
||||
ImagePtr userDefPhoto(int index);
|
||||
ImagePtr chatDefPhoto(int index);
|
||||
ImagePtr channelDefPhoto(int index);
|
||||
|
||||
class EmptyUserpic {
|
||||
public:
|
||||
EmptyUserpic();
|
||||
EmptyUserpic(int index, const QString &name);
|
||||
|
||||
void set(int index, const QString &name);
|
||||
void clear();
|
||||
|
||||
explicit operator bool() const {
|
||||
return (_impl != nullptr);
|
||||
}
|
||||
|
||||
void paint(Painter &p, int x, int y, int outerWidth, int size) const;
|
||||
QPixmap generate(int size);
|
||||
|
||||
~EmptyUserpic();
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
std_::unique_ptr<Impl> _impl;
|
||||
friend class Impl;
|
||||
|
||||
};
|
||||
|
||||
static const PhotoId UnknownPeerPhotoId = 0xFFFFFFFFFFFFFFFFULL;
|
||||
|
||||
|
@ -292,9 +313,9 @@ public:
|
|||
style::color color;
|
||||
|
||||
void setUserpic(ImagePtr userpic);
|
||||
void paintUserpic(Painter &p, int size, int x, int y) const;
|
||||
void paintUserpicLeft(Painter &p, int size, int x, int y, int w) const {
|
||||
paintUserpic(p, size, rtl() ? (w - x - size) : x, y);
|
||||
void paintUserpic(Painter &p, int x, int y, int size) const;
|
||||
void paintUserpicLeft(Painter &p, int x, int y, int w, int size) const {
|
||||
paintUserpic(p, rtl() ? (w - x - size) : x, y, size);
|
||||
}
|
||||
void loadUserpic(bool loadFirst = false, bool prior = true) {
|
||||
_userpic->load(loadFirst, prior);
|
||||
|
@ -331,6 +352,7 @@ protected:
|
|||
|
||||
ImagePtr _userpic;
|
||||
ImagePtr currentUserpic() const;
|
||||
mutable EmptyUserpic _userpicEmpty;
|
||||
|
||||
private:
|
||||
void fillNames();
|
||||
|
|
|
@ -36,7 +36,7 @@ PeerAvatarButton::PeerAvatarButton(QWidget *parent, PeerData *peer, const style:
|
|||
void PeerAvatarButton::paintEvent(QPaintEvent *e) {
|
||||
if (_peer) {
|
||||
Painter p(this);
|
||||
_peer->paintUserpic(p, _st.photoSize, (_st.size - _st.photoSize) / 2, (_st.size - _st.photoSize) / 2);
|
||||
_peer->paintUserpic(p, (_st.size - _st.photoSize) / 2, (_st.size - _st.photoSize) / 2, _st.photoSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -444,6 +444,11 @@ public:
|
|||
ImagePtr(int32 width, int32 height, const MTPFileLocation &location, ImagePtr def = ImagePtr());
|
||||
ImagePtr(int32 width, int32 height) : Parent(internal::getImage(width, height)) {
|
||||
}
|
||||
|
||||
explicit operator bool() const {
|
||||
return (_data != nullptr) && !_data->isNull();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
inline QSize shrinkToKeepAspect(int32 width, int32 height, int32 towidth, int32 toheight) {
|
||||
|
|
|
@ -612,7 +612,7 @@ void Notification::updateNotifyDisplay() {
|
|||
|
||||
if (!options.hideNameAndPhoto) {
|
||||
_history->peer->loadUserpic(true, true);
|
||||
_history->peer->paintUserpicLeft(p, st::notifyPhotoSize, st::notifyPhotoPos.x(), st::notifyPhotoPos.y(), width());
|
||||
_history->peer->paintUserpicLeft(p, st::notifyPhotoPos.x(), st::notifyPhotoPos.y(), width(), st::notifyPhotoSize);
|
||||
} else {
|
||||
static QPixmap icon = App::pixmapFromImageInPlace(App::wnd()->iconLarge().scaled(st::notifyPhotoSize, st::notifyPhotoSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||
icon.setDevicePixelRatio(cRetinaFactor());
|
||||
|
@ -680,7 +680,7 @@ void Notification::updatePeerPhoto() {
|
|||
auto img = _cache.toImage();
|
||||
{
|
||||
Painter p(&img);
|
||||
_peer->paintUserpicLeft(p, st::notifyPhotoSize, st::notifyPhotoPos.x(), st::notifyPhotoPos.y(), width());
|
||||
_peer->paintUserpicLeft(p, st::notifyPhotoPos.x(), st::notifyPhotoPos.y(), width(), st::notifyPhotoSize);
|
||||
}
|
||||
_cache = App::pixmapFromImageInPlace(std_::move(img));
|
||||
update();
|
||||
|
|
|
@ -34,6 +34,63 @@ namespace Window {
|
|||
namespace Theme {
|
||||
namespace {
|
||||
|
||||
QString fillLetters(const QString &name) {
|
||||
QList<QString> letters;
|
||||
QList<int> levels;
|
||||
auto level = 0;
|
||||
auto letterFound = false;
|
||||
auto ch = name.constData(), end = ch + name.size();
|
||||
while (ch != end) {
|
||||
auto emojiLength = 0;
|
||||
if (auto emoji = emojiFromText(ch, end, &emojiLength)) {
|
||||
ch += emojiLength;
|
||||
} else if (ch->isHighSurrogate()) {
|
||||
++ch;
|
||||
if (ch != end && ch->isLowSurrogate()) {
|
||||
++ch;
|
||||
}
|
||||
} else if (!letterFound && ch->isLetterOrNumber()) {
|
||||
letterFound = true;
|
||||
if (ch + 1 != end && chIsDiac(*(ch + 1))) {
|
||||
letters.push_back(QString(ch, 2));
|
||||
levels.push_back(level);
|
||||
++ch;
|
||||
} else {
|
||||
letters.push_back(QString(ch, 1));
|
||||
levels.push_back(level);
|
||||
}
|
||||
++ch;
|
||||
} else {
|
||||
if (*ch == ' ') {
|
||||
level = 0;
|
||||
letterFound = false;
|
||||
} else if (letterFound && *ch == '-') {
|
||||
level = 1;
|
||||
letterFound = true;
|
||||
}
|
||||
++ch;
|
||||
}
|
||||
}
|
||||
|
||||
// We prefer the second letter to be after ' ', but it can also be after '-'.
|
||||
auto result = QString();
|
||||
if (!letters.isEmpty()) {
|
||||
result += letters.front();
|
||||
auto bestIndex = 0;
|
||||
auto bestLevel = 2;
|
||||
for (auto i = letters.size(); i != 1;) {
|
||||
if (levels[--i] < bestLevel) {
|
||||
bestIndex = i;
|
||||
bestLevel = levels[i];
|
||||
}
|
||||
}
|
||||
if (bestIndex > 0) {
|
||||
result += letters[bestIndex];
|
||||
}
|
||||
}
|
||||
return result.toUpper();
|
||||
}
|
||||
|
||||
class Generator {
|
||||
public:
|
||||
Generator(const Instance &theme, const CurrentData ¤t);
|
||||
|
@ -48,6 +105,7 @@ private:
|
|||
};
|
||||
struct Row {
|
||||
Text name;
|
||||
QString letters;
|
||||
enum class Type {
|
||||
User,
|
||||
Group,
|
||||
|
@ -107,7 +165,7 @@ private:
|
|||
void paintBubble(const Bubble &bubble);
|
||||
void paintService(QString text);
|
||||
|
||||
void paintUserpic(int x, int y, Row::Type type, int index);
|
||||
void paintUserpic(int x, int y, Row::Type type, int index, QString letters);
|
||||
|
||||
void setTextPalette(const style::TextPalette &st);
|
||||
void restoreTextPalette();
|
||||
|
@ -156,6 +214,9 @@ void Generator::prepare() {
|
|||
void Generator::addRow(QString name, int peerIndex, QString date, QString text) {
|
||||
Row row;
|
||||
row.name.setText(st::msgNameStyle, name, _textNameOptions);
|
||||
|
||||
row.letters = fillLetters(name);
|
||||
|
||||
row.peerIndex = peerIndex;
|
||||
row.date = date;
|
||||
row.text.setRichText(st::dialogsTextStyle, text, _textDlgOptions);
|
||||
|
@ -503,7 +564,7 @@ void Generator::paintRow(const Row &row) {
|
|||
if (row.active || row.selected) {
|
||||
_p->fillRect(fullRect, row.active ? st::dialogsBgActive[_palette] : st::dialogsBgOver[_palette]);
|
||||
}
|
||||
paintUserpic(x + st::dialogsPadding.x(), y + st::dialogsPadding.y(), row.type, row.peerIndex);
|
||||
paintUserpic(x + st::dialogsPadding.x(), y + st::dialogsPadding.y(), row.type, row.peerIndex, row.letters);
|
||||
|
||||
auto nameleft = x + st::dialogsPadding.x() + st::dialogsPhotoSize + st::dialogsPhotoPadding;
|
||||
auto namewidth = x + fullWidth - nameleft - st::dialogsPadding.x();
|
||||
|
@ -763,38 +824,33 @@ void Generator::paintService(QString text) {
|
|||
_historyBottom = bubbleTop - st::msgServiceMargin.top();
|
||||
}
|
||||
|
||||
void Generator::paintUserpic(int x, int y, Row::Type type, int index) {
|
||||
const style::icon *userIcons[] = {
|
||||
&st::historyPeer1UserpicPerson,
|
||||
&st::historyPeer2UserpicPerson,
|
||||
&st::historyPeer3UserpicPerson,
|
||||
&st::historyPeer4UserpicPerson,
|
||||
&st::historyPeer5UserpicPerson,
|
||||
&st::historyPeer6UserpicPerson,
|
||||
&st::historyPeer7UserpicPerson,
|
||||
&st::historyPeer8UserpicPerson,
|
||||
void Generator::paintUserpic(int x, int y, Row::Type type, int index, QString letters) {
|
||||
style::color colors[] = {
|
||||
st::historyPeer1UserpicBg,
|
||||
st::historyPeer2UserpicBg,
|
||||
st::historyPeer3UserpicBg,
|
||||
st::historyPeer4UserpicBg,
|
||||
st::historyPeer5UserpicBg,
|
||||
st::historyPeer6UserpicBg,
|
||||
st::historyPeer7UserpicBg,
|
||||
st::historyPeer8UserpicBg,
|
||||
};
|
||||
const style::icon *chatIcons[] = {
|
||||
&st::historyPeer1UserpicChat,
|
||||
&st::historyPeer2UserpicChat,
|
||||
&st::historyPeer3UserpicChat,
|
||||
&st::historyPeer4UserpicChat,
|
||||
};
|
||||
const style::icon *channelIcons[] = {
|
||||
&st::historyPeer1UserpicChannel,
|
||||
&st::historyPeer2UserpicChannel,
|
||||
&st::historyPeer3UserpicChannel,
|
||||
&st::historyPeer4UserpicChannel,
|
||||
};
|
||||
auto userpic = (type == Row::Type::User) ? userIcons[index % base::array_size(userIcons)] : (type == Row::Type::Group) ? chatIcons[index % base::array_size(chatIcons)] : channelIcons[index % base::array_size(channelIcons)];
|
||||
auto color = colors[index % base::array_size(colors)];
|
||||
|
||||
auto image = QImage(userpic->width() * cIntRetinaFactor(), userpic->height() * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
|
||||
auto image = QImage(st::dialogsPhotoSize * cIntRetinaFactor(), st::dialogsPhotoSize * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
|
||||
image.setDevicePixelRatio(cRetinaFactor());
|
||||
image.fill(color[_palette]->c);
|
||||
{
|
||||
Painter p(&image);
|
||||
userpic->paint(p, 0, 0, userpic->width());
|
||||
auto fontsize = (st::dialogsPhotoSize * 13) / 33;
|
||||
auto font = st::historyPeerUserpicFont->f;
|
||||
font.setPixelSize(fontsize);
|
||||
|
||||
p.setFont(font);
|
||||
p.setBrush(Qt::NoBrush);
|
||||
p.setPen(st::historyPeerUserpicFg[_palette]);
|
||||
p.drawText(QRect(0, 0, st::dialogsPhotoSize, st::dialogsPhotoSize), letters, QTextOption(style::al_center));
|
||||
}
|
||||
image = std_::move(image).scaled(st::dialogsPhotoSize * cIntRetinaFactor(), st::dialogsPhotoSize * cIntRetinaFactor(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||
Images::prepareCircle(image);
|
||||
_p->drawImage(rtl() ? (_rect.width() - x - st::dialogsPhotoSize) : x, y, image);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue