Handle mouse events in log entry message parts.

Also highlight mentions and hashtags in them.
This commit is contained in:
John Preston 2017-06-23 13:54:18 +03:00
parent 17e08f9291
commit 693c30d264
3 changed files with 69 additions and 33 deletions

View File

@ -40,6 +40,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
namespace { namespace {
constexpr auto kMaxGifForwardedBarLines = 4; constexpr auto kMaxGifForwardedBarLines = 4;
constexpr auto kMaxOriginalEntryLines = 8192;
TextParseOptions _webpageTitleOptions = { TextParseOptions _webpageTitleOptions = {
TextParseMultiline | TextParseRichText, // flags TextParseMultiline | TextParseRichText, // flags
@ -48,7 +49,7 @@ TextParseOptions _webpageTitleOptions = {
Qt::LayoutDirectionAuto, // dir Qt::LayoutDirectionAuto, // dir
}; };
TextParseOptions _webpageDescriptionOptions = { TextParseOptions _webpageDescriptionOptions = {
TextParseLinks | TextParseMultiline | TextParseRichText, // flags TextParseLinks | TextParseMentions | TextParseHashtags | TextParseMultiline | TextParseRichText, // flags
0, // maxw 0, // maxw
0, // maxh 0, // maxh
Qt::LayoutDirectionAuto, // dir Qt::LayoutDirectionAuto, // dir
@ -3227,17 +3228,17 @@ void HistoryWebPage::initDimensions() {
} }
// init dimensions // init dimensions
int32 l = st::msgPadding.left() + st::webPageLeft, r = st::msgPadding.right(); auto l = st::msgPadding.left() + st::webPageLeft, r = st::msgPadding.right();
int32 skipBlockWidth = _parent->skipBlockWidth(); auto skipBlockWidth = _parent->skipBlockWidth();
_maxw = skipBlockWidth; _maxw = skipBlockWidth;
_minh = 0; _minh = 0;
int32 siteNameHeight = _data->siteName.isEmpty() ? 0 : lineHeight; auto siteNameHeight = _data->siteName.isEmpty() ? 0 : lineHeight;
int32 titleMinHeight = _title.isEmpty() ? 0 : lineHeight; auto titleMinHeight = _title.isEmpty() ? 0 : lineHeight;
int32 descMaxLines = (3 + (siteNameHeight ? 0 : 1) + (titleMinHeight ? 0 : 1)); auto descMaxLines = isLogEntryOriginal() ? kMaxOriginalEntryLines : (3 + (siteNameHeight ? 0 : 1) + (titleMinHeight ? 0 : 1));
int32 descriptionMinHeight = _description.isEmpty() ? 0 : qMin(_description.minHeight(), descMaxLines * lineHeight); auto descriptionMinHeight = _description.isEmpty() ? 0 : qMin(_description.minHeight(), descMaxLines * lineHeight);
int32 articleMinHeight = siteNameHeight + titleMinHeight + descriptionMinHeight; auto articleMinHeight = siteNameHeight + titleMinHeight + descriptionMinHeight;
int32 articlePhotoMaxWidth = 0; auto articlePhotoMaxWidth = 0;
if (_asArticle) { if (_asArticle) {
articlePhotoMaxWidth = st::webPagePhotoDelta + qMax(articleThumbWidth(_data->photo, articleMinHeight), lineHeight); articlePhotoMaxWidth = st::webPagePhotoDelta + qMax(articleThumbWidth(_data->photo, articleMinHeight), lineHeight);
} }
@ -3298,7 +3299,7 @@ int HistoryWebPage::resizeGetHeight(int width) {
width -= st::msgPadding.left() + st::webPageLeft + st::msgPadding.right(); width -= st::msgPadding.left() + st::webPageLeft + st::msgPadding.right();
auto lineHeight = unitedLineHeight(); auto lineHeight = unitedLineHeight();
auto linesMax = 5; auto linesMax = isLogEntryOriginal() ? kMaxOriginalEntryLines : 5;
auto siteNameLines = _siteNameWidth ? 1 : 0; auto siteNameLines = _siteNameWidth ? 1 : 0;
auto siteNameHeight = _siteNameWidth ? lineHeight : 0; auto siteNameHeight = _siteNameWidth ? lineHeight : 0;
if (_asArticle) { if (_asArticle) {
@ -3322,11 +3323,13 @@ int HistoryWebPage::resizeGetHeight(int width) {
auto descriptionHeight = _description.countHeight(wleft); auto descriptionHeight = _description.countHeight(wleft);
if (descriptionHeight < (linesMax - siteNameLines - _titleLines) * st::webPageDescriptionFont->height) { if (descriptionHeight < (linesMax - siteNameLines - _titleLines) * st::webPageDescriptionFont->height) {
_descriptionLines = (descriptionHeight / st::webPageDescriptionFont->height); // We have height for all the lines.
_descriptionLines = -1;
_height += descriptionHeight;
} else { } else {
_descriptionLines = (linesMax - siteNameLines - _titleLines); _descriptionLines = (linesMax - siteNameLines - _titleLines);
_height += _descriptionLines * lineHeight;
} }
_height += _descriptionLines * lineHeight;
if (_height >= _pixh) { if (_height >= _pixh) {
break; break;
@ -3354,11 +3357,13 @@ int HistoryWebPage::resizeGetHeight(int width) {
} else { } else {
auto descriptionHeight = _description.countHeight(width); auto descriptionHeight = _description.countHeight(width);
if (descriptionHeight < (linesMax - siteNameLines - _titleLines) * st::webPageDescriptionFont->height) { if (descriptionHeight < (linesMax - siteNameLines - _titleLines) * st::webPageDescriptionFont->height) {
_descriptionLines = (descriptionHeight / st::webPageDescriptionFont->height); // We have height for all the lines.
_descriptionLines = -1;
_height += descriptionHeight;
} else { } else {
_descriptionLines = (linesMax - siteNameLines - _titleLines); _descriptionLines = (linesMax - siteNameLines - _titleLines);
_height += _descriptionLines * lineHeight;
} }
_height += _descriptionLines * lineHeight;
} }
if (_attach) { if (_attach) {
@ -3455,8 +3460,13 @@ void HistoryWebPage::draw(Painter &p, const QRect &r, TextSelection selection, T
if (_description.hasSkipBlock()) { if (_description.hasSkipBlock()) {
endskip = _parent->skipBlockWidth(); endskip = _parent->skipBlockWidth();
} }
_description.drawLeftElided(p, padding.left(), tshift, width, _width, _descriptionLines, style::al_left, 0, -1, endskip, false, toDescriptionSelection(selection)); if (_descriptionLines > 0) {
tshift += _descriptionLines * lineHeight; _description.drawLeftElided(p, padding.left(), tshift, width, _width, _descriptionLines, style::al_left, 0, -1, endskip, false, toDescriptionSelection(selection));
tshift += _descriptionLines * lineHeight;
} else {
_description.drawLeft(p, padding.left(), tshift, width, _width, style::al_left, 0, -1, toDescriptionSelection(selection));
tshift += _description.countHeight(width);
}
} }
if (_attach) { if (_attach) {
auto attachAtTop = !_siteNameWidth && !_titleLines && !_descriptionLines; auto attachAtTop = !_siteNameWidth && !_titleLines && !_descriptionLines;
@ -3543,14 +3553,19 @@ HistoryTextState HistoryWebPage::getState(QPoint point, HistoryStateRequest requ
tshift += _titleLines * lineHeight; tshift += _titleLines * lineHeight;
} }
if (_descriptionLines) { if (_descriptionLines) {
if (point.y() >= tshift && point.y() < tshift + _descriptionLines * lineHeight) { auto descriptionHeight = (_descriptionLines > 0) ? _descriptionLines * lineHeight : _description.countHeight(width);
Text::StateRequestElided descriptionRequest = request.forText(); if (point.y() >= tshift && point.y() < tshift + descriptionHeight) {
descriptionRequest.lines = _descriptionLines; if (_descriptionLines > 0) {
result = _description.getStateElidedLeft(point - QPoint(padding.left(), tshift), width, _width, descriptionRequest); Text::StateRequestElided descriptionRequest = request.forText();
} else if (point.y() >= tshift + _descriptionLines * lineHeight) { descriptionRequest.lines = _descriptionLines;
result = _description.getStateElidedLeft(point - QPoint(padding.left(), tshift), width, _width, descriptionRequest);
} else {
result = _description.getStateLeft(point - QPoint(padding.left(), tshift), width, _width, request.forText());
}
} else if (point.y() >= tshift + descriptionHeight) {
symbolAdd += _description.length(); symbolAdd += _description.length();
} }
tshift += _descriptionLines * lineHeight; tshift += descriptionHeight;
} }
if (inThumb) { if (inThumb) {
result.link = _openl; result.link = _openl;
@ -3647,12 +3662,16 @@ QMargins HistoryWebPage::inBubblePadding() const {
return QMargins(lshift, tshift, rshift, bshift); return QMargins(lshift, tshift, rshift, bshift);
} }
bool HistoryWebPage::isLogEntryOriginal() const {
return _parent->isLogEntry() && _parent->getMedia() != this;
}
int HistoryWebPage::bottomInfoPadding() const { int HistoryWebPage::bottomInfoPadding() const {
if (!isBubbleBottom()) return 0; if (!isBubbleBottom()) return 0;
auto result = st::msgDateFont->height; auto result = st::msgDateFont->height;
// we use padding greater than st::msgPadding.bottom() in the // We use padding greater than st::msgPadding.bottom() in the
// bottom of the bubble so that the left line looks pretty. // bottom of the bubble so that the left line looks pretty.
// but if we have bottom skip because of the info display // but if we have bottom skip because of the info display
// we don't need that additional padding so we replace it // we don't need that additional padding so we replace it

View File

@ -831,6 +831,7 @@ private:
} }
QMargins inBubblePadding() const; QMargins inBubblePadding() const;
int bottomInfoPadding() const; int bottomInfoPadding() const;
bool isLogEntryOriginal() const;
gsl::not_null<WebPageData*> _data; gsl::not_null<WebPageData*> _data;
ClickHandlerPtr _openl; ClickHandlerPtr _openl;

View File

@ -828,7 +828,7 @@ void HistoryMessage::initDimensions() {
auto mediaOnBottom = (mediaDisplayed && _media->isBubbleBottom()) || (entry/* && entry->_page->isBubbleBottom()*/); auto mediaOnBottom = (mediaDisplayed && _media->isBubbleBottom()) || (entry/* && entry->_page->isBubbleBottom()*/);
auto mediaOnTop = (mediaDisplayed && _media->isBubbleTop()) || (entry && entry->_page->isBubbleTop()); auto mediaOnTop = (mediaDisplayed && _media->isBubbleTop()) || (entry && entry->_page->isBubbleTop());
if (mediaDisplayed && mediaOnBottom) { if (mediaOnBottom) {
if (_text.hasSkipBlock()) { if (_text.hasSkipBlock()) {
_text.removeSkipBlock(); _text.removeSkipBlock();
_textWidth = -1; _textWidth = -1;
@ -1723,9 +1723,18 @@ HistoryTextState HistoryMessage::getState(QPoint point, HistoryStateRequest requ
} }
if (drawBubble()) { if (drawBubble()) {
auto entry = Get<HistoryMessageLogEntryOriginal>();
auto mediaDisplayed = _media && _media->isDisplayed(); auto mediaDisplayed = _media && _media->isDisplayed();
auto trect = g.marginsAdded(-st::msgPadding);
if (mediaDisplayed && _media->isBubbleTop()) { // Entry page is always a bubble bottom.
auto mediaOnBottom = (mediaDisplayed && _media->isBubbleBottom()) || (entry/* && entry->_page->isBubbleBottom()*/);
auto mediaOnTop = (mediaDisplayed && _media->isBubbleTop()) || (entry && entry->_page->isBubbleTop());
auto trect = g.marginsRemoved(st::msgPadding);
if (mediaOnBottom) {
trect.setHeight(trect.height() + st::msgPadding.bottom());
}
if (mediaOnTop) {
trect.setY(trect.y() - st::msgPadding.top()); trect.setY(trect.y() - st::msgPadding.top());
} else { } else {
if (getStateFromName(point, trect, &result)) return result; if (getStateFromName(point, trect, &result)) return result;
@ -1733,11 +1742,18 @@ HistoryTextState HistoryMessage::getState(QPoint point, HistoryStateRequest requ
if (getStateReplyInfo(point, trect, &result)) return result; if (getStateReplyInfo(point, trect, &result)) return result;
if (getStateViaBotIdInfo(point, trect, &result)) return result; if (getStateViaBotIdInfo(point, trect, &result)) return result;
} }
if (mediaDisplayed && _media->isBubbleBottom()) { if (entry) {
trect.setHeight(trect.height() + st::msgPadding.bottom()); auto entryHeight = entry->_page->height();
trect.setHeight(trect.height() - entryHeight);
auto entryLeft = g.left();
auto entryTop = trect.y() + trect.height();
if (point.y() >= entryTop && point.y() < entryTop + entryHeight) {
result = entry->_page->getState(point - QPoint(entryLeft, entryTop), request);
result.symbol += _text.length();
}
} }
auto needDateCheck = true; auto needDateCheck = mediaOnBottom ? !(entry ? entry->_page->customInfoLayout() : _media->customInfoLayout()) : true;
if (mediaDisplayed) { if (mediaDisplayed) {
auto mediaAboveText = _media->isAboveMessage(); auto mediaAboveText = _media->isAboveMessage();
auto mediaHeight = _media->height(); auto mediaHeight = _media->height();
@ -1751,11 +1767,11 @@ HistoryTextState HistoryMessage::getState(QPoint point, HistoryStateRequest requ
if (mediaAboveText) { if (mediaAboveText) {
trect.setY(trect.y() + mediaHeight); trect.setY(trect.y() + mediaHeight);
} }
getStateText(point, trect, &result, request); if (trect.contains(point)) {
getStateText(point, trect, &result, request);
}
} }
} else if (trect.contains(point)) {
needDateCheck = !_media->customInfoLayout();
} else {
getStateText(point, trect, &result, request); getStateText(point, trect, &result, request);
} }
if (needDateCheck) { if (needDateCheck) {