"Fossies" - the Fresh Open Source Software Archive

Member "tdesktop-2.6.1/Telegram/SourceFiles/chat_helpers/bot_keyboard.cpp" (24 Feb 2021, 7696 Bytes) of package /linux/misc/tdesktop-2.6.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "bot_keyboard.cpp" see the Fossies "Dox" file reference documentation.

    1 /*
    2 This file is part of Telegram Desktop,
    3 the official desktop application for the Telegram messaging service.
    4 
    5 For license and copyright information please follow this link:
    6 https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
    7 */
    8 #include "chat_helpers/bot_keyboard.h"
    9 
   10 #include "history/history.h"
   11 #include "history/history_item_components.h"
   12 #include "data/data_user.h"
   13 #include "data/data_session.h"
   14 #include "main/main_session.h"
   15 #include "ui/cached_round_corners.h"
   16 #include "facades.h"
   17 #include "styles/style_widgets.h"
   18 #include "styles/style_chat.h"
   19 
   20 namespace {
   21 
   22 class Style : public ReplyKeyboard::Style {
   23 public:
   24     Style(
   25         not_null<BotKeyboard*> parent,
   26         const style::BotKeyboardButton &st);
   27 
   28     int buttonRadius() const override;
   29 
   30     void startPaint(Painter &p) const override;
   31     const style::TextStyle &textStyle() const override;
   32     void repaint(not_null<const HistoryItem*> item) const override;
   33 
   34 protected:
   35     void paintButtonBg(
   36         Painter &p,
   37         const QRect &rect,
   38         float64 howMuchOver) const override;
   39     void paintButtonIcon(
   40         Painter &p,
   41         const QRect &rect,
   42         int outerWidth,
   43         HistoryMessageMarkupButton::Type type) const override;
   44     void paintButtonLoading(Painter &p, const QRect &rect) const override;
   45     int minButtonWidth(HistoryMessageMarkupButton::Type type) const override;
   46 
   47 private:
   48     not_null<BotKeyboard*> _parent;
   49 
   50 };
   51 
   52 Style::Style(
   53     not_null<BotKeyboard*> parent,
   54     const style::BotKeyboardButton &st)
   55 : ReplyKeyboard::Style(st), _parent(parent) {
   56 }
   57 
   58 void Style::startPaint(Painter &p) const {
   59     p.setPen(st::botKbColor);
   60     p.setFont(st::botKbStyle.font);
   61 }
   62 
   63 const style::TextStyle &Style::textStyle() const {
   64     return st::botKbStyle;
   65 }
   66 
   67 void Style::repaint(not_null<const HistoryItem*> item) const {
   68     _parent->update();
   69 }
   70 
   71 int Style::buttonRadius() const {
   72     return st::roundRadiusSmall;
   73 }
   74 
   75 void Style::paintButtonBg(
   76         Painter &p,
   77         const QRect &rect,
   78         float64 howMuchOver) const {
   79     Ui::FillRoundRect(p, rect, st::botKbBg, Ui::BotKeyboardCorners);
   80 }
   81 
   82 void Style::paintButtonIcon(
   83         Painter &p,
   84         const QRect &rect,
   85         int outerWidth,
   86         HistoryMessageMarkupButton::Type type) const {
   87     // Buttons with icons should not appear here.
   88 }
   89 
   90 void Style::paintButtonLoading(Painter &p, const QRect &rect) const {
   91     // Buttons with loading progress should not appear here.
   92 }
   93 
   94 int Style::minButtonWidth(HistoryMessageMarkupButton::Type type) const {
   95     int result = 2 * buttonPadding();
   96     return result;
   97 }
   98 
   99 } // namespace
  100 
  101 BotKeyboard::BotKeyboard(not_null<Main::Session*> session, QWidget *parent)
  102 : TWidget(parent)
  103 , _session(session)
  104 , _st(&st::botKbButton) {
  105     setGeometry(0, 0, _st->margin, st::botKbScroll.deltat);
  106     _height = st::botKbScroll.deltat;
  107     setMouseTracking(true);
  108 }
  109 
  110 void BotKeyboard::paintEvent(QPaintEvent *e) {
  111     Painter p(this);
  112 
  113     auto clip = e->rect();
  114     p.fillRect(clip, st::historyComposeAreaBg);
  115 
  116     if (_impl) {
  117         int x = rtl() ? st::botKbScroll.width : _st->margin;
  118         p.translate(x, st::botKbScroll.deltat);
  119         _impl->paint(p, width(), clip.translated(-x, -st::botKbScroll.deltat));
  120     }
  121 }
  122 
  123 void BotKeyboard::mousePressEvent(QMouseEvent *e) {
  124     _lastMousePos = e->globalPos();
  125     updateSelected();
  126 
  127     ClickHandler::pressed();
  128 }
  129 
  130 void BotKeyboard::mouseMoveEvent(QMouseEvent *e) {
  131     _lastMousePos = e->globalPos();
  132     updateSelected();
  133 }
  134 
  135 void BotKeyboard::mouseReleaseEvent(QMouseEvent *e) {
  136     _lastMousePos = e->globalPos();
  137     updateSelected();
  138 
  139     if (ClickHandlerPtr activated = ClickHandler::unpressed()) {
  140         ActivateClickHandler(window(), activated, e->button());
  141     }
  142 }
  143 
  144 void BotKeyboard::enterEventHook(QEvent *e) {
  145     _lastMousePos = QCursor::pos();
  146     updateSelected();
  147 }
  148 
  149 void BotKeyboard::leaveEventHook(QEvent *e) {
  150     clearSelection();
  151 }
  152 
  153 bool BotKeyboard::moderateKeyActivate(int key) {
  154     if (const auto item = _session->data().message(_wasForMsgId)) {
  155         if (const auto markup = item->Get<HistoryMessageReplyMarkup>()) {
  156             if (key >= Qt::Key_1 && key <= Qt::Key_9) {
  157                 const auto index = int(key - Qt::Key_1);
  158                 if (!markup->rows.empty()
  159                     && index >= 0
  160                     && index < int(markup->rows.front().size())) {
  161                     App::activateBotCommand(item, 0, index);
  162                     return true;
  163                 }
  164             } else if (const auto user = item->history()->peer->asUser()) {
  165                 if (user->isBot() && item->from() == user) {
  166                     if (key == Qt::Key_Q) {
  167                         App::sendBotCommand(user, user, qsl("/translate"));
  168                     } else if (key == Qt::Key_W) {
  169                         App::sendBotCommand(user, user, qsl("/eng"));
  170                     }
  171                     return true;
  172                 }
  173             }
  174         }
  175     }
  176     return false;
  177 }
  178 
  179 void BotKeyboard::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) {
  180     if (!_impl) return;
  181     _impl->clickHandlerActiveChanged(p, active);
  182 }
  183 
  184 void BotKeyboard::clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed) {
  185     if (!_impl) return;
  186     _impl->clickHandlerPressedChanged(p, pressed);
  187 }
  188 
  189 bool BotKeyboard::updateMarkup(HistoryItem *to, bool force) {
  190     if (!to || !to->definesReplyKeyboard()) {
  191         if (_wasForMsgId.msg) {
  192             _maximizeSize = _singleUse = _forceReply = false;
  193             _wasForMsgId = FullMsgId();
  194             _impl = nullptr;
  195             return true;
  196         }
  197         return false;
  198     }
  199 
  200     if (_wasForMsgId == FullMsgId(to->channelId(), to->id) && !force) {
  201         return false;
  202     }
  203 
  204     _wasForMsgId = FullMsgId(to->channelId(), to->id);
  205 
  206     auto markupFlags = to->replyKeyboardFlags();
  207     _forceReply = markupFlags & MTPDreplyKeyboardMarkup_ClientFlag::f_force_reply;
  208     _maximizeSize = !(markupFlags & MTPDreplyKeyboardMarkup::Flag::f_resize);
  209     _singleUse = _forceReply || (markupFlags & MTPDreplyKeyboardMarkup::Flag::f_single_use);
  210 
  211     _impl = nullptr;
  212     if (auto markup = to->Get<HistoryMessageReplyMarkup>()) {
  213         if (!markup->rows.empty()) {
  214             _impl = std::make_unique<ReplyKeyboard>(
  215                 to,
  216                 std::make_unique<Style>(this, *_st));
  217         }
  218     }
  219 
  220     resizeToWidth(width(), _maxOuterHeight);
  221 
  222     return true;
  223 }
  224 
  225 bool BotKeyboard::hasMarkup() const {
  226     return _impl != nullptr;
  227 }
  228 
  229 bool BotKeyboard::forceReply() const {
  230     return _forceReply;
  231 }
  232 
  233 int BotKeyboard::resizeGetHeight(int newWidth) {
  234     updateStyle(newWidth);
  235     _height = st::botKbScroll.deltat + st::botKbScroll.deltab + (_impl ? _impl->naturalHeight() : 0);
  236     if (_maximizeSize) {
  237         accumulate_max(_height, _maxOuterHeight);
  238     }
  239     if (_impl) {
  240         int implWidth = newWidth - _st->margin - st::botKbScroll.width;
  241         int implHeight = _height - (st::botKbScroll.deltat + st::botKbScroll.deltab);
  242         _impl->resize(implWidth, implHeight);
  243     }
  244     return _height;
  245 }
  246 
  247 bool BotKeyboard::maximizeSize() const {
  248     return _maximizeSize;
  249 }
  250 
  251 bool BotKeyboard::singleUse() const {
  252     return _singleUse;
  253 }
  254 
  255 void BotKeyboard::updateStyle(int newWidth) {
  256     if (!_impl) return;
  257 
  258     int implWidth = newWidth - st::botKbButton.margin - st::botKbScroll.width;
  259     _st = _impl->isEnoughSpace(implWidth, st::botKbButton) ? &st::botKbButton : &st::botKbTinyButton;
  260 
  261     _impl->setStyle(std::make_unique<Style>(this, *_st));
  262 }
  263 
  264 void BotKeyboard::clearSelection() {
  265     if (_impl) {
  266         if (ClickHandler::setActive(ClickHandlerPtr(), this)) {
  267             Ui::Tooltip::Hide();
  268             setCursor(style::cur_default);
  269         }
  270     }
  271 }
  272 
  273 QPoint BotKeyboard::tooltipPos() const {
  274     return _lastMousePos;
  275 }
  276 
  277 bool BotKeyboard::tooltipWindowActive() const {
  278     return Ui::AppInFocus() && Ui::InFocusChain(window());
  279 }
  280 
  281 QString BotKeyboard::tooltipText() const {
  282     if (ClickHandlerPtr lnk = ClickHandler::getActive()) {
  283         return lnk->tooltip();
  284     }
  285     return QString();
  286 }
  287 
  288 void BotKeyboard::updateSelected() {
  289     Ui::Tooltip::Show(1000, this);
  290 
  291     if (!_impl) return;
  292 
  293     auto p = mapFromGlobal(_lastMousePos);
  294     auto x = rtl() ? st::botKbScroll.width : _st->margin;
  295 
  296     auto link = _impl->getLink(p - QPoint(x, _st->margin));
  297     if (ClickHandler::setActive(link, this)) {
  298         Ui::Tooltip::Hide();
  299         setCursor(link ? style::cur_pointer : style::cur_default);
  300     }
  301 }
  302 
  303 BotKeyboard::~BotKeyboard() = default;