Support rich text in toasts.
This commit is contained in:
parent
14c5da49f9
commit
8d8d561127
7 changed files with 75 additions and 5 deletions
|
|
@ -271,6 +271,10 @@ inlineResultsMinWidth: 48px;
|
||||||
inlineDurationMargin: 3px;
|
inlineDurationMargin: 3px;
|
||||||
|
|
||||||
toastTextStyle: defaultTextStyle;
|
toastTextStyle: defaultTextStyle;
|
||||||
|
toastTextPalette: TextPalette(defaultTextPalette) {
|
||||||
|
linkFg: mediaviewTextLinkFg;
|
||||||
|
monoFg: mediaviewCaptionFg;
|
||||||
|
}
|
||||||
toastMaxWidth: 480px;
|
toastMaxWidth: 480px;
|
||||||
toastMinMargin: 13px;
|
toastMinMargin: 13px;
|
||||||
toastPadding: margins(19px, 13px, 19px, 12px);
|
toastPadding: margins(19px, 13px, 19px, 12px);
|
||||||
|
|
|
||||||
|
|
@ -1321,6 +1321,12 @@ QString SingleLine(const QString &text) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextWithEntities SingleLine(const TextWithEntities &text) {
|
||||||
|
auto copy = text;
|
||||||
|
Trim(copy);
|
||||||
|
return { SingleLine(copy.text), std::move(copy.entities) };
|
||||||
|
}
|
||||||
|
|
||||||
QString RemoveAccents(const QString &text) {
|
QString RemoveAccents(const QString &text) {
|
||||||
auto result = text;
|
auto result = text;
|
||||||
auto copying = false;
|
auto copying = false;
|
||||||
|
|
|
||||||
|
|
@ -285,6 +285,7 @@ QString MarkdownPreBadAfter();
|
||||||
QString Clean(const QString &text);
|
QString Clean(const QString &text);
|
||||||
QString EscapeForRichParsing(const QString &text);
|
QString EscapeForRichParsing(const QString &text);
|
||||||
QString SingleLine(const QString &text);
|
QString SingleLine(const QString &text);
|
||||||
|
TextWithEntities SingleLine(const TextWithEntities &text);
|
||||||
QString RemoveAccents(const QString &text);
|
QString RemoveAccents(const QString &text);
|
||||||
QString RemoveEmoji(const QString &text);
|
QString RemoveEmoji(const QString &text);
|
||||||
QStringList PrepareSearchWords(const QString &query, const QRegularExpression *SplitterOverride = nullptr);
|
QStringList PrepareSearchWords(const QString &query, const QRegularExpression *SplitterOverride = nullptr);
|
||||||
|
|
|
||||||
|
|
@ -50,13 +50,13 @@ void Show(const Config &config) {
|
||||||
|
|
||||||
void Show(not_null<QWidget*> parent, const QString &text) {
|
void Show(not_null<QWidget*> parent, const QString &text) {
|
||||||
auto config = Config();
|
auto config = Config();
|
||||||
config.text = text;
|
config.text = { text };
|
||||||
Show(parent, config);
|
Show(parent, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Show(const QString &text) {
|
void Show(const QString &text) {
|
||||||
auto config = Config();
|
auto config = Config();
|
||||||
config.text = text;
|
config.text = { text };
|
||||||
Show(config);
|
Show(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ui/effects/animations.h"
|
#include "ui/effects/animations.h"
|
||||||
|
#include "ui/text/text_entity.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
namespace Toast {
|
namespace Toast {
|
||||||
|
|
@ -18,7 +19,7 @@ class Widget;
|
||||||
|
|
||||||
inline constexpr auto kDefaultDuration = crl::time(1500);
|
inline constexpr auto kDefaultDuration = crl::time(1500);
|
||||||
struct Config {
|
struct Config {
|
||||||
QString text;
|
TextWithEntities text;
|
||||||
QMargins padding;
|
QMargins padding;
|
||||||
crl::time durationMs = kDefaultDuration;
|
crl::time durationMs = kDefaultDuration;
|
||||||
int minWidth = 0;
|
int minWidth = 0;
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,8 @@
|
||||||
#include "ui/image/image_prepare.h"
|
#include "ui/image/image_prepare.h"
|
||||||
#include "styles/palette.h"
|
#include "styles/palette.h"
|
||||||
|
|
||||||
|
#include <QtGui/QtEvents>
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
namespace Toast {
|
namespace Toast {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
@ -29,12 +31,16 @@ Widget::Widget(QWidget *parent, const Config &config)
|
||||||
_maxTextHeight,
|
_maxTextHeight,
|
||||||
Qt::LayoutDirectionAuto
|
Qt::LayoutDirectionAuto
|
||||||
};
|
};
|
||||||
_text.setText(
|
_text.setMarkedText(
|
||||||
st::toastTextStyle,
|
st::toastTextStyle,
|
||||||
_multiline ? config.text : TextUtilities::SingleLine(config.text),
|
_multiline ? config.text : TextUtilities::SingleLine(config.text),
|
||||||
toastOptions);
|
toastOptions);
|
||||||
|
|
||||||
|
if (_text.hasLinks()) {
|
||||||
|
setMouseTracking(true);
|
||||||
|
} else {
|
||||||
setAttribute(Qt::WA_TransparentForMouseEvents);
|
setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||||
|
}
|
||||||
|
|
||||||
onParentResized();
|
onParentResized();
|
||||||
show();
|
show();
|
||||||
|
|
@ -63,11 +69,58 @@ void Widget::paintEvent(QPaintEvent *e) {
|
||||||
p.setOpacity(_shownLevel);
|
p.setOpacity(_shownLevel);
|
||||||
_roundRect.paint(p, rect());
|
_roundRect.paint(p, rect());
|
||||||
|
|
||||||
|
p.setTextPalette(st::toastTextPalette);
|
||||||
|
|
||||||
const auto lines = _maxTextHeight / st::toastTextStyle.font->height;
|
const auto lines = _maxTextHeight / st::toastTextStyle.font->height;
|
||||||
p.setPen(st::toastFg);
|
p.setPen(st::toastFg);
|
||||||
_text.drawElided(p, _padding.left(), _padding.top(), _textWidth + 1, lines);
|
_text.drawElided(p, _padding.left(), _padding.top(), _textWidth + 1, lines);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Widget::leaveEventHook(QEvent *e) {
|
||||||
|
if (!_text.hasLinks()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ClickHandler::getActive()) {
|
||||||
|
ClickHandler::setActive(nullptr);
|
||||||
|
setCursor(style::cur_default);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::mouseMoveEvent(QMouseEvent *e) {
|
||||||
|
if (!_text.hasLinks()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto point = e->pos() - QPoint(_padding.left(), _padding.top());
|
||||||
|
const auto lines = _maxTextHeight / st::toastTextStyle.font->height;
|
||||||
|
const auto state = _text.getStateElided(point, _textWidth + 1);
|
||||||
|
const auto was = ClickHandler::getActive();
|
||||||
|
if (was != state.link) {
|
||||||
|
ClickHandler::setActive(state.link);
|
||||||
|
if ((was != nullptr) != (state.link != nullptr)) {
|
||||||
|
setCursor(was ? style::cur_default : style::cur_pointer);
|
||||||
|
}
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::mousePressEvent(QMouseEvent *e) {
|
||||||
|
if (!_text.hasLinks() || e->button() != Qt::LeftButton) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ClickHandler::pressed();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::mouseReleaseEvent(QMouseEvent *e) {
|
||||||
|
if (!_text.hasLinks() || e->button() != Qt::LeftButton) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (const auto handler = ClickHandler::unpressed()) {
|
||||||
|
handler->onClick({ e->button() });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace Toast
|
} // namespace Toast
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,11 @@ public:
|
||||||
protected:
|
protected:
|
||||||
void paintEvent(QPaintEvent *e) override;
|
void paintEvent(QPaintEvent *e) override;
|
||||||
|
|
||||||
|
void leaveEventHook(QEvent *e) override;
|
||||||
|
void mouseMoveEvent(QMouseEvent *e) override;
|
||||||
|
void mousePressEvent(QMouseEvent *e) override;
|
||||||
|
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int widthWithoutPadding(int w) {
|
int widthWithoutPadding(int w) {
|
||||||
return w - _padding.left() - _padding.right();
|
return w - _padding.left() - _padding.right();
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue