Show emoji fingerprint tooltip in call panel.

This commit is contained in:
John Preston 2017-04-29 21:41:41 +03:00
parent f42f79ea95
commit 29fc69ebaa
4 changed files with 74 additions and 17 deletions

View File

@ -35,6 +35,11 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "platform/platform_specific.h" #include "platform/platform_specific.h"
namespace Calls { namespace Calls {
namespace {
constexpr auto kTooltipShowTimeoutMs = 1000;
} // namespace
class Panel::Button : public Ui::RippleButton { class Panel::Button : public Ui::RippleButton {
public: public:
@ -105,6 +110,7 @@ Panel::Panel(gsl::not_null<Call*> call)
, _mute(this, st::callMuteToggle) , _mute(this, st::callMuteToggle)
, _name(this, st::callName) , _name(this, st::callName)
, _status(this, st::callStatus) { , _status(this, st::callStatus) {
setMouseTracking(true);
initControls(); initControls();
initLayout(); initLayout();
showAndActivate(); showAndActivate();
@ -358,14 +364,12 @@ void Panel::paintEvent(QPaintEvent *e) {
} }
if (!_fingerprint.empty()) { if (!_fingerprint.empty()) {
App::roundRect(p, _fingerprintArea, st::callFingerprintBg, ImageRoundRadius::Small);
auto realSize = Ui::Emoji::Size(Ui::Emoji::Index() + 1); auto realSize = Ui::Emoji::Size(Ui::Emoji::Index() + 1);
auto size = realSize / cIntRetinaFactor(); auto size = realSize / cIntRetinaFactor();
auto count = _fingerprint.size(); auto left = _fingerprintArea.left() + st::callFingerprintPadding.left();
auto rectWidth = count * size + (count - 1) * st::callFingerprintSkip; auto top = _fingerprintArea.top() + st::callFingerprintPadding.top();
auto rectHeight = size;
auto left = (width() - rectWidth) / 2;
auto top = _contentTop - st::callFingerprintBottom - st::callFingerprintPadding.bottom() - size;
App::roundRect(p, QRect(left, top, rectWidth, rectHeight).marginsAdded(st::callFingerprintPadding), st::callFingerprintBg, ImageRoundRadius::Small);
for (auto emoji : _fingerprint) { for (auto emoji : _fingerprint) {
p.drawPixmap(QPoint(left, top), App::emojiLarge(), QRect(emoji->x() * realSize, emoji->y() * realSize, realSize, realSize)); p.drawPixmap(QPoint(left, top), App::emojiLarge(), QRect(emoji->x() * realSize, emoji->y() * realSize, realSize, realSize));
left += st::callFingerprintSkip + size; left += st::callFingerprintSkip + size;
@ -384,11 +388,16 @@ void Panel::mousePressEvent(QMouseEvent *e) {
void Panel::mouseMoveEvent(QMouseEvent *e) { void Panel::mouseMoveEvent(QMouseEvent *e) {
if (_dragging) { if (_dragging) {
Ui::Tooltip::Hide();
if (!(e->buttons() & Qt::LeftButton)) { if (!(e->buttons() & Qt::LeftButton)) {
_dragging = false; _dragging = false;
} else { } else {
move(_dragStartMyPosition + (e->globalPos() - _dragStartMousePosition)); move(_dragStartMyPosition + (e->globalPos() - _dragStartMousePosition));
} }
} else if (_fingerprintArea.contains(e->pos())) {
Ui::Tooltip::Show(kTooltipShowTimeoutMs, this);
} else {
Ui::Tooltip::Hide();
} }
} }
@ -398,6 +407,26 @@ void Panel::mouseReleaseEvent(QMouseEvent *e) {
} }
} }
void Panel::leaveEventHook(QEvent *e) {
Ui::Tooltip::Hide();
}
void Panel::leaveToChildEvent(QEvent *e, QWidget *child) {
Ui::Tooltip::Hide();
}
QString Panel::tooltipText() const {
return lng_call_fingerprint_tooltip(lt_user, App::peerName(_user));
}
QPoint Panel::tooltipPos() const {
return QCursor::pos();
}
bool Panel::tooltipWindowActive() const {
return !isHidden();
}
void Panel::stateChanged(State state) { void Panel::stateChanged(State state) {
updateStatusText(state); updateStatusText(state);
@ -425,14 +454,28 @@ void Panel::stateChanged(State state) {
} }
if (_fingerprint.empty() && _call && _call->isKeyShaForFingerprintReady()) { if (_fingerprint.empty() && _call && _call->isKeyShaForFingerprintReady()) {
_fingerprint = ComputeEmojiFingerprint(_call.get()); fillFingerprint();
update();
} }
if (state == State::Established && !isActiveWindow()) { if (state == State::Established && !isActiveWindow()) {
hideDeactivated(); hideDeactivated();
} }
} }
void Panel::fillFingerprint() {
_fingerprint = ComputeEmojiFingerprint(_call.get());
auto realSize = Ui::Emoji::Size(Ui::Emoji::Index() + 1);
auto size = realSize / cIntRetinaFactor();
auto count = _fingerprint.size();
auto rectWidth = count * size + (count - 1) * st::callFingerprintSkip;
auto rectHeight = size;
auto left = (width() - rectWidth) / 2;
auto top = _contentTop - st::callFingerprintBottom - st::callFingerprintPadding.bottom() - size;
_fingerprintArea = QRect(left, top, rectWidth, rectHeight).marginsAdded(st::callFingerprintPadding);
update();
}
void Panel::updateStatusText(State state) { void Panel::updateStatusText(State state) {
auto statusText = [this, state]() -> QString { auto statusText = [this, state]() -> QString {
switch (state) { switch (state) {

View File

@ -21,8 +21,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#pragma once #pragma once
#include "base/weak_unique_ptr.h" #include "base/weak_unique_ptr.h"
#include "calls/calls_call.h"
#include "base/timer.h" #include "base/timer.h"
#include "calls/calls_call.h"
#include "ui/widgets/tooltip.h"
namespace Ui { namespace Ui {
class IconButton; class IconButton;
@ -31,7 +32,7 @@ class FlatLabel;
namespace Calls { namespace Calls {
class Panel : public TWidget, private base::Subscriber { class Panel : public TWidget, private base::Subscriber, private Ui::AbstractTooltipShower {
public: public:
Panel(gsl::not_null<Call*> call); Panel(gsl::not_null<Call*> call);
@ -43,12 +44,19 @@ protected:
void mousePressEvent(QMouseEvent *e) override; void mousePressEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override; void mouseReleaseEvent(QMouseEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override; void mouseMoveEvent(QMouseEvent *e) override;
void leaveEventHook(QEvent *e) override;
void leaveToChildEvent(QEvent *e, QWidget *child) override;
bool event(QEvent *e) override; bool event(QEvent *e) override;
private: private:
using State = Call::State; using State = Call::State;
using Type = Call::Type; using Type = Call::Type;
// AbstractTooltipShower interface
QString tooltipText() const override;
QPoint tooltipPos() const override;
bool tooltipWindowActive() const override;
void initControls(); void initControls();
void initLayout(); void initLayout();
void initGeometry(); void initGeometry();
@ -68,6 +76,7 @@ private:
void stateChanged(State state); void stateChanged(State state);
void updateStatusText(State state); void updateStatusText(State state);
void startDurationUpdateTimer(TimeMs currentDuration); void startDurationUpdateTimer(TimeMs currentDuration);
void fillFingerprint();
base::weak_unique_ptr<Call> _call; base::weak_unique_ptr<Call> _call;
gsl::not_null<UserData*> _user; gsl::not_null<UserData*> _user;
@ -90,6 +99,7 @@ private:
object_ptr<Ui::FlatLabel> _name; object_ptr<Ui::FlatLabel> _name;
object_ptr<Ui::FlatLabel> _status; object_ptr<Ui::FlatLabel> _status;
std::vector<EmojiPtr> _fingerprint; std::vector<EmojiPtr> _fingerprint;
QRect _fingerprintArea;
base::Timer _updateDurationTimer; base::Timer _updateDurationTimer;

View File

@ -24,6 +24,14 @@ namespace Ui {
Tooltip *TooltipInstance = nullptr; Tooltip *TooltipInstance = nullptr;
bool AbstractTooltipShower::tooltipWindowActive() const {
if (auto window = App::wnd()) {
window->updateIsActive(0);
return window->isActive();
}
return false;
}
const style::Tooltip *AbstractTooltipShower::tooltipSt() const { const style::Tooltip *AbstractTooltipShower::tooltipSt() const {
return &st::defaultTooltip; return &st::defaultTooltip;
} }
@ -49,13 +57,7 @@ Tooltip::Tooltip() : TWidget(nullptr) {
void Tooltip::onShow() { void Tooltip::onShow() {
if (_shower) { if (_shower) {
auto text = QString(); auto text = _shower->tooltipWindowActive() ? _shower->tooltipText() : QString();
if (auto window = App::wnd()) {
window->updateIsActive(0);
if (window->isActive()) {
text = _shower->tooltipText();
}
}
if (text.isEmpty()) { if (text.isEmpty()) {
Hide(); Hide();
} else { } else {

View File

@ -27,8 +27,10 @@ class AbstractTooltipShower {
public: public:
virtual QString tooltipText() const = 0; virtual QString tooltipText() const = 0;
virtual QPoint tooltipPos() const = 0; virtual QPoint tooltipPos() const = 0;
virtual bool tooltipWindowActive() const;
virtual const style::Tooltip *tooltipSt() const; virtual const style::Tooltip *tooltipSt() const;
virtual ~AbstractTooltipShower(); virtual ~AbstractTooltipShower();
}; };
class Tooltip : public TWidget { class Tooltip : public TWidget {