From 29fc69ebaa0e289d0fc5f53fb2dd084f95a96765 Mon Sep 17 00:00:00 2001 From: John Preston Date: Sat, 29 Apr 2017 21:41:41 +0300 Subject: [PATCH] Show emoji fingerprint tooltip in call panel. --- Telegram/SourceFiles/calls/calls_panel.cpp | 59 ++++++++++++++++++--- Telegram/SourceFiles/calls/calls_panel.h | 14 ++++- Telegram/SourceFiles/ui/widgets/tooltip.cpp | 16 +++--- Telegram/SourceFiles/ui/widgets/tooltip.h | 2 + 4 files changed, 74 insertions(+), 17 deletions(-) diff --git a/Telegram/SourceFiles/calls/calls_panel.cpp b/Telegram/SourceFiles/calls/calls_panel.cpp index 498d20134..b8ed190e1 100644 --- a/Telegram/SourceFiles/calls/calls_panel.cpp +++ b/Telegram/SourceFiles/calls/calls_panel.cpp @@ -35,6 +35,11 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "platform/platform_specific.h" namespace Calls { +namespace { + +constexpr auto kTooltipShowTimeoutMs = 1000; + +} // namespace class Panel::Button : public Ui::RippleButton { public: @@ -105,6 +110,7 @@ Panel::Panel(gsl::not_null call) , _mute(this, st::callMuteToggle) , _name(this, st::callName) , _status(this, st::callStatus) { + setMouseTracking(true); initControls(); initLayout(); showAndActivate(); @@ -358,14 +364,12 @@ void Panel::paintEvent(QPaintEvent *e) { } if (!_fingerprint.empty()) { + App::roundRect(p, _fingerprintArea, st::callFingerprintBg, ImageRoundRadius::Small); + 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; - App::roundRect(p, QRect(left, top, rectWidth, rectHeight).marginsAdded(st::callFingerprintPadding), st::callFingerprintBg, ImageRoundRadius::Small); + auto left = _fingerprintArea.left() + st::callFingerprintPadding.left(); + auto top = _fingerprintArea.top() + st::callFingerprintPadding.top(); for (auto emoji : _fingerprint) { p.drawPixmap(QPoint(left, top), App::emojiLarge(), QRect(emoji->x() * realSize, emoji->y() * realSize, realSize, realSize)); left += st::callFingerprintSkip + size; @@ -384,11 +388,16 @@ void Panel::mousePressEvent(QMouseEvent *e) { void Panel::mouseMoveEvent(QMouseEvent *e) { if (_dragging) { + Ui::Tooltip::Hide(); if (!(e->buttons() & Qt::LeftButton)) { _dragging = false; } else { 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) { updateStatusText(state); @@ -425,14 +454,28 @@ void Panel::stateChanged(State state) { } if (_fingerprint.empty() && _call && _call->isKeyShaForFingerprintReady()) { - _fingerprint = ComputeEmojiFingerprint(_call.get()); - update(); + fillFingerprint(); } if (state == State::Established && !isActiveWindow()) { 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) { auto statusText = [this, state]() -> QString { switch (state) { diff --git a/Telegram/SourceFiles/calls/calls_panel.h b/Telegram/SourceFiles/calls/calls_panel.h index 9706be3c0..b5ab46e9c 100644 --- a/Telegram/SourceFiles/calls/calls_panel.h +++ b/Telegram/SourceFiles/calls/calls_panel.h @@ -21,8 +21,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #pragma once #include "base/weak_unique_ptr.h" -#include "calls/calls_call.h" #include "base/timer.h" +#include "calls/calls_call.h" +#include "ui/widgets/tooltip.h" namespace Ui { class IconButton; @@ -31,7 +32,7 @@ class FlatLabel; namespace Calls { -class Panel : public TWidget, private base::Subscriber { +class Panel : public TWidget, private base::Subscriber, private Ui::AbstractTooltipShower { public: Panel(gsl::not_null call); @@ -43,12 +44,19 @@ protected: void mousePressEvent(QMouseEvent *e) override; void mouseReleaseEvent(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; private: using State = Call::State; using Type = Call::Type; + // AbstractTooltipShower interface + QString tooltipText() const override; + QPoint tooltipPos() const override; + bool tooltipWindowActive() const override; + void initControls(); void initLayout(); void initGeometry(); @@ -68,6 +76,7 @@ private: void stateChanged(State state); void updateStatusText(State state); void startDurationUpdateTimer(TimeMs currentDuration); + void fillFingerprint(); base::weak_unique_ptr _call; gsl::not_null _user; @@ -90,6 +99,7 @@ private: object_ptr _name; object_ptr _status; std::vector _fingerprint; + QRect _fingerprintArea; base::Timer _updateDurationTimer; diff --git a/Telegram/SourceFiles/ui/widgets/tooltip.cpp b/Telegram/SourceFiles/ui/widgets/tooltip.cpp index 1642d5867..7c63fe0b8 100644 --- a/Telegram/SourceFiles/ui/widgets/tooltip.cpp +++ b/Telegram/SourceFiles/ui/widgets/tooltip.cpp @@ -24,6 +24,14 @@ namespace Ui { 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 { return &st::defaultTooltip; } @@ -49,13 +57,7 @@ Tooltip::Tooltip() : TWidget(nullptr) { void Tooltip::onShow() { if (_shower) { - auto text = QString(); - if (auto window = App::wnd()) { - window->updateIsActive(0); - if (window->isActive()) { - text = _shower->tooltipText(); - } - } + auto text = _shower->tooltipWindowActive() ? _shower->tooltipText() : QString(); if (text.isEmpty()) { Hide(); } else { diff --git a/Telegram/SourceFiles/ui/widgets/tooltip.h b/Telegram/SourceFiles/ui/widgets/tooltip.h index a84286010..ee530798d 100644 --- a/Telegram/SourceFiles/ui/widgets/tooltip.h +++ b/Telegram/SourceFiles/ui/widgets/tooltip.h @@ -27,8 +27,10 @@ class AbstractTooltipShower { public: virtual QString tooltipText() const = 0; virtual QPoint tooltipPos() const = 0; + virtual bool tooltipWindowActive() const; virtual const style::Tooltip *tooltipSt() const; virtual ~AbstractTooltipShower(); + }; class Tooltip : public TWidget {