| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 |
- /*
- This file is part of Telegram Desktop,
- the official desktop application for the Telegram messaging service.
- For license and copyright information please follow this link:
- https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
- */
- #include "calls/calls_userpic.h"
- #include "data/data_peer.h"
- #include "main/main_session.h"
- #include "data/data_changes.h"
- #include "data/data_peer.h"
- #include "data/data_session.h"
- #include "data/data_cloud_file.h"
- #include "data/data_photo_media.h"
- #include "data/data_file_origin.h"
- #include "ui/empty_userpic.h"
- #include "ui/painter.h"
- #include "apiwrap.h" // requestFullPeer.
- #include "styles/style_calls.h"
- namespace Calls {
- namespace {
- } // namespace
- Userpic::Userpic(
- not_null<QWidget*> parent,
- not_null<PeerData*> peer,
- rpl::producer<bool> muted)
- : _content(parent)
- , _peer(peer) {
- setGeometry(0, 0, 0);
- setup(std::move(muted));
- }
- Userpic::~Userpic() = default;
- void Userpic::setVisible(bool visible) {
- _content.setVisible(visible);
- }
- void Userpic::setGeometry(int x, int y, int size) {
- if (this->size() != size) {
- _userPhoto = QPixmap();
- _userPhotoFull = false;
- }
- _content.setGeometry(x, y, size, size);
- _content.update();
- if (_userPhoto.isNull()) {
- refreshPhoto();
- }
- }
- void Userpic::setup(rpl::producer<bool> muted) {
- _content.show();
- _content.setAttribute(Qt::WA_TransparentForMouseEvents);
- _content.paintRequest(
- ) | rpl::start_with_next([=] {
- paint();
- }, lifetime());
- std::move(
- muted
- ) | rpl::start_with_next([=](bool muted) {
- setMuted(muted);
- }, lifetime());
- _peer->session().changes().peerFlagsValue(
- _peer,
- Data::PeerUpdate::Flag::Photo
- ) | rpl::start_with_next([=] {
- processPhoto();
- }, lifetime());
- _peer->session().downloaderTaskFinished(
- ) | rpl::start_with_next([=] {
- refreshPhoto();
- }, lifetime());
- _mutedAnimation.stop();
- }
- void Userpic::setMuteLayout(QPoint position, int size, int stroke) {
- _mutePosition = position;
- _muteSize = size;
- _muteStroke = stroke;
- _content.update();
- }
- void Userpic::paint() {
- auto p = QPainter(&_content);
- p.drawPixmap(0, 0, _userPhoto);
- if (_muted && _muteSize > 0) {
- auto hq = PainterHighQualityEnabler(p);
- auto pen = st::callBgOpaque->p;
- pen.setWidth(_muteStroke);
- p.setPen(pen);
- p.setBrush(st::callHangupBg);
- const auto rect = QRect(
- _mutePosition.x() - _muteSize / 2,
- _mutePosition.y() - _muteSize / 2,
- _muteSize,
- _muteSize);
- p.drawEllipse(rect);
- st::callMutedPeerIcon.paintInCenter(p, rect);
- }
- }
- void Userpic::setMuted(bool muted) {
- if (_muted == muted) {
- return;
- }
- _muted = muted;
- _content.update();
- //_mutedAnimation.start(
- // [=] { _content.update(); },
- // _muted ? 0. : 1.,
- // _muted ? 1. : 0.,
- // st::fadeWrapDuration);
- }
- int Userpic::size() const {
- return _content.width();
- }
- void Userpic::processPhoto() {
- _userpic = _peer->createUserpicView();
- _peer->loadUserpic();
- const auto photo = _peer->userpicPhotoId()
- ? _peer->owner().photo(_peer->userpicPhotoId()).get()
- : nullptr;
- if (isGoodPhoto(photo)) {
- _photo = photo->createMediaView();
- _photo->wanted(Data::PhotoSize::Thumbnail, _peer->userpicPhotoOrigin());
- } else {
- _photo = nullptr;
- if (_peer->userpicPhotoUnknown() || (photo && photo->isNull())) {
- _peer->session().api().requestFullPeer(_peer);
- }
- }
- refreshPhoto();
- }
- void Userpic::refreshPhoto() {
- if (!size()) {
- return;
- }
- const auto isNewBigPhoto = [&] {
- return _photo
- && (_photo->image(Data::PhotoSize::Thumbnail) != nullptr)
- && (_photo->owner()->id != _userPhotoId || !_userPhotoFull);
- }();
- if (isNewBigPhoto) {
- _userPhotoId = _photo->owner()->id;
- _userPhotoFull = true;
- createCache(_photo->image(Data::PhotoSize::Thumbnail));
- } else if (_userPhoto.isNull()) {
- if (const auto cloud = _peer->userpicCloudImage(_userpic)) {
- auto image = Image(base::duplicate(*cloud));
- createCache(&image);
- } else {
- createCache(nullptr);
- }
- }
- }
- void Userpic::createCache(Image *image) {
- const auto size = this->size();
- const auto real = size * style::DevicePixelRatio();
- //_useTransparency
- // ? (Images::Option::RoundLarge
- // | Images::Option::RoundSkipBottomLeft
- // | Images::Option::RoundSkipBottomRight)
- // : Images::Option::None;
- if (image) {
- auto width = image->width();
- auto height = image->height();
- if (width > height) {
- width = qMax((width * real) / height, 1);
- height = real;
- } else {
- height = qMax((height * real) / width, 1);
- width = real;
- }
- _userPhoto = image->pixNoCache(
- { width, height },
- {
- .options = Images::Option::RoundCircle,
- .outer = { size, size },
- });
- _userPhoto.setDevicePixelRatio(style::DevicePixelRatio());
- } else {
- auto filled = QImage(
- QSize(real, real),
- QImage::Format_ARGB32_Premultiplied);
- filled.setDevicePixelRatio(style::DevicePixelRatio());
- filled.fill(Qt::transparent);
- {
- auto p = QPainter(&filled);
- Ui::EmptyUserpic(
- Ui::EmptyUserpic::UserpicColor(_peer->colorIndex()),
- _peer->name()
- ).paintCircle(p, 0, 0, size, size);
- }
- //_userPhoto = Images::PixmapFast(Images::Round(
- // std::move(filled),
- // ImageRoundRadius::Large,
- // RectPart::TopLeft | RectPart::TopRight));
- _userPhoto = Images::PixmapFast(std::move(filled));
- }
- _content.update();
- }
- bool Userpic::isGoodPhoto(PhotoData *photo) const {
- if (!photo || photo->isNull()) {
- return false;
- }
- const auto badAspect = [](int a, int b) {
- return a > 10 * b;
- };
- const auto width = photo->width();
- const auto height = photo->height();
- return !badAspect(width, height) && !badAspect(height, width);
- }
- } // namespace Calls
|